From 2159047f7a97bd07d66507696a8b038f6aef0509 Mon Sep 17 00:00:00 2001 From: niklas Date: Mon, 8 Jan 1996 11:03:33 +0000 Subject: [PATCH] Initial GNU binutils 2.6 import --- gnu/usr.bin/binutils/COPYING | 339 + gnu/usr.bin/binutils/COPYING.LIB | 481 + gnu/usr.bin/binutils/Makefile.in | 1289 ++ gnu/usr.bin/binutils/README | 47 + gnu/usr.bin/binutils/bfd/COPYING | 339 + gnu/usr.bin/binutils/bfd/ChangeLog | 1721 +++ gnu/usr.bin/binutils/bfd/ChangeLog.1 | 6951 +++++++++ gnu/usr.bin/binutils/bfd/ChangeLog.2 | 8830 +++++++++++ gnu/usr.bin/binutils/bfd/Makefile.in | 976 ++ gnu/usr.bin/binutils/bfd/PORTING | 83 + gnu/usr.bin/binutils/bfd/TODO | 25 + gnu/usr.bin/binutils/bfd/VERSION | 1 + gnu/usr.bin/binutils/bfd/acconfig.h | 17 + gnu/usr.bin/binutils/bfd/aclocal.m4 | 64 + gnu/usr.bin/binutils/bfd/aix386-core.c | 289 + gnu/usr.bin/binutils/bfd/aout-adobe.c | 532 + gnu/usr.bin/binutils/bfd/aout-arm.c | 548 + gnu/usr.bin/binutils/bfd/aout-encap.c | 236 + gnu/usr.bin/binutils/bfd/aout-ns32k.c | 399 + gnu/usr.bin/binutils/bfd/aout-target.h | 604 + gnu/usr.bin/binutils/bfd/aout0.c | 32 + gnu/usr.bin/binutils/bfd/aout32.c | 23 + gnu/usr.bin/binutils/bfd/aout64.c | 31 + gnu/usr.bin/binutils/bfd/aoutf1.h | 792 + gnu/usr.bin/binutils/bfd/aoutx.h | 5355 +++++++ gnu/usr.bin/binutils/bfd/archive.c | 2154 +++ gnu/usr.bin/binutils/bfd/archures.c | 712 + gnu/usr.bin/binutils/bfd/bfd-in.h | 646 + gnu/usr.bin/binutils/bfd/bfd-in2.h | 2406 +++ gnu/usr.bin/binutils/bfd/bfd.c | 1048 ++ gnu/usr.bin/binutils/bfd/binary.c | 359 + gnu/usr.bin/binutils/bfd/bout.c | 1481 ++ gnu/usr.bin/binutils/bfd/cache.c | 343 + gnu/usr.bin/binutils/bfd/cf-i386lynx.c | 31 + gnu/usr.bin/binutils/bfd/cf-m68klynx.c | 223 + gnu/usr.bin/binutils/bfd/cf-sparclynx.c | 28 + gnu/usr.bin/binutils/bfd/cisco-core.c | 322 + gnu/usr.bin/binutils/bfd/coff-a29k.c | 641 + gnu/usr.bin/binutils/bfd/coff-alpha.c | 2103 +++ gnu/usr.bin/binutils/bfd/coff-apollo.c | 162 + gnu/usr.bin/binutils/bfd/coff-arm.c | 537 + gnu/usr.bin/binutils/bfd/coff-go32.c | 25 + gnu/usr.bin/binutils/bfd/coff-h8300.c | 640 + gnu/usr.bin/binutils/bfd/coff-h8500.c | 355 + gnu/usr.bin/binutils/bfd/coff-i386.c | 491 + gnu/usr.bin/binutils/bfd/coff-i860.c | 423 + gnu/usr.bin/binutils/bfd/coff-i960.c | 661 + gnu/usr.bin/binutils/bfd/coff-m68k.c | 201 + gnu/usr.bin/binutils/bfd/coff-m88k.c | 158 + gnu/usr.bin/binutils/bfd/coff-mips.c | 2610 ++++ gnu/usr.bin/binutils/bfd/coff-pmac.c | 27 + gnu/usr.bin/binutils/bfd/coff-ppc.c | 2346 +++ gnu/usr.bin/binutils/bfd/coff-rs6000.c | 1413 ++ gnu/usr.bin/binutils/bfd/coff-sh.c | 1540 ++ gnu/usr.bin/binutils/bfd/coff-sparc.c | 278 + gnu/usr.bin/binutils/bfd/coff-u68k.c | 35 + gnu/usr.bin/binutils/bfd/coff-w65.c | 446 + gnu/usr.bin/binutils/bfd/coff-we32k.c | 110 + gnu/usr.bin/binutils/bfd/coff-z8k.c | 281 + gnu/usr.bin/binutils/bfd/coffcode.h | 3463 +++++ gnu/usr.bin/binutils/bfd/coffgen.c | 2167 +++ gnu/usr.bin/binutils/bfd/cofflink.c | 2489 ++++ gnu/usr.bin/binutils/bfd/coffswap.h | 807 + gnu/usr.bin/binutils/bfd/config.bfd | 464 + gnu/usr.bin/binutils/bfd/config.in | 58 + gnu/usr.bin/binutils/bfd/configure | 2005 +++ gnu/usr.bin/binutils/bfd/configure.bat | 18 + gnu/usr.bin/binutils/bfd/configure.host | 86 + gnu/usr.bin/binutils/bfd/configure.in | 544 + gnu/usr.bin/binutils/bfd/corefile.c | 106 + gnu/usr.bin/binutils/bfd/cpu-a29k.c | 39 + gnu/usr.bin/binutils/bfd/cpu-alpha.c | 38 + gnu/usr.bin/binutils/bfd/cpu-arm.c | 39 + gnu/usr.bin/binutils/bfd/cpu-h8300.c | 246 + gnu/usr.bin/binutils/bfd/cpu-h8500.c | 199 + gnu/usr.bin/binutils/bfd/cpu-hppa.c | 54 + gnu/usr.bin/binutils/bfd/cpu-i386.c | 38 + gnu/usr.bin/binutils/bfd/cpu-i860.c | 40 + gnu/usr.bin/binutils/bfd/cpu-i960.c | 156 + gnu/usr.bin/binutils/bfd/cpu-m68k.c | 42 + gnu/usr.bin/binutils/bfd/cpu-m88k.c | 42 + gnu/usr.bin/binutils/bfd/cpu-mips.c | 85 + gnu/usr.bin/binutils/bfd/cpu-ns32k.c | 868 ++ gnu/usr.bin/binutils/bfd/cpu-powerpc.c | 124 + gnu/usr.bin/binutils/bfd/cpu-rs6000.c | 70 + gnu/usr.bin/binutils/bfd/cpu-sh.c | 68 + gnu/usr.bin/binutils/bfd/cpu-sparc.c | 54 + gnu/usr.bin/binutils/bfd/cpu-vax.c | 39 + gnu/usr.bin/binutils/bfd/cpu-w65.c | 54 + gnu/usr.bin/binutils/bfd/cpu-we32k.c | 39 + gnu/usr.bin/binutils/bfd/cpu-z8k.c | 198 + gnu/usr.bin/binutils/bfd/demo64.c | 24 + gnu/usr.bin/binutils/bfd/dep-in.sed | 24 + gnu/usr.bin/binutils/bfd/doc/ChangeLog | 262 + gnu/usr.bin/binutils/bfd/doc/Makefile.in | 308 + gnu/usr.bin/binutils/bfd/doc/bfd.texinfo | 348 + gnu/usr.bin/binutils/bfd/doc/bfdsumm.texi | 148 + gnu/usr.bin/binutils/bfd/doc/chew.c | 1551 ++ gnu/usr.bin/binutils/bfd/doc/doc.str | 158 + gnu/usr.bin/binutils/bfd/doc/proto.str | 135 + gnu/usr.bin/binutils/bfd/ecoff.c | 4784 ++++++ gnu/usr.bin/binutils/bfd/ecofflink.c | 2490 ++++ gnu/usr.bin/binutils/bfd/ecoffswap.h | 830 ++ gnu/usr.bin/binutils/bfd/elf-bfd.h | 725 + gnu/usr.bin/binutils/bfd/elf.c | 2887 ++++ gnu/usr.bin/binutils/bfd/elf32-gen.c | 37 + gnu/usr.bin/binutils/bfd/elf32-hppa.c | 3028 ++++ gnu/usr.bin/binutils/bfd/elf32-hppa.h | 152 + gnu/usr.bin/binutils/bfd/elf32-i386.c | 1525 ++ gnu/usr.bin/binutils/bfd/elf32-i860.c | 33 + gnu/usr.bin/binutils/bfd/elf32-m68k.c | 1558 ++ gnu/usr.bin/binutils/bfd/elf32-m88k.c | 35 + gnu/usr.bin/binutils/bfd/elf32-mips.c | 3017 ++++ gnu/usr.bin/binutils/bfd/elf32-ppc.c | 1521 ++ gnu/usr.bin/binutils/bfd/elf32-sparc.c | 1513 ++ gnu/usr.bin/binutils/bfd/elf32.c | 23 + gnu/usr.bin/binutils/bfd/elf64-gen.c | 37 + gnu/usr.bin/binutils/bfd/elf64-sparc.c | 438 + gnu/usr.bin/binutils/bfd/elf64.c | 22 + gnu/usr.bin/binutils/bfd/elfcode.h | 1291 ++ gnu/usr.bin/binutils/bfd/elfcore.h | 484 + gnu/usr.bin/binutils/bfd/elflink.c | 204 + gnu/usr.bin/binutils/bfd/elflink.h | 3146 ++++ gnu/usr.bin/binutils/bfd/elfxx-target.h | 443 + gnu/usr.bin/binutils/bfd/filemode.c | 193 + gnu/usr.bin/binutils/bfd/format.c | 322 + gnu/usr.bin/binutils/bfd/gen-aout.c | 101 + gnu/usr.bin/binutils/bfd/genlink.h | 106 + gnu/usr.bin/binutils/bfd/hash.c | 739 + gnu/usr.bin/binutils/bfd/host-aout.c | 79 + gnu/usr.bin/binutils/bfd/hosts/alphalinux.h | 6 + gnu/usr.bin/binutils/bfd/hosts/decstation.h | 17 + gnu/usr.bin/binutils/bfd/hosts/delta68.h | 18 + gnu/usr.bin/binutils/bfd/hosts/dpx2.h | 8 + gnu/usr.bin/binutils/bfd/hosts/hp300bsd.h | 13 + gnu/usr.bin/binutils/bfd/hosts/i386bsd.h | 25 + gnu/usr.bin/binutils/bfd/hosts/i386linux.h | 8 + gnu/usr.bin/binutils/bfd/hosts/i386mach3.h | 25 + gnu/usr.bin/binutils/bfd/hosts/i386nbsd.h | 14 + gnu/usr.bin/binutils/bfd/hosts/i386sco.h | 19 + gnu/usr.bin/binutils/bfd/hosts/i860mach3.h | 27 + gnu/usr.bin/binutils/bfd/hosts/m68knbsd.h | 13 + gnu/usr.bin/binutils/bfd/hosts/m88kmach3.h | 11 + gnu/usr.bin/binutils/bfd/hosts/mipsbsd.h | 12 + gnu/usr.bin/binutils/bfd/hosts/mipsmach3.h | 10 + gnu/usr.bin/binutils/bfd/hosts/mipsnbsd.h | 13 + gnu/usr.bin/binutils/bfd/hosts/nbsd.h | 14 + gnu/usr.bin/binutils/bfd/hosts/news-mips.h | 12 + gnu/usr.bin/binutils/bfd/hosts/news.h | 9 + gnu/usr.bin/binutils/bfd/hosts/ns32knbsd.h | 13 + gnu/usr.bin/binutils/bfd/hosts/pc532mach.h | 24 + gnu/usr.bin/binutils/bfd/hosts/riscos.h | 10 + gnu/usr.bin/binutils/bfd/hosts/sparcnbsd.h | 18 + gnu/usr.bin/binutils/bfd/hosts/symmetry.h | 20 + gnu/usr.bin/binutils/bfd/hosts/tahoe.h | 12 + gnu/usr.bin/binutils/bfd/hosts/vaxbsd.h | 19 + gnu/usr.bin/binutils/bfd/hosts/vaxult.h | 8 + gnu/usr.bin/binutils/bfd/hosts/vaxult2.h | 8 + gnu/usr.bin/binutils/bfd/hp300bsd.c | 38 + gnu/usr.bin/binutils/bfd/hp300hpux.c | 874 ++ gnu/usr.bin/binutils/bfd/hppa_stubs.h | 23 + gnu/usr.bin/binutils/bfd/hppabsd-core.c | 308 + gnu/usr.bin/binutils/bfd/hpux-core.c | 270 + gnu/usr.bin/binutils/bfd/i386aout.c | 68 + gnu/usr.bin/binutils/bfd/i386bsd.c | 46 + gnu/usr.bin/binutils/bfd/i386dynix.c | 80 + gnu/usr.bin/binutils/bfd/i386linux.c | 768 + gnu/usr.bin/binutils/bfd/i386lynx.c | 570 + gnu/usr.bin/binutils/bfd/i386mach3.c | 65 + gnu/usr.bin/binutils/bfd/i386msdos.c | 260 + gnu/usr.bin/binutils/bfd/i386netbsd.c | 33 + gnu/usr.bin/binutils/bfd/i386os9k.c | 373 + gnu/usr.bin/binutils/bfd/ieee.c | 3437 +++++ gnu/usr.bin/binutils/bfd/init.c | 50 + gnu/usr.bin/binutils/bfd/irix-core.c | 263 + gnu/usr.bin/binutils/bfd/libaout.h | 613 + gnu/usr.bin/binutils/bfd/libbfd-in.h | 477 + gnu/usr.bin/binutils/bfd/libbfd.c | 1118 ++ gnu/usr.bin/binutils/bfd/libbfd.h | 687 + gnu/usr.bin/binutils/bfd/libcoff-in.h | 339 + gnu/usr.bin/binutils/bfd/libcoff.h | 666 + gnu/usr.bin/binutils/bfd/libecoff.h | 336 + gnu/usr.bin/binutils/bfd/libhppa.h | 537 + gnu/usr.bin/binutils/bfd/libieee.h | 135 + gnu/usr.bin/binutils/bfd/libnlm.h | 264 + gnu/usr.bin/binutils/bfd/liboasys.h | 83 + gnu/usr.bin/binutils/bfd/linker.c | 2725 ++++ gnu/usr.bin/binutils/bfd/lynx-core.c | 251 + gnu/usr.bin/binutils/bfd/m68k4knetbsd.c | 35 + gnu/usr.bin/binutils/bfd/m68klynx.c | 54 + gnu/usr.bin/binutils/bfd/m68knetbsd.c | 35 + gnu/usr.bin/binutils/bfd/m88kmach3.c | 38 + gnu/usr.bin/binutils/bfd/makefile.dos | 49 + gnu/usr.bin/binutils/bfd/mipsbsd.c | 467 + gnu/usr.bin/binutils/bfd/mpw-config.in | 69 + gnu/usr.bin/binutils/bfd/mpw-make.sed | 55 + gnu/usr.bin/binutils/bfd/netbsd.h | 108 + gnu/usr.bin/binutils/bfd/newsos3.c | 40 + gnu/usr.bin/binutils/bfd/nlm-target.h | 228 + gnu/usr.bin/binutils/bfd/nlm.c | 58 + gnu/usr.bin/binutils/bfd/nlm32-alpha.c | 898 ++ gnu/usr.bin/binutils/bfd/nlm32-i386.c | 457 + gnu/usr.bin/binutils/bfd/nlm32-ppc.c | 1051 ++ gnu/usr.bin/binutils/bfd/nlm32-sparc.c | 446 + gnu/usr.bin/binutils/bfd/nlm32.c | 21 + gnu/usr.bin/binutils/bfd/nlm64.c | 21 + gnu/usr.bin/binutils/bfd/nlmcode.h | 2087 +++ gnu/usr.bin/binutils/bfd/nlmswap.h | 157 + gnu/usr.bin/binutils/bfd/ns32knetbsd.c | 53 + gnu/usr.bin/binutils/bfd/oasys.c | 1565 ++ gnu/usr.bin/binutils/bfd/opncls.c | 608 + gnu/usr.bin/binutils/bfd/osf-core.c | 256 + gnu/usr.bin/binutils/bfd/pc532-mach.c | 121 + gnu/usr.bin/binutils/bfd/pe-arm.c | 32 + gnu/usr.bin/binutils/bfd/pe-i386.c | 30 + gnu/usr.bin/binutils/bfd/pe-ppc.c | 39 + gnu/usr.bin/binutils/bfd/pei-arm.c | 33 + gnu/usr.bin/binutils/bfd/pei-i386.c | 33 + gnu/usr.bin/binutils/bfd/pei-ppc.c | 44 + gnu/usr.bin/binutils/bfd/peicode.h | 1572 ++ gnu/usr.bin/binutils/bfd/ptrace-core.c | 244 + gnu/usr.bin/binutils/bfd/reloc.c | 2350 +++ gnu/usr.bin/binutils/bfd/reloc16.c | 294 + gnu/usr.bin/binutils/bfd/riscix.c | 647 + gnu/usr.bin/binutils/bfd/rs6000-core.c | 414 + gnu/usr.bin/binutils/bfd/section.c | 969 ++ gnu/usr.bin/binutils/bfd/som.c | 6047 ++++++++ gnu/usr.bin/binutils/bfd/som.h | 224 + gnu/usr.bin/binutils/bfd/sparclynx.c | 265 + gnu/usr.bin/binutils/bfd/sparcnetbsd.c | 33 + gnu/usr.bin/binutils/bfd/srec.c | 1347 ++ gnu/usr.bin/binutils/bfd/stab-syms.c | 75 + gnu/usr.bin/binutils/bfd/sunos.c | 2776 ++++ gnu/usr.bin/binutils/bfd/syms.c | 674 + gnu/usr.bin/binutils/bfd/sysdep.h | 107 + gnu/usr.bin/binutils/bfd/targets.c | 868 ++ gnu/usr.bin/binutils/bfd/tekhex.c | 1049 ++ gnu/usr.bin/binutils/bfd/trad-core.c | 327 + gnu/usr.bin/binutils/bfd/versados.c | 909 ++ gnu/usr.bin/binutils/bfd/xcofflink.c | 5814 ++++++++ gnu/usr.bin/binutils/binutils/ChangeLog | 3337 +++++ gnu/usr.bin/binutils/binutils/Makefile.in | 694 + gnu/usr.bin/binutils/binutils/NEWS | 91 + gnu/usr.bin/binutils/binutils/README | 95 + gnu/usr.bin/binutils/binutils/TODO | 20 + gnu/usr.bin/binutils/binutils/acconfig.h | 14 + gnu/usr.bin/binutils/binutils/aclocal.m4 | 1 + gnu/usr.bin/binutils/binutils/alloca.c | 191 + gnu/usr.bin/binutils/binutils/ar.1 | 487 + gnu/usr.bin/binutils/binutils/ar.c | 1229 ++ gnu/usr.bin/binutils/binutils/arlex.c | 1802 +++ gnu/usr.bin/binutils/binutils/arlex.l | 82 + gnu/usr.bin/binutils/binutils/arparse.c | 1026 ++ gnu/usr.bin/binutils/binutils/arparse.h | 26 + gnu/usr.bin/binutils/binutils/arparse.y | 200 + gnu/usr.bin/binutils/binutils/arsup.c | 452 + gnu/usr.bin/binutils/binutils/arsup.h | 75 + gnu/usr.bin/binutils/binutils/binutils.info | 1668 +++ gnu/usr.bin/binutils/binutils/binutils.texi | 1863 +++ gnu/usr.bin/binutils/binutils/bucomm.c | 215 + gnu/usr.bin/binutils/binutils/bucomm.h | 103 + gnu/usr.bin/binutils/binutils/coffdump.c | 544 + gnu/usr.bin/binutils/binutils/coffgrok.c | 733 + gnu/usr.bin/binutils/binutils/coffgrok.h | 206 + gnu/usr.bin/binutils/binutils/config.in | 43 + gnu/usr.bin/binutils/binutils/config.texi | 1 + gnu/usr.bin/binutils/binutils/configure | 1404 ++ gnu/usr.bin/binutils/binutils/configure.bat | 63 + gnu/usr.bin/binutils/binutils/configure.in | 184 + gnu/usr.bin/binutils/binutils/cxxfilt.man | 114 + gnu/usr.bin/binutils/binutils/deflex.l | 85 + gnu/usr.bin/binutils/binutils/defparse.y | 132 + gnu/usr.bin/binutils/binutils/dlltool.c | 2030 +++ gnu/usr.bin/binutils/binutils/filemode.c | 264 + gnu/usr.bin/binutils/binutils/gmalloc.c | 1116 ++ gnu/usr.bin/binutils/binutils/is-ranlib.c | 3 + gnu/usr.bin/binutils/binutils/is-strip.c | 4 + gnu/usr.bin/binutils/binutils/mac-binutils.r | 42 + gnu/usr.bin/binutils/binutils/maybe-ranlib.c | 4 + gnu/usr.bin/binutils/binutils/maybe-strip.c | 4 + gnu/usr.bin/binutils/binutils/mpw-config.in | 23 + gnu/usr.bin/binutils/binutils/mpw-make.sed | 78 + gnu/usr.bin/binutils/binutils/nlmconv.1 | 110 + gnu/usr.bin/binutils/binutils/nlmconv.c | 2346 +++ gnu/usr.bin/binutils/binutils/nlmconv.h | 84 + gnu/usr.bin/binutils/binutils/nlmheader.c | 1931 +++ gnu/usr.bin/binutils/binutils/nlmheader.y | 979 ++ gnu/usr.bin/binutils/binutils/nm.1 | 219 + gnu/usr.bin/binutils/binutils/nm.c | 1340 ++ gnu/usr.bin/binutils/binutils/not-ranlib.c | 3 + gnu/usr.bin/binutils/binutils/not-strip.c | 4 + gnu/usr.bin/binutils/binutils/objcopy.1 | 254 + gnu/usr.bin/binutils/binutils/objcopy.c | 1844 +++ gnu/usr.bin/binutils/binutils/objdump.1 | 338 + gnu/usr.bin/binutils/binutils/objdump.c | 1960 +++ gnu/usr.bin/binutils/binutils/ranlib.1 | 83 + gnu/usr.bin/binutils/binutils/ranlib.sh | 3 + gnu/usr.bin/binutils/binutils/sanity.sh | 50 + gnu/usr.bin/binutils/binutils/size.1 | 161 + gnu/usr.bin/binutils/binutils/size.c | 428 + gnu/usr.bin/binutils/binutils/srconv.c | 2023 +++ gnu/usr.bin/binutils/binutils/strings.1 | 151 + gnu/usr.bin/binutils/binutils/strings.c | 502 + gnu/usr.bin/binutils/binutils/strip.1 | 171 + gnu/usr.bin/binutils/binutils/sysdump.c | 765 + gnu/usr.bin/binutils/binutils/sysinfo.c | 1249 ++ gnu/usr.bin/binutils/binutils/sysinfo.h | 13 + gnu/usr.bin/binutils/binutils/sysinfo.y | 413 + gnu/usr.bin/binutils/binutils/syslex.c | 1651 ++ gnu/usr.bin/binutils/binutils/syslex.l | 51 + gnu/usr.bin/binutils/binutils/sysroff.info | 504 + .../binutils/binutils/testsuite/ChangeLog | 347 + .../binutils/testsuite/binutils-all/ar.exp | 158 + .../binutils/testsuite/binutils-all/bintest.s | 12 + .../testsuite/binutils-all/hppa/addendbug.s | 23 + .../testsuite/binutils-all/hppa/objdump.exp | 53 + .../binutils/testsuite/binutils-all/nm.exp | 115 + .../testsuite/binutils-all/objcopy.exp | 401 + .../testsuite/binutils-all/objdump.exp | 128 + .../binutils/testsuite/binutils-all/size.exp | 70 + .../testsuite/binutils-all/testprog.c | 28 + .../binutils/testsuite/config/default.exp | 113 + .../binutils/testsuite/config/hppa.sed | 4 + .../binutils/testsuite/lib/utils-lib.exp | 187 + gnu/usr.bin/binutils/binutils/version.c | 5 + gnu/usr.bin/binutils/config-ml.in | 664 + gnu/usr.bin/binutils/config.guess | 565 + gnu/usr.bin/binutils/config.sub | 1091 ++ gnu/usr.bin/binutils/config/ChangeLog | 198 + gnu/usr.bin/binutils/config/mh-a68bsd | 12 + gnu/usr.bin/binutils/config/mh-aix386 | 1 + gnu/usr.bin/binutils/config/mh-apollo68 | 3 + gnu/usr.bin/binutils/config/mh-cxux | 15 + gnu/usr.bin/binutils/config/mh-decstation | 5 + gnu/usr.bin/binutils/config/mh-delta88 | 4 + gnu/usr.bin/binutils/config/mh-dgux | 4 + gnu/usr.bin/binutils/config/mh-go32 | 27 + gnu/usr.bin/binutils/config/mh-hp300 | 13 + gnu/usr.bin/binutils/config/mh-hpux | 4 + gnu/usr.bin/binutils/config/mh-hpux8 | 4 + gnu/usr.bin/binutils/config/mh-i386win32 | 26 + gnu/usr.bin/binutils/config/mh-irix4 | 8 + gnu/usr.bin/binutils/config/mh-irix5 | 3 + gnu/usr.bin/binutils/config/mh-linux | 2 + gnu/usr.bin/binutils/config/mh-lynxos | 2 + gnu/usr.bin/binutils/config/mh-lynxrs6k | 8 + gnu/usr.bin/binutils/config/mh-ncr3000 | 17 + gnu/usr.bin/binutils/config/mh-ncrsvr43 | 9 + gnu/usr.bin/binutils/config/mh-papic | 1 + gnu/usr.bin/binutils/config/mh-riscos | 15 + gnu/usr.bin/binutils/config/mh-sco | 10 + gnu/usr.bin/binutils/config/mh-solaris | 7 + gnu/usr.bin/binutils/config/mh-sparcpic | 1 + gnu/usr.bin/binutils/config/mh-sun3 | 3 + gnu/usr.bin/binutils/config/mh-sysv | 3 + gnu/usr.bin/binutils/config/mh-sysv4 | 11 + gnu/usr.bin/binutils/config/mh-vaxult2 | 2 + gnu/usr.bin/binutils/config/mh-x86pic | 1 + gnu/usr.bin/binutils/config/mpw-mh-mpw | 138 + gnu/usr.bin/binutils/config/mt-netware | 1 + gnu/usr.bin/binutils/config/mt-papic | 1 + gnu/usr.bin/binutils/config/mt-sparcpic | 1 + gnu/usr.bin/binutils/config/mt-v810 | 9 + gnu/usr.bin/binutils/config/mt-x86pic | 1 + gnu/usr.bin/binutils/configure | 1231 ++ gnu/usr.bin/binutils/configure.bat | 17 + gnu/usr.bin/binutils/configure.in | 658 + gnu/usr.bin/binutils/etc/Makefile.in | 100 + gnu/usr.bin/binutils/etc/cfg-paper.info | 659 + gnu/usr.bin/binutils/etc/cfg-paper.texi | 717 + gnu/usr.bin/binutils/etc/configure.in | 17 + gnu/usr.bin/binutils/etc/configure.info | 64 + gnu/usr.bin/binutils/etc/configure.info-1 | 1174 ++ gnu/usr.bin/binutils/etc/configure.info-2 | 572 + gnu/usr.bin/binutils/etc/configure.man | 166 + gnu/usr.bin/binutils/etc/configure.texi | 1830 +++ gnu/usr.bin/binutils/etc/make-stds.texi | 528 + gnu/usr.bin/binutils/etc/standards.info | 59 + gnu/usr.bin/binutils/etc/standards.info-1 | 1225 ++ gnu/usr.bin/binutils/etc/standards.info-2 | 1462 ++ gnu/usr.bin/binutils/etc/standards.texi | 2295 +++ gnu/usr.bin/binutils/gas/CONTRIBUTORS | 99 + gnu/usr.bin/binutils/gas/COPYING | 339 + gnu/usr.bin/binutils/gas/ChangeLog | 480 + gnu/usr.bin/binutils/gas/ChangeLog.1 | 12409 ++++++++++++++++ gnu/usr.bin/binutils/gas/Makefile.in | 545 + gnu/usr.bin/binutils/gas/NEWS | 201 + gnu/usr.bin/binutils/gas/NOTES | 142 + gnu/usr.bin/binutils/gas/NOTES.config | 52 + gnu/usr.bin/binutils/gas/README | 295 + gnu/usr.bin/binutils/gas/README-quirks | 7 + gnu/usr.bin/binutils/gas/README-vms | 248 + gnu/usr.bin/binutils/gas/README.coff | 79 + gnu/usr.bin/binutils/gas/README.rich | 143 + gnu/usr.bin/binutils/gas/acconfig.h | 54 + gnu/usr.bin/binutils/gas/aclocal.m4 | 95 + gnu/usr.bin/binutils/gas/app.c | 1012 ++ gnu/usr.bin/binutils/gas/as.c | 772 + gnu/usr.bin/binutils/gas/as.h | 659 + gnu/usr.bin/binutils/gas/atof-generic.c | 635 + gnu/usr.bin/binutils/gas/bignum-copy.c | 80 + gnu/usr.bin/binutils/gas/bignum.h | 52 + gnu/usr.bin/binutils/gas/bit_fix.h | 51 + gnu/usr.bin/binutils/gas/cond.c | 368 + gnu/usr.bin/binutils/gas/conf.in | 117 + gnu/usr.bin/binutils/gas/config-gas.com | 169 + .../binutils/gas/config/alpha-opcode.h | 835 ++ gnu/usr.bin/binutils/gas/config/aout_gnu.h | 455 + gnu/usr.bin/binutils/gas/config/arm-big.mt | 1 + gnu/usr.bin/binutils/gas/config/arm-lit.mt | 1 + gnu/usr.bin/binutils/gas/config/atof-ieee.c | 584 + gnu/usr.bin/binutils/gas/config/atof-tahoe.c | 431 + gnu/usr.bin/binutils/gas/config/atof-vax.c | 510 + gnu/usr.bin/binutils/gas/config/e-mipsecoff.c | 34 + gnu/usr.bin/binutils/gas/config/e-mipself.c | 34 + gnu/usr.bin/binutils/gas/config/go32.cfg | 93 + gnu/usr.bin/binutils/gas/config/i386coff.mt | 1 + gnu/usr.bin/binutils/gas/config/m68k-parse.h | 261 + gnu/usr.bin/binutils/gas/config/m68k-parse.y | 982 ++ gnu/usr.bin/binutils/gas/config/m68kcoff.mt | 1 + gnu/usr.bin/binutils/gas/config/m88k-opcode.h | 559 + gnu/usr.bin/binutils/gas/config/m88kcoff.mt | 1 + gnu/usr.bin/binutils/gas/config/mips-big.mt | 1 + gnu/usr.bin/binutils/gas/config/mips-lit.mt | 1 + gnu/usr.bin/binutils/gas/config/obj-aout.c | 558 + gnu/usr.bin/binutils/gas/config/obj-aout.h | 230 + gnu/usr.bin/binutils/gas/config/obj-bout.c | 330 + gnu/usr.bin/binutils/gas/config/obj-bout.h | 308 + gnu/usr.bin/binutils/gas/config/obj-coff.c | 4070 +++++ gnu/usr.bin/binutils/gas/config/obj-coff.h | 782 + gnu/usr.bin/binutils/gas/config/obj-ecoff.c | 299 + gnu/usr.bin/binutils/gas/config/obj-ecoff.h | 65 + gnu/usr.bin/binutils/gas/config/obj-elf.c | 1232 ++ gnu/usr.bin/binutils/gas/config/obj-elf.h | 132 + gnu/usr.bin/binutils/gas/config/obj-generic.c | 41 + gnu/usr.bin/binutils/gas/config/obj-generic.h | 80 + gnu/usr.bin/binutils/gas/config/obj-hp300.c | 52 + gnu/usr.bin/binutils/gas/config/obj-hp300.h | 71 + gnu/usr.bin/binutils/gas/config/obj-ieee.c | 616 + gnu/usr.bin/binutils/gas/config/obj-ieee.h | 50 + gnu/usr.bin/binutils/gas/config/obj-multi.c | 4 + gnu/usr.bin/binutils/gas/config/obj-multi.h | 41 + gnu/usr.bin/binutils/gas/config/obj-som.c | 227 + gnu/usr.bin/binutils/gas/config/obj-som.h | 70 + gnu/usr.bin/binutils/gas/config/obj-vms.c | 5421 +++++++ gnu/usr.bin/binutils/gas/config/obj-vms.h | 544 + gnu/usr.bin/binutils/gas/config/ppc-big.mt | 1 + gnu/usr.bin/binutils/gas/config/ppc-lit.mt | 1 + gnu/usr.bin/binutils/gas/config/tc-a29k.c | 1253 ++ gnu/usr.bin/binutils/gas/config/tc-a29k.h | 48 + gnu/usr.bin/binutils/gas/config/tc-alpha.c | 2741 ++++ gnu/usr.bin/binutils/gas/config/tc-alpha.h | 65 + gnu/usr.bin/binutils/gas/config/tc-arm.c | 4212 ++++++ gnu/usr.bin/binutils/gas/config/tc-arm.h | 108 + gnu/usr.bin/binutils/gas/config/tc-generic.c | 0 gnu/usr.bin/binutils/gas/config/tc-generic.h | 38 + gnu/usr.bin/binutils/gas/config/tc-h8300.c | 1458 ++ gnu/usr.bin/binutils/gas/config/tc-h8300.h | 50 + gnu/usr.bin/binutils/gas/config/tc-h8500.c | 1652 ++ gnu/usr.bin/binutils/gas/config/tc-h8500.h | 50 + gnu/usr.bin/binutils/gas/config/tc-hppa.c | 6438 ++++++++ gnu/usr.bin/binutils/gas/config/tc-hppa.h | 168 + gnu/usr.bin/binutils/gas/config/tc-i386.c | 3037 ++++ gnu/usr.bin/binutils/gas/config/tc-i386.h | 392 + gnu/usr.bin/binutils/gas/config/tc-i860.c | 1290 ++ gnu/usr.bin/binutils/gas/config/tc-i860.h | 22 + gnu/usr.bin/binutils/gas/config/tc-i960.c | 3231 ++++ gnu/usr.bin/binutils/gas/config/tc-i960.h | 162 + gnu/usr.bin/binutils/gas/config/tc-m68851.h | 304 + gnu/usr.bin/binutils/gas/config/tc-m68k.c | 6162 ++++++++ gnu/usr.bin/binutils/gas/config/tc-m68k.h | 136 + gnu/usr.bin/binutils/gas/config/tc-m88k.c | 1449 ++ gnu/usr.bin/binutils/gas/config/tc-m88k.h | 104 + gnu/usr.bin/binutils/gas/config/tc-mips.c | 7261 +++++++++ gnu/usr.bin/binutils/gas/config/tc-mips.h | 132 + gnu/usr.bin/binutils/gas/config/tc-ns32k.c | 2384 +++ gnu/usr.bin/binutils/gas/config/tc-ns32k.h | 103 + gnu/usr.bin/binutils/gas/config/tc-ppc.c | 4304 ++++++ gnu/usr.bin/binutils/gas/config/tc-ppc.h | 222 + gnu/usr.bin/binutils/gas/config/tc-sh.c | 1692 +++ gnu/usr.bin/binutils/gas/config/tc-sh.h | 75 + gnu/usr.bin/binutils/gas/config/tc-sparc.c | 2478 +++ gnu/usr.bin/binutils/gas/config/tc-sparc.h | 109 + gnu/usr.bin/binutils/gas/config/tc-tahoe.c | 2027 +++ gnu/usr.bin/binutils/gas/config/tc-tahoe.h | 43 + gnu/usr.bin/binutils/gas/config/tc-vax.c | 3238 ++++ gnu/usr.bin/binutils/gas/config/tc-vax.h | 26 + gnu/usr.bin/binutils/gas/config/tc-w65.c | 1245 ++ gnu/usr.bin/binutils/gas/config/tc-w65.h | 52 + gnu/usr.bin/binutils/gas/config/tc-z8k.c | 1608 ++ gnu/usr.bin/binutils/gas/config/tc-z8k.h | 43 + gnu/usr.bin/binutils/gas/config/te-386bsd.h | 31 + gnu/usr.bin/binutils/gas/config/te-delta.h | 13 + gnu/usr.bin/binutils/gas/config/te-delta88.h | 13 + gnu/usr.bin/binutils/gas/config/te-dpx2.h | 12 + gnu/usr.bin/binutils/gas/config/te-generic.h | 22 + gnu/usr.bin/binutils/gas/config/te-go32.h | 11 + gnu/usr.bin/binutils/gas/config/te-hp300.h | 25 + gnu/usr.bin/binutils/gas/config/te-hppa.h | 26 + gnu/usr.bin/binutils/gas/config/te-i386aix.h | 29 + gnu/usr.bin/binutils/gas/config/te-ic960.h | 34 + gnu/usr.bin/binutils/gas/config/te-linux.h | 2 + gnu/usr.bin/binutils/gas/config/te-lynx.h | 7 + gnu/usr.bin/binutils/gas/config/te-mach.h | 2 + gnu/usr.bin/binutils/gas/config/te-macos.h | 11 + gnu/usr.bin/binutils/gas/config/te-multi.h | 22 + gnu/usr.bin/binutils/gas/config/te-nbsd.h | 21 + gnu/usr.bin/binutils/gas/config/te-nbsd532.h | 19 + .../binutils/gas/config/te-pc532mach.h | 19 + gnu/usr.bin/binutils/gas/config/te-pe.h | 3 + gnu/usr.bin/binutils/gas/config/te-ppcnw.h | 31 + gnu/usr.bin/binutils/gas/config/te-sco386.h | 10 + gnu/usr.bin/binutils/gas/config/te-sun3.h | 48 + gnu/usr.bin/binutils/gas/config/te-sysv32.h | 6 + gnu/usr.bin/binutils/gas/config/vax-inst.h | 77 + gnu/usr.bin/binutils/gas/config/vms-conf.h | 121 + gnu/usr.bin/binutils/gas/configure | 2234 +++ gnu/usr.bin/binutils/gas/configure.bat | 57 + gnu/usr.bin/binutils/gas/configure.in | 589 + gnu/usr.bin/binutils/gas/debug.c | 104 + gnu/usr.bin/binutils/gas/doc/Makefile.in | 174 + gnu/usr.bin/binutils/gas/doc/all.texi | 65 + gnu/usr.bin/binutils/gas/doc/as.1 | 293 + gnu/usr.bin/binutils/gas/doc/as.info | 262 + gnu/usr.bin/binutils/gas/doc/as.info-1 | 1338 ++ gnu/usr.bin/binutils/gas/doc/as.info-2 | 1464 ++ gnu/usr.bin/binutils/gas/doc/as.info-3 | 1393 ++ gnu/usr.bin/binutils/gas/doc/as.info-4 | 1388 ++ gnu/usr.bin/binutils/gas/doc/as.info-5 | 741 + gnu/usr.bin/binutils/gas/doc/as.info-6 | 776 + gnu/usr.bin/binutils/gas/doc/as.texinfo | 4459 ++++++ gnu/usr.bin/binutils/gas/doc/c-a29k.texi | 182 + gnu/usr.bin/binutils/gas/doc/c-h8300.texi | 342 + gnu/usr.bin/binutils/gas/doc/c-h8500.texi | 272 + gnu/usr.bin/binutils/gas/doc/c-hppa.texi | 263 + gnu/usr.bin/binutils/gas/doc/c-i386.texi | 467 + gnu/usr.bin/binutils/gas/doc/c-i960.texi | 298 + gnu/usr.bin/binutils/gas/doc/c-m68k.texi | 452 + gnu/usr.bin/binutils/gas/doc/c-mips.texi | 173 + gnu/usr.bin/binutils/gas/doc/c-ns32k.texi | 30 + gnu/usr.bin/binutils/gas/doc/c-sh.texi | 265 + gnu/usr.bin/binutils/gas/doc/c-sparc.texi | 122 + gnu/usr.bin/binutils/gas/doc/c-vax.texi | 323 + gnu/usr.bin/binutils/gas/doc/c-z8k.texi | 380 + gnu/usr.bin/binutils/gas/doc/gasp.info | 1087 ++ gnu/usr.bin/binutils/gas/doc/gasp.texi | 1086 ++ gnu/usr.bin/binutils/gas/doc/h8.texi | 26 + gnu/usr.bin/binutils/gas/doc/internals.texi | 788 + gnu/usr.bin/binutils/gas/ecoff.c | 5346 +++++++ gnu/usr.bin/binutils/gas/ecoff.h | 102 + gnu/usr.bin/binutils/gas/emul-target.h | 43 + gnu/usr.bin/binutils/gas/emul.h | 23 + gnu/usr.bin/binutils/gas/expr.c | 1560 ++ gnu/usr.bin/binutils/gas/expr.h | 145 + gnu/usr.bin/binutils/gas/flonum-copy.c | 73 + gnu/usr.bin/binutils/gas/flonum-konst.c | 181 + gnu/usr.bin/binutils/gas/flonum-mult.c | 200 + gnu/usr.bin/binutils/gas/flonum.h | 115 + gnu/usr.bin/binutils/gas/frags.c | 336 + gnu/usr.bin/binutils/gas/frags.h | 67 + gnu/usr.bin/binutils/gas/gasp.c | 3662 +++++ gnu/usr.bin/binutils/gas/gdbinit.in | 38 + gnu/usr.bin/binutils/gas/hash.c | 967 ++ gnu/usr.bin/binutils/gas/hash.h | 68 + gnu/usr.bin/binutils/gas/input-file.c | 248 + gnu/usr.bin/binutils/gas/input-file.h | 68 + gnu/usr.bin/binutils/gas/input-scrub.c | 479 + gnu/usr.bin/binutils/gas/link.cmd | 10 + gnu/usr.bin/binutils/gas/listing.c | 1172 ++ gnu/usr.bin/binutils/gas/listing.h | 56 + gnu/usr.bin/binutils/gas/literal.c | 95 + gnu/usr.bin/binutils/gas/m68k-parse.c | 1916 +++ gnu/usr.bin/binutils/gas/mac-as.r | 42 + gnu/usr.bin/binutils/gas/macro.c | 1219 ++ gnu/usr.bin/binutils/gas/macro.h | 47 + gnu/usr.bin/binutils/gas/make-gas.com | 126 + gnu/usr.bin/binutils/gas/messages.c | 537 + gnu/usr.bin/binutils/gas/mpw-config.in | 96 + gnu/usr.bin/binutils/gas/mpw-make.sed | 81 + gnu/usr.bin/binutils/gas/obj.h | 77 + gnu/usr.bin/binutils/gas/output-file.c | 154 + gnu/usr.bin/binutils/gas/output-file.h | 25 + gnu/usr.bin/binutils/gas/read.c | 3929 +++++ gnu/usr.bin/binutils/gas/read.h | 133 + gnu/usr.bin/binutils/gas/sb.c | 289 + gnu/usr.bin/binutils/gas/sb.h | 99 + gnu/usr.bin/binutils/gas/stabs.c | 435 + gnu/usr.bin/binutils/gas/struc-symbol.h | 162 + gnu/usr.bin/binutils/gas/subsegs.c | 544 + gnu/usr.bin/binutils/gas/subsegs.h | 150 + gnu/usr.bin/binutils/gas/symbols.c | 1594 ++ gnu/usr.bin/binutils/gas/symbols.h | 83 + gnu/usr.bin/binutils/gas/tc.h | 112 + gnu/usr.bin/binutils/gas/testsuite/ChangeLog | 949 ++ .../binutils/gas/testsuite/config/default.exp | 46 + .../binutils/gas/testsuite/gas/all/comment.s | 3 + .../binutils/gas/testsuite/gas/all/diff1.s | 5 + .../binutils/gas/testsuite/gas/all/float.s | 4 + .../binutils/gas/testsuite/gas/all/gas.exp | 94 + .../binutils/gas/testsuite/gas/all/p1480.s | 3 + .../binutils/gas/testsuite/gas/all/p2425.s | 6 + .../binutils/gas/testsuite/gas/all/struct.d | 8 + .../binutils/gas/testsuite/gas/all/struct.s | 10 + .../binutils/gas/testsuite/gas/all/x930509.s | 3 + .../binutils/gas/testsuite/gas/alpha/fp.d | 7 + .../binutils/gas/testsuite/gas/alpha/fp.exp | 15 + .../binutils/gas/testsuite/gas/alpha/fp.s | 14 + .../binutils/gas/testsuite/gas/arm/arm.exp | 26 + .../binutils/gas/testsuite/gas/arm/arm3.s | 6 + .../binutils/gas/testsuite/gas/arm/arm6.s | 12 + .../binutils/gas/testsuite/gas/arm/arm7dm.s | 12 + .../binutils/gas/testsuite/gas/arm/copro.s | 24 + .../binutils/gas/testsuite/gas/arm/float.s | 162 + .../binutils/gas/testsuite/gas/arm/inst.s | 189 + .../gas/testsuite/gas/arm/le-fpconst.d | 8 + .../gas/testsuite/gas/arm/le-fpconst.s | 8 + .../binutils/gas/testsuite/gas/h8300/cmpsi2.s | 28 + .../binutils/gas/testsuite/gas/h8300/ffxx1.d | 23 + .../binutils/gas/testsuite/gas/h8300/ffxx1.s | 20 + .../gas/testsuite/gas/h8300/h8300.exp | 11 + .../binutils/gas/testsuite/gas/hppa/README | 34 + .../gas/testsuite/gas/hppa/basic/add.s | 100 + .../gas/testsuite/gas/hppa/basic/addi.s | 83 + .../gas/testsuite/gas/hppa/basic/basic.exp | 2259 +++ .../gas/testsuite/gas/hppa/basic/branch.s | 227 + .../gas/testsuite/gas/hppa/basic/comclr.s | 50 + .../gas/testsuite/gas/hppa/basic/copr.s | 19 + .../gas/testsuite/gas/hppa/basic/coprmem.s | 55 + .../gas/testsuite/gas/hppa/basic/dcor.s | 41 + .../gas/testsuite/gas/hppa/basic/deposit.s | 88 + .../gas/testsuite/gas/hppa/basic/ds.s | 32 + .../gas/testsuite/gas/hppa/basic/extract.s | 51 + .../gas/testsuite/gas/hppa/basic/fmem.s | 52 + .../gas/testsuite/gas/hppa/basic/fmemLRbug.s | 76 + .../gas/testsuite/gas/hppa/basic/fp_comp.s | 81 + .../gas/testsuite/gas/hppa/basic/fp_conv.s | 92 + .../gas/testsuite/gas/hppa/basic/fp_fcmp.s | 114 + .../gas/testsuite/gas/hppa/basic/fp_misc.s | 18 + .../gas/testsuite/gas/hppa/basic/imem.s | 93 + .../gas/testsuite/gas/hppa/basic/immed.s | 21 + .../gas/testsuite/gas/hppa/basic/logical.s | 60 + .../gas/testsuite/gas/hppa/basic/purge.s | 35 + .../gas/testsuite/gas/hppa/basic/sh1add.s | 67 + .../gas/testsuite/gas/hppa/basic/sh2add.s | 67 + .../gas/testsuite/gas/hppa/basic/sh3add.s | 67 + .../gas/testsuite/gas/hppa/basic/shift.s | 34 + .../gas/testsuite/gas/hppa/basic/special.s | 15 + .../gas/testsuite/gas/hppa/basic/spop.s | 34 + .../gas/testsuite/gas/hppa/basic/sub.s | 117 + .../gas/testsuite/gas/hppa/basic/subi.s | 49 + .../gas/testsuite/gas/hppa/basic/system.s | 46 + .../gas/testsuite/gas/hppa/basic/unit.s | 55 + .../gas/testsuite/gas/hppa/basic/weird.s | 870 ++ .../gas/testsuite/gas/hppa/parse/align1.s | 41 + .../gas/testsuite/gas/hppa/parse/align2.s | 15 + .../gas/testsuite/gas/hppa/parse/appbug.s | 1 + .../gas/testsuite/gas/hppa/parse/badfmpyadd.s | 33 + .../gas/testsuite/gas/hppa/parse/block1.s | 18 + .../gas/testsuite/gas/hppa/parse/block2.s | 15 + .../testsuite/gas/hppa/parse/calldatabug.s | 189 + .../testsuite/gas/hppa/parse/callinfobug.s | 8 + .../gas/testsuite/gas/hppa/parse/defbug.s | 18 + .../gas/testsuite/gas/hppa/parse/entrybug.s | 24 + .../gas/testsuite/gas/hppa/parse/exportbug.s | 14 + .../gas/testsuite/gas/hppa/parse/exprbug.s | 39 + .../gas/testsuite/gas/hppa/parse/fixup7bug.s | 6192 ++++++++ .../gas/testsuite/gas/hppa/parse/global.s | 15 + .../gas/testsuite/gas/hppa/parse/labelbug.s | 35 + .../gas/testsuite/gas/hppa/parse/linesepbug.s | 20 + .../gas/testsuite/gas/hppa/parse/lselbug.s | 18 + .../gas/testsuite/gas/hppa/parse/nosubspace.s | 21 + .../gas/testsuite/gas/hppa/parse/parse.exp | 222 + .../gas/testsuite/gas/hppa/parse/procbug.s | 16 + .../gas/testsuite/gas/hppa/parse/regpopbug.s | 17 + .../gas/testsuite/gas/hppa/parse/spacebug.s | 3 + .../gas/testsuite/gas/hppa/parse/ssbug.s | 10 + .../gas/testsuite/gas/hppa/parse/stdreg.s | 27 + .../gas/testsuite/gas/hppa/parse/stringer.s | 19 + .../gas/testsuite/gas/hppa/parse/undefbug.s | 14 + .../gas/testsuite/gas/hppa/parse/versionbug.s | 9 + .../gas/testsuite/gas/hppa/parse/xmpyubug.s | 17 + .../gas/testsuite/gas/hppa/reloc/applybug.s | 130 + .../gas/testsuite/gas/hppa/reloc/blebug.s | 16 + .../gas/testsuite/gas/hppa/reloc/blebug2.s | 14 + .../gas/testsuite/gas/hppa/reloc/blebug3.s | 14 + .../gas/testsuite/gas/hppa/reloc/exitbug.s | 19 + .../gas/testsuite/gas/hppa/reloc/fixupbug.s | 19 + .../testsuite/gas/hppa/reloc/funcrelocbug.s | 186 + .../gas/testsuite/gas/hppa/reloc/labelopbug.s | 37 + .../gas/testsuite/gas/hppa/reloc/longcall.s | 40 + .../gas/testsuite/gas/hppa/reloc/picreloc.s | 13 + .../gas/testsuite/gas/hppa/reloc/plabelbug.s | 47 + .../gas/testsuite/gas/hppa/reloc/r_no_reloc.s | 45 + .../gas/testsuite/gas/hppa/reloc/reduce.s | 48 + .../gas/testsuite/gas/hppa/reloc/reduce2.s | 80 + .../gas/testsuite/gas/hppa/reloc/reduce3.s | 51 + .../gas/testsuite/gas/hppa/reloc/reloc.exp | 679 + .../gas/testsuite/gas/hppa/reloc/roundmode.s | 23 + .../testsuite/gas/hppa/reloc/selectorbug.s | 28 + .../gas/testsuite/gas/hppa/unsorted/align3.s | 20 + .../gas/testsuite/gas/hppa/unsorted/align4.s | 4 + .../testsuite/gas/hppa/unsorted/brlenbug.s | 3502 +++++ .../gas/testsuite/gas/hppa/unsorted/common.s | 8 + .../gas/testsuite/gas/hppa/unsorted/fragbug.s | 3 + .../testsuite/gas/hppa/unsorted/globalbug.s | 16 + .../testsuite/gas/hppa/unsorted/importbug.s | 42 + .../testsuite/gas/hppa/unsorted/labeldiffs.s | 40 + .../testsuite/gas/hppa/unsorted/locallabel.s | 15 + .../testsuite/gas/hppa/unsorted/ss_align.s | 12 + .../testsuite/gas/hppa/unsorted/unsorted.exp | 258 + .../binutils/gas/testsuite/gas/i386/all.exp | 12 + .../binutils/gas/testsuite/gas/i386/inout.s | 11 + .../binutils/gas/testsuite/gas/i386/pushw.l | 5 + .../binutils/gas/testsuite/gas/i386/pushw.s | 2 + .../gas/testsuite/gas/ieee-fp/x930509a.exp | 22 + .../gas/testsuite/gas/ieee-fp/x930509a.s | 5 + .../gas/testsuite/gas/m68k-coff/gas.exp | 15 + .../gas/testsuite/gas/m68k-coff/p2389.s | 19 + .../gas/testsuite/gas/m68k-coff/p2389a.s | 3 + .../gas/testsuite/gas/m68k-coff/p2430.s | 6 + .../gas/testsuite/gas/m68k-coff/p2430a.s | 4 + .../binutils/gas/testsuite/gas/m68k-coff/t1.s | 36 + .../binutils/gas/testsuite/gas/m68k/all.exp | 43 + .../gas/testsuite/gas/m68k/bitfield.d | 28 + .../gas/testsuite/gas/m68k/bitfield.s | 24 + .../binutils/gas/testsuite/gas/m68k/cas.d | 20 + .../binutils/gas/testsuite/gas/m68k/cas.s | 16 + .../binutils/gas/testsuite/gas/m68k/disperr.s | 16 + .../binutils/gas/testsuite/gas/m68k/fmoveml.d | 37 + .../binutils/gas/testsuite/gas/m68k/fmoveml.s | 33 + .../binutils/gas/testsuite/gas/m68k/link.d | 16 + .../binutils/gas/testsuite/gas/m68k/link.s | 12 + .../binutils/gas/testsuite/gas/m68k/op68000.d | 188 + .../gas/testsuite/gas/m68k/operands.d | 242 + .../gas/testsuite/gas/m68k/operands.s | 273 + .../binutils/gas/testsuite/gas/m68k/p2410.s | 15 + .../binutils/gas/testsuite/gas/m68k/p2663.s | 16 + .../binutils/gas/testsuite/gas/m68k/pic1.s | 5 + .../binutils/gas/testsuite/gas/m68k/schwab.d | 88 + .../binutils/gas/testsuite/gas/m68k/schwab.s | 59 + .../binutils/gas/testsuite/gas/m68k/t2.s | 6 + .../binutils/gas/testsuite/gas/macros/err.s | 5 + .../binutils/gas/testsuite/gas/macros/irp.d | 13 + .../binutils/gas/testsuite/gas/macros/irp.s | 8 + .../gas/testsuite/gas/macros/macros.exp | 15 + .../binutils/gas/testsuite/gas/macros/rept.d | 10 + .../binutils/gas/testsuite/gas/macros/rept.s | 3 + .../binutils/gas/testsuite/gas/macros/test1.d | 5 + .../binutils/gas/testsuite/gas/macros/test1.s | 7 + .../binutils/gas/testsuite/gas/macros/test2.d | 10 + .../binutils/gas/testsuite/gas/macros/test2.s | 9 + .../binutils/gas/testsuite/gas/macros/test3.d | 8 + .../binutils/gas/testsuite/gas/macros/test3.s | 7 + .../binutils/gas/testsuite/gas/mips/abs.d | 16 + .../binutils/gas/testsuite/gas/mips/abs.s | 4 + .../binutils/gas/testsuite/gas/mips/add.d | 21 + .../binutils/gas/testsuite/gas/mips/add.s | 12 + .../binutils/gas/testsuite/gas/mips/and.d | 35 + .../binutils/gas/testsuite/gas/mips/and.s | 22 + .../binutils/gas/testsuite/gas/mips/beq.d | 40 + .../binutils/gas/testsuite/gas/mips/beq.s | 23 + .../binutils/gas/testsuite/gas/mips/bge.d | 53 + .../binutils/gas/testsuite/gas/mips/bge.s | 25 + .../binutils/gas/testsuite/gas/mips/bgeu.d | 47 + .../binutils/gas/testsuite/gas/mips/bgeu.s | 23 + .../binutils/gas/testsuite/gas/mips/blt.d | 53 + .../binutils/gas/testsuite/gas/mips/blt.s | 25 + .../binutils/gas/testsuite/gas/mips/bltu.d | 47 + .../binutils/gas/testsuite/gas/mips/bltu.s | 23 + .../binutils/gas/testsuite/gas/mips/div.d | 132 + .../binutils/gas/testsuite/gas/mips/div.s | 40 + .../gas/testsuite/gas/mips/jal-empic.d | 26 + .../gas/testsuite/gas/mips/jal-svr4pic.d | 39 + .../gas/testsuite/gas/mips/jal-svr4pic.s | 14 + .../binutils/gas/testsuite/gas/mips/jal.d | 24 + .../binutils/gas/testsuite/gas/mips/jal.s | 11 + .../gas/testsuite/gas/mips/la-empic.d | 105 + .../gas/testsuite/gas/mips/la-empic.s | 57 + .../gas/testsuite/gas/mips/la-svr4pic.d | 474 + .../binutils/gas/testsuite/gas/mips/la.d | 395 + .../binutils/gas/testsuite/gas/mips/la.s | 108 + .../gas/testsuite/gas/mips/lb-empic.d | 102 + .../binutils/gas/testsuite/gas/mips/lb-pic.s | 52 + .../gas/testsuite/gas/mips/lb-svr4pic.d | 182 + .../binutils/gas/testsuite/gas/mips/lb.d | 407 + .../binutils/gas/testsuite/gas/mips/lb.s | 120 + .../gas/testsuite/gas/mips/ld-empic.d | 186 + .../binutils/gas/testsuite/gas/mips/ld-pic.s | 54 + .../gas/testsuite/gas/mips/ld-svr4pic.d | 225 + .../binutils/gas/testsuite/gas/mips/ld.d | 647 + .../binutils/gas/testsuite/gas/mips/ld.s | 141 + .../binutils/gas/testsuite/gas/mips/li.d | 17 + .../binutils/gas/testsuite/gas/mips/li.s | 8 + .../gas/testsuite/gas/mips/lif-empic.d | 21 + .../gas/testsuite/gas/mips/lif-svr4pic.d | 28 + .../binutils/gas/testsuite/gas/mips/lifloat.d | 23 + .../binutils/gas/testsuite/gas/mips/lifloat.s | 8 + .../binutils/gas/testsuite/gas/mips/mips.exp | 49 + .../binutils/gas/testsuite/gas/mips/mips4.d | 51 + .../binutils/gas/testsuite/gas/mips/mips4.s | 47 + .../binutils/gas/testsuite/gas/mips/mul.d | 91 + .../binutils/gas/testsuite/gas/mips/mul.s | 24 + .../binutils/gas/testsuite/gas/mips/rol.d | 37 + .../binutils/gas/testsuite/gas/mips/rol.s | 11 + .../binutils/gas/testsuite/gas/mips/sb.d | 407 + .../binutils/gas/testsuite/gas/mips/sb.s | 120 + .../binutils/gas/testsuite/gas/mips/trunc.d | 30 + .../binutils/gas/testsuite/gas/mips/trunc.s | 5 + .../binutils/gas/testsuite/gas/mips/uld.d | 276 + .../binutils/gas/testsuite/gas/mips/uld.s | 62 + .../gas/testsuite/gas/mips/ulh-empic.d | 91 + .../binutils/gas/testsuite/gas/mips/ulh-pic.s | 29 + .../gas/testsuite/gas/mips/ulh-svr4pic.d | 117 + .../binutils/gas/testsuite/gas/mips/ulh.d | 380 + .../binutils/gas/testsuite/gas/mips/ulh.s | 65 + .../binutils/gas/testsuite/gas/mips/ulw.d | 276 + .../binutils/gas/testsuite/gas/mips/ulw.s | 62 + .../binutils/gas/testsuite/gas/mips/usd.d | 276 + .../binutils/gas/testsuite/gas/mips/usd.s | 62 + .../binutils/gas/testsuite/gas/mips/ush.d | 461 + .../binutils/gas/testsuite/gas/mips/ush.s | 62 + .../binutils/gas/testsuite/gas/mips/usw.d | 276 + .../binutils/gas/testsuite/gas/mips/usw.s | 62 + .../binutils/gas/testsuite/gas/mri/char.d | 9 + .../binutils/gas/testsuite/gas/mri/char.s | 6 + .../binutils/gas/testsuite/gas/mri/comment.d | 9 + .../binutils/gas/testsuite/gas/mri/comment.s | 13 + .../binutils/gas/testsuite/gas/mri/common.d | 8 + .../binutils/gas/testsuite/gas/mri/common.s | 11 + .../gas/testsuite/gas/mri/constants.d | 19 + .../gas/testsuite/gas/mri/constants.s | 14 + .../binutils/gas/testsuite/gas/mri/empty.s | 9 + .../binutils/gas/testsuite/gas/mri/equ.d | 7 + .../binutils/gas/testsuite/gas/mri/equ.s | 3 + .../binutils/gas/testsuite/gas/mri/expr.d | 11 + .../binutils/gas/testsuite/gas/mri/expr.s | 7 + .../binutils/gas/testsuite/gas/mri/float.d | 10 + .../binutils/gas/testsuite/gas/mri/float.s | 7 + .../binutils/gas/testsuite/gas/mri/for.d | 30 + .../binutils/gas/testsuite/gas/mri/for.s | 22 + .../binutils/gas/testsuite/gas/mri/if.d | 25 + .../binutils/gas/testsuite/gas/mri/if.s | 17 + .../binutils/gas/testsuite/gas/mri/label.d | 8 + .../binutils/gas/testsuite/gas/mri/label.s | 5 + .../binutils/gas/testsuite/gas/mri/mri.exp | 25 + .../binutils/gas/testsuite/gas/mri/repeat.d | 16 + .../binutils/gas/testsuite/gas/mri/repeat.s | 14 + .../binutils/gas/testsuite/gas/mri/while.d | 18 + .../binutils/gas/testsuite/gas/mri/while.s | 14 + .../testsuite/gas/sparc-solaris/addend.exp | 36 + .../gas/testsuite/gas/sparc-solaris/addend.s | 11 + .../gas/testsuite/gas/sparc-solaris/gas.exp | 10 + .../gas/testsuite/gas/sparc-solaris/sol-cc.s | 81 + .../gas/testsuite/gas/sparc-solaris/sol-gcc.s | 66 + .../binutils/gas/testsuite/gas/sparc/asi.d | 33 + .../binutils/gas/testsuite/gas/sparc/asi.s | 28 + .../binutils/gas/testsuite/gas/sparc/membar.d | 17 + .../binutils/gas/testsuite/gas/sparc/membar.s | 12 + .../gas/testsuite/gas/sparc/prefetch.d | 17 + .../gas/testsuite/gas/sparc/prefetch.s | 11 + .../binutils/gas/testsuite/gas/sparc/rdpr.d | 24 + .../binutils/gas/testsuite/gas/sparc/rdpr.s | 19 + .../gas/testsuite/gas/sparc/sparc.exp | 17 + .../gas/testsuite/gas/sparc/synth64.d | 18 + .../gas/testsuite/gas/sparc/synth64.s | 16 + .../binutils/gas/testsuite/gas/sparc/wrpr.d | 22 + .../binutils/gas/testsuite/gas/sparc/wrpr.s | 17 + .../binutils/gas/testsuite/gas/sun4/addend.d | 13 + .../gas/testsuite/gas/sun4/addend.exp | 7 + .../binutils/gas/testsuite/gas/sun4/addend.s | 11 + .../binutils/gas/testsuite/gas/template | 96 + .../binutils/gas/testsuite/gas/vax/quad.exp | 23 + .../binutils/gas/testsuite/gas/vax/quad.s | 2 + .../binutils/gas/testsuite/gasp/INC1.H | 3 + .../binutils/gas/testsuite/gasp/INC2.H | 2 + .../binutils/gas/testsuite/gasp/assign.asm | 13 + .../binutils/gas/testsuite/gasp/assign.err | 1 + .../binutils/gas/testsuite/gasp/assign.out | 22 + .../binutils/gas/testsuite/gasp/condass.asm | 129 + .../binutils/gas/testsuite/gasp/condass.err | 0 .../binutils/gas/testsuite/gasp/condass.out | 155 + .../binutils/gas/testsuite/gasp/crash.asm | 22 + .../binutils/gas/testsuite/gasp/crash.err | 1 + .../binutils/gas/testsuite/gasp/crash.out | 3059 ++++ .../binutils/gas/testsuite/gasp/crash1.asm | 13 + .../binutils/gas/testsuite/gasp/crash1.err | 0 .../binutils/gas/testsuite/gasp/crash1.out | 24 + .../binutils/gas/testsuite/gasp/crash2.asm | 41 + .../binutils/gas/testsuite/gasp/crash2.err | 0 .../binutils/gas/testsuite/gasp/crash2.out | 69 + .../binutils/gas/testsuite/gasp/data.asm | 23 + .../binutils/gas/testsuite/gasp/data.err | 0 .../binutils/gas/testsuite/gasp/data.out | 45 + .../binutils/gas/testsuite/gasp/exp.asm | 80 + .../binutils/gas/testsuite/gasp/exp.err | 7 + .../binutils/gas/testsuite/gasp/exp.out | 124 + .../binutils/gas/testsuite/gasp/gasp.exp | 40 + .../binutils/gas/testsuite/gasp/include.asm | 4 + .../binutils/gas/testsuite/gasp/include.err | 0 .../binutils/gas/testsuite/gasp/include.out | 15 + .../binutils/gas/testsuite/gasp/listing.asm | 15 + .../binutils/gas/testsuite/gasp/listing.err | 0 .../binutils/gas/testsuite/gasp/listing.out | 28 + .../binutils/gas/testsuite/gasp/macro.asm | 102 + .../binutils/gas/testsuite/gasp/macro.err | 0 .../binutils/gas/testsuite/gasp/macro.out | 370 + .../binutils/gas/testsuite/gasp/mdouble.asm | 47 + .../binutils/gas/testsuite/gasp/mdouble.err | 0 .../binutils/gas/testsuite/gasp/mdouble.out | 68 + .../binutils/gas/testsuite/gasp/mri/embed.asm | 5 + .../binutils/gas/testsuite/gasp/mri/embed.out | 9 + .../gas/testsuite/gasp/mri/exists.asm | 10 + .../gas/testsuite/gasp/mri/exists.out | 24 + .../binutils/gas/testsuite/gasp/mri/irp.asm | 4 + .../binutils/gas/testsuite/gasp/mri/irp.out | 8 + .../binutils/gas/testsuite/gasp/mri/irpc.asm | 3 + .../binutils/gas/testsuite/gasp/mri/irpc.out | 8 + .../binutils/gas/testsuite/gasp/mri/macro.asm | 8 + .../binutils/gas/testsuite/gasp/mri/macro.out | 18 + .../binutils/gas/testsuite/gasp/mri/narg.asm | 9 + .../binutils/gas/testsuite/gasp/mri/narg.out | 38 + .../binutils/gas/testsuite/gasp/mri/rept.asm | 3 + .../binutils/gas/testsuite/gasp/mri/rept.out | 16 + .../binutils/gas/testsuite/gasp/pl1.asm | 20 + .../binutils/gas/testsuite/gasp/pl1.err | 1 + .../binutils/gas/testsuite/gasp/pl1.out | 49 + .../binutils/gas/testsuite/gasp/pl2.asm | 28 + .../binutils/gas/testsuite/gasp/pl2.err | 0 .../binutils/gas/testsuite/gasp/pl2.out | 51 + .../binutils/gas/testsuite/gasp/pl3.asm | 30 + .../binutils/gas/testsuite/gasp/pl3.err | 0 .../binutils/gas/testsuite/gasp/pl3.out | 86 + .../binutils/gas/testsuite/gasp/pl4.asm | 10 + .../binutils/gas/testsuite/gasp/pl4.err | 0 .../binutils/gas/testsuite/gasp/pl4.out | 16 + .../binutils/gas/testsuite/gasp/pl5.asm | 15 + .../binutils/gas/testsuite/gasp/pl5.err | 0 .../binutils/gas/testsuite/gasp/pl5.out | 32 + .../binutils/gas/testsuite/gasp/pl6.asm | 21 + .../binutils/gas/testsuite/gasp/pl6.err | 0 .../binutils/gas/testsuite/gasp/pl6.out | 54 + .../binutils/gas/testsuite/gasp/pl7.asm | 12 + .../binutils/gas/testsuite/gasp/pl7.err | 1 + .../binutils/gas/testsuite/gasp/pl7.out | 26 + .../binutils/gas/testsuite/gasp/pl8.asm | 18 + .../binutils/gas/testsuite/gasp/pl8.err | 0 .../binutils/gas/testsuite/gasp/pl8.out | 33 + .../binutils/gas/testsuite/gasp/pr7583.asm | 3 + .../binutils/gas/testsuite/gasp/pr7583.err | 0 .../binutils/gas/testsuite/gasp/pr7583.out | 5 + .../binutils/gas/testsuite/gasp/reg.asm | 9 + .../binutils/gas/testsuite/gasp/reg.err | 0 .../binutils/gas/testsuite/gasp/reg.out | 15 + .../binutils/gas/testsuite/gasp/rep.asm | 13 + .../binutils/gas/testsuite/gasp/rep.err | 0 .../binutils/gas/testsuite/gasp/rep.out | 391 + .../binutils/gas/testsuite/gasp/repeat.asm | 14 + .../binutils/gas/testsuite/gasp/repeat.err | 0 .../binutils/gas/testsuite/gasp/repeat.out | 211 + .../binutils/gas/testsuite/gasp/reperr.asm | 2 + .../binutils/gas/testsuite/gasp/reperr.err | 1 + .../binutils/gas/testsuite/gasp/reperr.out | 5 + .../binutils/gas/testsuite/gasp/reperr1.asm | 3 + .../binutils/gas/testsuite/gasp/reperr1.err | 1 + .../binutils/gas/testsuite/gasp/reperr1.out | 5 + .../binutils/gas/testsuite/gasp/reperr2.asm | 6 + .../binutils/gas/testsuite/gasp/reperr2.err | 1 + .../binutils/gas/testsuite/gasp/reperr2.out | 14 + .../binutils/gas/testsuite/gasp/reperr3.asm | 21 + .../binutils/gas/testsuite/gasp/reperr3.err | 6 + .../binutils/gas/testsuite/gasp/reperr3.out | 2035 +++ .../binutils/gas/testsuite/gasp/sdata.asm | 24 + .../binutils/gas/testsuite/gasp/sdata.err | 3 + .../binutils/gas/testsuite/gasp/sdata.out | 59 + .../binutils/gas/testsuite/gasp/sfunc.asm | 26 + .../binutils/gas/testsuite/gasp/sfunc.err | 0 .../binutils/gas/testsuite/gasp/sfunc.out | 49 + .../binutils/gas/testsuite/gasp/t1.asm | 3 + .../binutils/gas/testsuite/gasp/t1.err | 0 .../binutils/gas/testsuite/gasp/t1.out | 5 + .../binutils/gas/testsuite/gasp/t2.asm | 8 + .../binutils/gas/testsuite/gasp/t2.err | 0 .../binutils/gas/testsuite/gasp/t2.out | 13 + .../binutils/gas/testsuite/gasp/t3.asm | 12 + .../binutils/gas/testsuite/gasp/t3.err | 1 + .../binutils/gas/testsuite/gasp/t3.out | 25 + .../binutils/gas/testsuite/gasp/while.asm | 18 + .../binutils/gas/testsuite/gasp/while.err | 0 .../binutils/gas/testsuite/gasp/while.out | 388 + gnu/usr.bin/binutils/gas/testsuite/lib/doboth | 19 + .../binutils/gas/testsuite/lib/doobjcmp | 88 + .../binutils/gas/testsuite/lib/dostriptest | 14 + gnu/usr.bin/binutils/gas/testsuite/lib/dotest | 43 + .../binutils/gas/testsuite/lib/dounsreloc | 8 + .../binutils/gas/testsuite/lib/dounssym | 8 + .../binutils/gas/testsuite/lib/gas-defs.exp | 485 + .../binutils/gas/testsuite/lib/gas-dg.exp | 55 + gnu/usr.bin/binutils/gas/testsuite/lib/run | 2 + gnu/usr.bin/binutils/gas/vmsconf.sh | 99 + gnu/usr.bin/binutils/gas/write.c | 2589 ++++ gnu/usr.bin/binutils/gas/write.h | 179 + gnu/usr.bin/binutils/gas/xmalloc.c | 70 + gnu/usr.bin/binutils/gprof/.gdbinit | 1 + gnu/usr.bin/binutils/gprof/ChangeLog | 719 + gnu/usr.bin/binutils/gprof/Makefile.in | 148 + gnu/usr.bin/binutils/gprof/NOTES | 438 + gnu/usr.bin/binutils/gprof/TEST | 7 + gnu/usr.bin/binutils/gprof/TODO | 72 + gnu/usr.bin/binutils/gprof/__bb_exit_func.c | 78 + gnu/usr.bin/binutils/gprof/alpha.c | 168 + gnu/usr.bin/binutils/gprof/alpha.h | 31 + gnu/usr.bin/binutils/gprof/basic_blocks.c | 512 + gnu/usr.bin/binutils/gprof/basic_blocks.h | 23 + gnu/usr.bin/binutils/gprof/bsd_callg_bl.c | 118 + gnu/usr.bin/binutils/gprof/bsd_callg_bl.m | 108 + gnu/usr.bin/binutils/gprof/call_graph.c | 97 + gnu/usr.bin/binutils/gprof/call_graph.h | 12 + gnu/usr.bin/binutils/gprof/cg_arcs.c | 651 + gnu/usr.bin/binutils/gprof/cg_arcs.h | 33 + gnu/usr.bin/binutils/gprof/cg_dfn.c | 281 + gnu/usr.bin/binutils/gprof/cg_dfn.h | 17 + gnu/usr.bin/binutils/gprof/cg_print.c | 656 + gnu/usr.bin/binutils/gprof/cg_print.h | 12 + gnu/usr.bin/binutils/gprof/configure | 805 + gnu/usr.bin/binutils/gprof/configure.bat | 18 + gnu/usr.bin/binutils/gprof/configure.in | 24 + gnu/usr.bin/binutils/gprof/core.c | 508 + gnu/usr.bin/binutils/gprof/core.h | 17 + gnu/usr.bin/binutils/gprof/dummy.c | 16 + gnu/usr.bin/binutils/gprof/dummy.h | 55 + gnu/usr.bin/binutils/gprof/flat_bl.c | 37 + gnu/usr.bin/binutils/gprof/flat_bl.m | 27 + gnu/usr.bin/binutils/gprof/fsf_callg_bl.c | 93 + gnu/usr.bin/binutils/gprof/fsf_callg_bl.m | 83 + gnu/usr.bin/binutils/gprof/gen-c-prog.awk | 26 + gnu/usr.bin/binutils/gprof/gmon.h | 118 + gnu/usr.bin/binutils/gprof/gmon_io.c | 396 + gnu/usr.bin/binutils/gprof/gmon_io.h | 20 + gnu/usr.bin/binutils/gprof/gmon_out.h | 51 + gnu/usr.bin/binutils/gprof/gprof.1 | 252 + gnu/usr.bin/binutils/gprof/gprof.c | 587 + gnu/usr.bin/binutils/gprof/gprof.h | 137 + gnu/usr.bin/binutils/gprof/gprof.info | 951 ++ gnu/usr.bin/binutils/gprof/gprof.texi | 1055 ++ gnu/usr.bin/binutils/gprof/hertz.c | 47 + gnu/usr.bin/binutils/gprof/hertz.h | 14 + gnu/usr.bin/binutils/gprof/hist.c | 594 + gnu/usr.bin/binutils/gprof/hist.h | 23 + gnu/usr.bin/binutils/gprof/i386.c | 110 + gnu/usr.bin/binutils/gprof/i386.h | 38 + gnu/usr.bin/binutils/gprof/ns532.c | 17 + gnu/usr.bin/binutils/gprof/ns532.h | 51 + gnu/usr.bin/binutils/gprof/search_list.c | 44 + gnu/usr.bin/binutils/gprof/search_list.h | 20 + gnu/usr.bin/binutils/gprof/source.c | 223 + gnu/usr.bin/binutils/gprof/source.h | 55 + gnu/usr.bin/binutils/gprof/sparc.c | 84 + gnu/usr.bin/binutils/gprof/sparc.h | 31 + gnu/usr.bin/binutils/gprof/sym_ids.c | 372 + gnu/usr.bin/binutils/gprof/sym_ids.h | 25 + gnu/usr.bin/binutils/gprof/symtab.c | 265 + gnu/usr.bin/binutils/gprof/symtab.h | 100 + gnu/usr.bin/binutils/gprof/tahoe.c | 319 + gnu/usr.bin/binutils/gprof/tahoe.h | 46 + gnu/usr.bin/binutils/gprof/utils.c | 103 + gnu/usr.bin/binutils/gprof/utils.h | 7 + gnu/usr.bin/binutils/gprof/vax.c | 323 + gnu/usr.bin/binutils/gprof/vax.h | 52 + gnu/usr.bin/binutils/include/COPYING | 339 + gnu/usr.bin/binutils/include/ChangeLog | 921 ++ gnu/usr.bin/binutils/include/ansidecl.h | 141 + gnu/usr.bin/binutils/include/aout/ChangeLog | 167 + gnu/usr.bin/binutils/include/aout/adobe.h | 297 + gnu/usr.bin/binutils/include/aout/aout64.h | 475 + gnu/usr.bin/binutils/include/aout/ar.h | 36 + gnu/usr.bin/binutils/include/aout/dynix3.h | 71 + gnu/usr.bin/binutils/include/aout/encap.h | 135 + gnu/usr.bin/binutils/include/aout/host.h | 22 + gnu/usr.bin/binutils/include/aout/hp.h | 82 + gnu/usr.bin/binutils/include/aout/hp300hpux.h | 119 + gnu/usr.bin/binutils/include/aout/hppa.h | 7 + gnu/usr.bin/binutils/include/aout/ranlib.h | 62 + gnu/usr.bin/binutils/include/aout/reloc.h | 66 + gnu/usr.bin/binutils/include/aout/stab.def | 264 + gnu/usr.bin/binutils/include/aout/stab_gnu.h | 36 + gnu/usr.bin/binutils/include/aout/sun4.h | 219 + gnu/usr.bin/binutils/include/bfdlink.h | 440 + gnu/usr.bin/binutils/include/bout.h | 182 + gnu/usr.bin/binutils/include/coff/ChangeLog | 594 + gnu/usr.bin/binutils/include/coff/a29k.h | 305 + gnu/usr.bin/binutils/include/coff/alpha.h | 342 + gnu/usr.bin/binutils/include/coff/apollo.h | 248 + gnu/usr.bin/binutils/include/coff/arm.h | 215 + gnu/usr.bin/binutils/include/coff/ecoff.h | 405 + gnu/usr.bin/binutils/include/coff/h8300.h | 203 + gnu/usr.bin/binutils/include/coff/h8500.h | 201 + gnu/usr.bin/binutils/include/coff/i386.h | 224 + gnu/usr.bin/binutils/include/coff/i860.h | 204 + gnu/usr.bin/binutils/include/coff/i960.h | 249 + gnu/usr.bin/binutils/include/coff/internal.h | 639 + gnu/usr.bin/binutils/include/coff/m68k.h | 217 + gnu/usr.bin/binutils/include/coff/m88k.h | 218 + gnu/usr.bin/binutils/include/coff/mips.h | 368 + gnu/usr.bin/binutils/include/coff/pe.h | 161 + gnu/usr.bin/binutils/include/coff/powerpc.h | 196 + gnu/usr.bin/binutils/include/coff/rs6000.h | 242 + gnu/usr.bin/binutils/include/coff/sh.h | 253 + gnu/usr.bin/binutils/include/coff/sparc.h | 209 + gnu/usr.bin/binutils/include/coff/sym.h | 484 + gnu/usr.bin/binutils/include/coff/symconst.h | 176 + gnu/usr.bin/binutils/include/coff/w65.h | 201 + gnu/usr.bin/binutils/include/coff/we32k.h | 206 + gnu/usr.bin/binutils/include/coff/z8k.h | 201 + gnu/usr.bin/binutils/include/demangle.h | 107 + gnu/usr.bin/binutils/include/dis-asm.h | 157 + gnu/usr.bin/binutils/include/elf/ChangeLog | 168 + gnu/usr.bin/binutils/include/elf/common.h | 236 + gnu/usr.bin/binutils/include/elf/dwarf.h | 319 + gnu/usr.bin/binutils/include/elf/external.h | 195 + gnu/usr.bin/binutils/include/elf/hppa.h | 94 + gnu/usr.bin/binutils/include/elf/internal.h | 178 + gnu/usr.bin/binutils/include/elf/mips.h | 298 + gnu/usr.bin/binutils/include/elf/ppc.h | 38 + gnu/usr.bin/binutils/include/floatformat.h | 88 + gnu/usr.bin/binutils/include/fopen-bin.h | 27 + gnu/usr.bin/binutils/include/fopen-same.h | 27 + gnu/usr.bin/binutils/include/gdbm.h | 91 + gnu/usr.bin/binutils/include/getopt.h | 129 + gnu/usr.bin/binutils/include/hp-symtab.h | 983 ++ gnu/usr.bin/binutils/include/ieee.h | 132 + gnu/usr.bin/binutils/include/libiberty.h | 129 + gnu/usr.bin/binutils/include/mpw/ChangeLog | 48 + gnu/usr.bin/binutils/include/mpw/README | 1 + gnu/usr.bin/binutils/include/mpw/dir.h | 23 + gnu/usr.bin/binutils/include/mpw/dirent.h | 31 + gnu/usr.bin/binutils/include/mpw/fcntl.h | 124 + gnu/usr.bin/binutils/include/mpw/grp.h | 10 + gnu/usr.bin/binutils/include/mpw/mpw.h | 124 + gnu/usr.bin/binutils/include/mpw/pwd.h | 15 + gnu/usr.bin/binutils/include/mpw/spin.h | 64 + gnu/usr.bin/binutils/include/mpw/stat.h | 75 + gnu/usr.bin/binutils/include/mpw/sys/file.h | 1 + gnu/usr.bin/binutils/include/mpw/sys/param.h | 1 + .../binutils/include/mpw/sys/resource.h | 9 + gnu/usr.bin/binutils/include/mpw/sys/stat.h | 44 + gnu/usr.bin/binutils/include/mpw/sys/time.h | 13 + gnu/usr.bin/binutils/include/mpw/sys/types.h | 15 + gnu/usr.bin/binutils/include/mpw/utime.h | 7 + gnu/usr.bin/binutils/include/mpw/varargs.h | 9 + gnu/usr.bin/binutils/include/nlm/ChangeLog | 83 + gnu/usr.bin/binutils/include/nlm/alpha-ext.h | 166 + gnu/usr.bin/binutils/include/nlm/common.h | 124 + gnu/usr.bin/binutils/include/nlm/external.h | 174 + gnu/usr.bin/binutils/include/nlm/i386-ext.h | 116 + gnu/usr.bin/binutils/include/nlm/internal.h | 309 + gnu/usr.bin/binutils/include/nlm/ppc-ext.h | 163 + .../binutils/include/nlm/sparc32-ext.h | 120 + gnu/usr.bin/binutils/include/oasys.h | 152 + gnu/usr.bin/binutils/include/obstack.h | 513 + gnu/usr.bin/binutils/include/opcode/ChangeLog | 751 + gnu/usr.bin/binutils/include/opcode/a29k.h | 285 + gnu/usr.bin/binutils/include/opcode/arm.h | 294 + gnu/usr.bin/binutils/include/opcode/convex.h | 1711 +++ gnu/usr.bin/binutils/include/opcode/h8300.h | 550 + gnu/usr.bin/binutils/include/opcode/hppa.h | 471 + gnu/usr.bin/binutils/include/opcode/i386.h | 863 ++ gnu/usr.bin/binutils/include/opcode/i860.h | 491 + gnu/usr.bin/binutils/include/opcode/i960.h | 452 + gnu/usr.bin/binutils/include/opcode/m68k.h | 297 + gnu/usr.bin/binutils/include/opcode/m88k.h | 923 ++ gnu/usr.bin/binutils/include/opcode/mips.h | 481 + gnu/usr.bin/binutils/include/opcode/np1.h | 422 + gnu/usr.bin/binutils/include/opcode/ns32k.h | 491 + gnu/usr.bin/binutils/include/opcode/pn.h | 282 + gnu/usr.bin/binutils/include/opcode/ppc.h | 248 + gnu/usr.bin/binutils/include/opcode/pyr.h | 287 + gnu/usr.bin/binutils/include/opcode/rs6k.h | 254 + gnu/usr.bin/binutils/include/opcode/sparc.h | 194 + gnu/usr.bin/binutils/include/opcode/tahoe.h | 213 + gnu/usr.bin/binutils/include/opcode/vax.h | 382 + gnu/usr.bin/binutils/include/os9k.h | 169 + gnu/usr.bin/binutils/include/progress.h | 37 + gnu/usr.bin/binutils/include/wait.h | 38 + gnu/usr.bin/binutils/install.sh | 236 + gnu/usr.bin/binutils/ld/ChangeLog | 5066 +++++++ gnu/usr.bin/binutils/ld/Makefile.in | 935 ++ gnu/usr.bin/binutils/ld/NEWS | 125 + gnu/usr.bin/binutils/ld/README | 51 + gnu/usr.bin/binutils/ld/TODO | 11 + gnu/usr.bin/binutils/ld/acconfig.h | 5 + gnu/usr.bin/binutils/ld/aclocal.m4 | 1 + gnu/usr.bin/binutils/ld/config.in | 34 + gnu/usr.bin/binutils/ld/configure | 1220 ++ gnu/usr.bin/binutils/ld/configure.bat | 72 + gnu/usr.bin/binutils/ld/configure.host | 113 + gnu/usr.bin/binutils/ld/configure.in | 117 + gnu/usr.bin/binutils/ld/configure.tgt | 124 + gnu/usr.bin/binutils/ld/dep-in.sed | 16 + gnu/usr.bin/binutils/ld/emulparams/README | 2 + gnu/usr.bin/binutils/ld/emulparams/a29k.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/aixppc.sh | 4 + gnu/usr.bin/binutils/ld/emulparams/aixrs6.sh | 4 + gnu/usr.bin/binutils/ld/emulparams/alpha.sh | 3 + .../binutils/ld/emulparams/armaoutb.sh | 7 + .../binutils/ld/emulparams/armaoutl.sh | 7 + gnu/usr.bin/binutils/ld/emulparams/armcoff.sh | 6 + gnu/usr.bin/binutils/ld/emulparams/armpe.sh | 6 + .../binutils/ld/emulparams/coff_sparc.sh | 7 + gnu/usr.bin/binutils/ld/emulparams/delta68.sh | 5 + .../binutils/ld/emulparams/ebmon29k.sh | 5 + .../binutils/ld/emulparams/elf32_sparc.sh | 9 + .../binutils/ld/emulparams/elf32b4300.sh | 25 + .../binutils/ld/emulparams/elf32bmip.sh | 26 + .../binutils/ld/emulparams/elf32l4300.sh | 25 + .../binutils/ld/emulparams/elf32lmip.sh | 26 + .../binutils/ld/emulparams/elf32lppc.sh | 9 + .../binutils/ld/emulparams/elf32ppc.sh | 9 + .../binutils/ld/emulparams/elf64_sparc.sh | 6 + .../binutils/ld/emulparams/elf_i386.sh | 9 + gnu/usr.bin/binutils/ld/emulparams/gld960.sh | 7 + .../binutils/ld/emulparams/gld960coff.sh | 19 + gnu/usr.bin/binutils/ld/emulparams/go32.sh | 7 + gnu/usr.bin/binutils/ld/emulparams/h8300.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/h8300h.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/h8500.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/h8500b.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/h8500c.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/h8500m.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/h8500s.sh | 5 + .../binutils/ld/emulparams/hp300bsd.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/hp3hpux.sh | 8 + gnu/usr.bin/binutils/ld/emulparams/hppaelf.sh | 7 + .../binutils/ld/emulparams/i386aout.sh | 6 + gnu/usr.bin/binutils/ld/emulparams/i386bsd.sh | 6 + .../binutils/ld/emulparams/i386coff.sh | 5 + .../binutils/ld/emulparams/i386go32.sh | 8 + .../binutils/ld/emulparams/i386linux.sh | 7 + .../binutils/ld/emulparams/i386lynx.sh | 9 + .../binutils/ld/emulparams/i386mach.sh | 7 + .../binutils/ld/emulparams/i386moss.sh | 9 + .../binutils/ld/emulparams/i386msdos.sh | 7 + .../binutils/ld/emulparams/i386nbsd.sh | 6 + gnu/usr.bin/binutils/ld/emulparams/i386nw.sh | 9 + gnu/usr.bin/binutils/ld/emulparams/i386pe.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/lnk960.sh | 6 + .../binutils/ld/emulparams/m68k4knbsd.sh | 7 + .../binutils/ld/emulparams/m68kaout.sh | 7 + .../binutils/ld/emulparams/m68kcoff.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/m68kelf.sh | 9 + .../binutils/ld/emulparams/m68klynx.sh | 8 + .../binutils/ld/emulparams/m68knbsd.sh | 7 + gnu/usr.bin/binutils/ld/emulparams/m88kbcs.sh | 6 + gnu/usr.bin/binutils/ld/emulparams/mipsbig.sh | 6 + gnu/usr.bin/binutils/ld/emulparams/mipsbsd.sh | 7 + gnu/usr.bin/binutils/ld/emulparams/mipsidt.sh | 10 + .../binutils/ld/emulparams/mipsidtl.sh | 10 + gnu/usr.bin/binutils/ld/emulparams/mipslit.sh | 6 + gnu/usr.bin/binutils/ld/emulparams/news.sh | 5 + .../binutils/ld/emulparams/ns32knbsd.sh | 5 + .../binutils/ld/emulparams/pc532machaout.sh | 7 + gnu/usr.bin/binutils/ld/emulparams/ppcnw.sh | 7 + gnu/usr.bin/binutils/ld/emulparams/ppcpe.sh | 4 + gnu/usr.bin/binutils/ld/emulparams/riscix.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/sa29200.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/sh.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/shl.sh | 5 + .../binutils/ld/emulparams/sparclynx.sh | 9 + .../binutils/ld/emulparams/sparcnbsd.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/st2000.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/sun3.sh | 8 + gnu/usr.bin/binutils/ld/emulparams/sun4.sh | 7 + gnu/usr.bin/binutils/ld/emulparams/vanilla.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/vax.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/vsta.sh | 8 + gnu/usr.bin/binutils/ld/emulparams/w65.sh | 5 + gnu/usr.bin/binutils/ld/emulparams/z8001.sh | 7 + gnu/usr.bin/binutils/ld/emulparams/z8002.sh | 6 + gnu/usr.bin/binutils/ld/emultempl/README | 3 + gnu/usr.bin/binutils/ld/emultempl/aix.em | 990 ++ gnu/usr.bin/binutils/ld/emultempl/elf32.em | 799 + gnu/usr.bin/binutils/ld/emultempl/generic.em | 118 + gnu/usr.bin/binutils/ld/emultempl/gld960.em | 176 + gnu/usr.bin/binutils/ld/emultempl/gld960c.em | 177 + gnu/usr.bin/binutils/ld/emultempl/hppaelf.em | 286 + gnu/usr.bin/binutils/ld/emultempl/linux.em | 207 + gnu/usr.bin/binutils/ld/emultempl/lnk960.em | 323 + gnu/usr.bin/binutils/ld/emultempl/m88kbcs.em | 119 + .../binutils/ld/emultempl/mipsecoff.em | 229 + gnu/usr.bin/binutils/ld/emultempl/pe.em | 518 + .../binutils/ld/emultempl/stringify.sed | 4 + gnu/usr.bin/binutils/ld/emultempl/sunos.em | 969 ++ gnu/usr.bin/binutils/ld/emultempl/vanilla.em | 69 + gnu/usr.bin/binutils/ld/gen-doc.texi | 13 + gnu/usr.bin/binutils/ld/genscripts.sh | 131 + gnu/usr.bin/binutils/ld/h8-doc.texi | 14 + gnu/usr.bin/binutils/ld/ld.1 | 994 ++ gnu/usr.bin/binutils/ld/ld.h | 143 + gnu/usr.bin/binutils/ld/ld.info | 66 + gnu/usr.bin/binutils/ld/ld.info-1 | 1239 ++ gnu/usr.bin/binutils/ld/ld.info-2 | 924 ++ gnu/usr.bin/binutils/ld/ld.info-3 | 343 + gnu/usr.bin/binutils/ld/ld.texinfo | 2641 ++++ gnu/usr.bin/binutils/ld/ldctor.c | 215 + gnu/usr.bin/binutils/ld/ldctor.h | 54 + gnu/usr.bin/binutils/ld/ldemul.c | 251 + gnu/usr.bin/binutils/ld/ldemul.h | 134 + gnu/usr.bin/binutils/ld/ldexp.c | 911 ++ gnu/usr.bin/binutils/ld/ldexp.h | 109 + gnu/usr.bin/binutils/ld/ldfile.c | 397 + gnu/usr.bin/binutils/ld/ldfile.h | 53 + gnu/usr.bin/binutils/ld/ldgram.c | 2052 +++ gnu/usr.bin/binutils/ld/ldgram.h | 94 + gnu/usr.bin/binutils/ld/ldgram.y | 681 + gnu/usr.bin/binutils/ld/ldint.texinfo | 303 + gnu/usr.bin/binutils/ld/ldlang.c | 3117 ++++ gnu/usr.bin/binutils/ld/ldlang.h | 402 + gnu/usr.bin/binutils/ld/ldlex.c | 3270 ++++ gnu/usr.bin/binutils/ld/ldlex.h | 59 + gnu/usr.bin/binutils/ld/ldlex.l | 581 + gnu/usr.bin/binutils/ld/ldmain.c | 1084 ++ gnu/usr.bin/binutils/ld/ldmain.h | 37 + gnu/usr.bin/binutils/ld/ldmisc.c | 463 + gnu/usr.bin/binutils/ld/ldmisc.h | 46 + gnu/usr.bin/binutils/ld/ldver.c | 88 + gnu/usr.bin/binutils/ld/ldver.h | 21 + gnu/usr.bin/binutils/ld/ldwrite.c | 588 + gnu/usr.bin/binutils/ld/ldwrite.h | 20 + gnu/usr.bin/binutils/ld/lexsup.c | 581 + gnu/usr.bin/binutils/ld/mac-ld.r | 16 + gnu/usr.bin/binutils/ld/mpw-config.in | 43 + gnu/usr.bin/binutils/ld/mpw-emipsidt.c | 430 + gnu/usr.bin/binutils/ld/mpw-eppcmacos.c | 841 ++ gnu/usr.bin/binutils/ld/mpw-esh.c | 315 + gnu/usr.bin/binutils/ld/mpw-make.sed | 74 + gnu/usr.bin/binutils/ld/mri.c | 376 + gnu/usr.bin/binutils/ld/mri.h | 38 + gnu/usr.bin/binutils/ld/scripttempl/README | 4 + gnu/usr.bin/binutils/ld/scripttempl/a29k.sc | 37 + gnu/usr.bin/binutils/ld/scripttempl/aix.sc | 54 + gnu/usr.bin/binutils/ld/scripttempl/alpha.sc | 71 + gnu/usr.bin/binutils/ld/scripttempl/aout.sc | 50 + .../binutils/ld/scripttempl/armaout.sc | 35 + .../binutils/ld/scripttempl/armcoff.sc | 39 + .../binutils/ld/scripttempl/delta68.sc | 49 + .../binutils/ld/scripttempl/ebmon29k.sc | 27 + gnu/usr.bin/binutils/ld/scripttempl/elf.sc | 156 + gnu/usr.bin/binutils/ld/scripttempl/elfppc.sc | 166 + .../binutils/ld/scripttempl/go32coff.sc | 33 + gnu/usr.bin/binutils/ld/scripttempl/h8300.sc | 59 + gnu/usr.bin/binutils/ld/scripttempl/h8300h.sc | 51 + gnu/usr.bin/binutils/ld/scripttempl/h8500.sc | 62 + gnu/usr.bin/binutils/ld/scripttempl/h8500b.sc | 62 + gnu/usr.bin/binutils/ld/scripttempl/h8500c.sc | 59 + gnu/usr.bin/binutils/ld/scripttempl/h8500m.sc | 61 + gnu/usr.bin/binutils/ld/scripttempl/h8500s.sc | 60 + .../binutils/ld/scripttempl/hppaelf.sc | 38 + .../binutils/ld/scripttempl/i386coff.sc | 43 + .../binutils/ld/scripttempl/i386go32.sc | 45 + .../binutils/ld/scripttempl/i386lynx.sc | 46 + .../binutils/ld/scripttempl/i386msdos.sc | 40 + gnu/usr.bin/binutils/ld/scripttempl/i960.sc | 25 + .../binutils/ld/scripttempl/m68kcoff.sc | 59 + .../binutils/ld/scripttempl/m68klynx.sc | 46 + .../binutils/ld/scripttempl/m88kbcs.sc | 49 + gnu/usr.bin/binutils/ld/scripttempl/mips.sc | 67 + .../binutils/ld/scripttempl/mipsbsd.sc | 30 + gnu/usr.bin/binutils/ld/scripttempl/nw.sc | 131 + gnu/usr.bin/binutils/ld/scripttempl/pe.sc | 124 + gnu/usr.bin/binutils/ld/scripttempl/ppcpe.sc | 191 + gnu/usr.bin/binutils/ld/scripttempl/riscix.sc | 35 + .../binutils/ld/scripttempl/sa29200.sc | 44 + gnu/usr.bin/binutils/ld/scripttempl/sh.sc | 57 + .../binutils/ld/scripttempl/sparccoff.sc | 48 + .../binutils/ld/scripttempl/sparclynx.sc | 47 + gnu/usr.bin/binutils/ld/scripttempl/st2000.sc | 26 + .../binutils/ld/scripttempl/vanilla.sc | 1 + gnu/usr.bin/binutils/ld/scripttempl/w65.sc | 58 + gnu/usr.bin/binutils/ld/scripttempl/z8000.sc | 54 + gnu/usr.bin/binutils/ld/sysdep.h | 62 + gnu/usr.bin/binutils/ld/testsuite/ChangeLog | 277 + .../binutils/ld/testsuite/config/default.exp | 123 + .../ld/testsuite/ld-bootstrap/bootstrap.exp | 88 + .../ld/testsuite/ld-cdtest/cdtest-bar.cc | 17 + .../ld/testsuite/ld-cdtest/cdtest-foo.cc | 89 + .../ld/testsuite/ld-cdtest/cdtest-foo.h | 24 + .../ld/testsuite/ld-cdtest/cdtest-main.cc | 40 + .../ld/testsuite/ld-cdtest/cdtest.dat | 15 + .../ld/testsuite/ld-cdtest/cdtest.exp | 100 + .../binutils/ld/testsuite/ld-empic/empic.exp | 247 + .../binutils/ld/testsuite/ld-empic/relax.t | 49 + .../binutils/ld/testsuite/ld-empic/relax1.c | 22 + .../binutils/ld/testsuite/ld-empic/relax2.c | 19 + .../binutils/ld/testsuite/ld-empic/relax3.c | 3 + .../binutils/ld/testsuite/ld-empic/relax4.c | 3 + .../binutils/ld/testsuite/ld-empic/run.c | 160 + .../binutils/ld/testsuite/ld-empic/runtest1.c | 117 + .../binutils/ld/testsuite/ld-empic/runtest2.c | 26 + .../binutils/ld/testsuite/ld-empic/runtesti.s | 94 + .../ld/testsuite/ld-scripts/defined.exp | 39 + .../ld/testsuite/ld-scripts/defined.s | 2 + .../ld/testsuite/ld-scripts/defined.t | 7 + .../ld/testsuite/ld-scripts/script.exp | 64 + .../binutils/ld/testsuite/ld-scripts/script.s | 8 + .../binutils/ld/testsuite/ld-scripts/script.t | 16 + .../ld/testsuite/ld-scripts/scriptm.t | 10 + .../ld/testsuite/ld-scripts/sizeof.exp | 55 + .../binutils/ld/testsuite/ld-scripts/sizeof.s | 1 + .../binutils/ld/testsuite/ld-scripts/sizeof.t | 17 + .../binutils/ld/testsuite/ld-sh/sh.exp | 141 + gnu/usr.bin/binutils/ld/testsuite/ld-sh/sh1.s | 13 + gnu/usr.bin/binutils/ld/testsuite/ld-sh/sh2.c | 120 + .../binutils/ld/testsuite/ld-sh/start.s | 27 + .../binutils/ld/testsuite/ld-shared/main.c | 72 + .../binutils/ld/testsuite/ld-shared/sh1.c | 147 + .../binutils/ld/testsuite/ld-shared/sh2.c | 14 + .../ld/testsuite/ld-shared/shared.dat | 15 + .../ld/testsuite/ld-shared/shared.exp | 230 + .../binutils/ld/testsuite/ld-shared/sun4.dat | 15 + .../binutils/ld/testsuite/ld-shared/xcoff.dat | 10 + .../binutils/ld/testsuite/ld-srec/sr1.c | 25 + .../binutils/ld/testsuite/ld-srec/sr2.c | 18 + .../binutils/ld/testsuite/ld-srec/sr3.cc | 80 + .../binutils/ld/testsuite/ld-srec/srec.exp | 293 + .../ld/testsuite/ld-undefined/undefined.c | 10 + .../ld/testsuite/ld-undefined/undefined.exp | 86 + .../binutils/ld/testsuite/ld-versados/t1-1.ro | Bin 0 -> 3840 bytes .../binutils/ld/testsuite/ld-versados/t1-2.ro | Bin 0 -> 256 bytes .../binutils/ld/testsuite/ld-versados/t1.ld | 281 + .../binutils/ld/testsuite/ld-versados/t1.ook | 133 + .../binutils/ld/testsuite/ld-versados/t2-1.ro | Bin 0 -> 256 bytes .../binutils/ld/testsuite/ld-versados/t2-2.ro | Bin 0 -> 2304 bytes .../binutils/ld/testsuite/ld-versados/t2-3.ro | Bin 0 -> 1024 bytes .../binutils/ld/testsuite/ld-versados/t2.ld | 281 + .../binutils/ld/testsuite/ld-versados/t2.ook | 99 + .../ld/testsuite/ld-versados/versados.exp | 99 + gnu/usr.bin/binutils/ld/testsuite/lib/ld.exp | 337 + gnu/usr.bin/binutils/libiberty/COPYING.LIB | 481 + gnu/usr.bin/binutils/libiberty/ChangeLog | 1707 +++ gnu/usr.bin/binutils/libiberty/Makefile.in | 316 + gnu/usr.bin/binutils/libiberty/README | 129 + gnu/usr.bin/binutils/libiberty/alloca-botch.h | 5 + gnu/usr.bin/binutils/libiberty/alloca-norm.h | 16 + gnu/usr.bin/binutils/libiberty/alloca.c | 475 + gnu/usr.bin/binutils/libiberty/argv.c | 328 + gnu/usr.bin/binutils/libiberty/basename.c | 43 + gnu/usr.bin/binutils/libiberty/bcmp.c | 49 + gnu/usr.bin/binutils/libiberty/bcopy.c | 35 + gnu/usr.bin/binutils/libiberty/bzero.c | 31 + gnu/usr.bin/binutils/libiberty/clock.c | 73 + gnu/usr.bin/binutils/libiberty/concat.c | 167 + gnu/usr.bin/binutils/libiberty/config.table | 73 + .../binutils/libiberty/config/mh-a68bsd | 2 + gnu/usr.bin/binutils/libiberty/config/mh-aix | 10 + .../binutils/libiberty/config/mh-apollo68 | 2 + .../binutils/libiberty/config/mh-cxux7 | 3 + gnu/usr.bin/binutils/libiberty/config/mh-go32 | 4 + .../binutils/libiberty/config/mh-hpbsd | 2 + gnu/usr.bin/binutils/libiberty/config/mh-hpux | 1 + .../binutils/libiberty/config/mh-i386win32 | 5 + .../binutils/libiberty/config/mh-irix4 | 4 + .../binutils/libiberty/config/mh-lynxos | 1 + .../binutils/libiberty/config/mh-ncr3000 | 19 + .../binutils/libiberty/config/mh-riscix | 6 + gnu/usr.bin/binutils/libiberty/config/mh-sysv | 1 + .../binutils/libiberty/config/mh-sysv4 | 3 + .../binutils/libiberty/config/mt-sunos4 | 2 + .../binutils/libiberty/config/mt-vxworks5 | 27 + gnu/usr.bin/binutils/libiberty/configure.bat | 15 + gnu/usr.bin/binutils/libiberty/configure.in | 69 + gnu/usr.bin/binutils/libiberty/copysign.c | 140 + gnu/usr.bin/binutils/libiberty/cplus-dem.c | 3001 ++++ gnu/usr.bin/binutils/libiberty/dummy.c | 49 + gnu/usr.bin/binutils/libiberty/fdmatch.c | 73 + gnu/usr.bin/binutils/libiberty/floatformat.c | 385 + gnu/usr.bin/binutils/libiberty/functions.def | 65 + gnu/usr.bin/binutils/libiberty/getcwd.c | 52 + gnu/usr.bin/binutils/libiberty/getopt.c | 757 + gnu/usr.bin/binutils/libiberty/getopt1.c | 190 + gnu/usr.bin/binutils/libiberty/getpagesize.c | 89 + gnu/usr.bin/binutils/libiberty/getruntime.c | 82 + gnu/usr.bin/binutils/libiberty/hex.c | 33 + gnu/usr.bin/binutils/libiberty/index.c | 11 + gnu/usr.bin/binutils/libiberty/insque.c | 50 + gnu/usr.bin/binutils/libiberty/makefile.dos | 29 + gnu/usr.bin/binutils/libiberty/memchr.c | 60 + gnu/usr.bin/binutils/libiberty/memcmp.c | 38 + gnu/usr.bin/binutils/libiberty/memcpy.c | 28 + gnu/usr.bin/binutils/libiberty/memmove.c | 18 + gnu/usr.bin/binutils/libiberty/memset.c | 19 + gnu/usr.bin/binutils/libiberty/mpw-config.in | 9 + gnu/usr.bin/binutils/libiberty/mpw-make.sed | 49 + gnu/usr.bin/binutils/libiberty/mpw.c | 996 ++ gnu/usr.bin/binutils/libiberty/msdos.c | 15 + gnu/usr.bin/binutils/libiberty/obstack.c | 493 + gnu/usr.bin/binutils/libiberty/random.c | 373 + gnu/usr.bin/binutils/libiberty/rename.c | 22 + gnu/usr.bin/binutils/libiberty/rindex.c | 11 + gnu/usr.bin/binutils/libiberty/sigsetmask.c | 30 + gnu/usr.bin/binutils/libiberty/spaces.c | 71 + gnu/usr.bin/binutils/libiberty/strcasecmp.c | 81 + gnu/usr.bin/binutils/libiberty/strchr.c | 34 + gnu/usr.bin/binutils/libiberty/strdup.c | 10 + gnu/usr.bin/binutils/libiberty/strerror.c | 829 ++ gnu/usr.bin/binutils/libiberty/strncasecmp.c | 82 + gnu/usr.bin/binutils/libiberty/strrchr.c | 34 + gnu/usr.bin/binutils/libiberty/strsignal.c | 627 + gnu/usr.bin/binutils/libiberty/strstr.c | 51 + gnu/usr.bin/binutils/libiberty/strtod.c | 122 + gnu/usr.bin/binutils/libiberty/strtol.c | 143 + gnu/usr.bin/binutils/libiberty/strtoul.c | 110 + gnu/usr.bin/binutils/libiberty/tmpnam.c | 39 + gnu/usr.bin/binutils/libiberty/vasprintf.c | 165 + gnu/usr.bin/binutils/libiberty/vfork.c | 8 + gnu/usr.bin/binutils/libiberty/vfprintf.c | 13 + gnu/usr.bin/binutils/libiberty/vmsbuild.com | 142 + gnu/usr.bin/binutils/libiberty/vprintf.c | 11 + gnu/usr.bin/binutils/libiberty/vsprintf.c | 55 + gnu/usr.bin/binutils/libiberty/waitpid.c | 11 + gnu/usr.bin/binutils/libiberty/win32.c | 64 + gnu/usr.bin/binutils/libiberty/xatexit.c | 82 + gnu/usr.bin/binutils/libiberty/xexit.c | 36 + gnu/usr.bin/binutils/libiberty/xmalloc.c | 106 + gnu/usr.bin/binutils/libiberty/xstrerror.c | 54 + gnu/usr.bin/binutils/makeall.bat | 16 + gnu/usr.bin/binutils/move-if-change | 15 + gnu/usr.bin/binutils/mpw-README | 223 + gnu/usr.bin/binutils/mpw-build.in | 206 + gnu/usr.bin/binutils/mpw-config.in | 103 + gnu/usr.bin/binutils/mpw-configure | 352 + gnu/usr.bin/binutils/opcodes/ChangeLog | 1492 ++ gnu/usr.bin/binutils/opcodes/Makefile.in | 207 + gnu/usr.bin/binutils/opcodes/a29k-dis.c | 353 + gnu/usr.bin/binutils/opcodes/aclocal.m4 | 1 + gnu/usr.bin/binutils/opcodes/alpha-dis.c | 335 + gnu/usr.bin/binutils/opcodes/alpha-opc.h | 741 + gnu/usr.bin/binutils/opcodes/arm-dis.c | 452 + gnu/usr.bin/binutils/opcodes/arm-opc.h | 142 + gnu/usr.bin/binutils/opcodes/config.in | 7 + gnu/usr.bin/binutils/opcodes/configure | 1168 ++ gnu/usr.bin/binutils/opcodes/configure.bat | 24 + gnu/usr.bin/binutils/opcodes/configure.in | 154 + gnu/usr.bin/binutils/opcodes/dis-buf.c | 70 + gnu/usr.bin/binutils/opcodes/disassemble.c | 169 + gnu/usr.bin/binutils/opcodes/h8300-dis.c | 401 + gnu/usr.bin/binutils/opcodes/h8500-dis.c | 344 + gnu/usr.bin/binutils/opcodes/h8500-opc.h | 3836 +++++ gnu/usr.bin/binutils/opcodes/hppa-dis.c | 620 + gnu/usr.bin/binutils/opcodes/i386-dis.c | 1975 +++ gnu/usr.bin/binutils/opcodes/i960-dis.c | 861 ++ gnu/usr.bin/binutils/opcodes/m68k-dis.c | 1143 ++ gnu/usr.bin/binutils/opcodes/m68k-opc.c | 1979 +++ gnu/usr.bin/binutils/opcodes/m88k-dis.c | 328 + gnu/usr.bin/binutils/opcodes/mips-dis.c | 295 + gnu/usr.bin/binutils/opcodes/mips-opc.c | 696 + gnu/usr.bin/binutils/opcodes/mpw-config.in | 27 + gnu/usr.bin/binutils/opcodes/mpw-make.sed | 9 + gnu/usr.bin/binutils/opcodes/ns32k-dis.c | 846 ++ gnu/usr.bin/binutils/opcodes/ppc-dis.c | 238 + gnu/usr.bin/binutils/opcodes/ppc-opc.c | 2823 ++++ gnu/usr.bin/binutils/opcodes/sh-dis.c | 274 + gnu/usr.bin/binutils/opcodes/sh-opc.h | 387 + gnu/usr.bin/binutils/opcodes/sparc-dis.c | 856 ++ gnu/usr.bin/binutils/opcodes/sparc-opc.c | 1615 ++ gnu/usr.bin/binutils/opcodes/stamp-h | 1 + gnu/usr.bin/binutils/opcodes/sysdep.h | 38 + gnu/usr.bin/binutils/opcodes/w65-dis.c | 118 + gnu/usr.bin/binutils/opcodes/w65-opc.h | 547 + gnu/usr.bin/binutils/opcodes/z8k-dis.c | 571 + gnu/usr.bin/binutils/opcodes/z8k-opc.h | 4438 ++++++ gnu/usr.bin/binutils/opcodes/z8kgen.c | 1314 ++ gnu/usr.bin/binutils/texinfo/gpl.texinfo | 398 + gnu/usr.bin/binutils/texinfo/lgpl.texinfo | 548 + gnu/usr.bin/binutils/texinfo/tex3patch | 68 + gnu/usr.bin/binutils/texinfo/texinfo.tex | 4119 +++++ 1574 files changed, 543169 insertions(+) create mode 100644 gnu/usr.bin/binutils/COPYING create mode 100644 gnu/usr.bin/binutils/COPYING.LIB create mode 100644 gnu/usr.bin/binutils/Makefile.in create mode 100644 gnu/usr.bin/binutils/README create mode 100644 gnu/usr.bin/binutils/bfd/COPYING create mode 100644 gnu/usr.bin/binutils/bfd/ChangeLog create mode 100644 gnu/usr.bin/binutils/bfd/ChangeLog.1 create mode 100644 gnu/usr.bin/binutils/bfd/ChangeLog.2 create mode 100644 gnu/usr.bin/binutils/bfd/Makefile.in create mode 100644 gnu/usr.bin/binutils/bfd/PORTING create mode 100644 gnu/usr.bin/binutils/bfd/TODO create mode 100644 gnu/usr.bin/binutils/bfd/VERSION create mode 100644 gnu/usr.bin/binutils/bfd/acconfig.h create mode 100644 gnu/usr.bin/binutils/bfd/aclocal.m4 create mode 100644 gnu/usr.bin/binutils/bfd/aix386-core.c create mode 100644 gnu/usr.bin/binutils/bfd/aout-adobe.c create mode 100644 gnu/usr.bin/binutils/bfd/aout-arm.c create mode 100644 gnu/usr.bin/binutils/bfd/aout-encap.c create mode 100644 gnu/usr.bin/binutils/bfd/aout-ns32k.c create mode 100644 gnu/usr.bin/binutils/bfd/aout-target.h create mode 100644 gnu/usr.bin/binutils/bfd/aout0.c create mode 100644 gnu/usr.bin/binutils/bfd/aout32.c create mode 100644 gnu/usr.bin/binutils/bfd/aout64.c create mode 100644 gnu/usr.bin/binutils/bfd/aoutf1.h create mode 100644 gnu/usr.bin/binutils/bfd/aoutx.h create mode 100644 gnu/usr.bin/binutils/bfd/archive.c create mode 100644 gnu/usr.bin/binutils/bfd/archures.c create mode 100644 gnu/usr.bin/binutils/bfd/bfd-in.h create mode 100644 gnu/usr.bin/binutils/bfd/bfd-in2.h create mode 100644 gnu/usr.bin/binutils/bfd/bfd.c create mode 100644 gnu/usr.bin/binutils/bfd/binary.c create mode 100644 gnu/usr.bin/binutils/bfd/bout.c create mode 100644 gnu/usr.bin/binutils/bfd/cache.c create mode 100644 gnu/usr.bin/binutils/bfd/cf-i386lynx.c create mode 100644 gnu/usr.bin/binutils/bfd/cf-m68klynx.c create mode 100644 gnu/usr.bin/binutils/bfd/cf-sparclynx.c create mode 100644 gnu/usr.bin/binutils/bfd/cisco-core.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-a29k.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-alpha.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-apollo.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-arm.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-go32.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-h8300.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-h8500.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-i386.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-i860.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-i960.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-m68k.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-m88k.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-mips.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-pmac.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-ppc.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-rs6000.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-sh.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-sparc.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-u68k.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-w65.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-we32k.c create mode 100644 gnu/usr.bin/binutils/bfd/coff-z8k.c create mode 100644 gnu/usr.bin/binutils/bfd/coffcode.h create mode 100644 gnu/usr.bin/binutils/bfd/coffgen.c create mode 100644 gnu/usr.bin/binutils/bfd/cofflink.c create mode 100644 gnu/usr.bin/binutils/bfd/coffswap.h create mode 100644 gnu/usr.bin/binutils/bfd/config.bfd create mode 100644 gnu/usr.bin/binutils/bfd/config.in create mode 100644 gnu/usr.bin/binutils/bfd/configure create mode 100644 gnu/usr.bin/binutils/bfd/configure.bat create mode 100644 gnu/usr.bin/binutils/bfd/configure.host create mode 100644 gnu/usr.bin/binutils/bfd/configure.in create mode 100644 gnu/usr.bin/binutils/bfd/corefile.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-a29k.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-alpha.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-arm.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-h8300.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-h8500.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-hppa.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-i386.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-i860.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-i960.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-m68k.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-m88k.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-mips.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-ns32k.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-powerpc.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-rs6000.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-sh.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-sparc.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-vax.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-w65.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-we32k.c create mode 100644 gnu/usr.bin/binutils/bfd/cpu-z8k.c create mode 100644 gnu/usr.bin/binutils/bfd/demo64.c create mode 100644 gnu/usr.bin/binutils/bfd/dep-in.sed create mode 100644 gnu/usr.bin/binutils/bfd/doc/ChangeLog create mode 100644 gnu/usr.bin/binutils/bfd/doc/Makefile.in create mode 100644 gnu/usr.bin/binutils/bfd/doc/bfd.texinfo create mode 100644 gnu/usr.bin/binutils/bfd/doc/bfdsumm.texi create mode 100644 gnu/usr.bin/binutils/bfd/doc/chew.c create mode 100644 gnu/usr.bin/binutils/bfd/doc/doc.str create mode 100644 gnu/usr.bin/binutils/bfd/doc/proto.str create mode 100644 gnu/usr.bin/binutils/bfd/ecoff.c create mode 100644 gnu/usr.bin/binutils/bfd/ecofflink.c create mode 100644 gnu/usr.bin/binutils/bfd/ecoffswap.h create mode 100644 gnu/usr.bin/binutils/bfd/elf-bfd.h create mode 100644 gnu/usr.bin/binutils/bfd/elf.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32-gen.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32-hppa.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32-hppa.h create mode 100644 gnu/usr.bin/binutils/bfd/elf32-i386.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32-i860.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32-m68k.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32-m88k.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32-mips.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32-ppc.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32-sparc.c create mode 100644 gnu/usr.bin/binutils/bfd/elf32.c create mode 100644 gnu/usr.bin/binutils/bfd/elf64-gen.c create mode 100644 gnu/usr.bin/binutils/bfd/elf64-sparc.c create mode 100644 gnu/usr.bin/binutils/bfd/elf64.c create mode 100644 gnu/usr.bin/binutils/bfd/elfcode.h create mode 100644 gnu/usr.bin/binutils/bfd/elfcore.h create mode 100644 gnu/usr.bin/binutils/bfd/elflink.c create mode 100644 gnu/usr.bin/binutils/bfd/elflink.h create mode 100644 gnu/usr.bin/binutils/bfd/elfxx-target.h create mode 100644 gnu/usr.bin/binutils/bfd/filemode.c create mode 100644 gnu/usr.bin/binutils/bfd/format.c create mode 100644 gnu/usr.bin/binutils/bfd/gen-aout.c create mode 100644 gnu/usr.bin/binutils/bfd/genlink.h create mode 100644 gnu/usr.bin/binutils/bfd/hash.c create mode 100644 gnu/usr.bin/binutils/bfd/host-aout.c create mode 100644 gnu/usr.bin/binutils/bfd/hosts/alphalinux.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/decstation.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/delta68.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/dpx2.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/hp300bsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/i386bsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/i386linux.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/i386mach3.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/i386nbsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/i386sco.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/i860mach3.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/m68knbsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/m88kmach3.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/mipsbsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/mipsmach3.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/mipsnbsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/nbsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/news-mips.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/news.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/ns32knbsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/pc532mach.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/riscos.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/sparcnbsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/symmetry.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/tahoe.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/vaxbsd.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/vaxult.h create mode 100644 gnu/usr.bin/binutils/bfd/hosts/vaxult2.h create mode 100644 gnu/usr.bin/binutils/bfd/hp300bsd.c create mode 100644 gnu/usr.bin/binutils/bfd/hp300hpux.c create mode 100644 gnu/usr.bin/binutils/bfd/hppa_stubs.h create mode 100644 gnu/usr.bin/binutils/bfd/hppabsd-core.c create mode 100644 gnu/usr.bin/binutils/bfd/hpux-core.c create mode 100644 gnu/usr.bin/binutils/bfd/i386aout.c create mode 100644 gnu/usr.bin/binutils/bfd/i386bsd.c create mode 100644 gnu/usr.bin/binutils/bfd/i386dynix.c create mode 100644 gnu/usr.bin/binutils/bfd/i386linux.c create mode 100644 gnu/usr.bin/binutils/bfd/i386lynx.c create mode 100644 gnu/usr.bin/binutils/bfd/i386mach3.c create mode 100644 gnu/usr.bin/binutils/bfd/i386msdos.c create mode 100644 gnu/usr.bin/binutils/bfd/i386netbsd.c create mode 100644 gnu/usr.bin/binutils/bfd/i386os9k.c create mode 100644 gnu/usr.bin/binutils/bfd/ieee.c create mode 100644 gnu/usr.bin/binutils/bfd/init.c create mode 100644 gnu/usr.bin/binutils/bfd/irix-core.c create mode 100644 gnu/usr.bin/binutils/bfd/libaout.h create mode 100644 gnu/usr.bin/binutils/bfd/libbfd-in.h create mode 100644 gnu/usr.bin/binutils/bfd/libbfd.c create mode 100644 gnu/usr.bin/binutils/bfd/libbfd.h create mode 100644 gnu/usr.bin/binutils/bfd/libcoff-in.h create mode 100644 gnu/usr.bin/binutils/bfd/libcoff.h create mode 100644 gnu/usr.bin/binutils/bfd/libecoff.h create mode 100644 gnu/usr.bin/binutils/bfd/libhppa.h create mode 100644 gnu/usr.bin/binutils/bfd/libieee.h create mode 100644 gnu/usr.bin/binutils/bfd/libnlm.h create mode 100644 gnu/usr.bin/binutils/bfd/liboasys.h create mode 100644 gnu/usr.bin/binutils/bfd/linker.c create mode 100644 gnu/usr.bin/binutils/bfd/lynx-core.c create mode 100644 gnu/usr.bin/binutils/bfd/m68k4knetbsd.c create mode 100644 gnu/usr.bin/binutils/bfd/m68klynx.c create mode 100644 gnu/usr.bin/binutils/bfd/m68knetbsd.c create mode 100644 gnu/usr.bin/binutils/bfd/m88kmach3.c create mode 100644 gnu/usr.bin/binutils/bfd/makefile.dos create mode 100644 gnu/usr.bin/binutils/bfd/mipsbsd.c create mode 100644 gnu/usr.bin/binutils/bfd/mpw-config.in create mode 100644 gnu/usr.bin/binutils/bfd/mpw-make.sed create mode 100644 gnu/usr.bin/binutils/bfd/netbsd.h create mode 100644 gnu/usr.bin/binutils/bfd/newsos3.c create mode 100644 gnu/usr.bin/binutils/bfd/nlm-target.h create mode 100644 gnu/usr.bin/binutils/bfd/nlm.c create mode 100644 gnu/usr.bin/binutils/bfd/nlm32-alpha.c create mode 100644 gnu/usr.bin/binutils/bfd/nlm32-i386.c create mode 100644 gnu/usr.bin/binutils/bfd/nlm32-ppc.c create mode 100644 gnu/usr.bin/binutils/bfd/nlm32-sparc.c create mode 100644 gnu/usr.bin/binutils/bfd/nlm32.c create mode 100644 gnu/usr.bin/binutils/bfd/nlm64.c create mode 100644 gnu/usr.bin/binutils/bfd/nlmcode.h create mode 100644 gnu/usr.bin/binutils/bfd/nlmswap.h create mode 100644 gnu/usr.bin/binutils/bfd/ns32knetbsd.c create mode 100644 gnu/usr.bin/binutils/bfd/oasys.c create mode 100644 gnu/usr.bin/binutils/bfd/opncls.c create mode 100644 gnu/usr.bin/binutils/bfd/osf-core.c create mode 100644 gnu/usr.bin/binutils/bfd/pc532-mach.c create mode 100644 gnu/usr.bin/binutils/bfd/pe-arm.c create mode 100644 gnu/usr.bin/binutils/bfd/pe-i386.c create mode 100644 gnu/usr.bin/binutils/bfd/pe-ppc.c create mode 100644 gnu/usr.bin/binutils/bfd/pei-arm.c create mode 100644 gnu/usr.bin/binutils/bfd/pei-i386.c create mode 100644 gnu/usr.bin/binutils/bfd/pei-ppc.c create mode 100644 gnu/usr.bin/binutils/bfd/peicode.h create mode 100644 gnu/usr.bin/binutils/bfd/ptrace-core.c create mode 100644 gnu/usr.bin/binutils/bfd/reloc.c create mode 100644 gnu/usr.bin/binutils/bfd/reloc16.c create mode 100644 gnu/usr.bin/binutils/bfd/riscix.c create mode 100644 gnu/usr.bin/binutils/bfd/rs6000-core.c create mode 100644 gnu/usr.bin/binutils/bfd/section.c create mode 100644 gnu/usr.bin/binutils/bfd/som.c create mode 100644 gnu/usr.bin/binutils/bfd/som.h create mode 100644 gnu/usr.bin/binutils/bfd/sparclynx.c create mode 100644 gnu/usr.bin/binutils/bfd/sparcnetbsd.c create mode 100644 gnu/usr.bin/binutils/bfd/srec.c create mode 100644 gnu/usr.bin/binutils/bfd/stab-syms.c create mode 100644 gnu/usr.bin/binutils/bfd/sunos.c create mode 100644 gnu/usr.bin/binutils/bfd/syms.c create mode 100644 gnu/usr.bin/binutils/bfd/sysdep.h create mode 100644 gnu/usr.bin/binutils/bfd/targets.c create mode 100644 gnu/usr.bin/binutils/bfd/tekhex.c create mode 100644 gnu/usr.bin/binutils/bfd/trad-core.c create mode 100644 gnu/usr.bin/binutils/bfd/versados.c create mode 100644 gnu/usr.bin/binutils/bfd/xcofflink.c create mode 100644 gnu/usr.bin/binutils/binutils/ChangeLog create mode 100644 gnu/usr.bin/binutils/binutils/Makefile.in create mode 100644 gnu/usr.bin/binutils/binutils/NEWS create mode 100644 gnu/usr.bin/binutils/binutils/README create mode 100644 gnu/usr.bin/binutils/binutils/TODO create mode 100644 gnu/usr.bin/binutils/binutils/acconfig.h create mode 100644 gnu/usr.bin/binutils/binutils/aclocal.m4 create mode 100644 gnu/usr.bin/binutils/binutils/alloca.c create mode 100644 gnu/usr.bin/binutils/binutils/ar.1 create mode 100644 gnu/usr.bin/binutils/binutils/ar.c create mode 100644 gnu/usr.bin/binutils/binutils/arlex.c create mode 100644 gnu/usr.bin/binutils/binutils/arlex.l create mode 100644 gnu/usr.bin/binutils/binutils/arparse.c create mode 100644 gnu/usr.bin/binutils/binutils/arparse.h create mode 100644 gnu/usr.bin/binutils/binutils/arparse.y create mode 100644 gnu/usr.bin/binutils/binutils/arsup.c create mode 100644 gnu/usr.bin/binutils/binutils/arsup.h create mode 100644 gnu/usr.bin/binutils/binutils/binutils.info create mode 100644 gnu/usr.bin/binutils/binutils/binutils.texi create mode 100644 gnu/usr.bin/binutils/binutils/bucomm.c create mode 100644 gnu/usr.bin/binutils/binutils/bucomm.h create mode 100644 gnu/usr.bin/binutils/binutils/coffdump.c create mode 100644 gnu/usr.bin/binutils/binutils/coffgrok.c create mode 100644 gnu/usr.bin/binutils/binutils/coffgrok.h create mode 100644 gnu/usr.bin/binutils/binutils/config.in create mode 100644 gnu/usr.bin/binutils/binutils/config.texi create mode 100644 gnu/usr.bin/binutils/binutils/configure create mode 100644 gnu/usr.bin/binutils/binutils/configure.bat create mode 100644 gnu/usr.bin/binutils/binutils/configure.in create mode 100644 gnu/usr.bin/binutils/binutils/cxxfilt.man create mode 100644 gnu/usr.bin/binutils/binutils/deflex.l create mode 100644 gnu/usr.bin/binutils/binutils/defparse.y create mode 100644 gnu/usr.bin/binutils/binutils/dlltool.c create mode 100644 gnu/usr.bin/binutils/binutils/filemode.c create mode 100644 gnu/usr.bin/binutils/binutils/gmalloc.c create mode 100644 gnu/usr.bin/binutils/binutils/is-ranlib.c create mode 100644 gnu/usr.bin/binutils/binutils/is-strip.c create mode 100644 gnu/usr.bin/binutils/binutils/mac-binutils.r create mode 100644 gnu/usr.bin/binutils/binutils/maybe-ranlib.c create mode 100644 gnu/usr.bin/binutils/binutils/maybe-strip.c create mode 100644 gnu/usr.bin/binutils/binutils/mpw-config.in create mode 100644 gnu/usr.bin/binutils/binutils/mpw-make.sed create mode 100644 gnu/usr.bin/binutils/binutils/nlmconv.1 create mode 100644 gnu/usr.bin/binutils/binutils/nlmconv.c create mode 100644 gnu/usr.bin/binutils/binutils/nlmconv.h create mode 100644 gnu/usr.bin/binutils/binutils/nlmheader.c create mode 100644 gnu/usr.bin/binutils/binutils/nlmheader.y create mode 100644 gnu/usr.bin/binutils/binutils/nm.1 create mode 100644 gnu/usr.bin/binutils/binutils/nm.c create mode 100644 gnu/usr.bin/binutils/binutils/not-ranlib.c create mode 100644 gnu/usr.bin/binutils/binutils/not-strip.c create mode 100644 gnu/usr.bin/binutils/binutils/objcopy.1 create mode 100644 gnu/usr.bin/binutils/binutils/objcopy.c create mode 100644 gnu/usr.bin/binutils/binutils/objdump.1 create mode 100644 gnu/usr.bin/binutils/binutils/objdump.c create mode 100644 gnu/usr.bin/binutils/binutils/ranlib.1 create mode 100644 gnu/usr.bin/binutils/binutils/ranlib.sh create mode 100644 gnu/usr.bin/binutils/binutils/sanity.sh create mode 100644 gnu/usr.bin/binutils/binutils/size.1 create mode 100644 gnu/usr.bin/binutils/binutils/size.c create mode 100644 gnu/usr.bin/binutils/binutils/srconv.c create mode 100644 gnu/usr.bin/binutils/binutils/strings.1 create mode 100644 gnu/usr.bin/binutils/binutils/strings.c create mode 100644 gnu/usr.bin/binutils/binutils/strip.1 create mode 100644 gnu/usr.bin/binutils/binutils/sysdump.c create mode 100644 gnu/usr.bin/binutils/binutils/sysinfo.c create mode 100644 gnu/usr.bin/binutils/binutils/sysinfo.h create mode 100644 gnu/usr.bin/binutils/binutils/sysinfo.y create mode 100644 gnu/usr.bin/binutils/binutils/syslex.c create mode 100644 gnu/usr.bin/binutils/binutils/syslex.l create mode 100644 gnu/usr.bin/binutils/binutils/sysroff.info create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/ChangeLog create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/binutils-all/ar.exp create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/binutils-all/bintest.s create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/binutils-all/hppa/addendbug.s create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/binutils-all/hppa/objdump.exp create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/binutils-all/nm.exp create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/binutils-all/objcopy.exp create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/binutils-all/objdump.exp create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/binutils-all/size.exp create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/binutils-all/testprog.c create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/config/default.exp create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/config/hppa.sed create mode 100644 gnu/usr.bin/binutils/binutils/testsuite/lib/utils-lib.exp create mode 100644 gnu/usr.bin/binutils/binutils/version.c create mode 100644 gnu/usr.bin/binutils/config-ml.in create mode 100644 gnu/usr.bin/binutils/config.guess create mode 100644 gnu/usr.bin/binutils/config.sub create mode 100644 gnu/usr.bin/binutils/config/ChangeLog create mode 100644 gnu/usr.bin/binutils/config/mh-a68bsd create mode 100644 gnu/usr.bin/binutils/config/mh-aix386 create mode 100644 gnu/usr.bin/binutils/config/mh-apollo68 create mode 100644 gnu/usr.bin/binutils/config/mh-cxux create mode 100644 gnu/usr.bin/binutils/config/mh-decstation create mode 100644 gnu/usr.bin/binutils/config/mh-delta88 create mode 100644 gnu/usr.bin/binutils/config/mh-dgux create mode 100644 gnu/usr.bin/binutils/config/mh-go32 create mode 100644 gnu/usr.bin/binutils/config/mh-hp300 create mode 100644 gnu/usr.bin/binutils/config/mh-hpux create mode 100644 gnu/usr.bin/binutils/config/mh-hpux8 create mode 100644 gnu/usr.bin/binutils/config/mh-i386win32 create mode 100644 gnu/usr.bin/binutils/config/mh-irix4 create mode 100644 gnu/usr.bin/binutils/config/mh-irix5 create mode 100644 gnu/usr.bin/binutils/config/mh-linux create mode 100644 gnu/usr.bin/binutils/config/mh-lynxos create mode 100644 gnu/usr.bin/binutils/config/mh-lynxrs6k create mode 100644 gnu/usr.bin/binutils/config/mh-ncr3000 create mode 100644 gnu/usr.bin/binutils/config/mh-ncrsvr43 create mode 100644 gnu/usr.bin/binutils/config/mh-papic create mode 100644 gnu/usr.bin/binutils/config/mh-riscos create mode 100644 gnu/usr.bin/binutils/config/mh-sco create mode 100644 gnu/usr.bin/binutils/config/mh-solaris create mode 100644 gnu/usr.bin/binutils/config/mh-sparcpic create mode 100644 gnu/usr.bin/binutils/config/mh-sun3 create mode 100644 gnu/usr.bin/binutils/config/mh-sysv create mode 100644 gnu/usr.bin/binutils/config/mh-sysv4 create mode 100644 gnu/usr.bin/binutils/config/mh-vaxult2 create mode 100644 gnu/usr.bin/binutils/config/mh-x86pic create mode 100644 gnu/usr.bin/binutils/config/mpw-mh-mpw create mode 100644 gnu/usr.bin/binutils/config/mt-netware create mode 100644 gnu/usr.bin/binutils/config/mt-papic create mode 100644 gnu/usr.bin/binutils/config/mt-sparcpic create mode 100644 gnu/usr.bin/binutils/config/mt-v810 create mode 100644 gnu/usr.bin/binutils/config/mt-x86pic create mode 100644 gnu/usr.bin/binutils/configure create mode 100644 gnu/usr.bin/binutils/configure.bat create mode 100644 gnu/usr.bin/binutils/configure.in create mode 100644 gnu/usr.bin/binutils/etc/Makefile.in create mode 100644 gnu/usr.bin/binutils/etc/cfg-paper.info create mode 100644 gnu/usr.bin/binutils/etc/cfg-paper.texi create mode 100644 gnu/usr.bin/binutils/etc/configure.in create mode 100644 gnu/usr.bin/binutils/etc/configure.info create mode 100644 gnu/usr.bin/binutils/etc/configure.info-1 create mode 100644 gnu/usr.bin/binutils/etc/configure.info-2 create mode 100644 gnu/usr.bin/binutils/etc/configure.man create mode 100644 gnu/usr.bin/binutils/etc/configure.texi create mode 100644 gnu/usr.bin/binutils/etc/make-stds.texi create mode 100644 gnu/usr.bin/binutils/etc/standards.info create mode 100644 gnu/usr.bin/binutils/etc/standards.info-1 create mode 100644 gnu/usr.bin/binutils/etc/standards.info-2 create mode 100644 gnu/usr.bin/binutils/etc/standards.texi create mode 100644 gnu/usr.bin/binutils/gas/CONTRIBUTORS create mode 100644 gnu/usr.bin/binutils/gas/COPYING create mode 100644 gnu/usr.bin/binutils/gas/ChangeLog create mode 100644 gnu/usr.bin/binutils/gas/ChangeLog.1 create mode 100644 gnu/usr.bin/binutils/gas/Makefile.in create mode 100644 gnu/usr.bin/binutils/gas/NEWS create mode 100644 gnu/usr.bin/binutils/gas/NOTES create mode 100644 gnu/usr.bin/binutils/gas/NOTES.config create mode 100644 gnu/usr.bin/binutils/gas/README create mode 100644 gnu/usr.bin/binutils/gas/README-quirks create mode 100644 gnu/usr.bin/binutils/gas/README-vms create mode 100644 gnu/usr.bin/binutils/gas/README.coff create mode 100644 gnu/usr.bin/binutils/gas/README.rich create mode 100644 gnu/usr.bin/binutils/gas/acconfig.h create mode 100644 gnu/usr.bin/binutils/gas/aclocal.m4 create mode 100644 gnu/usr.bin/binutils/gas/app.c create mode 100644 gnu/usr.bin/binutils/gas/as.c create mode 100644 gnu/usr.bin/binutils/gas/as.h create mode 100644 gnu/usr.bin/binutils/gas/atof-generic.c create mode 100644 gnu/usr.bin/binutils/gas/bignum-copy.c create mode 100644 gnu/usr.bin/binutils/gas/bignum.h create mode 100644 gnu/usr.bin/binutils/gas/bit_fix.h create mode 100644 gnu/usr.bin/binutils/gas/cond.c create mode 100644 gnu/usr.bin/binutils/gas/conf.in create mode 100644 gnu/usr.bin/binutils/gas/config-gas.com create mode 100644 gnu/usr.bin/binutils/gas/config/alpha-opcode.h create mode 100644 gnu/usr.bin/binutils/gas/config/aout_gnu.h create mode 100644 gnu/usr.bin/binutils/gas/config/arm-big.mt create mode 100644 gnu/usr.bin/binutils/gas/config/arm-lit.mt create mode 100644 gnu/usr.bin/binutils/gas/config/atof-ieee.c create mode 100644 gnu/usr.bin/binutils/gas/config/atof-tahoe.c create mode 100644 gnu/usr.bin/binutils/gas/config/atof-vax.c create mode 100644 gnu/usr.bin/binutils/gas/config/e-mipsecoff.c create mode 100644 gnu/usr.bin/binutils/gas/config/e-mipself.c create mode 100644 gnu/usr.bin/binutils/gas/config/go32.cfg create mode 100644 gnu/usr.bin/binutils/gas/config/i386coff.mt create mode 100644 gnu/usr.bin/binutils/gas/config/m68k-parse.h create mode 100644 gnu/usr.bin/binutils/gas/config/m68k-parse.y create mode 100644 gnu/usr.bin/binutils/gas/config/m68kcoff.mt create mode 100644 gnu/usr.bin/binutils/gas/config/m88k-opcode.h create mode 100644 gnu/usr.bin/binutils/gas/config/m88kcoff.mt create mode 100644 gnu/usr.bin/binutils/gas/config/mips-big.mt create mode 100644 gnu/usr.bin/binutils/gas/config/mips-lit.mt create mode 100644 gnu/usr.bin/binutils/gas/config/obj-aout.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-aout.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-bout.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-bout.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-coff.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-coff.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-ecoff.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-ecoff.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-elf.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-elf.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-generic.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-generic.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-hp300.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-hp300.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-ieee.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-ieee.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-multi.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-multi.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-som.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-som.h create mode 100644 gnu/usr.bin/binutils/gas/config/obj-vms.c create mode 100644 gnu/usr.bin/binutils/gas/config/obj-vms.h create mode 100644 gnu/usr.bin/binutils/gas/config/ppc-big.mt create mode 100644 gnu/usr.bin/binutils/gas/config/ppc-lit.mt create mode 100644 gnu/usr.bin/binutils/gas/config/tc-a29k.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-a29k.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-alpha.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-alpha.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-arm.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-arm.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-generic.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-generic.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-h8300.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-h8300.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-h8500.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-h8500.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-hppa.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-hppa.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-i386.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-i386.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-i860.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-i860.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-i960.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-i960.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-m68851.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-m68k.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-m68k.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-m88k.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-m88k.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-mips.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-mips.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-ns32k.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-ns32k.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-ppc.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-ppc.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-sh.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-sh.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-sparc.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-sparc.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-tahoe.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-tahoe.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-vax.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-vax.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-w65.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-w65.h create mode 100644 gnu/usr.bin/binutils/gas/config/tc-z8k.c create mode 100644 gnu/usr.bin/binutils/gas/config/tc-z8k.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-386bsd.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-delta.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-delta88.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-dpx2.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-generic.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-go32.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-hp300.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-hppa.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-i386aix.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-ic960.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-linux.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-lynx.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-mach.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-macos.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-multi.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-nbsd.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-nbsd532.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-pc532mach.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-pe.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-ppcnw.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-sco386.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-sun3.h create mode 100644 gnu/usr.bin/binutils/gas/config/te-sysv32.h create mode 100644 gnu/usr.bin/binutils/gas/config/vax-inst.h create mode 100644 gnu/usr.bin/binutils/gas/config/vms-conf.h create mode 100644 gnu/usr.bin/binutils/gas/configure create mode 100644 gnu/usr.bin/binutils/gas/configure.bat create mode 100644 gnu/usr.bin/binutils/gas/configure.in create mode 100644 gnu/usr.bin/binutils/gas/debug.c create mode 100644 gnu/usr.bin/binutils/gas/doc/Makefile.in create mode 100644 gnu/usr.bin/binutils/gas/doc/all.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/as.1 create mode 100644 gnu/usr.bin/binutils/gas/doc/as.info create mode 100644 gnu/usr.bin/binutils/gas/doc/as.info-1 create mode 100644 gnu/usr.bin/binutils/gas/doc/as.info-2 create mode 100644 gnu/usr.bin/binutils/gas/doc/as.info-3 create mode 100644 gnu/usr.bin/binutils/gas/doc/as.info-4 create mode 100644 gnu/usr.bin/binutils/gas/doc/as.info-5 create mode 100644 gnu/usr.bin/binutils/gas/doc/as.info-6 create mode 100644 gnu/usr.bin/binutils/gas/doc/as.texinfo create mode 100644 gnu/usr.bin/binutils/gas/doc/c-a29k.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-h8300.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-h8500.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-hppa.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-i386.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-i960.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-m68k.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-mips.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-ns32k.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-sh.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-sparc.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-vax.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/c-z8k.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/gasp.info create mode 100644 gnu/usr.bin/binutils/gas/doc/gasp.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/h8.texi create mode 100644 gnu/usr.bin/binutils/gas/doc/internals.texi create mode 100644 gnu/usr.bin/binutils/gas/ecoff.c create mode 100644 gnu/usr.bin/binutils/gas/ecoff.h create mode 100644 gnu/usr.bin/binutils/gas/emul-target.h create mode 100644 gnu/usr.bin/binutils/gas/emul.h create mode 100644 gnu/usr.bin/binutils/gas/expr.c create mode 100644 gnu/usr.bin/binutils/gas/expr.h create mode 100644 gnu/usr.bin/binutils/gas/flonum-copy.c create mode 100644 gnu/usr.bin/binutils/gas/flonum-konst.c create mode 100644 gnu/usr.bin/binutils/gas/flonum-mult.c create mode 100644 gnu/usr.bin/binutils/gas/flonum.h create mode 100644 gnu/usr.bin/binutils/gas/frags.c create mode 100644 gnu/usr.bin/binutils/gas/frags.h create mode 100644 gnu/usr.bin/binutils/gas/gasp.c create mode 100644 gnu/usr.bin/binutils/gas/gdbinit.in create mode 100644 gnu/usr.bin/binutils/gas/hash.c create mode 100644 gnu/usr.bin/binutils/gas/hash.h create mode 100644 gnu/usr.bin/binutils/gas/input-file.c create mode 100644 gnu/usr.bin/binutils/gas/input-file.h create mode 100644 gnu/usr.bin/binutils/gas/input-scrub.c create mode 100644 gnu/usr.bin/binutils/gas/link.cmd create mode 100644 gnu/usr.bin/binutils/gas/listing.c create mode 100644 gnu/usr.bin/binutils/gas/listing.h create mode 100644 gnu/usr.bin/binutils/gas/literal.c create mode 100644 gnu/usr.bin/binutils/gas/m68k-parse.c create mode 100644 gnu/usr.bin/binutils/gas/mac-as.r create mode 100644 gnu/usr.bin/binutils/gas/macro.c create mode 100644 gnu/usr.bin/binutils/gas/macro.h create mode 100644 gnu/usr.bin/binutils/gas/make-gas.com create mode 100644 gnu/usr.bin/binutils/gas/messages.c create mode 100644 gnu/usr.bin/binutils/gas/mpw-config.in create mode 100644 gnu/usr.bin/binutils/gas/mpw-make.sed create mode 100644 gnu/usr.bin/binutils/gas/obj.h create mode 100644 gnu/usr.bin/binutils/gas/output-file.c create mode 100644 gnu/usr.bin/binutils/gas/output-file.h create mode 100644 gnu/usr.bin/binutils/gas/read.c create mode 100644 gnu/usr.bin/binutils/gas/read.h create mode 100644 gnu/usr.bin/binutils/gas/sb.c create mode 100644 gnu/usr.bin/binutils/gas/sb.h create mode 100644 gnu/usr.bin/binutils/gas/stabs.c create mode 100644 gnu/usr.bin/binutils/gas/struc-symbol.h create mode 100644 gnu/usr.bin/binutils/gas/subsegs.c create mode 100644 gnu/usr.bin/binutils/gas/subsegs.h create mode 100644 gnu/usr.bin/binutils/gas/symbols.c create mode 100644 gnu/usr.bin/binutils/gas/symbols.h create mode 100644 gnu/usr.bin/binutils/gas/tc.h create mode 100644 gnu/usr.bin/binutils/gas/testsuite/ChangeLog create mode 100644 gnu/usr.bin/binutils/gas/testsuite/config/default.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/all/comment.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/all/diff1.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/all/float.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/all/gas.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/all/p1480.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/all/p2425.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/all/struct.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/all/struct.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/all/x930509.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/alpha/fp.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/alpha/fp.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/alpha/fp.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/arm/arm.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/arm/arm3.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/arm/arm6.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/arm/arm7dm.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/arm/copro.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/arm/float.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/arm/inst.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/arm/le-fpconst.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/arm/le-fpconst.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/h8300/cmpsi2.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/h8300/ffxx1.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/h8300/ffxx1.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/h8300/h8300.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/README create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/add.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/addi.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/basic.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/branch.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/comclr.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/copr.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/coprmem.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/dcor.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/deposit.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/ds.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/extract.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/fmem.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/fmemLRbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/fp_comp.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/fp_conv.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/fp_fcmp.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/fp_misc.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/imem.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/immed.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/logical.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/purge.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/sh1add.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/sh2add.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/sh3add.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/shift.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/special.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/spop.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/sub.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/subi.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/system.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/unit.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/weird.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/align1.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/align2.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/appbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/badfmpyadd.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/block1.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/block2.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/calldatabug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/callinfobug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/defbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/entrybug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/exportbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/exprbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/fixup7bug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/global.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/labelbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/linesepbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/lselbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/nosubspace.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/parse.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/procbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/regpopbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/spacebug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/ssbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/stdreg.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/stringer.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/undefbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/versionbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/parse/xmpyubug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/applybug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/blebug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/blebug2.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/blebug3.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/exitbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/fixupbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/funcrelocbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/labelopbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/longcall.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/picreloc.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/plabelbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/r_no_reloc.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/reduce.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/reduce2.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/reduce3.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/reloc.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/roundmode.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/reloc/selectorbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/align3.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/align4.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/brlenbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/common.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/fragbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/globalbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/importbug.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/labeldiffs.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/locallabel.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/ss_align.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/hppa/unsorted/unsorted.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/i386/all.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/i386/inout.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/i386/pushw.l create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/i386/pushw.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/ieee-fp/x930509a.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/ieee-fp/x930509a.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k-coff/gas.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k-coff/p2389.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k-coff/p2389a.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k-coff/p2430.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k-coff/p2430a.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k-coff/t1.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/all.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/bitfield.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/bitfield.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/cas.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/cas.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/disperr.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/fmoveml.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/fmoveml.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/link.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/link.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/op68000.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/operands.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/operands.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/p2410.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/p2663.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/pic1.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/schwab.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/schwab.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/m68k/t2.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/err.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/irp.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/irp.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/macros.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/rept.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/rept.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/test1.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/test1.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/test2.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/test2.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/test3.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/macros/test3.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/abs.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/abs.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/add.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/add.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/and.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/and.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/beq.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/beq.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/bge.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/bge.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/bgeu.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/bgeu.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/blt.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/blt.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/bltu.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/bltu.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/div.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/div.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/jal-empic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/jal-svr4pic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/jal-svr4pic.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/jal.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/jal.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/la-empic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/la-empic.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/la-svr4pic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/la.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/la.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/lb-empic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/lb-pic.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/lb-svr4pic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/lb.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/lb.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ld-empic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ld-pic.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ld-svr4pic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ld.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ld.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/li.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/li.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/lif-empic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/lif-svr4pic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/lifloat.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/lifloat.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips4.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips4.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/mul.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/mul.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/rol.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/rol.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/sb.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/sb.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/trunc.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/trunc.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/uld.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/uld.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ulh-empic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ulh-pic.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ulh-svr4pic.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ulh.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ulh.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ulw.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ulw.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/usd.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/usd.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ush.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/ush.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/usw.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mips/usw.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/char.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/char.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/comment.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/comment.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/common.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/common.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/constants.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/constants.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/empty.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/equ.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/equ.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/expr.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/expr.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/float.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/float.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/for.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/for.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/if.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/if.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/label.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/label.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/mri.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/repeat.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/repeat.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/while.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/mri/while.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc-solaris/addend.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc-solaris/addend.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc-solaris/gas.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc-solaris/sol-cc.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc-solaris/sol-gcc.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/asi.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/asi.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/membar.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/membar.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/prefetch.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/prefetch.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/rdpr.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/rdpr.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/sparc.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/synth64.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/synth64.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/wrpr.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sparc/wrpr.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sun4/addend.d create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sun4/addend.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/sun4/addend.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/template create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/vax/quad.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gas/vax/quad.s create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/INC1.H create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/INC2.H create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/assign.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/assign.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/assign.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/condass.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/condass.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/condass.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/crash.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/crash.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/crash.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/crash1.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/crash1.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/crash1.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/crash2.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/crash2.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/crash2.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/data.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/data.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/data.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/exp.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/exp.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/exp.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/gasp.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/include.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/include.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/include.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/listing.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/listing.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/listing.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/macro.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/macro.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/macro.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mdouble.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mdouble.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mdouble.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/embed.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/embed.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/exists.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/exists.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/irp.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/irp.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/irpc.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/irpc.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/macro.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/macro.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/narg.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/narg.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/rept.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/mri/rept.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl1.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl1.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl1.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl2.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl2.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl2.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl3.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl3.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl3.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl4.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl4.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl4.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl5.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl5.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl5.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl6.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl6.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl6.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl7.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl7.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl7.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl8.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl8.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pl8.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pr7583.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pr7583.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/pr7583.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reg.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reg.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reg.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/rep.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/rep.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/rep.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/repeat.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/repeat.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/repeat.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr1.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr1.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr1.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr2.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr2.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr2.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr3.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr3.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/reperr3.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/sdata.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/sdata.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/sdata.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/sfunc.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/sfunc.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/sfunc.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/t1.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/t1.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/t1.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/t2.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/t2.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/t2.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/t3.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/t3.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/t3.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/while.asm create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/while.err create mode 100644 gnu/usr.bin/binutils/gas/testsuite/gasp/while.out create mode 100644 gnu/usr.bin/binutils/gas/testsuite/lib/doboth create mode 100644 gnu/usr.bin/binutils/gas/testsuite/lib/doobjcmp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/lib/dostriptest create mode 100644 gnu/usr.bin/binutils/gas/testsuite/lib/dotest create mode 100644 gnu/usr.bin/binutils/gas/testsuite/lib/dounsreloc create mode 100644 gnu/usr.bin/binutils/gas/testsuite/lib/dounssym create mode 100644 gnu/usr.bin/binutils/gas/testsuite/lib/gas-defs.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/lib/gas-dg.exp create mode 100644 gnu/usr.bin/binutils/gas/testsuite/lib/run create mode 100644 gnu/usr.bin/binutils/gas/vmsconf.sh create mode 100644 gnu/usr.bin/binutils/gas/write.c create mode 100644 gnu/usr.bin/binutils/gas/write.h create mode 100644 gnu/usr.bin/binutils/gas/xmalloc.c create mode 100644 gnu/usr.bin/binutils/gprof/.gdbinit create mode 100644 gnu/usr.bin/binutils/gprof/ChangeLog create mode 100644 gnu/usr.bin/binutils/gprof/Makefile.in create mode 100644 gnu/usr.bin/binutils/gprof/NOTES create mode 100644 gnu/usr.bin/binutils/gprof/TEST create mode 100644 gnu/usr.bin/binutils/gprof/TODO create mode 100644 gnu/usr.bin/binutils/gprof/__bb_exit_func.c create mode 100644 gnu/usr.bin/binutils/gprof/alpha.c create mode 100644 gnu/usr.bin/binutils/gprof/alpha.h create mode 100644 gnu/usr.bin/binutils/gprof/basic_blocks.c create mode 100644 gnu/usr.bin/binutils/gprof/basic_blocks.h create mode 100644 gnu/usr.bin/binutils/gprof/bsd_callg_bl.c create mode 100644 gnu/usr.bin/binutils/gprof/bsd_callg_bl.m create mode 100644 gnu/usr.bin/binutils/gprof/call_graph.c create mode 100644 gnu/usr.bin/binutils/gprof/call_graph.h create mode 100644 gnu/usr.bin/binutils/gprof/cg_arcs.c create mode 100644 gnu/usr.bin/binutils/gprof/cg_arcs.h create mode 100644 gnu/usr.bin/binutils/gprof/cg_dfn.c create mode 100644 gnu/usr.bin/binutils/gprof/cg_dfn.h create mode 100644 gnu/usr.bin/binutils/gprof/cg_print.c create mode 100644 gnu/usr.bin/binutils/gprof/cg_print.h create mode 100644 gnu/usr.bin/binutils/gprof/configure create mode 100644 gnu/usr.bin/binutils/gprof/configure.bat create mode 100644 gnu/usr.bin/binutils/gprof/configure.in create mode 100644 gnu/usr.bin/binutils/gprof/core.c create mode 100644 gnu/usr.bin/binutils/gprof/core.h create mode 100644 gnu/usr.bin/binutils/gprof/dummy.c create mode 100644 gnu/usr.bin/binutils/gprof/dummy.h create mode 100644 gnu/usr.bin/binutils/gprof/flat_bl.c create mode 100644 gnu/usr.bin/binutils/gprof/flat_bl.m create mode 100644 gnu/usr.bin/binutils/gprof/fsf_callg_bl.c create mode 100644 gnu/usr.bin/binutils/gprof/fsf_callg_bl.m create mode 100644 gnu/usr.bin/binutils/gprof/gen-c-prog.awk create mode 100644 gnu/usr.bin/binutils/gprof/gmon.h create mode 100644 gnu/usr.bin/binutils/gprof/gmon_io.c create mode 100644 gnu/usr.bin/binutils/gprof/gmon_io.h create mode 100644 gnu/usr.bin/binutils/gprof/gmon_out.h create mode 100644 gnu/usr.bin/binutils/gprof/gprof.1 create mode 100644 gnu/usr.bin/binutils/gprof/gprof.c create mode 100644 gnu/usr.bin/binutils/gprof/gprof.h create mode 100644 gnu/usr.bin/binutils/gprof/gprof.info create mode 100644 gnu/usr.bin/binutils/gprof/gprof.texi create mode 100644 gnu/usr.bin/binutils/gprof/hertz.c create mode 100644 gnu/usr.bin/binutils/gprof/hertz.h create mode 100644 gnu/usr.bin/binutils/gprof/hist.c create mode 100644 gnu/usr.bin/binutils/gprof/hist.h create mode 100644 gnu/usr.bin/binutils/gprof/i386.c create mode 100644 gnu/usr.bin/binutils/gprof/i386.h create mode 100644 gnu/usr.bin/binutils/gprof/ns532.c create mode 100644 gnu/usr.bin/binutils/gprof/ns532.h create mode 100644 gnu/usr.bin/binutils/gprof/search_list.c create mode 100644 gnu/usr.bin/binutils/gprof/search_list.h create mode 100644 gnu/usr.bin/binutils/gprof/source.c create mode 100644 gnu/usr.bin/binutils/gprof/source.h create mode 100644 gnu/usr.bin/binutils/gprof/sparc.c create mode 100644 gnu/usr.bin/binutils/gprof/sparc.h create mode 100644 gnu/usr.bin/binutils/gprof/sym_ids.c create mode 100644 gnu/usr.bin/binutils/gprof/sym_ids.h create mode 100644 gnu/usr.bin/binutils/gprof/symtab.c create mode 100644 gnu/usr.bin/binutils/gprof/symtab.h create mode 100644 gnu/usr.bin/binutils/gprof/tahoe.c create mode 100644 gnu/usr.bin/binutils/gprof/tahoe.h create mode 100644 gnu/usr.bin/binutils/gprof/utils.c create mode 100644 gnu/usr.bin/binutils/gprof/utils.h create mode 100644 gnu/usr.bin/binutils/gprof/vax.c create mode 100644 gnu/usr.bin/binutils/gprof/vax.h create mode 100644 gnu/usr.bin/binutils/include/COPYING create mode 100644 gnu/usr.bin/binutils/include/ChangeLog create mode 100644 gnu/usr.bin/binutils/include/ansidecl.h create mode 100644 gnu/usr.bin/binutils/include/aout/ChangeLog create mode 100644 gnu/usr.bin/binutils/include/aout/adobe.h create mode 100644 gnu/usr.bin/binutils/include/aout/aout64.h create mode 100644 gnu/usr.bin/binutils/include/aout/ar.h create mode 100644 gnu/usr.bin/binutils/include/aout/dynix3.h create mode 100644 gnu/usr.bin/binutils/include/aout/encap.h create mode 100644 gnu/usr.bin/binutils/include/aout/host.h create mode 100644 gnu/usr.bin/binutils/include/aout/hp.h create mode 100644 gnu/usr.bin/binutils/include/aout/hp300hpux.h create mode 100644 gnu/usr.bin/binutils/include/aout/hppa.h create mode 100644 gnu/usr.bin/binutils/include/aout/ranlib.h create mode 100644 gnu/usr.bin/binutils/include/aout/reloc.h create mode 100644 gnu/usr.bin/binutils/include/aout/stab.def create mode 100644 gnu/usr.bin/binutils/include/aout/stab_gnu.h create mode 100644 gnu/usr.bin/binutils/include/aout/sun4.h create mode 100644 gnu/usr.bin/binutils/include/bfdlink.h create mode 100644 gnu/usr.bin/binutils/include/bout.h create mode 100644 gnu/usr.bin/binutils/include/coff/ChangeLog create mode 100644 gnu/usr.bin/binutils/include/coff/a29k.h create mode 100644 gnu/usr.bin/binutils/include/coff/alpha.h create mode 100644 gnu/usr.bin/binutils/include/coff/apollo.h create mode 100644 gnu/usr.bin/binutils/include/coff/arm.h create mode 100644 gnu/usr.bin/binutils/include/coff/ecoff.h create mode 100644 gnu/usr.bin/binutils/include/coff/h8300.h create mode 100644 gnu/usr.bin/binutils/include/coff/h8500.h create mode 100644 gnu/usr.bin/binutils/include/coff/i386.h create mode 100644 gnu/usr.bin/binutils/include/coff/i860.h create mode 100644 gnu/usr.bin/binutils/include/coff/i960.h create mode 100644 gnu/usr.bin/binutils/include/coff/internal.h create mode 100644 gnu/usr.bin/binutils/include/coff/m68k.h create mode 100644 gnu/usr.bin/binutils/include/coff/m88k.h create mode 100644 gnu/usr.bin/binutils/include/coff/mips.h create mode 100644 gnu/usr.bin/binutils/include/coff/pe.h create mode 100644 gnu/usr.bin/binutils/include/coff/powerpc.h create mode 100644 gnu/usr.bin/binutils/include/coff/rs6000.h create mode 100644 gnu/usr.bin/binutils/include/coff/sh.h create mode 100644 gnu/usr.bin/binutils/include/coff/sparc.h create mode 100644 gnu/usr.bin/binutils/include/coff/sym.h create mode 100644 gnu/usr.bin/binutils/include/coff/symconst.h create mode 100644 gnu/usr.bin/binutils/include/coff/w65.h create mode 100644 gnu/usr.bin/binutils/include/coff/we32k.h create mode 100644 gnu/usr.bin/binutils/include/coff/z8k.h create mode 100644 gnu/usr.bin/binutils/include/demangle.h create mode 100644 gnu/usr.bin/binutils/include/dis-asm.h create mode 100644 gnu/usr.bin/binutils/include/elf/ChangeLog create mode 100644 gnu/usr.bin/binutils/include/elf/common.h create mode 100644 gnu/usr.bin/binutils/include/elf/dwarf.h create mode 100644 gnu/usr.bin/binutils/include/elf/external.h create mode 100644 gnu/usr.bin/binutils/include/elf/hppa.h create mode 100644 gnu/usr.bin/binutils/include/elf/internal.h create mode 100644 gnu/usr.bin/binutils/include/elf/mips.h create mode 100644 gnu/usr.bin/binutils/include/elf/ppc.h create mode 100644 gnu/usr.bin/binutils/include/floatformat.h create mode 100644 gnu/usr.bin/binutils/include/fopen-bin.h create mode 100644 gnu/usr.bin/binutils/include/fopen-same.h create mode 100644 gnu/usr.bin/binutils/include/gdbm.h create mode 100644 gnu/usr.bin/binutils/include/getopt.h create mode 100644 gnu/usr.bin/binutils/include/hp-symtab.h create mode 100644 gnu/usr.bin/binutils/include/ieee.h create mode 100644 gnu/usr.bin/binutils/include/libiberty.h create mode 100644 gnu/usr.bin/binutils/include/mpw/ChangeLog create mode 100644 gnu/usr.bin/binutils/include/mpw/README create mode 100644 gnu/usr.bin/binutils/include/mpw/dir.h create mode 100644 gnu/usr.bin/binutils/include/mpw/dirent.h create mode 100644 gnu/usr.bin/binutils/include/mpw/fcntl.h create mode 100644 gnu/usr.bin/binutils/include/mpw/grp.h create mode 100644 gnu/usr.bin/binutils/include/mpw/mpw.h create mode 100644 gnu/usr.bin/binutils/include/mpw/pwd.h create mode 100644 gnu/usr.bin/binutils/include/mpw/spin.h create mode 100644 gnu/usr.bin/binutils/include/mpw/stat.h create mode 100644 gnu/usr.bin/binutils/include/mpw/sys/file.h create mode 100644 gnu/usr.bin/binutils/include/mpw/sys/param.h create mode 100644 gnu/usr.bin/binutils/include/mpw/sys/resource.h create mode 100644 gnu/usr.bin/binutils/include/mpw/sys/stat.h create mode 100644 gnu/usr.bin/binutils/include/mpw/sys/time.h create mode 100644 gnu/usr.bin/binutils/include/mpw/sys/types.h create mode 100644 gnu/usr.bin/binutils/include/mpw/utime.h create mode 100644 gnu/usr.bin/binutils/include/mpw/varargs.h create mode 100644 gnu/usr.bin/binutils/include/nlm/ChangeLog create mode 100644 gnu/usr.bin/binutils/include/nlm/alpha-ext.h create mode 100644 gnu/usr.bin/binutils/include/nlm/common.h create mode 100644 gnu/usr.bin/binutils/include/nlm/external.h create mode 100644 gnu/usr.bin/binutils/include/nlm/i386-ext.h create mode 100644 gnu/usr.bin/binutils/include/nlm/internal.h create mode 100644 gnu/usr.bin/binutils/include/nlm/ppc-ext.h create mode 100644 gnu/usr.bin/binutils/include/nlm/sparc32-ext.h create mode 100644 gnu/usr.bin/binutils/include/oasys.h create mode 100644 gnu/usr.bin/binutils/include/obstack.h create mode 100644 gnu/usr.bin/binutils/include/opcode/ChangeLog create mode 100644 gnu/usr.bin/binutils/include/opcode/a29k.h create mode 100644 gnu/usr.bin/binutils/include/opcode/arm.h create mode 100644 gnu/usr.bin/binutils/include/opcode/convex.h create mode 100644 gnu/usr.bin/binutils/include/opcode/h8300.h create mode 100644 gnu/usr.bin/binutils/include/opcode/hppa.h create mode 100644 gnu/usr.bin/binutils/include/opcode/i386.h create mode 100644 gnu/usr.bin/binutils/include/opcode/i860.h create mode 100644 gnu/usr.bin/binutils/include/opcode/i960.h create mode 100644 gnu/usr.bin/binutils/include/opcode/m68k.h create mode 100644 gnu/usr.bin/binutils/include/opcode/m88k.h create mode 100644 gnu/usr.bin/binutils/include/opcode/mips.h create mode 100644 gnu/usr.bin/binutils/include/opcode/np1.h create mode 100644 gnu/usr.bin/binutils/include/opcode/ns32k.h create mode 100644 gnu/usr.bin/binutils/include/opcode/pn.h create mode 100644 gnu/usr.bin/binutils/include/opcode/ppc.h create mode 100644 gnu/usr.bin/binutils/include/opcode/pyr.h create mode 100644 gnu/usr.bin/binutils/include/opcode/rs6k.h create mode 100644 gnu/usr.bin/binutils/include/opcode/sparc.h create mode 100644 gnu/usr.bin/binutils/include/opcode/tahoe.h create mode 100644 gnu/usr.bin/binutils/include/opcode/vax.h create mode 100644 gnu/usr.bin/binutils/include/os9k.h create mode 100644 gnu/usr.bin/binutils/include/progress.h create mode 100644 gnu/usr.bin/binutils/include/wait.h create mode 100644 gnu/usr.bin/binutils/install.sh create mode 100644 gnu/usr.bin/binutils/ld/ChangeLog create mode 100644 gnu/usr.bin/binutils/ld/Makefile.in create mode 100644 gnu/usr.bin/binutils/ld/NEWS create mode 100644 gnu/usr.bin/binutils/ld/README create mode 100644 gnu/usr.bin/binutils/ld/TODO create mode 100644 gnu/usr.bin/binutils/ld/acconfig.h create mode 100644 gnu/usr.bin/binutils/ld/aclocal.m4 create mode 100644 gnu/usr.bin/binutils/ld/config.in create mode 100644 gnu/usr.bin/binutils/ld/configure create mode 100644 gnu/usr.bin/binutils/ld/configure.bat create mode 100644 gnu/usr.bin/binutils/ld/configure.host create mode 100644 gnu/usr.bin/binutils/ld/configure.in create mode 100644 gnu/usr.bin/binutils/ld/configure.tgt create mode 100644 gnu/usr.bin/binutils/ld/dep-in.sed create mode 100644 gnu/usr.bin/binutils/ld/emulparams/README create mode 100644 gnu/usr.bin/binutils/ld/emulparams/a29k.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/aixppc.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/aixrs6.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/alpha.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/armaoutb.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/armaoutl.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/armcoff.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/armpe.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/coff_sparc.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/delta68.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/ebmon29k.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/elf32_sparc.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/elf32b4300.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/elf32bmip.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/elf32l4300.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/elf32lmip.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/elf32lppc.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/elf32ppc.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/elf64_sparc.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/elf_i386.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/gld960.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/gld960coff.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/go32.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/h8300.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/h8300h.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/h8500.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/h8500b.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/h8500c.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/h8500m.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/h8500s.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/hp300bsd.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/hp3hpux.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/hppaelf.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386aout.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386bsd.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386coff.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386go32.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386linux.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386lynx.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386mach.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386moss.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386msdos.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386nbsd.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386nw.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/i386pe.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/lnk960.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/m68k4knbsd.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/m68kaout.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/m68kcoff.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/m68kelf.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/m68klynx.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/m68knbsd.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/m88kbcs.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/mipsbig.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/mipsbsd.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/mipsidt.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/mipsidtl.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/mipslit.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/news.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/ns32knbsd.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/pc532machaout.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/ppcnw.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/ppcpe.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/riscix.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/sa29200.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/sh.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/shl.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/sparclynx.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/sparcnbsd.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/st2000.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/sun3.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/sun4.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/vanilla.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/vax.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/vsta.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/w65.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/z8001.sh create mode 100644 gnu/usr.bin/binutils/ld/emulparams/z8002.sh create mode 100644 gnu/usr.bin/binutils/ld/emultempl/README create mode 100644 gnu/usr.bin/binutils/ld/emultempl/aix.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/elf32.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/generic.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/gld960.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/gld960c.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/hppaelf.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/linux.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/lnk960.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/m88kbcs.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/pe.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/stringify.sed create mode 100644 gnu/usr.bin/binutils/ld/emultempl/sunos.em create mode 100644 gnu/usr.bin/binutils/ld/emultempl/vanilla.em create mode 100644 gnu/usr.bin/binutils/ld/gen-doc.texi create mode 100644 gnu/usr.bin/binutils/ld/genscripts.sh create mode 100644 gnu/usr.bin/binutils/ld/h8-doc.texi create mode 100644 gnu/usr.bin/binutils/ld/ld.1 create mode 100644 gnu/usr.bin/binutils/ld/ld.h create mode 100644 gnu/usr.bin/binutils/ld/ld.info create mode 100644 gnu/usr.bin/binutils/ld/ld.info-1 create mode 100644 gnu/usr.bin/binutils/ld/ld.info-2 create mode 100644 gnu/usr.bin/binutils/ld/ld.info-3 create mode 100644 gnu/usr.bin/binutils/ld/ld.texinfo create mode 100644 gnu/usr.bin/binutils/ld/ldctor.c create mode 100644 gnu/usr.bin/binutils/ld/ldctor.h create mode 100644 gnu/usr.bin/binutils/ld/ldemul.c create mode 100644 gnu/usr.bin/binutils/ld/ldemul.h create mode 100644 gnu/usr.bin/binutils/ld/ldexp.c create mode 100644 gnu/usr.bin/binutils/ld/ldexp.h create mode 100644 gnu/usr.bin/binutils/ld/ldfile.c create mode 100644 gnu/usr.bin/binutils/ld/ldfile.h create mode 100644 gnu/usr.bin/binutils/ld/ldgram.c create mode 100644 gnu/usr.bin/binutils/ld/ldgram.h create mode 100644 gnu/usr.bin/binutils/ld/ldgram.y create mode 100644 gnu/usr.bin/binutils/ld/ldint.texinfo create mode 100644 gnu/usr.bin/binutils/ld/ldlang.c create mode 100644 gnu/usr.bin/binutils/ld/ldlang.h create mode 100644 gnu/usr.bin/binutils/ld/ldlex.c create mode 100644 gnu/usr.bin/binutils/ld/ldlex.h create mode 100644 gnu/usr.bin/binutils/ld/ldlex.l create mode 100644 gnu/usr.bin/binutils/ld/ldmain.c create mode 100644 gnu/usr.bin/binutils/ld/ldmain.h create mode 100644 gnu/usr.bin/binutils/ld/ldmisc.c create mode 100644 gnu/usr.bin/binutils/ld/ldmisc.h create mode 100644 gnu/usr.bin/binutils/ld/ldver.c create mode 100644 gnu/usr.bin/binutils/ld/ldver.h create mode 100644 gnu/usr.bin/binutils/ld/ldwrite.c create mode 100644 gnu/usr.bin/binutils/ld/ldwrite.h create mode 100644 gnu/usr.bin/binutils/ld/lexsup.c create mode 100644 gnu/usr.bin/binutils/ld/mac-ld.r create mode 100644 gnu/usr.bin/binutils/ld/mpw-config.in create mode 100644 gnu/usr.bin/binutils/ld/mpw-emipsidt.c create mode 100644 gnu/usr.bin/binutils/ld/mpw-eppcmacos.c create mode 100644 gnu/usr.bin/binutils/ld/mpw-esh.c create mode 100644 gnu/usr.bin/binutils/ld/mpw-make.sed create mode 100644 gnu/usr.bin/binutils/ld/mri.c create mode 100644 gnu/usr.bin/binutils/ld/mri.h create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/README create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/a29k.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/aix.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/alpha.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/aout.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/armaout.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/armcoff.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/delta68.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/ebmon29k.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/elf.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/elfppc.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/go32coff.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/h8300.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/h8300h.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/h8500.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/h8500b.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/h8500c.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/h8500m.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/h8500s.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/hppaelf.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/i386coff.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/i386go32.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/i386lynx.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/i386msdos.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/i960.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/m68kcoff.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/m68klynx.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/m88kbcs.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/mips.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/mipsbsd.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/nw.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/pe.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/ppcpe.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/riscix.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/sa29200.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/sh.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/sparccoff.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/sparclynx.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/st2000.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/vanilla.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/w65.sc create mode 100644 gnu/usr.bin/binutils/ld/scripttempl/z8000.sc create mode 100644 gnu/usr.bin/binutils/ld/sysdep.h create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ChangeLog create mode 100644 gnu/usr.bin/binutils/ld/testsuite/config/default.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-bootstrap/bootstrap.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-cdtest/cdtest-bar.cc create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-cdtest/cdtest-foo.cc create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-cdtest/cdtest-foo.h create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-cdtest/cdtest-main.cc create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-cdtest/cdtest.dat create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-cdtest/cdtest.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/empic.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/relax.t create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/relax1.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/relax2.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/relax3.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/relax4.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/run.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/runtest1.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/runtest2.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-empic/runtesti.s create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/defined.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/defined.s create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/defined.t create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/script.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/script.s create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/script.t create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/scriptm.t create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/sizeof.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/sizeof.s create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-scripts/sizeof.t create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-sh/sh.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-sh/sh1.s create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-sh/sh2.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-sh/start.s create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-shared/main.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-shared/sh1.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-shared/sh2.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-shared/shared.dat create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-shared/shared.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-shared/sun4.dat create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-shared/xcoff.dat create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-srec/sr1.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-srec/sr2.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-srec/sr3.cc create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-srec/srec.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-undefined/undefined.c create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-undefined/undefined.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/t1-1.ro create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/t1-2.ro create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/t1.ld create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/t1.ook create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/t2-1.ro create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/t2-2.ro create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/t2-3.ro create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/t2.ld create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/t2.ook create mode 100644 gnu/usr.bin/binutils/ld/testsuite/ld-versados/versados.exp create mode 100644 gnu/usr.bin/binutils/ld/testsuite/lib/ld.exp create mode 100644 gnu/usr.bin/binutils/libiberty/COPYING.LIB create mode 100644 gnu/usr.bin/binutils/libiberty/ChangeLog create mode 100644 gnu/usr.bin/binutils/libiberty/Makefile.in create mode 100644 gnu/usr.bin/binutils/libiberty/README create mode 100644 gnu/usr.bin/binutils/libiberty/alloca-botch.h create mode 100644 gnu/usr.bin/binutils/libiberty/alloca-norm.h create mode 100644 gnu/usr.bin/binutils/libiberty/alloca.c create mode 100644 gnu/usr.bin/binutils/libiberty/argv.c create mode 100644 gnu/usr.bin/binutils/libiberty/basename.c create mode 100644 gnu/usr.bin/binutils/libiberty/bcmp.c create mode 100644 gnu/usr.bin/binutils/libiberty/bcopy.c create mode 100644 gnu/usr.bin/binutils/libiberty/bzero.c create mode 100644 gnu/usr.bin/binutils/libiberty/clock.c create mode 100644 gnu/usr.bin/binutils/libiberty/concat.c create mode 100644 gnu/usr.bin/binutils/libiberty/config.table create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-a68bsd create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-aix create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-apollo68 create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-cxux7 create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-go32 create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-hpbsd create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-hpux create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-i386win32 create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-irix4 create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-lynxos create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-ncr3000 create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-riscix create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-sysv create mode 100644 gnu/usr.bin/binutils/libiberty/config/mh-sysv4 create mode 100644 gnu/usr.bin/binutils/libiberty/config/mt-sunos4 create mode 100644 gnu/usr.bin/binutils/libiberty/config/mt-vxworks5 create mode 100644 gnu/usr.bin/binutils/libiberty/configure.bat create mode 100644 gnu/usr.bin/binutils/libiberty/configure.in create mode 100644 gnu/usr.bin/binutils/libiberty/copysign.c create mode 100644 gnu/usr.bin/binutils/libiberty/cplus-dem.c create mode 100644 gnu/usr.bin/binutils/libiberty/dummy.c create mode 100644 gnu/usr.bin/binutils/libiberty/fdmatch.c create mode 100644 gnu/usr.bin/binutils/libiberty/floatformat.c create mode 100644 gnu/usr.bin/binutils/libiberty/functions.def create mode 100644 gnu/usr.bin/binutils/libiberty/getcwd.c create mode 100644 gnu/usr.bin/binutils/libiberty/getopt.c create mode 100644 gnu/usr.bin/binutils/libiberty/getopt1.c create mode 100644 gnu/usr.bin/binutils/libiberty/getpagesize.c create mode 100644 gnu/usr.bin/binutils/libiberty/getruntime.c create mode 100644 gnu/usr.bin/binutils/libiberty/hex.c create mode 100644 gnu/usr.bin/binutils/libiberty/index.c create mode 100644 gnu/usr.bin/binutils/libiberty/insque.c create mode 100644 gnu/usr.bin/binutils/libiberty/makefile.dos create mode 100644 gnu/usr.bin/binutils/libiberty/memchr.c create mode 100644 gnu/usr.bin/binutils/libiberty/memcmp.c create mode 100644 gnu/usr.bin/binutils/libiberty/memcpy.c create mode 100644 gnu/usr.bin/binutils/libiberty/memmove.c create mode 100644 gnu/usr.bin/binutils/libiberty/memset.c create mode 100644 gnu/usr.bin/binutils/libiberty/mpw-config.in create mode 100644 gnu/usr.bin/binutils/libiberty/mpw-make.sed create mode 100644 gnu/usr.bin/binutils/libiberty/mpw.c create mode 100644 gnu/usr.bin/binutils/libiberty/msdos.c create mode 100644 gnu/usr.bin/binutils/libiberty/obstack.c create mode 100644 gnu/usr.bin/binutils/libiberty/random.c create mode 100644 gnu/usr.bin/binutils/libiberty/rename.c create mode 100644 gnu/usr.bin/binutils/libiberty/rindex.c create mode 100644 gnu/usr.bin/binutils/libiberty/sigsetmask.c create mode 100644 gnu/usr.bin/binutils/libiberty/spaces.c create mode 100644 gnu/usr.bin/binutils/libiberty/strcasecmp.c create mode 100644 gnu/usr.bin/binutils/libiberty/strchr.c create mode 100644 gnu/usr.bin/binutils/libiberty/strdup.c create mode 100644 gnu/usr.bin/binutils/libiberty/strerror.c create mode 100644 gnu/usr.bin/binutils/libiberty/strncasecmp.c create mode 100644 gnu/usr.bin/binutils/libiberty/strrchr.c create mode 100644 gnu/usr.bin/binutils/libiberty/strsignal.c create mode 100644 gnu/usr.bin/binutils/libiberty/strstr.c create mode 100644 gnu/usr.bin/binutils/libiberty/strtod.c create mode 100644 gnu/usr.bin/binutils/libiberty/strtol.c create mode 100644 gnu/usr.bin/binutils/libiberty/strtoul.c create mode 100644 gnu/usr.bin/binutils/libiberty/tmpnam.c create mode 100644 gnu/usr.bin/binutils/libiberty/vasprintf.c create mode 100644 gnu/usr.bin/binutils/libiberty/vfork.c create mode 100644 gnu/usr.bin/binutils/libiberty/vfprintf.c create mode 100644 gnu/usr.bin/binutils/libiberty/vmsbuild.com create mode 100644 gnu/usr.bin/binutils/libiberty/vprintf.c create mode 100644 gnu/usr.bin/binutils/libiberty/vsprintf.c create mode 100644 gnu/usr.bin/binutils/libiberty/waitpid.c create mode 100644 gnu/usr.bin/binutils/libiberty/win32.c create mode 100644 gnu/usr.bin/binutils/libiberty/xatexit.c create mode 100644 gnu/usr.bin/binutils/libiberty/xexit.c create mode 100644 gnu/usr.bin/binutils/libiberty/xmalloc.c create mode 100644 gnu/usr.bin/binutils/libiberty/xstrerror.c create mode 100644 gnu/usr.bin/binutils/makeall.bat create mode 100644 gnu/usr.bin/binutils/move-if-change create mode 100644 gnu/usr.bin/binutils/mpw-README create mode 100644 gnu/usr.bin/binutils/mpw-build.in create mode 100644 gnu/usr.bin/binutils/mpw-config.in create mode 100644 gnu/usr.bin/binutils/mpw-configure create mode 100644 gnu/usr.bin/binutils/opcodes/ChangeLog create mode 100644 gnu/usr.bin/binutils/opcodes/Makefile.in create mode 100644 gnu/usr.bin/binutils/opcodes/a29k-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/aclocal.m4 create mode 100644 gnu/usr.bin/binutils/opcodes/alpha-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/alpha-opc.h create mode 100644 gnu/usr.bin/binutils/opcodes/arm-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/arm-opc.h create mode 100644 gnu/usr.bin/binutils/opcodes/config.in create mode 100644 gnu/usr.bin/binutils/opcodes/configure create mode 100644 gnu/usr.bin/binutils/opcodes/configure.bat create mode 100644 gnu/usr.bin/binutils/opcodes/configure.in create mode 100644 gnu/usr.bin/binutils/opcodes/dis-buf.c create mode 100644 gnu/usr.bin/binutils/opcodes/disassemble.c create mode 100644 gnu/usr.bin/binutils/opcodes/h8300-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/h8500-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/h8500-opc.h create mode 100644 gnu/usr.bin/binutils/opcodes/hppa-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/i386-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/i960-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/m68k-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/m68k-opc.c create mode 100644 gnu/usr.bin/binutils/opcodes/m88k-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/mips-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/mips-opc.c create mode 100644 gnu/usr.bin/binutils/opcodes/mpw-config.in create mode 100644 gnu/usr.bin/binutils/opcodes/mpw-make.sed create mode 100644 gnu/usr.bin/binutils/opcodes/ns32k-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/ppc-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/ppc-opc.c create mode 100644 gnu/usr.bin/binutils/opcodes/sh-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/sh-opc.h create mode 100644 gnu/usr.bin/binutils/opcodes/sparc-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/sparc-opc.c create mode 100644 gnu/usr.bin/binutils/opcodes/stamp-h create mode 100644 gnu/usr.bin/binutils/opcodes/sysdep.h create mode 100644 gnu/usr.bin/binutils/opcodes/w65-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/w65-opc.h create mode 100644 gnu/usr.bin/binutils/opcodes/z8k-dis.c create mode 100644 gnu/usr.bin/binutils/opcodes/z8k-opc.h create mode 100644 gnu/usr.bin/binutils/opcodes/z8kgen.c create mode 100644 gnu/usr.bin/binutils/texinfo/gpl.texinfo create mode 100644 gnu/usr.bin/binutils/texinfo/lgpl.texinfo create mode 100644 gnu/usr.bin/binutils/texinfo/tex3patch create mode 100644 gnu/usr.bin/binutils/texinfo/texinfo.tex diff --git a/gnu/usr.bin/binutils/COPYING b/gnu/usr.bin/binutils/COPYING new file mode 100644 index 00000000000..a43ea2126fb --- /dev/null +++ b/gnu/usr.bin/binutils/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. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You 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. + + , 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/gnu/usr.bin/binutils/COPYING.LIB b/gnu/usr.bin/binutils/COPYING.LIB new file mode 100644 index 00000000000..eb685a5ec98 --- /dev/null +++ b/gnu/usr.bin/binutils/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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/gnu/usr.bin/binutils/Makefile.in b/gnu/usr.bin/binutils/Makefile.in new file mode 100644 index 00000000000..b80362031ac --- /dev/null +++ b/gnu/usr.bin/binutils/Makefile.in @@ -0,0 +1,1289 @@ +# +# 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 +NM = nm +# Not plain GZIP, since gzip looks there for extra command-line options. +GZIPPROG = gzip + +BISON = bison -y +LEX = `if [ -f $$r/flex/flex ] ; \ + then echo $$r/flex/flex ; \ + else echo flex ; 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 = + +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)' \ + '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)' \ + 'HOST_CC=$(CC_FOR_BUILD)' \ + 'HOST_PREFIX=$(HOST_PREFIX)' \ + 'HOST_PREFIX_1=$(HOST_PREFIX_1)' \ + 'NM=$(NM)' \ + 'RANLIB=$$(RANLIB_FOR_TARGET)' + +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 + +# 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 + +# 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; \ + 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; \ + if (cd ./$$i; \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + $${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; \ + 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; \ + if (cd $(TARGET_SUBDIR)/$$i; \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + $${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 + +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 ; \ + (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; \ + (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; \ + (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; \ + (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; \ + (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; \ + (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; \ + 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; \ + 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} "Makefile" ; then \ + true; \ + 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; \ + (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; \ + (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; \ + (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; \ + (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; \ + (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; \ + (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; \ + (cd gcc; $(MAKE) $(GCC_FLAGS_TO_PASS) all); \ + else \ + true; \ + fi + +.PHONY: check-gcc +check-gcc: + @if [ -f ./gcc/Makefile ] ; then \ + r=`pwd`; export r; \ + srcroot=`cd $(srcdir); pwd`; export srcroot; \ + (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; \ + (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; \ + (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: +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-gdb: all-libiberty all-opcodes all-bfd all-mmalloc all-readline all-byacc all-sim $(gdbnlmrequirements) +all-gprof: all-libiberty all-bfd +all-grep: all-libiberty +all-grez: all-libiberty all-bfd +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-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-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-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-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-time: +all-wdiff: +all-target-winsup: all-target-newlib 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 + +# 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/' \ + 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 //' \ + 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 +GDBTK_SUPPORT_DIRS= `if [ -d tcl -a -d tk ] ; then echo tcl tk ; fi` +gdb.tar.gz: $(DIST_SUPPORT) $(GDB_SUPPORT_DIRS) gdb + $(MAKE) -f Makefile.in taz TOOL=gdb \ + SUPPORT_FILES="$(GDB_SUPPORT_DIRS) $(GDBTK_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). +# Compensate here by configuring newlib for a simple (no multilib support) +# cross target (sparc64), building the info files, and doing make distclean +# ourselves. +newlib.tar.gz: $(DIST_SUPPORT) $(NEWLIB_SUPPORT_DIRS) newlib + rootme=`pwd` ; \ + cd newlib && ../configure --srcdir $$rootme/newlib \ + --host sun4 --target sparc64-elf + cd newlib ; make info + cd newlib ; make distclean + $(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/gnu/usr.bin/binutils/README b/gnu/usr.bin/binutils/README new file mode 100644 index 00000000000..622a5be4309 --- /dev/null +++ b/gnu/usr.bin/binutils/README @@ -0,0 +1,47 @@ + 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 + +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, and this file, is +copyright 1993 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/gnu/usr.bin/binutils/bfd/COPYING b/gnu/usr.bin/binutils/bfd/COPYING new file mode 100644 index 00000000000..a43ea2126fb --- /dev/null +++ b/gnu/usr.bin/binutils/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. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You 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. + + , 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/gnu/usr.bin/binutils/bfd/ChangeLog b/gnu/usr.bin/binutils/bfd/ChangeLog new file mode 100644 index 00000000000..ce248a21726 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/ChangeLog @@ -0,0 +1,1721 @@ +Thu Nov 16 17:32:55 1995 Ken Raeburn + + * VERSION: Updated to 2.6. + +Wed Nov 15 19:30:07 1995 Ken Raeburn + + * targets.c (m68k4knetbsd_vec): Declare. + +Wed Nov 15 18:05:52 1995 Ian Lance Taylor + + * targets.c (bfd_target): Change type of second argument to + _bfd_print_private_bfd_data from void * to PTR. + * libbfd-in.h (_bfd_generic_bfd_print_private_bfd_data): Cast + using PTR rather than void *. + * bfd-in2, libbfd.h: Rebuild. + * peicode.h (pe_print_private_bfd_data): Change vfile from void * + to PTR. + * elfxx-target.h (bfd_elfNN_bfd_print_private_bfd_data): Define as + _bfd_generic_bfd_print_private_bfd_data rather than casting + bfd_true. + +Wed Nov 15 04:09:14 1995 Ken Raeburn + + * Makefile.in (.dep1): Fix stupid typo in last change. Remove any + "DO NOT DELETE" lines or blank lines that mkdep writes on some + systems. + (BFD_LIBS_CFILES, ALL_MACHINES_CFILES, BFD32_BACKENDS_CFILES, + BFD64_BACKENDS_CFILES): New variables. + (CFILES): Use them. + +Tue Nov 14 11:52:23 1995 Ian Lance Taylor + + * peicode.h (coff_swap_aouthdr_out): For PPC PE, start isize at 0, + not at the file position of the first section. + * coffcode.h (coff_compute_section_file_positions): Avoid using + unportable #elif. + (coff_write_object_contents): When generating a PPC PE executable + with no symbols, round up the file size to a COFF_PAGE_SIZE + boundary. + * cofflink.c (_bfd_coff_final_link): If there are no symbols, + don't write out a string table. + + * elf.c (bfd_section_from_shdr): When using a different section + header, pass the new one to _bfd_elf_make_section_from_shdr. + (elf_fake_sections): Don't set sh_info and sh_entsize fields. + (elf_map_symbols): Add section VMA to symbol value when comparing + against 0. + (_bfd_elf_compute_section_file_positions): Only build symbol table + if there are some symbols. Set file offset of symtab and strtab + sections. + (assign_file_positions_except_relocs): Remove dosyms parameter. + Change all callers. Never set file offset of symtab and strtab + sections. + (_bfd_elf_copy_private_section_data): New function. + (MAP_ONESYMTAB, MAP_DYNSYMTAB, MAP_STRTAB, MAP_SHSTRTAB): Define. + (_bfd_elf_copy_private_symbol_data): New function. + (swap_out_syms): Check for special mapping of st_shndx created by + copy_private_symbol_data. + * elfxx-target.h: Use new copy routines. + * elf-bfd.h (_bfd_elf_copy_private_symbol_data): Declare. + (_bfd_elf_copy_private_section_data): Declare. + + * config.bfd (sh-*-*): Set targ_defvec to shcoff_vec. + + * coffcode.h (coff_slurp_symbol_table): If COFF_WITH_PE, handle + C_NT_WEAK. + + * coff-sh.c (shlcoff_vec): Use _bfd_generic_archive_p, not + _bfd_dummy_target, matching the recent change to archive + recognition. + +Mon Nov 13 13:24:38 1995 Ian Lance Taylor + + * libbfd.c (bfd_get_file_window): Use casts to avoid doing + arithmetic on PTR types. + + * aout-target.h (MY(callback)): Set the lma of the sections. + + * ecoff.c (ecoff_reloc_link_order): Turn a reloc against a defined + symbol into a reloc against the section. + +Mon Nov 13 07:31:35 1995 Kim Knuttila + + * coff-ppc.c (ppc_coff_link_hash_entry): added support for inline + glue for the relocs: IMGLUE and IFGLUE. + (record_toc): new function - tracks toc contents + (ppc_mark_symbol_as_glue): new function - supports the IMGLUE reloc + (coff_ppc_relocate_section): Added support and fixes for IMGLUE/IFGLUE + (ppc_coff_rtype2howto): removed invalid IMGLUE hack + (coff_ppc_rtype_to_howto): removed invalid IMGLUE hack + (ppc_record_toc_entry): Removed a debug define (duh) + + * peicode.h (coff_swap_scnhdr_out): Fixed invalid strcmp for ".reldata" + (pe_print_idata): New function - formats the idata section data + (pe_print_pdata): New function - formats the pdata section data + (pe_print_private_bfd_data): calls to above + +Sun Nov 12 12:23:24 1995 Stan Shebs + + * Makefile.in (bfd_libs_here, etc): Provide empty definitions. + * coff-rs6000.c (rs6000coff_vec): Add conditional defines + TARGET_SYM and TARGET_NAME for vector and BFD name. + * coff-pmac.c (pmac_xcoff_vec): Remove. + (TARGET_SYM, TARGET_NAME): Define. + * coffcode.h (coff_set_arch_mach_hook) [POWERMAC]: Set the + machine to 0, not all PowerMacs are 601s. + +Fri Nov 10 12:10:14 1995 Ian Lance Taylor + + * elfcode.h (elf_object_p): Read in any program headers. + * elf.c (_bfd_elf_make_section_from_shdr): Adjust section lma + based on the program headers, if any. + (elf_fake_sections): Set sh_addr from the vma, not the lma. + (map_program_segments): Set p_paddr of program headers based on + the lma. + +Thu Nov 9 13:01:31 1995 Ian Lance Taylor + + * archive.c (bfd_generic_archive_p): Preserve tdata in case of + failure. + + * aoutx.h (NAME(aout,final_link)): Report a reasonable error when + trying to do a relocateable link with a non-a.out object file. + + * archive.c (bfd_generic_archive_p): Check the first object file + in an archive even if target_defaulted is set. If the object file + has the wrong xvec, reject it. + + * aoutx.h (NAME(aout,set_section_contents)): If a section can not + be represented, report the name via _bfd_error_handler. + (translate_to_native_sym_flags): Likewise. + * elf32-mips.c (mips_elf_final_link): Likewise. + * oasys.c (oasys_write_sections): Likewise. + + * coffcode.h (coff_set_alignment_hook): Write RS6000COFF_C version + which checks for STYP_OVRFLO sections. + (coff_compute_section_file_positions): If RS6000COFF_C, handle + reloc and lineno count overflows. + (coff_write_object_contents): Call coff_count_linenumbers before + coff_compute_section_file_positions. If RS6000COFF_C, handle + reloc and lineno count overflows. + * xcofflink.c (_bfd_xcoff_bfd_final_link): Count line numbers and + relocs before dealing with .pad sections. Count overflow section + headers when handling .pad sections. + + * coffcode.h (coff_write_object_contents): Set a.out vstamp to 1 + if RS6000COFF_C. + + * xcofflink.c (XCOFF_DESCRIPTOR): Define. + (struct xcoff_link_hash_table): Add descriptor_section and + special_sections fields. + (_bfd_xcoff_bfd_link_hash_table_create): Initialize new fields. + (xcoff_link_add_symbols): Set linkage section alignment. Create + descriptor section. Check for magic symbol names (_text, etc.), + and record them in special_sections if found. Set + XCOFF_DESCRIPTOR flag for a function descriptor, and set its + descriptor field to point back to the function code symbol. + (xcoff_sweep): Always mark the special descriptor_section. + (bfd_xcoff_export_symbol): Check whether the symbol might be a + function descriptor, and mark it if it is. + (bfd_xcoff_size_dynamic_sections): Add new special_sections + parameter, and fill it in. Allocate space for the descriptor + section. + (xcoff_build_ldsyms): Set XCOFF_DEF_REGULAR flag when defining + global linkage code. If an undefined function descriptor is + exported, arrange to define it. Warn about any other undefined + exported symbol. + (_bfd_xcoff_bfd_final_link): Write out the descriptor section. + (xcoff_write_global_symbol): Create a function descriptor when + necessary. + * bfd-in.h (bfd_xcoff_size_dynamic_sections): Update declaration. + * bfd-in2.h: Rebuild. + +Thu Nov 9 08:40:23 1995 Kim Knuttila + + * coff-ppc.c (ppc_coff_link_hash_entry): new types for hashing + (ppc_coff_link_hash_table): new types for hashing + (ppc_coff_link_hash_newfunc): hash entry constructor + (ppc_coff_link_hash_table_init): hash table initializer + (ppc_coff_link_hash_table_create): hash table constructor + (ppc_record_toc_entry): changed references to hash table + (coff_ppc_relocate_section): changed references to hash table + + * libcoff-in.h (coff_link_hash_entry): removed toc_offset + * libcoff.h: Rebuild + + * cofflink.c (_bfd_coff_link_hash_newfunc): removed toc_offset init + (coff_link_add_symbols): removed toc_offset init + +Thu Nov 9 04:00:38 1995 Ken Raeburn + + * Makefile.in (.dep1): Make sure the file mkdep is to write exists + first. + + * configure.in: Added new option --with[out]-mmap. Set USE_MMAP + if it is given and mmep is available. + * acconfig.h: Undef USE_MMAP. + * configure, config.in: Regenerated. + * aoutx.h: If USE_MMAP is not defined, do all symbol and string + table handling the old way. + (aout_get_external_symbols): Don't complain if last byte of string + table is nonzero. + * libbfd.c [HAVE_MADVISE]: Include sys/types.h and sys/mman.h. + (bfd_free_window) [! USE_MMAP]: Don't define. + (bfd_get_file_window, + _bfd_generic_get_section_contents_in_window) [! USE_MMAP]: Abort. + +Wed Nov 8 20:03:44 1995 Eric Freudenthal + + * coff-a29k.c (SIGN_EXTEND_HWORD): Use ~0xffff rather than + 0xffff0000. + +Wed Nov 8 11:31:11 1995 Ian Lance Taylor + + * coff-a29k.c (a29k_reloc): Change handling of R_IREL reloc to be + compatible with AMD generated COFF files. Try to support both AMD + and GNU formats simultaneously. + (coff_a29k_relocate_section): Likewise. + + * libbfd.c (bfd_get_file_window): Change writable parameter from + int to boolean; update all callers. Pass MAP_SHARED if not + writable--it's required on Solaris. Cast fprintf argument to + avoid warning. + * bfd-in.h (bfd_get_file_window): Update declaration. + * bfd-in2.h: Rebuild. + * aoutx.h: Update calls to bfd_get_file_window. + + * xcofflink.c (XCOFF_DEF_DYNAMIC): Rename from XCOFF_REF_DYNAMIC. + Change all uses. + (xcoff_swap_ldhdr_in): New static function. + (xcoff_swap_ldsym_in): New static function. + (xcoff_find_reloc): Handle the case of a single reloc correctly. + (xcoff_link_add_symbols): If we just created a descriptor, pass it + to _bfd_generic_link_add_one_symbol, to save a hash lookup. + Handle XTY_ER/XMC_XO symbols correctly. + (xcoff_link_add_dynamic_symbols): Rewrite to read .loader symbols + rather than normal symbol table. + (bfd_xcoff_import_symbol): It's not an error if the symbol is + already defined with the same absolute value. + (xcoff_mark): When considering called symbols, check whether the + descriptor is from a dynamic object, rather than the symbol + itself. + (xcoff_build_ldsyms): Likewise. + + * libbfd.c (bfd_get_file_window): Change return type to boolean. + Cast realloc and malloc return values. If malloc or realloc fail, + set bfd_error_no_memory. + * bfd-in.h (bfd_get_file_window): Change type to boolean. + * bfd-in2.h: Rebuild. + +Tue Nov 7 11:53:48 1995 Kim Knuttila + + * coff-ppc.c (ppc_record_toc_entry): new function. + (in_reloc_p): changed return value. + (coff_ppc_relocate_section): much rework. + (ppc_allocate_toc_section): new function. + (ppc_process_before_allocation): new function. + (ppc_coff_swap_sym_in_hook): new function. + + * cofflink.c (_bfd_coff_link_hash_newfunc): initialize toc_offset. + (coff_link_add_symbols): initialize toc_offset. + + * peicode.h (coff_swap_sym_in): Added coff_swap_sym_in_hook + (coff_swap_aouthdr_out): Added more sections to the data + dictionary for the pe file header. Also changed linker version + number on the ppc side. + (dir_names): small improvements to the dictionary printing. + (pe_mkobject_hook): save the file level flags. + + * libcoff-in.h (coff_link_hash_entry): added toc_offset field + (pe_tdata): added real_flags field + (coff_tdata): added local_toc_sym_map and access macro + + * libcoff.h (coff_link_hash_entry): added toc_offset field + (pe_tdata): added real_flags field + (coff_tdata): added local_toc_sym_map and access macro + + * coffcode.h (coff_set_alignment_hook): added hook for PE. + (coff_mkobject): init for local_toc_sym_map + (coff_write_object_contents): set the internal_a.magic to + IMAGE_NT_OPTIONAL_HDR_MAGIC which appears to be what other + ppc compilers use. + +Tue Nov 7 13:48:58 1995 Ian Lance Taylor + + * ecofflink.c (_bfd_ecoff_locate_line): Keep looking through stabs + entries until both the line number address and the function name + address are too large. + + * configure.in: Call AC_CHECK_PROG to find and cache AR. + * configure: Rebuilt. + + * aclocal.m4 (BFD_CC_FOR_BUILD): Don't define CC_FOR_BUILD if it + is defined in the environment. + +Tue Nov 7 10:57:24 1995 Jeffrey A Law (law@cygnus.com) + + * som.c (som_get_section_contents_in_window): Define to use + generic version. + +Mon Nov 6 17:13:15 1995 Harry Dolan + + * coff-i860.c: New file, based on coff-i386.c. + * cpu-i860.c: New file, based on cpu-i386.c. + * hosts/i860mach3.h: New file, based on hosts/i386mach3.h. + * config.bfd (i860-*-mach3*, i860-*-osf1*, i860-*-coff*): New + targets, using i860coff_vec. + * configure.in (i860-*-mach3*, i860-*-osf1*): New hosts, using + trad-core.o and hosts/i860mach3.h. + (i860coff_vec): Use coff-i860.o and cofflink.o. + * configure: Rebuild. + * Makefile.in: Rebuild dependencies. + (ALL_MACHINES): Add cpu-i860.o. + (BFD32_BACKENDS): Add coff-i860.o. + (CFILES): Add cpu-i860.c and coff-i860.c. + * targets.c (i860coff_vec): Declare. + (bfd_target_vector): Add &i860coff_vec. + * archures.c (bfd_i860_arch): Declare. + (bfd_archures_list): Add &bfd_i860_arch. + * coffcode.h (coff_set_arch_mach_hook): Handle I860 magic number. + (coff_set_flags): Handle bfd_arch_i860. + (coff_write_object_contents): Handle I860 a.out magic number. + +Mon Nov 6 14:34:07 1995 Ian Lance Taylor + + * xcofflink.c (xcoff_link_add_symbols): Set the alignment power of + the created .tc section to 2. + (xcoff_mark): Don't keep a .loader reloc for a call to an + undefined symbol when creating a shared library. + (xcoff_build_ldsyms): When creating a shared library, generate + global linkage code for a call to an undefined symbol. + +Sun Nov 5 21:44:13 1995 Ken Raeburn + + * Makefile.in (CFILES): Rebuild list from BFD_LIBS, ALL_MACHINES, + BFD32_BACKENDS, BFD64_BACKENDS. + (.dep1): Put mkdep output in a separate file. + Rebuilt dependencies. + + * ecoff.c (_bfd_ecoff_slurp_armap): Cast _bfd_read_ar_hdr return + value. + + Permit use of mmap when available: + + * configure.in: Check for mmap, madvise, mprotect. + * config.in, configure: Regenerated. + + * libbfd.c (struct _bfd_window_internal): Define type. + (bfd_init_window, bfd_free_window, bfd_get_file_window): New + functions. + (ok_to_map): New static variable for debugging. + (_bfd_generic_get_section_contents_in_window): New function. + * bfd-in.h (bfd_window_internal): Declare type. + (bfd_window): Define type. + (bfd_init_window, bfd_free_window, bfd_get_file_window): Declare. + * libbfd-in.h (_bfd_generic_get_section_contents_in_window): + Declare. + + * libaout.h (struct aoutdata): Add two window fields. + (obj_aout_sym_window, obj_aout_string_window): New macros. + * aoutx.h (some_aout_object_p): Initialize windows. + (aout_get_external_symbols): Get symbol data and strings in + windows instead of explicitly allocated buffers. + (slurp_symbol_table): Free window instead of memory. + (bfd_free_cached_info): Release windows instead of freeing storage + directly. + (aout_link_free_symbols): Ditto. + + * targets.c (bfd_target): Add new field for + get_section_contents_in_window. + (BFD_JUMP_TABLE_GENERIC): Updated. + * aout-adobe.c, aout-target.h, binary.c, bout.c, coff-alpha.c, + coff-mips.c, elfxx-target.h, i386msdos.c, i386os9k.c, ieee.c, + libcoff-in.h, oasys.c, srec.c, tekhex.c, versados.c: Added new + macros for get_section_contents_in_window field. + +Sat Nov 4 12:23:26 1995 Fred Fish + + * core.c: Renamed to corefile.c + * makefile.dos (OBJS): Change core.o to corefile.o + * Makefile.in (CFILES, BFD_LIBS): Use corefile.c instead of core.c + +Fri Nov 3 15:54:59 1995 Ian Lance Taylor + + * xcofflink.c (xcoff_link_add_symbols): Rename local variable sub + to o. Clobber and restore the list of new csects around the call + to _bfd_generic_link_add_one_symbol, in case it wants to report a + linker error and the linker wants to read the symbol table. Reset + the line number count of a real section even if it has no relocs. + (_bfd_xcoff_bfd_final_link): If shared, set the DYNAMIC flag. + + * coffgen.c (_bfd_coff_read_string_table): Warn if the string size + is too small. + +Thu Nov 2 23:16:39 1995 Ian Lance Taylor + + * xcofflink.c (_bfd_ppc_xcoff_relocate_section): Don't warn about + an undefined symbol in a shared link. + + * linker.c (_bfd_generic_link_add_one_symbol): Correct type of + oldtype from bfd_link_order_type to bfd_link_hash_type. From + phdm@info.ucl.ac.be (Philippe De Muyter). + +Wed Nov 1 14:26:02 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 + + * coff-m88k.c (rtype2howto): New static function. + (RTYPE2HOWTO): Use it rather than a macro definition. + + * coffcode.h (coff_write_object_contents): set internal_a.magic + to PAGEMAGICPEXECPAGED #if defined (M68) && !defined (LYNXOS). + + * configure.in: m68*-motorola-sysv* does not use ptrace-core.o; + define TRAD_HEADER to new file hosts/delta68.h. + m88*-motorola-sysv*, however, does use ptrace-core.o. + * hosts/delta68.h: New file. + + * ptrace-core.c (ptrace_unix_core_file_p): change bfd_zmalloc to + bfd_zalloc; provide proper parm abfd to calls to bfd_zalloc. + +Wed Nov 1 13:51:54 1995 Ken Raeburn + + * i386linux.c (MY(vec)): Declare before use. + +Wed Nov 1 11:45:07 1995 Ian Lance Taylor + + * reloc16.c (bfd_coff_reloc16_get_relocated_section_contents): + Pass input_bfd, not in_bfd, to bfd_coff_reloc16_extra_cases. + + * elf.c (bfd_elf_set_dt_needed_name): Don't do anything if the + BFD is not of the right type. + (bfd_elf_get_needed_list): Likewise. + * i386linux.c (bfd_linux_size_dynamic_sections): Likewise. + * sunos.c (bfd_sunos_get_needed_list): Likewise. + * xcofflink.c (XCOFF_XVECP): Define. + (bfd_xcoff_link_record_set): Don't do anything if the BFD is not + of the right type. + (bfd_xcoff_import_symbol): Likewise. + (bfd_xcoff_export_symbol): Likewise. + (bfd_xcoff_link_count_reloc): Likewise. + (bfd_xcoff_record_link_assignment): Likewise. + (bfd_xcoff_size_dynamic_sections): Likewise. + + * sunos.c (sunos_scan_ext_relocs): Only check the reloc symbol + table index against the number of symbols for a base relative + reloc. + + * coff-rs6000.c (_bfd_xcoff_sizeof_headers): Change from macro to + static function. + * xcofflink.c (_bfd_xcoff_bfd_link_hash_table_create): Set + full_aouthdr flag here... + (_bfd_xcoff_bfd_final_link): ...not here. + +Tue Oct 31 12:52:02 1995 Fred Fish + + * libelf.h: Rename to elf-bfd.h to avoid conflict with + systems that have a system . + * Makefile.in: Globally replace libelf.h with elf-bfd.h. + * bfd.c, elf.c, elf32-arc.c, elf32-gen.c, elf32-hppa.c, + elf32-hppa.h, elf32-i386.c, elf32-i860.c, elf32-m68k.c, + elf32-m88k.c, elf32-mips.c, elf32-ppc.c, elf32-sparc.c, + elf64-gen.c, elf64-sparc.c, elfcode.h, elflink.c, + elfxx-target.h: Include elf-bfd.h rather than libelf.h. + * elfxx-target.h: Change libelf.h reference to elf-bfd.h. + +Tue Oct 31 15:30:07 1995 David Mosberger-Tang + + * ecoff.c (ecoff_set_symbol_info): Add new parameter weak. If + set, set BSF_WEAK in symbol. Change all callers. + (ecoff_get_extr): Set weakext based on BSF_WEAK. + (ecoff_link_add_externals): If weakext is set, pass BSF_WEAK to + _bfd_generic_link_add_one_symbol. + (ecoff_indirect_link_order): Check that the section tdata relocs + are not NULL before using them. + + * configure.in (alpha*-*-linux*): Set COREFILE to trad-core.o and + define TRAD_HEADER as hosts/alphalinux.h. + * configure: Rebuild. + * hosts/alphalinux.h: New file. + * trad-core.c (trad_unix_core_file_p): Cast u.u_ar0 to bfd_vma, + not int. + +Tue Oct 31 12:34:11 1995 Ian Lance Taylor + + * coffcode.h (coff_slurp_symbol_table): Accept C_BCOMM and + C_ECOMM storage classes. + + * xcofflink.c (xcoff_mark_symbol): New static function, broken out + of xcoff_mark. + (xcoff_mark): Call xcoff_mark_symbol. + (bfd_xcoff_export_symbol): Call xcoff_mark_symbol. + (bfd_xcoff_link_count_reloc): Call xcoff_mark_symbol rather than + doing it by hand. + (xcoff_build_ldsyms): Build a .loader symbol for an export symbol. + +Mon Oct 30 14:53:48 1995 Ian Lance Taylor + + * xcofflink.c (struct xcoff_final_link_info): Add new line_filepos + field. + (xcoff_find_reloc): New static function. + (xcoff_link_add_symbols): Use it. + (_bfd_xcoff_bfd_final_link): Set finfo.line_filepos. + (xcoff_link_input_bfd): Handle C_BINCL and C_EINCL. Don't + relocate the value of C_DECL. + + * elf.c (elf_fake_sections): Remove bogus BFD_ASSERT. + +Sat Oct 28 01:25:34 1995 steve chamberlain + + * cofflink.c (_bfd_coff_generic_relocate_section): Make + callback decide what goes in .relocs. + * pe[i]-i386.c (TARGET_UNDERSCORE): Define. + * peicode.h (pe_mkobject_hook): Only copy aouthdr if + there is one. + +Sat Oct 28 01:51:02 1995 Ian Lance Taylor + + * xcofflink.c (xcoff_link_add_symbols): Handle csects in the + absolute section. + +Fri Oct 27 18:14:39 1995 Ian Lance Taylor + + * xcofflink.c: More improvements, mostly to fix handling of + constructors and a few other special cases. + * coff-rs6000.c (rs6000coff_vec): Set symbol_leading_char back to + zero, reverting yesterday's change. + * bfd-in.h (bfd_xcoff_link_record_set): Declare. + (bfd_xcoff_link_count_reloc): Declare. + (bfd_xcoff_record_link_assignment): Declare. + * bfd-in2.h: Rebuild. + +Fri Oct 27 14:42:15 1995 Niklas Hallqvist + + * PORTING, aout-arm.c, aout-encap.c, aout-rce.c, aout-target.h, + aoutx.h, gen-aout.c, host-aout.c, hp300bsd.c, i386aout.c + i386bsd.c, i386dynix.c, i386linux.c, i386lynx.c, i386mach3.c, + i386netbsd.c, m68klynx.c, m88kmach3.c, mipsbsd.c, newsos3.c, + ns32knetbsd.c, pc532-mach.c, riscix.c, sparclynx.c, sparcnetbsd.c: + Change PAGE_SIZE to TARGET_PAGE_SIZE. + + * m68knetbsd.c: Ditto as well as add support for the m68k4k object + format. + + * netbsd.h: Double ditto (incl. m68k4k support). NetBSD's text + segments includes the a.out header. See to that the magic number + *always* is big-endian. + + * config.bfd: Add m68*-hp*-netbsd* case. Cross-pollinate m68k and + m68k4k NetBSD configurations. + + * configure.in, configure: Separate i386 & mips NetBSD + configurations from other BSD ones. Don't assume DEC is the only + thing NetBSD/mips run on. Add {m68k,ns32k,sparc}-*-netbsd* + configurations. Add support for m68k4k NetBSD object format. + + * libaout.h: Added M_68K4K_NETBSD magic. + + * m68k4knetbsd.c: New file. + + * hosts/{m68k,sparc}nbsd.h: Don't define HOST_BIG_ENDIAN_P. + + * hosts/nbsd.h: Define HOST_BIG_ENDIAN_P according to + . + + * hosts/mipsnbsd.h: New file. + +Thu Oct 26 14:16:47 1995 Ian Lance Taylor + + * xcofflink.c: Numerous changes to get closer to a working XCOFF + linker. + * libcoff-in.h (struct xcoff_tdata): Add full_aouthdr, + toc_section, and entry_section fields. + (struct xcoff_section_tdata): Remove ldrel_count field. + * libcoff.h: Rebuild. + * coffcode.h (coff_mkobject_hook): Initialize new xcoff_data + fields. + (coff_compute_section_file_positions): If RS6000COFF_C, generate + full a.out header if full_aouthdr is set in xcoff_data. + (coff_write_object_contents): Likewise. Set o_snentry and o_sntoc + based on sections stored in xcoff_data. + * coff-rs6000.c (xcoff_copy_private_bfd_data): Copy new xcoff_data + fields. + (xcoff_reloc_type_lookup): Handle BFD_RELOC_CTOR. + (rs6000coff_vec): Set symbol_leading_char to '.'. + * coffgen.c (coff_get_symbol_info): If fix_value is set, fix the + value stored in ret rather than returning a pointer value. + +Wed Oct 25 23:10:39 1995 Michael Meissner + + * config.bfd (powerpc{,le}-{elf,sysv4,eabi,solaris2}): Remove MAC + format for now. + +Wed Oct 25 16:19:27 1995 Jeffrey A Law (law@cygnus.com) + + * som.c (som_slurp_string_table): Allocate the strings with malloc + since they're free'd by free_cached_info. + (som_slurp_symbol_table): Similarly for the symbol table. + +Wed Oct 25 14:59:22 1995 Per Bothner + + * Makefile.in (diststuff): Don't make headers. + +Wed Oct 25 11:32:54 1995 Ian Lance Taylor + + * Makefile.in: Rebuild dependencies. + + * sunos.c (bfd_sunos_record_link_assignment): Don't do anything if + output_bfd is not SunOS. + (bfd_sunos_size_dynamic_sections): Likewise. Don't scan relocs of + non-SunOS input files. + + * xcofflink.c: Extensive changes to support linking shared objects + and generating a .loader section. + * libcoff-in.h (struct xcoff_tdata): Add import_file_id field. + (struct xcoff_section_tdata): Add lineno_count, first_symndx, + last_symndx, and ldrel_count fields. + * libcoff.h: Rebuild. + * coff-rs6000.c (xcoff_howto_table): Correct reloc names. + * coffcode.h (styp_to_sec_flags): Don't set any flags if STYP_PAD + is set. + * bfd-in.h (bfd_xcoff_import_symbol): Declare. + (bfd_xcoff_export_symbol): Declare. + (bfd_xcoff_size_dynamic_sections): Declare. + * bfd-in2.h: Rebuild. + +Tue Oct 24 17:44:20 1995 Stan Shebs + + * configure.in: Add xcofflink.o to pmac_xcoff_vec. + * configure: Rebuild. + * mpw-config.in: Add xcofflink.c.o to powerpc-apple-macos. + * coff-pmac.c: Include coff-rs6000.c instead of duplicating its + contents. + (pmac_xcoff_vec): Update to use new xcoff support. + * coff-rs6000.c (xcoff_generic_stat_arch_elt): Make static. + (xcoff_write_armap): Declare buf as unsigned char. + * xcofflink.c (xcoff_link_add_symbols): Declare a local as PTR. + + * mpw-make.sed: Generalize subdir_do edit. + +Tue Oct 24 10:25:01 1995 Jeffrey A Law (law@cygnus.com) + + * hppabsd-core.c (make_bfd_asection): Initialize asect->filepos + correctly. Don't initialize asect->vma. + +Fri Oct 20 13:23:48 1995 Ken Raeburn + + * opncls.c (_bfd_new_bfd): If _bfd_chunksize wasn't preset, use + something a little less than the page size. + +Thu Oct 19 13:06:09 1995 Ian Lance Taylor + + * coff-i960.c (coff_i960_adjust_symndx): Clear *adjustedp. + +Wed Oct 18 16:20:08 1995 steve chamberlain + + * coff-i386.c (coff_i386_reloc_type_lookup): New. + * coffcode.h (coff_write_object_contents): If .bss is before + .data us that as data_start. + * cofflink.c (_bfd_coff_generic_relocate_section): Get reloc + calc correct. + * peicode.h (add_data_entry): Use _cooked_size of data directory. + (coff_swap_outhdr_out): Hardwire in version number. + +Wed Oct 18 16:50:54 1995 Ken Raeburn + + * sunos.c (sunos_add_dynamic_symbols): Rename local variables + major and minor to *_vno, since the former are also macros in + SunOS header files. Cast result of bfd_alloc to appropriate + type. + + * coffgen.c (coff_find_nearest_line): Cast used_by_bfd value + before assigning to sec_data. + +Wed Oct 18 13:25:17 1995 Ian Lance Taylor + + * ecoff.c (_bfd_ecoff_find_nearest_line): The offset argument is + now relative to the section, not absolute. + * ecofflink.c (_bfd_ecoff_locate_line): Use the right symbol to + get the file name when there is a N_SO directory name. When + handling stabs, remember that section->vma was added to the + offset. + +Tue Oct 17 18:24:54 1995 Ian Lance Taylor + + * sunos.c (struct sunos_link_hash_table): Add needed field. + (sunos_link_hash_table_create): Call bfd_release, not free. + (sunos_link_hash_table_create): Initialize needed field. + (sunos_add_dynamic_symbols): Record needed objects. + (bfd_sunos_get_needed_list): New function. + * bfd-in.h (bfd_sunos_get_needed_list): Declare. + * bfd-in2.h: Rebuild. + +Mon Oct 16 14:43:59 1995 steve chamberlain + + * libcoff-in.h (pe_data_type.in_reloc_p): New. + +Mon Oct 16 10:52:50 1995 Ian Lance Taylor + + * bfd-in.h (struct bfd_link_needed_list): Rename from + bfd_elf_link_needed_list. + * bfd-in2.h: Rebuild. + * elf.c, elflink.h, libelf.h: Corresponding changes. + + Add start at AIX linker support; no shared libraries yet. + * xcofflink.c: New file. + * configure.in (rs600coff_vec): Use xcofflink.o. + * configure: Rebuild. + * libcoff-in.h (struct xcoff_tdata): Add csects and debug_indices + fields. + (struct xcoff_section_tdata): Define. + (xcoff_section_data): Define macro. + (_bfd_xcoff_bfd_link_hash_table_create): Declare. + (_bfd_xcoff_bfd_link_add_symbols): Declare. + (_bfd_xcoff_bfd_final_link): Declare. + (_bfd_ppc_xcoff_relocate_section): Declare. + * libcoff.h: Rebuild. + * coff-rs6000.c: Clean up a bit. + (xcoff_mkobject): Default modtype to 1L, not RE. Initialize + cputype, csects, and debug_indices. + (xcoff_copy_private_bfd_data): Copy cputype. + (xcoff_howto_table): Rename from rs6000coff_howto_table. + (xcoff_rtype2howto): Rename from rs6000coff_rtype2howto. + (xcoff_reloc_type_lookup): Rename from + rs6000coff_reloc_type_lookup. + (coff_relocate_section): Define. + (_bfd_xcoff_sizeof_headers): Define. + (_bfd_xcoff_bfd_get_relocated_section_contents): Define. + (_bfd_xcoff_bfd_relax_section): Define. + (_bfd_xcoff_bfd_link_split_section): Define. + (rs6000coff_vec): For BFD_JUMP_TABLE_LINK, use _bfd_xcoff, not + coff. + * coffcode.h (coff_compute_section_file_positions): If AIX, + increment sofar by SMALL_AOUTSZ if not executable. + (coff_write_object_contents): If AIX, always output an a.out + header; if not executable, header size of SMALL_AOUTSZ. + * hash.c (struct bfd_strtab_hash): Add xcoff field. + (_bfd_stringtab_init): Initialize xcoff field. + (_bfd_xcoff_stringtab_init): New function. + (_bfd_stringtab_add): In XCOFF mode, leave two bytes for length. + (_bfd_stringtab_emit): In XCOFF mode, write out length. + * libbfd-in.h (_bfd_xcoff_stringtab_init): Declare. + * libbfd.h: Rebuild. + * Makefile.in: Rebuild dependencies. + (BFD32_BACKENDS): Add xcofflink.o. + (CFILES): Add xcofflink.c. + + * elf32-mips.c (mips_elf_symbol_processing): Set SEC_ALLOC, not + SEC_NO_FLAGS, for .acommon section. From Peter Schauer + . + +Sat Oct 14 21:36:02 1995 Michael Meissner + + * coff-ppc.c (in_reloc_p): Add, clone from coff-i386.c. + +Fri Oct 13 17:48:43 1995 Ken Raeburn + + * acconfig.h (HAVE_SYS_PROCFS_H): Undef, with comment. + * config.in: Regenerated. + + * opncls.c (getpagesize) [!HAVE_GETPAGESIZE]: Define as 2048. + (_bfd_chunksize): New variable. + (_bfd_new_bfd): Set it to getpagesize() if negative, and use it + for obstack chunk size. + * configure.in: Check for getpagesize. + * configure: Regenerated. + + Mon Sep 25 22:49:32 1995 Andreas Schwab + + * trad-core.c (rawptr): Make it a local variable of + ptrace_unix_core_file_p. + +Fri Oct 13 11:22:01 1995 steve chamberlain + + * coff-arm.c (in_reloc_p): New. + * coff-i386.c (in_reloc_p): New. + * coffcode.h: Allways include peicode.h if COFF_WITH_PE. + (coff_write_object_contents): Only set has_reloc_section + if PE_IMAGE. + * cofflink.c (_bfd_coff_generic_relocate_section): Call + in_reloc_p to decide if reloc should be emitted. + * libcoff.h (pe_data_type.in_reloc_p): New. + * peicode.h (pe_mkobject): Initialize in_reloc_p. + +Wed Oct 11 00:49:29 1995 Ian Lance Taylor + + * cofflink.c (_bfd_coff_internal_syment_name): Move to coffgen.c. + (_bfd_coff_read_internal_relocs): Likewise. + * coffgen.c (_bfd_coff_internal_syment_name): Copy from coffgen.c. + (_bfd_coff_read_internal_relocs): Likewise. + + * elflink.h (elf_link_add_object_symbols): Correct conditions + under which type and size change warnings are issued. + +Tue Oct 10 18:32:46 1995 Ian Lance Taylor + + * coffgen.c (coff_count_linenumbers): Don't count line numbers for + a symbol which is not in a real section. + (coff_write_native_symbol): Corresponding change. + + * cofflink.c (_bfd_coff_link_hash_newfunc): Rename from + coff_link_hash_newfunc and make non-static. + (_bfd_coff_link_hash_table_init): New function, broken out of + _bfd_coff_link_hash_table_create. + (_bfd_coff_link_hash_table_create): Use it. + (process_embedded_commands): Make static. + * libcoff-in.h ((_bfd_coff_link_hash_newfunc): Declare. + (_bfd_coff_link_hash_table_init): Declare. + * libcoff.h: Rebuild. + + * coffcode.h (coff_mkobject_hook): If RS6000COFF_C, set cputype + field in XCOFF tdata. + (coff_set_arch_mach_hook): Check ifdef RS6000COFF_C, not ifdef + U802ROMAGIC, for clarity. Try to set arch and machine correctly + based on cputype stored in a.out header, or in n_type of initial + .file symbol. + (coff_write_object_contents): Set cputype correctly in a.out + header. + (coff_slurp_symbol_table): Add casts to file_ptr to avoid + warnings. + * coffswap.h (coff_swap_aouthdr_in): Swap in cputype field. + (coff_swap_aouthdr_out): Swap out cputype field. Don't clear + old resv1 field. + * libcoff-in.h (struct xcoff_tdata): Add cputype field. + * libcoff.h: Rebuild. + + * cpu-rs6000.c (rs6000_compatible): New static function. + (bfd_rs6000_arch): Use it. + * cpu-powerpc.c (powerpc_compatible): New static function. + (arch_info_struct): Define various flavours of PowerPC. + (bfd_powerpc_arch): Use powerpc_compatible. Point at + arch_info_struct. + +Tue Oct 10 10:50:46 1995 Fred Fish + + * Makefile.in (FLAGS_TO_PASS): Remove BISON. + +Tue Oct 10 01:28:29 1995 Ian Lance Taylor + + * elflink.h (elf_link_add_object_symbols): Don't warn about + changing the size or type if the old definition was weak. + +Mon Oct 9 11:24:08 1995 Ian Lance Taylor + + * coffcode.h (combined_entry_type): Add fix_line field. + (coff_slurp_line_table): Warn if we try to set the lineno field of + a symbol twice. + (coff_slurp_symbol_table): If RS6000COFF_C, handle C_BINCL and + C_EINCL by setting fix_line. Fix C_BSTAT symbol value. + * coffgen.c (coff_mangle_symbols): Handle fix_line. + (coff_write_symbol): Only use N_DEBUG if the symbol is in the + absolute section. + (coff_print_symbol): Print fix_value symbols in a useful fashion. + * libcoff.h: Rebuild. + + * libcoff-in.h (struct xcoff_tdata): Define. + (xcoff_data): Define. + * bfd.c (struct _bfd): Add xcoff_obj_data field to tdata union. + * bfd-in2.h, libcoff.h: Rebuild. + * coff-rs6000.c (xcoff_mkobject): New static function. + (coff_mkobject): Define. + (xcoff_copy_private_bfd_data): New static function. + (coff_bfd_copy_private_bfd_data): Define. + (rs6000coff_howto_table): Change R_TOC complain_on_overflow from + signed to bitfield. + (rs6000coff_vec): Add DYNAMIC to object_flags. + * coffcode.h (sec_to_styp_flags): If RS6000COFF_C, handle .pad and + .loader sections specially. + (coff_new_section_hook): If RS6000COFF_C, get the .text and .data + section alignment from the XCOFF tdata information. + (coff_mkobject_hook): If RS6000COFF_C, set DYNAMIC based on + F_SHROBJ, and copy the extra a.out header information into the + XCOFF tdata structure. + (coff_write_object_contents): If RS6000COFF_C, set F_SHROBJ, + F_DYNLOAD and the extra a.out header information. + (coff_slurp_symbol_table): Set BSF_NOT_AT_END for a C_EXT or + C_HIDEXT symbol with attached csect information. + * coffswap.h (coff_swap_aouthdr_in): If RS6000COFF_C, swap + in the o_maxdata field. + (coff_swap_aouthdr_out): If RS6000COFF_C, swap extra XCOFF fields. + * coffgen.c (coff_renumber_symbols): Don't move any symbol to the + end if BSF_NOT_AT_END is set. + + * targets.c (bfd_target): Rename _bfd_read_ar_hdr field to + _bfd_read_ar_hdr_fn. + * libbfd-in.h (_bfd_read_ar_hdr): Update accordingly. + * bfd-in2.h, libbfd.h: Rebuild. + * archive.c (_bfd_get_elt_at_filepos): Cast _bfd_read_ar_hdr + return value. + (do_slurp_bsd_armap, do_slurp_coff_armap): Likewise. + (bfd_slurp_bsd_armap_f2): Likewise. + (_bfd_slurp_extended_name_table): Likewise. + +Fri Oct 6 16:18:35 1995 Ken Raeburn + + Mon Sep 25 22:49:32 1995 Andreas Schwab + + * archive.c (bfd_get_next_mapent): Return BFD_NO_MORE_SYMBOLS + when the symbol table is empty. + + * elf32-m68k.c (elf_m68k_size_dynamic_sections): Don't reserve + space for section symbols, since we don't output them either. + (elf_m68k_adjust_dynindx): Removed. + + * ptrace-core.c (rawptr): Make it a local variable of + ptrace_unix_core_file_p. + +Fri Oct 6 12:24:47 1995 Michael Meissner + + * coff-rs6000.c (xcoff_write_archive_contents): Return false, not + NULL. + + * config.bfd (powerpc{,le}-{elf,sysv4,eabi,solaris2}): Add NT, and + Mac object file formats. + +Fri Oct 6 12:04:02 1995 Ian Lance Taylor + + * coffgen.c (coff_fix_symbol_name): Don't try to set up file + auxent if there isn't one. + (coff_write_symbols): If there is no file auxent, use SYMNMLEN + rather than FILNMLEN as the maximum name length. + + * coffcode.h (bfd_coff_backend_data): Add new field + _bfd_coff_print_aux. + (bfd_coff_print_aux): New static function. + (coff_pointerize_aux_hook (RS6000COFF_C version)): Pointerize the + scnlen field of an XTY_LD csect aux entry. + (coff_print_aux): New static function. + (coff_slurp_symbol_table): Don't pointerize scnlen field; now done + in coff_pointerize_aux_hook. + (bfd_coff_std_swap_table): Initialize new field. + * coffgen.c (coff_print_symbol): Call bfd_coff_print_aux. + * libcoff.h: Rebuild. + * coff-alpha.c (alpha_ecoff_backend_data): Initialize new field. + * coff-mips.c (mips_ecoff_backend_data): Likewise. + + * coffcode.h (coff_write_object_contents): On AIX, clear F_RELFLG + if there are symbols, for native AIX ld compatibility. + + * coffcode.h (bfd_coff_backend_data): Add new field + _bfd_coff_pointerize_aux_hook. + (coff_pointerize_aux_hook): Define as a function if RS6000COFF_C + or I960, and as 0 otherwise. + (bfd_coff_std_swap_table): Initialize new field. + * libcoff.h: Rebuild. + * coffgen.c (coff_pointerize_aux): Change parameters to take + symbol pointer instead of type and class, and to take aux index. + Call _bfd_coff_pointerize_aux_hook if it is defined. + (coff_get_normalized_symtab): Always call coff_pointerize_aux. + * coff-alpha.c (alpha_ecoff_backend_data): Initialize all fields. + * coff-mips.c (mips_ecoff_backend_data): Likewise. + + * coff-rs6000.c: Add full support for AIX archives. Rewrite old + read-only/host-only support. + + * coffcode.h (coff_slurp_symbol_table): Set C_HIDEXT symbols to be + BSF_LOCAL. + (OTHER_GLOBAL_CLASS): Do not define to be C_HIDEXT if + RS6000COFF_C. + + * targets.c (bfd_target): Add _bfd_read_ar_hdr field. Modify + BFD_JUMP_TABLE_ARCHIVE accordingly. + * libbfd-in.h (_bfd_snarf_ar_hdr): Don't declare. + (_bfd_compute_and_write_armap): Declare. + (_bfd_generic_read_ar_hdr): Declare. + (_bfd_read_ar_hdr): Define. + (_bfd_noarchive_read_ar_hdr): Define. + (_bfd_archive_bsd_read_ar_hdr): Define. + (_bfd_archive_coff_read_ar_hdr): Define. + * archive.c: Change all callers of _bfd_snarf_ar_hdr to call + _bfd_read_ar_hdr instead. + (_bfd_generic_read_ar_hdr): Rename from _bfd_snarf_ar_hdr. + (_bfd_compute_and_write_armap): Rename from + compute_and_write_armap. Make non-static. Change all callers. + * ecoff.c (_bfd_ecoff_slurp_armap): Call _bfd_read_ar_hdr rather + than _bfd_snarf_ar_hdr. + * aout-target.h (MY_read_ar_hdr): Define if not defined. + * ieee.c (ieee_read_ar_hdr): Define. + * libecoff.h (_bfd_ecoff_read_ar_hdr): Define. + * oasys.c (oasys_read_ar_hdr): Define. + * som.c (som_read_ar_hdr): Define. + * bfd-in2.h, libbfd.h: Rebuild. + +Thu Oct 5 14:04:07 1995 steve chamberlain + + * peicode.c (coff_swap_filehdr_in): If symptr is + zero, there aren't any symbols, even if nsyms is set. + +Thu Oct 5 11:45:02 1995 Ian Lance Taylor + + * libecoff.h (struct ecoff_backend_data): Add adjust_headers + field. + * ecoff.c (ecoff_sec_to_styp_flags): Check for various Alpha + sections, and set styp correctly for them: .got, .hash, .dynamic, + .liblist, .rel.dyn, .conflic, .dynstr, .dynsym, .comment. + (_bfd_ecoff_styp_to_sec_flags): Check for various Alpha section + types. + (ecoff_sort_hdrs): New static function. + (ecoff_compute_section_file_positions): Return boolean, not void. + Sort the sections by VMA before looking through them. Put the + first non SEC_ALLOC section on a new page. Put every SEC_ALLOC + section on an appropriate boundary within the page. + (ecoff_compute_reloc_file_positions): Check return value of + ecoff_compute_section_file_positions. + (_bfd_ecoff_set_section_contents): Likewise. + (_bfd_ecoff_write_object_contents): Check for various Alpha + section types when incrementing text_size and data_size. Call + adjust_headers backend function if it exists. + * coff-alpha.c (alpha_adjust_headers): New static function. + (alpha_ecoff_backend_data): Initialize adjust_headers field. + * coff-mips.c (mips_ecoff_backend_data): Likewise. + + * hosts/i386bsd.h: Restore file incorrectly deleted on Sep 6. + +Wed Oct 4 18:15:02 1995 Jeff Law (law@hurl.cygnus.com) + + * rs6000-core.c (CORE_VERSION_1): Use CORE_VERSION_1 instead + of ALTERNATE_AIX_CORE_FORMAT. + * configure.in (aix4): No longer need CORE_FLAGS. + * configure: Updated. + +Wed Oct 4 15:36:36 1995 Ken Raeburn + + NS32k changes from Ian Dall: + * aoutx.h (MY_final_link_relocate, MY_relocate_contents): New + macros. + (aout_link_input_section_std, aout_link_input_section_ext, + aout_link_reloc_link_order): Call them instead of _bfd_* + versions. + * aout-target.h (MY_exec_header_not_counted): New macro, defaults + to zero. + (backend_data): Use it instead of hardcoded zero. + + * aout-ns32k.c (CTOR_TABLE_RELOC_HOWTO): New macro. + (MY_swap_std_reloc_out): Use udata.i for KEEPIT, don't call stoi. + + * ns32knetbsd.c: Include bfd.h. + (MY_text_includes_header, MY_bfd_reloc_type_lookup): New macros. + (MY_bfd_reloc_type_lookup): Declare function too. + * pc532-mach.c (set_sizes): Don't declare. + (MY_text_includes_header, MY_exec_header_not_counted): Define. + (backend_data, MY_backend_data): Don't define. + + * config.bfd: Treat ns32k-pc532-ux* like ns32k-pc532-mach*, and + ns32k-*-lites* like ns32k-*-netbsd*. + + * hosts/nbsd.h: Swap order of sys/vmparam.h and sys/param.h, to + compile on lites. + +Wed Oct 4 14:15:52 1995 Ian Lance Taylor + + * coffcode.h (coff_write_object_contents): Restore setting + f_timdat to 0, deleted on August 22. + +Tue Oct 3 16:28:32 1995 steve chamberlain + + * coffcode.h (coff_bfd_copy_private_symbol_data, + coff_bfd_copy_private_section_data, + coff_bfd_copy_private_bfd_data): ifdef to allow overrides. + * peicode.h (coff_bfd_copy_private_bfd_data): New + (pe_bfd_copy_private_bfd_data): New. + (coff_swap_scnhdr_in): Swap bss size into the right place. + (pe_print_private_bfd_data): Add some newlines. + +Tue Oct 3 11:53:04 1995 Jeff Law (law@hurl.cygnus.com) + + * som.c (setup_sections): Don't die if a space has no subspaces. + +Mon Oct 2 14:08:55 1995 Ian Lance Taylor + + * elflink.h (elf_link_add_object_symbols): Don't let a weak + dynamic symbol override a common symbol. Don't change the size or + type if they have been set and the new symbol is not a definition. + Warn if the size or type changes. + +Sun Oct 1 01:34:41 1995 Jeff Law (law@hurl.cygnus.com) + + * som.c (som_begin_writing): Don't write the symbol table or + symbol strings. + (som_finish_writing): Write them here. Place them after the + subspace data, but before the relocs. + +Fri Sep 29 11:01:55 1995 Ian Lance Taylor + + * sunos.c (sunos_add_one_symbol): Just pass false, not + info->shared_library, to sunos_create_dynamic_sections. + (sunos_scan_ext_relocs): Don't warn about a reloc in the .text + section. + (sunos_check_dynamic_reloc): Remove .text section assertion. + +Thu Sep 28 18:48:47 1995 Stan Shebs + + * config.bfd: Add powerpc-*-macos*, powerpc-*-mpw*. + * configure, configure.in: Add pmac_xcoff_vec case. + * Makefile.in (BFD32_BACKENDS): Add coff-pmac.o. + * coff-pmac.c: New file, PowerMac XCOFF support. + * coffcode.h (coff_set_arch_mach_hook): Add PowerMac case. + * targets.c (pmac_xcoff_vec): Declare. + + * mpw-config.in: Various changes to be compatible with the + autoconf-based configury. + * mpw-make.sed: New file, sed commands to translate Unix + makefile into MPW syntax. + * mpw-make.in: Remove. + * hosts/mpw.h: Remove. + * bfd-in.h, bfd-in2.h: If MPW, include the file that defines + true and false as enums, then define TRUE_FALSE_ALREADY_DEFINED. + +Thu Sep 28 17:06:23 1995 steve chamberlain + + * binary.c (binary_get_symtab): Return an empty string on error. + * opncls.c (bfd_fdpenr): Change WIN32 restriction to WINGDB. + +Thu Sep 28 15:30:44 1995 Kim Knuttila + + * coff-ppc.c: Reformatted according to gnu conventions + Removed irrelevant "if 0" code + +Thu Sep 28 11:19:53 1995 Ian Lance Taylor + + * hp300hpux.c (convert_sym_type): Treat secondary symbols as weak + symbols rather than as indirect symbols. + (MY(slurp_symbol_table)): Don't do anything special about + secondary symbols. + + * coffcode.h (coff_new_section_hook): Make sure that the alignment + of .ctors and .dtors sections is no larger than 2. + + * sunos.c (sunos_add_one_symbol): Don't change + bfd_link_hash_common to bfd_link_hash_new, since it may be on the + undef list. + (bfd_sunos_record_link_assignment): Don't put __DYNAMIC in the + dynamic symbols when creating a shared library. + (sunos_scan_ext_relocs): Handle relocs correctly when creating a + shared library. + (sunos_scan_dynamic_symbol): Don't mark the __DYNAMIC symbol as + written even if it is not defined in a regular object. + (sunos_write_dynamic_symbol): Use plt_offset for the address of + the jump table reloc. Add an assertion. Use RELOC_JMP_SLOT + rather than the constant 22. + (sunos_check_dynamic_reloc): Handle creating a shared library. + (sunos_finish_dynamic_link): Set the first entry in the GOT to + zero when creating a shared library. + * aoutx.h (NAME(aout,final_link)): If there is a symbol __DYNAMIC, + write it out at the start of the symbol table. + + * Makefile.in (BFD32_BACKENDS): Add coff-arm.o. + +Thu Sep 28 00:58:05 1995 Doug Evans + + * config.bfd: Add arm-*-coff. + * configure.in, configure: Add armcoff_{little,big}_vec. + * targets.c (armcoff_{little,big}_vec): Declare. + (bfd_target_vector): Add armcoff_{little,big}_vec. + * coff-arm.c (armcoff_{little,big}_vec): Always define. + +Wed Sep 27 10:37:14 1995 Ian Lance Taylor + + * targets.c (bfd_find_target): Remove debugging code. + +Wed Sep 27 07:23:39 1995 Kim Knuttila + + * coff-ppc.c, pe-ppc.c, pei-ppc.c: Initial bfd for coff/PE + support on powerpc. + * Makefile.in: added *-ppc files + * coffcode.h: ppc MAGIC, and use peicode.h rather than coffswap.h to + allow pe based .o's to be shared with other tools on ppc/NT + * config.bfd: added powerpc[le]-[pe|winnt] config support + * configure, configure.in: added bfd_powerpc[le]_pe[i]_vec + * peicode.h: Added more section flags for PE on ppc + Added coff_swap_filehdr_out to allow peicode.h to be + used for non-image PE files on ppc. + Check for image, or not, before copying pe_opthdr + * targets.c: Added new bfd's + * targets.c: Removed two inactive bfds that shouldn't have made it this + far. + +Tue Sep 26 14:06:41 1995 Michael Meissner + + * elf32-ppc.c (ppc_reloc_type): Rename from reloc_type, and use + explicit values to initialize all relocs. Change all users. + (ppc_elf_brtaken_inner): New function to handle branch predicition + relocs. + (ppc_elf_brtaken_reloc): Ditto. + (ppc_elf_howto_raw): Use new functions. Make sure all unsupported + relocs use ppc_elf_unsupported_reloc. + (ppc_elf_merge_private_bfd_data): Keep track of whether an error + needs to be reported. + (ppc_elf_relocate_section): Support branch prediction relocs. + +Tue Sep 26 12:48:05 1995 Ian Lance Taylor + + * bfd.c (bfd_assert): Remove \n from string passed to + _bfd_error_handler. + + * coff-i386.c: (TWO_DATA_SECS): Don't define. + * coffcode.h (bfd_coff_backend_data): Remove _bfd_make_section_hook. + (bfd_coff_make_section_hook): Don't define. + (coff_make_section_hook): Remove. + (sec_to_styp_flags): Remove TWO_DATA_SECS case. + (styp_to_sec_flags): Likewise. + (coff_write_object_contents): Likewise. + (bfd_coff_std_swap_table): Don't initialize make_section_hook + field. + * libcoff.h: Rebuild. + * coffgen.c (make_a_section_from_file): Just call + bfd_make_section_anyway, not bfd_make_section or + bfd_coff_make_section_hook. + * ecoff.c (_bfd_ecoff_make_section_hook): Remove. + * libecoff.h (_bfd_ecoff_make_section_hook): Don't declare. + * coff-alpha.c (alpha_ecoff_backend_data): Don't initialize + make_section_hook field. + * coff-mips.c (mips_ecoff_backend_data): Likewise. + + * aoutx.h (translate_from_native_sym_flags): Don't try to stuff + pointers into value field for warning and indirect symbols; just + leave the value field alone. + * linker.c (generic_link_add_symbol_list): Use next symbol for + warning and indirect symbols, rather than looking in symbol value. + * ecoff.c (ecoff_set_symbol_info): Remove indirect_ptr_ptr + parameter. Change all callers. Remove support for indirect + symbols; it didn't work anyhow. + (_bfd_ecoff_slurp_symbol_table): Remove indirect_ptr variable. + * syms.c: Change comments about BSF_WARNING and BSF_INDIRECT. + * bfd-in2.h: Rebuild. + +Mon Sep 25 16:04:09 1995 Michael Meissner + + * elf32-ppc.c (ppc_elf_howto_raw): For all 14-bit branch relocs, + go back to telling the tools this reloc operates on 32 bits. + +Mon Sep 25 11:48:02 1995 Ian Lance Taylor + + * aout-adobe.c (aout_adobe_callback): Use _bfd_error_handler + rather than a direct fprintf. + * archive.c (_bfd_write_archive_contents): Likewise. + * coffcode.h (coff_slurp_symbol_table): Likewise. + * elf32-ppc.c (ppc_elf_merge_private_bfd_data): Likewise. + (ppc_elf_unsupported_reloc): Likewise. + (ppc_elf_relocate_section): Likewise. + * i386linux.c (linux_tally_symbols): Likewise. + (linux_finish_dynamic_link): Likewise. + * osf-core.c (osf_core_core_file_p): Likewise. + * rs6000-core.c (rs6000coff_get_section_contents): Likewise. + * som.c (som_sizeof_headers): Likewise. + * srec.c (srec_bad_byte): Likewise. + * bfd.c (bfd_assert): Likewise. Also change file to be const. + * libbfd-in.h (bfd_assert): Declare first parameter const. + * libbfd.h: Rebuild. + * coff-a29k.c (a29k_reloc): Don't bother to fprintf; returning + bfd_reloc_overflow is enough. + * coff-h8300.c (rtype2howto): Don't bother to fprintf; just abort. + * coff-h8500.c (rtype2howto): Likewise. + * coff-z8k.c (rtype2howto): Likewise. + * coffcode.h (dummy_reloc16_extra_cases): Likewise. + * elf.c (_bfd_elf_get_lineno): Likewise. + (_bfd_elf_no_info_to_howto): Likewise. + (_bfd_elf_no_info_to_howto_rel): Likewise. + * hp300hpux.c (convert_sym_type): Likewise. + (MY(swap_std_reloc_in)): Likewise. + * elf.c (bfd_section_from_shdr): Remove #if 0 sections. + + * libaout.h (struct aoutdata): Add line_buf field. + * aoutx.h (NAME(aout,find_nearest_line)): Remove statics buffer + and filename_buffer. Instead, use a malloc buffer stored in the + new line_buf field. Remove length restrictions. + + * coffgen.c (string_size): Remove static variable. + (debug_string_size, debug_string_section): Likewise. + (coff_fix_symbol_name): Add string_size_p, debug_string_section_p, + and debug_string_size_p parameters. Use them instead of the + global variables. Change all callers. + (coff_write_symbol): Likewise. + (coff_write_alien_symbol, coff_write_native_symbol): Likewise. + (coff_write_symbols): Add local variables to replace removed + global variables. + + * libcoff-in.h (struct coff_section_tdata): Add offset, i, + function, and line_base fields. + * libcoff.h: Rebuild. + * coffgen.c (coff_find_nearest_line): Use section tdata to cache + information, rather than using static variables. + + * sunos.c (sunos_read_dynamic_info): Adjust offsets in an NMAGIC + file. From Peter DeWolf . + + * init.c (initialized): Remove static variable. + (bfd_init): Don't bother setting initialized. + (bfd_check_init): Remove. + * opncls.c (_bfd_new_bfd): Don't call bfd_check_init. + * libbfd.h: Rebuild. + +Sat Sep 23 01:22:23 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * rs6000-core.c (rs6000coff_core_p): Don't check the core file + size for full core dumps. Copy core file header to private data. + (rs6000coff_core_file_failing_command, + rs6000coff_core_file_failing_signal): New functions to extract + the file name and terminating signal from the core file. + * coff-rs6000.c: Use them. + +Fri Sep 22 17:44:47 1995 Ian Lance Taylor + + Change arch info to be const, initialized at compile time. + * archures.c: Reindent many functions. Change CONST to const. + (bfd_arch_info_type): Make arch_name const. Remove disassemble; + nothing set it anyhow. Make next const. + (bfd_arch_info_list): Remove. + (bfd_archures_list): Rename from archures_init_table. Change from + a table of function pointers to a table of bfd_arch_info_type + structure addresses. + (bfd_scan_arch): Rewrite accordingly. Return a const pointer. + (bfd_lookup_arch): Likewise. + (bfd_set_arch_info): Rewrite accordingly. Change argument to be a + const pointer. + (bfd_default_arch_struct): Make const. + (bfd_arch_init, bfd_arch_linkin): Remove. + (bfd_get_arch_info): Return a const pointer. + * init.c (bfd_init): Don't call bfd_arch_init. + * bfd.c (struct _bfd): Make arch_info const. + * bfd-in2.h: Rebuild. + * libbfd.h: Rebuild. + * configure.in: Put & before everything in $selarchs. + * configure: Rebuild. + * cpu-*.c: Change bfd_*_arch from a function which calls + bfd_arch_linkin to a const structure. + * ieee.c (ieee_object_p): Make arch const. + +Fri Sep 22 16:23:18 1995 Michael Meissner + + * reloc.c (bfd_reloc_code_type): Add relocations to support all of + PowerPC V.4. + * bfd-in2.h: Regenerate. + * libbfd.h: Regenerate. + + * elf32-ppc.c (reloc_type): Update names to match current draft. + (ppc_elf_howto_raw): Mark 14 bit relocs as short sized and PC + relative. Update names to current V.4 draft. + (ppc_elf_reloc_type_lookup): Add support for more relocations. + (ppc_elf_relocate_section): Rename relocations to match draft. + +Thu Sep 21 21:53:18 1995 Michael Meissner + + * elf32-ppc.c (ppc_elf_merge_private_bfd_data): Allow modules + compiled with -mrelocatable-lib to be linked with either normal + modules or -mrelocatable modules. + +Wed Sep 20 12:03:26 1995 Ian Lance Taylor + + * coffcode.h (coff_write_object_contents): Clear the vstamp field + in the a.out header. + + * aoutx.h (NAME(aout,swap_ext_reloc_out)): Don't set r_extern for + a reloc against a local symbol, even if it's not a section. + +Tue Sep 19 17:02:26 1995 Ian Lance Taylor + + * targets.c (bfd_target): Remove unused align_power_min field. + * bfd-in2.h: Rebuild. + * All backends: Remove initialization of align_power_min. + +Tue Sep 19 14:02:21 1995 steve chamberlain + + * peicode.h (coff_swap_scnhdr_out): Get sizes for BSS right. + +Mon Sep 18 14:35:01 1995 Arne H. Juul + + * config.bfd (mips-dec-netbsd*): New target. + * configure.host (mips-dec-netbsd*): New host. + * configure.in (mips-dec-netbsd*): New native. + * configure: Rebuild. + +Fri Sep 15 10:24:36 1995 Ian Lance Taylor + + Make the COFF backend linker merge common types: + * cofflink.c (struct coff_debug_merge_element): Define. + (struct coff_debug_merge_type): Define. + (struct coff_debug_merge_hash_entry): Define. + (struct coff_debug_merge_hash_table): Define. + (coff_debug_merge_hash_table_init): Define. + (coff_debug_merge_hash_table_free): Define. + (coff_debug_merge_hash_lookup): Define. + (struct coff_final_link_info): Add debug_merge field. + (coff_debug_merge_hash_newfunc): New static function. + (_bfd_coff_final_link): Allocate and free debug_merge table. + (coff_link_input_bfd): Merge identical enum, struct and union + types. + +Thu Sep 14 14:53:58 1995 Ian Lance Taylor + + Convert i960 COFF to use COFF backend linker. + * coff-i960.c (coff_i960_relocate): Use a coff_section_data + structure to store the symbol being used. + (coff_i960_start_final_link): New static function. + (coff_i960_relocate_section): New static function. + (coff_i960_adjust_symndx): New static function. + (coff_start_final_link): Define. + (coff_relocate_section): Define. + (coff_adjust_symndx): Define. + * coffcode.h (bfd_coff_backend_data): Add new callback function + _bfd_coff_start_final_link. + (bfd_coff_start_final_link): Define. + (coff_start_final_link): Define if not defined. + (bfd_coff_std_swap_table): Add coff_start_final_link. + * cofflink.c (_bfd_coff_internal_syment_name): Make globally + visible. + (_bfd_coff_final_link): Call bfd_coff_start_final_link if the + function callback is not NULL. + * libcoff-in.h (struct coff_section_tdata): Add tdata field. + (_bfd_coff_internal_syment_name): Declare. + * libcoff.h: Rebuild. + * configure.in (icoff_big_vec): Add cofflink.o. + (icoff_little_vec): Likewise. + * configure: Rebuild. + +Wed Sep 13 17:38:23 1995 Fred Fish + + * Makefile.in (clean-info): Remove extraneous tab from line + following action. + +Wed Sep 13 13:27:53 1995 Ian Lance Taylor + + * cofflink.c (coff_link_input_bfd): Fail if a section with no + contents has relocs. + +Thu Sep 12 12:45:34 1995 steve chamberlain + + * coffcode.h (coff_compute_section_file_positions): Keep the + raw size safe. + (coff_write_object_contents): Remember if it's a relocatable + file. + * libcoff-in.h (pe_data_type): New member 'has_reloc_section' + * peicode.h (coff_swap_filehdr_out): Clear not-reloc flag + if relocatable file. Swap out saved raw size. + +Tue Sep 12 12:14:33 1995 Ian Lance Taylor + + * Makefile.in (do_maintainer_clean): Rename from do_realclean. + (maintainer-clean): Rename from realclean, passing + maintainer-clean down to subdirectories, but leave realclean as a + synonym. + + * linker.c (_bfd_generic_link_add_one_symbol): Pass symbol name to + warning callback. + + * dep-in.sed: Remove config.h from generated dependencies. + + * sunos.c (sunos_slurp_dynamic_symtab): New static function, + broken out of sunos_canonicalize_dynamic_symtab. + (sunos_canonicalize_dynamic_symtab): Call new function + sunos_slurp_dynamic_symtab. + (sunos_add_dynamic_symbols): Add three new parameters. Return the + dynamic symbol table to the caller. + * aoutx.h (aout_link_add_symbols): Permit add_dynamic_symbols + callback to override the symbols being read. + * libaout.h (struct aout_backend_data): Add three new parameters + to add_dynamic_symbols callback. + + Extensive minor changes to avoid various gcc warnings. Also: + * Makefile.in (BFD32_BACKENDS): Remove coff-arm.o. + * archures.c (bfd_arch_info_type): Change mach field from long to + unsigned long. + (bfd_lookup_arch): Change machine parameter from long to unsigned + long. + +Mon Sep 11 10:55:47 1995 Ian Lance Taylor + + * sunos.c (sunos_scan_std_relocs): Fix BFD_ASSERT: it's OK to find + a symbol with a non-zero plt_offset. + +Fri Sep 8 11:47:24 1995 Ian Lance Taylor + + * elfcode.h (align_file_position): Remove; not used. + + * configure.in: Only check for on a native system, + and make sure it defines prstatus_t. + * configure: Rebuild. + +Thu Sep 7 12:48:01 1995 Ian Lance Taylor + + * sunos.c (sunos_write_dynamic_symbol): Correct m68k abort test. + + * config.in: Rename from config.h.in. + * configure.in: Call AC_CONFIG_HEADER with config.h:config.in. + Check for config.h:config.in when creating stamp-h. + * configure: Rebuild. + * Makefile.in (stamp-h): Depend upon config.in rather than + config.h.in. Set CONFIG_HEADERS to config.h:config.in when + calling config.status. + + * Makefile.in (do_distclean): Remove config.h and stamp-h. + (Makefile): Just rebuild Makefile. + (config.h, stamp-h): New targets. + * configure.in: Create stamp-h when rebuilding config.h. + * configure: Rebuild. + +Wed Sep 6 15:00:33 1995 Ian Lance Taylor + + * configure.in: Call AC_CONFIG_HEADER. Substitute + HOST_64BIT_LONG. Check that various header files exist. Check + that fcntl exists. Call BFD_BINARY_FOPEN. Check whether malloc + and/or free need to be declared. Don't make a link to sysdep.h. + Define TRAD_HEADER for various hosts. + * configure: Rebuild. + * configure.host: Don't set my_host. Add definitions taken from + host header files for various entries. Remove entries which now + do nothing. + * acconfig.h: New file. + * config.h.in: New file, built by autoheader. + * sysdep.h: New file. + * Makefile.in (do_distclean): Don't remove sysdep.h. + (RECONFIG): Remove. + (LOCAL_H_DEPS): New variable. + ($(BFD_LIBS)): Use $(LOCAL_H_DEPS) rather than libbfd.h and + $(RECONFIG). + ($(BFD_MACHINES), $(BFD_BACKENDS)): Likewise. + ($(OPTIONAL_BACKENDS)): Likewise. + (stmp-bfd.h): Just substitute for BFD_HOST_64BIT_LONG, rather than + looking through sysdep.h. + * bfd-in.h (BFD_HOST_64BIT_LONG): Define; set by Makefile. + (BFD_HOST_64_BIT): Define based on BFD_HOST_64BIT_LONG. + (fprintf_vma, sprintf_vma): Likewise. + (int64_type, uint64_type): Don't define. + * bfd-in2.h: Rebuild. + * archures.c, bfd.c, srec.c: Include . + * elfcore.h: Check HAVE_SYS_PROCFS_H rather than HAVE_PROCFS. + * lynx-core.c: Include stuff from old hosts/lynx.h. + * opncls.c (bfd_fdopenr): Check HAVE_FNCTL and defined (F_GETFL), + rather than NO_FCNTL. + * targets.c (bfd_target_list): Check HOST_HPPAHPUX and ! __STDC__ + rather than NATIVE_HPPAHPUX_COMPILER. + * trad-core.c: Don't include . Include TRAD_HEADER if it + is defined. + * hosts/*.h: Remove all header files which merely include, + declare, and define things. Leave header files which define + information needed by trad-core.c. + + * aclocal.m4 (BFD_BINARY_FOPEN): Define. + (BFD_CC_FOR_BUILD): Define. + * configure.in: Use BFD_CC_FOR_BUILD. + * configure: Rebuild. + +Tue Sep 5 19:35:28 1995 Ian Lance Taylor + + * aclocal.m4: Don't try to grep ../Makefile if it doesn't exist. + * configure: Rebuild. + + * coff-sparc.c (CALC_ADDEND): Don't set the addend to the value of + a global symbol. + +Tue Sep 5 12:48:26 1995 Jason Molenda (crash@phydeaux.cygnus.com) + + * config.bfd: i386pe_ve -> i386pe_vec. + +Mon Sep 4 14:02:43 1995 Ian Lance Taylor + + * configure.host: Incorporate host Makefile fragments by setting + shell variables. + * configure.in: Call AC_PROG_CC. Substitute CFLAGS, HDEFINES and + AR. Call AC_PROG_INSTALL. Substitute CC_FOR_BUILD, choosing a + value based on whether the code is being compiled by a cross + compiler. Don't substitute host_makefile_frag or frags. + * aclocal.m4: New file to define local AC_PROG_CC. + * configure: Rebuild. + * Makefile.in (INSTALL): Set to @INSTALL@. + (INSTALL_PROGRAM): Set to @INSTALL_PROGRAM@. + (INSTALL_DATA): Set to @INSTALL_DATA@. + (AR): Set to @AR@. + (CC): Define as @CC@. + (CFLAGS): Set to @CFLAGS@. + (CC_FOR_BUILD): Set to @CC_FOR_BUILD@. + (@host_makefile_frag@): Remove. + (ALL_CFLAGS): Change $(HDEFINES) to @HDEFINES@. Move $(CFLAGS) + after other options. + (config.status): Remove dependency upon @frags@. + * config/*.mh, config/README: Remove. + + * config.bfd: Rewrite to incorporate the contents of the Makefile + fragments by setting shell variables, rather than merely returning + the name of a Makefile fragment. + * configure.in: Use shell variables set by config.bfd rather than + looking at the target Makefile fragment files. Don't substitute + target_makefile_frag. Do substitute TDEFINES. + * configure: Rebuild. + * Makefile.in (@target_makefile_frag@): Remove. + (ALL_CFLAGS): Change $(TDEFINES) to @TDEFINES@. + * config/*.mt: Remove. + +Mon Sep 4 03:13:28 1995 Ken Raeburn + + * configure.in: Put changequote lines around "i[345]86" patterns + section of core file support. + +Sun Sep 3 11:31:58 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_print_private_bfd_data): Define to use the + generic version. + +Fri Sep 1 17:08:40 1995 steve chamberlain + + * peicode.h (coff_swap_aouthdr_in): Add ImageBase to + entry, text_start and data_start. + +Fri Sep 1 18:06:28 1995 Ian Lance Taylor + + * Makefile.in (OFILES): Remove $(TDEPFILES). + * config/apollo.mt (TDEPFILES): Remove. + * config/README: Update. + + * configure.in: For a native configuration, set COREFILE and + COREFLAG based on the canonical host name. + * configure: Rebuild. + * Makefile.in: Rebuild dependencies. + (ALL_CFLAGS): Add @COREFLAG@. + (OFILES): Replace $(HDEPFILES) with @COREFILE@. + * coff-rs6000.c: Check AIX_CORE rather than HOST_AIX for core file + support routines. Check LYNX_CORE rather than HOST_LYNX. + * lynx-core.c: Check LYNX_CORE rather than HOST_LYNX. + * i386lynx.c: Likewise. + * m68klynx.c: Likewise. + * sparclynx.c: Likewise. + * rs6000-core.c: Check AIX_CORE rather than HOST_AIX. + * *-core.c: Comment changes. + * config/decstation.mh (HDEPFILES): Remove. + (HDEFINES): Remove -DTRAD_CORE. + * config/irix3.mh (RANLIB): Remove. + * config/irix4.mh (HDEPFILES, RANLIB): Remove. + (HDEFINES): Remove -DIRIX_CORE. + * config/riscos.mh (RANLIB, HDEPFILES): Remove. + (HDEFINES): Remove -DTRAD_CORE. + * config/ncr3000.mh (AR_FLAGS, RANLIB): Remove. + * config/ultra3.mh (RANLIB): Remove. + * config/aix4.mh, config/alphaosf.mh, config/amix.mh: Remove. + * config/apollo.mh, config/delta68.mh, config/delta88.mh: Remove. + * config/dpx2.mh, config/esix.mh, config/harris.mh: Remove. + * config/hp300.mh, config/hp300bsd.mh, config/hppabsd.mh: Remove. + * config/hppahpux.mh, config/hppaosf.mh: Remove. + * config/i386aix.mh, config/i386bsd.mh: Remove. + * config/i386linux.mh, config/i386mach3.mh: Remove. + * config/i386sco.mh, config/i386v.mh, config/i386v4.mh: Remove. + * config/irix5.mh, config/m88kmach3.mh, config/mipsbsd.mh: Remove. + * config/mipsmach3.mh, config/news-mips.mh: Remove. + * config/news.mh, config/pc532mach.mh, config/riscix.mh: Remove. + * config/rs600.mh, config/rs6000lynx.mh: Remove. + * config/solaris2.mh, config/stratus.mh: Remove. + * config/symmetry.mh, config/sysv4.mh, config/tahoe.mh: Remove. + * config/vaxbsd.mh, config/vaxult.mh, config/vaxult2.mh: Remove. + +Fri Sep 1 15:18:50 1995 Kazumoto Kojima + + * elflink.h (elf_bfd_final_link): Don't change a DT_INIT or + DT_FINI entry if the appropriate symbol is not in the hash table. + + * libelf.h (struct elf_backend_data): Add create_program_headers + and want_hdr_in_seg fields. + * elfxx-target.h (elf_backend_want_hdr_in_seg): Define if not + defined. + (elf_backend_create_program_headers): Likewise. + (elfNN_bed): Initialize create_program_headers and + want_hdr_in_seg. + * elf.c (get_program_header_size): Call create_program_headers + backend routine. + (map_program_segments): Check want_hdr_in_seg backend field. Call + create_program_headers backend routine. + + * elf.c (assign_file_positions_except_relocs): Align non allocated + sections when creating an executable. + + * elfcode.h (elf_swap_phdr_in): Make non static. + (elf_swap_phdr_out): Make non static. + * libelf.h (bfd_elf32_swap_phdr_in): Declare. + (bfd_elf32_swap_phdr_out): Declare. + (bfd_elf64_swap_phdr_in): Declare. + (bfd_elf64_swap_phdr_out): Declare. + + * ecofflink.c (ecoff_collect_shuffle): New static function. + (_bfd_ecoff_get_accumulated_pdr): New function. + (_bfd_ecoff_get_accumulated_sym): New function. + (_bfd_ecoff_get_accumulated_ss): New function. + * libbfd-in.h (_bfd_ecoff_get_accumulated_pdr): Declare. + (_bfd_ecoff_get_accumulated_sym): Declare. + (_bfd_ecoff_get_accumulated_ss): Declare. + * libbfd.h: Rebuild. + +Fri Sep 1 13:20:25 1995 Ian Lance Taylor + + * libecoff.h (_bfd_ecoff_bfd_print_private_bfd_data): Fix typo. + + * elflink.h (elf_link_add_object_symbols): Handle indirect and + warning symbols. If any section is named .gnu.warning.XXX, treat + the contents as a warning to be issued if the symbol XXX is + referenced. + (elf_link_output_extsym): For an indirect or warning symbol, just + output the symbol it points to. + + * linker.c (_bfd_link_hash_newfunc): Don't bother to set bfd_error + if bfd_hash_allocate fails, since it will already be set. + (generic_link_hash_newfunc): Likewise. + (archive_hash_newfunc): Likewise. + (hash_entry_bfd): New static function. + (_bfd_generic_link_add_one_symbol): Pass new arguments to warning + callback. Allocate a new warning using the hash table newfunc. + Use bfd_hash_replace to update the entry in the hash table, rather + than assuming we can copy the fields with structure assignment. + + * hash.c (bfd_hash_replace): New function. + * bfd-in.h (bfd_hash_replace): Declare. + * bfd-in2.h: Rebuild. + +Fri Sep 1 08:12:50 1995 James G. Smith + + * config.bfd: Add mips*vr4300-*-elf* target. + * config/mipsbvr4300.mt: Added. + +See file ChangeLog.2 + + +Local Variables: +mode: indented-text +left-margin: 8 +fill-column: 74 +version-control: never +End: diff --git a/gnu/usr.bin/binutils/bfd/ChangeLog.1 b/gnu/usr.bin/binutils/bfd/ChangeLog.1 new file mode 100644 index 00000000000..f36ed3cd01c --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/ChangeLog.1 @@ -0,0 +1,6951 @@ +Sun Oct 31 09:35:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * targets.c: Move enum target_flavour outside of struct and change + the name to enum bfd_flavour. This means bfd clients can use it. + * bfd-in.h: Add macro bfd_get_flavour. + * bfd-in2.h: Rebuilt. + + * som.c: Add comment about how abort() on corrupt executable is evil. + +Sat Oct 30 12:27:09 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * aoutx.h (aout,slurp_reloc_table): Avoid a goto. + +Fri Oct 29 16:04:33 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * gen-aout.c, libbfd.c: exit(1) instead of exit(-1). + +Fri Oct 29 13:17:21 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * bfd-in.h: Added commands for object file flag values. + * bfd-in2.h: Rebuilt. + * elfcode.h (elf_object_p): If type is ET_DYN, set DYNAMIC flag, + not EXEC_P. + * bout.c, coff-h8300.c, coff-sh.c: Add BFD_IS_RELAXABLE to + object_flags field for target vector. + * aix386-core.c, aout-adobe.c, aout-target.h, bout.c, coff-a29k.c, + coff-alpha.c, coff-apollo.c, coff-h8300.c, coff-h8500.c, + coff-i386.c, coff-i960.c, coff-m68k.c, coff-m88k.c, coff-mips.c, + coff-rs6000.c, coff-sh.c, coff-we32k.c, coff-z8k.c, hpux-core.c, + ieee.c, mipsbsd.c, nlm-target.h, oasys.c, osf-core.c, som.c, + srec.c, tekhex.c, trad-core.c: Remove DYNAMIC from object_flags + field for target vector. + +Thu Oct 28 20:02:31 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * hosts/std-host.h: Don't declare time; causes error on mach3. + * configure.in (i386mach3_vec): Require aout32.o stab-syms.o. + +Thu Oct 28 16:33:26 1993 Stan Shebs (shebs@rtl.cygnus.com) + + LynxOS and Sparc LynxOS changes: + * config.bfd: Recognize sparc-*-lynxos*. + * configure.host: Recognize sparc-*-lynxos*. + * configure.in: Recognize Sparc Lynx vectors. + * targets.c (sparclynx_aout_vec): Declare. + (sparclynx_coff_vec): Declare. + (target_vector): Add them. + * cf-i386lynx.c: New file, renamed from i386lynx-cf.c. + * cf-m68klynx.c: New file, renamed from m68klynx-cf.c. + * cf-sparclynx.c: New file, support for coff in Sparc LynxOS. + * coff-sparc.c: New file, basic Sparc coff support. + * sparclynx.c: New file, support for a.out in Sparc LynxOS. + * Makefile.in: Change filenames appropriately, add Sparc rules. + * coffcode.h (coff_set_arch_mach_hook): Recognize Sparc magic + number. + (coff_set_flags): Use LynxOS magic number for i386, m68k, and + Sparc LynxOS, set Sparc magic number for Sparcs. + * config/m68k-lynx.mt (SELECT_VECS): Remove redundant vector. + * config/sparc-lynx.mt: New file. + * hosts/i386lynx.h: Cosmetic improvements. + * hosts/m68klynx.h: Add ifdefs, #define of cfree. + * hosts/sparclynx.h: New file. + +Thu Oct 28 16:23:40 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + gcc -Wall lint: + * coff-h8300.c (h8300_reloc16_estimate): Declare return type. + Remove useless statement probably left by code copy. + * cpu-i960.c (compatible): Fully bracket matrix initializer. + * elf32-hppa.c (hppa_elf_build_arg_reloc_stub): Use bfd_xmalloc + rather than xmalloc. Use realloc and check the return value + rather than xrealloc. + (hppa_elf_get_section_contents): Add some casts. + * elf32-i386.c (elf_i386_reloc_type_lookup): Remove unused + variable. Add default case to switch. + * hp300hpux.c: Declare aout_32_write_syms. + * i386bsd.c, i386linux.c, netbsd386.c (N_SHARED_LIB): Define as 0 + (definition from aout/aout64.h is always 0 anyhow). + * i386lynx.c (swap_std_reloc_in): Remove unused variable. + * ieee.c (ieee_write_id): length can never be negative. + (read_id): Likewise. + (ieee_archive_p): Remove unused variable. + * libcoff-in.h (bfd_perform_slip): Declare. + * libcoff.h: Rebuilt. + * oasys.c (oasys_write_sections): Remove zero initialization of + static structure. + * reloc16.c: Indentation change. + +Wed Oct 27 16:51:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * configure.in, config/i386-mach3.mt: Update for new configuration + (--with-targets and so on). + * hosts/i386mach3.h: Declare errno. + * targets.c: Declare i386mach3_vec. + +Wed Oct 27 12:18:07 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmcode.h (nlm_swap_auxiliary_headers_in, + nlm_swap_auxiliary_headers_out): Handle sharedDebugRecordOffset + and sharedDebugRecordCount fields. + +Tue Oct 26 16:21:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * targets.c (target_vector): Remove SCO_CORE. On Sep 11 1993, + we started using trad-core.c for SCO instead. + + * targets.c (target_vector): Re-enable generic ELF and NLM targets. + +Tue Oct 26 16:53:12 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (assign_file_position_for_section): Align sh_offset to + sh_addralign (this is what UnixWare does, and it shouldn't hurt). + +Tue Oct 26 10:16:54 1993 Ken Raeburn (raeburn@cygnus.com) + + From Jeff Law and Pete Hoogenboom at Utah: + + * elf32-hppa.h (hppa_elf_stub_finish): Add prototype. + (ELF32_HPPA_R_ARG_RELOC): Renamed without the ELF32 prefix + and moved into libhppa.h. All references changed. + (ELF32_HPPA_R_CONSTANT, ELF32_HPPA_R_ADDEND): Likewise. + (get_opcode and opcode defines): Move into libhppa.h + * elf32-hppa.c (hppa_elf_insn2fmt): Rename and move info + libhppa.h. + * libhppa.h (HPPA_R_*): Moved here. Reformatted slightly to make + for easier reading. + (get_opcode): Moved here. FIXME! this really should be a C function + inside the opcode library! + (bfd_hppa_insn2fmt): Likewise. + + * targets.c (target_vector): Enable elf32-hppa vector. + + * elf32-hppa.c (hppa_elf_get_section_contents): Add new comments + and clarify existing comments. Do not use DEFUN to declare this + function. Fix numerous indention problems. Correctly handle cases + where symbol extension section may need to be read from disk, + read from memory, or built then read from memory. + + * elf32-hppa.h: Reformat with gnu-indent and hand fix numerous + formatting and indention problems gnu-indent can not handle. + Clarify some comments about relocation types. Comment basic + relocation "classes". Group PARAM declarations together. + (HPPA_SXT_{NULL, SYMNDX, RG_RELOC}): Make members of a new + enumerated type rather than #defines. + +Tue Oct 26 02:40:46 1993 Stu Grossman (grossman at cygnus.com) + + * som.c (hppa_object_setup): Set SEC_CODE for .text section so + that GDB can figure out text_start and text_end. + +Mon Oct 25 16:05:23 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Fix up warnings from gcc -Wall: + * coffgen.c (coff_print_symbol): Use %lx and cast n_value to + unsigned long. Use %ld for tagndx. Use %lx for offset + vma and + cast it to unsigned long. + * ecoff.c (ecoff_emit_aggregate): Use %ld. + (ecoff_print_symbol): Use %ld, and cast indx and sym_base to long. + * coffcode.h (dummy_reloc16_estimate): Specify return type. + + * libbfd.c (bfd_write): If not everything is written out, set + bfd_error to system_call_error. If the return value is + non-negative, set errno to ENOSPC (if ENOSPC is defined). + (bfd_seek): If the seek fails, set bfd_error to system_call_error. + (bfd_generic_set_section_contents): For a bad offset + count, set + bfd_error to bad_value. + * seclet.c (rel): Don't abort. Instead, return false. + +Mon Oct 25 09:59:37 1993 Ken Raeburn (raeburn@cygnus.com) + + * aoutx.h (reloc_type_lookup): Handle BFD_RELOC_SPARC_WDISP22. + +Fri Oct 22 20:35:54 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * config.bfd: handle mips*-* instead of mips-*, use mips*el + instead of mips-*-*l + +Fri Oct 22 14:03:33 1993 Mark Eichin (eichin@cygnus.com) + + * m68k-lynx.mt, i386-lynx.mt (TDEFINES): set + FPRINTF_ALREADY_DECLARED because the objdump.c declaration of + fprintf collides with the native one. + +Fri Oct 22 11:50:25 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * targets.c (target_vector): Enable MIPS ELF vectors. + +Fri Oct 22 07:51:51 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config.bfd: Use bigmips for mips-sony-bsd*. + + * configure.host, config.bfd: Add * to end of all OS names. + +Thu Oct 21 12:16:26 1993 Ken Raeburn (raeburn@cygnus.com) + + * elfcode.h (FILE_ALIGN): Renamed from EALIGN, to avoid conflict + with Ultrix header files. + + * som.h (struct som_section_data_struct): Renamed from + som_section_data to avoid conflict with macro by that name. + + Changes from Jeff Law and Peter Hoogenboom at Utah: + + * elf32-hppa.c (hppa_elf_reloc): Target register for a 'jump + in delay slot' optimization in combination with a long call + stub should always be r31. + + * elf32-hppa.c: (hppa_elf_relocate_insn): To be consistent + across all relocation types, retrieve instruction addends from + the relocation entry rather than from the instruction itself. + + * elf32-hppa.c: (hppa_elf_relocate_insn): Fix a relocation + error that only occurred when the addend of an 'addil' or + 'ldil' was larger than 21 bits and very close to a 2K byte + boundary. + + * elf32-hppa.c: (hppa_elf_reloc): Handle the optimization in + which a jump is placed in the delay slot of a function call. + The jump was being accomplished via an adjustment to the + return pointer. This optimization would break the long call + stub code, if there was any. + + * elf32-hppa.c: (hppa_elf_build_long_branch_stub): Corrections + to long branch stubs to avoid use of general register 2. + + * hppa_stubs.h: New stub instructions. + + * elfcode.h: Declare bfd_elf_find_section. + + * som.h (som_section_data): Add new "subspace_index" field. + + * som.c (setup_sections): Save the original SOM subspace index + in the BFD section associated with that subspace. + (som_get_symtab_upper_bound): Implement. + (som_get_symtab): Implement. + (som_print_symbol): Implement. + (som_slurp_string_table): New function to read a string table + from a SOM object file. + (som_section_from_subspace_index): New function to return the + section which corresponds to a SOM subspace index. + (som_slurp_symbol_table): New function to read the symbol + table from a SOM object file. + (som_make_empty_symbol): Check for errors from bfd_zalloc. + (som_new_section_hook): Initialize subspace_index field to + -1 instead of 0. + + * som.c (som_object_setup): Fix polarity of test to set HAS_RELOC. + Set EXEC_P for executables. + (setup_sections): Correctly identify when a section has + relocations. + (log2): New function. + (setup_sections): Correctly convert between SOM alignments and BFD + alignments. + + * som.c (setup_sections): Do not set SEC_ALLOC or SEC_LOAD + for sections which correspond to SOM spaces, doing so confuses + many utilities. Set assorted SEC_* flags for SOM subspaces + which correspond to BFD sections. + + * elf32-hppa.c: (elf32_hppa_backend_fake_sections): The stab + string table should have sh_type == SHT_STRTAB. Add + processing to make it so. + + * elfcode.h: (bfd_section_from_shdr): String tables (other + than .strtab) were not getting the file offsets recorded, so + they could not be read from disk. + + * elfcode.h: (elf_make_sections): Leave the sh_addr field of + the section header and the vma field of a section at 0 if the + section is not part of the program execution image. (e.g., + .stab) + + * som.[hc]: Change target vector prefix from "hppa" to "som". + Consistently use obj_som prefix to access fields in backend data + structures. Fix all callers/references. + + * som.h: Do not include files only needed for core file reading here. + Include a.out for both HOST_HPPAHPUX and HOST_HPPABSD. Delete + forward structure declarations, they are unnecessary. + (struct somdata): Delete aux_hdr, and hp_symbol_entry_size fields. + Change "symbols" to "symtab". Add "stringtab" and "reloc_filepos" + fields for future use. Change obj_som_* macros as appropriate. + (som_section_data): New structure to keep SOM specific information + about BFD sections (for future use). + + * som.c: Provide PARAMS declarations for all functions currently + in this file. + (struct container): Delete unwanted structure definition. + (som_object_setup): Add comments. Use som_mkobject to allocate + SOM specific information in the BFD; use information from the + file and (possibly empty) auxiliary headers to initialize this + information. Delete redundant bfd_get_symcount (abfd) "calls". + (setup_sections): Return type is now boolean, fix return statements. + "Fix" handling of BSS like subspaces in the computation of the + containing space's size. If the subspace has relocations, set the + appropriate BFD section flags and record the index into and the + size of the fixup stream. Always return a value. + (som_object_p): Set bfd_error appropriately if errors are detected + from bfd_{read,seek} functions. Handle EXECLIBMAGIC type files. + Do not try to read a non-existant auxiliary header. + (som_mkobject): Flesh out. + (som_section_hook): Allocate space to hold SOM specific information + about sections. + +Thu Oct 21 12:41:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + gcc -Wall lint: + * coff-h8300.c, coffcode.h: Change shrink parameter + in *_reloc16_estimate to unsigned to match prototype. + * archive.c: Avoid "/*" in comment. + +Thu Oct 21 13:05:16 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * dep-in.sed: Create our own line breaks for a more aesthetic + Makefile. + * Makefile.in: Rebuilt dependencies. + + * elf32-mips.c: Include "seclet.h". + (mips_elf_fake_sections): Force size of .reginfo section to sizeof + Elf32_External_RegInfo. + (mips_elf_seclet_link): New function. Link the .reginfo section + specially, and pass everything else to the generic routine. + (bfd_elf32_bfd_seclet_link): Define macro. + * elf32-target.h: If bfd_elf32_bfd_seclet_link is already defined, + don't override it. + +Wed Oct 20 12:22:37 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * libnlm.h (nlm_backend_data): Added signature field. + (nlm_signature): New macro. + * nlmcode.h (nlm_object_p, nlm_write_object_contents): Use the NLM + signature from the backend rather than the constant NLM_SIGNATURE. + * nlm32-i386.c (nlm32_i386_backend): Initialize signature field. + + * aoutf1.h (MACHTYPE_OK): Accept M_UNKNOWN. + (NAME(sunos,set_arch_mach)): Treat M_UNKNOWN as 68000, not 68020. + +Wed Oct 20 10:28:27 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hosts/i386bsd.h [__bsdi__]: Define HOST_DATA_START_ADDR. + +Wed Oct 20 10:10:07 1993 Ken Raeburn (raeburn@cygnus.com) + + * Makefile.in (HFILES): New variable, for use in "make dep". + (.dep): Depend on $(CFILES) and $(HFILES). Delete .dep1 and + remake it, so that "$?" is complete. + (.dep1): Don't need to remove .dep1 first. + (dep.sed): Depend on config.status, not Makefile. + (CFILES): Add nlm.c. + +Tue Oct 19 15:26:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-alpha.c: Implemented reloc handling for the linker, made + various other related changes. + * libecoff.h (ecoff_backend_data): Added rdata_in_text field. + Renamed finish_reloc to adjust_reloc_in. Added adjust_reloc_out + field. + (ecoff_bfd_get_relocated_section_contents): Don't define. + * ecoff.c (ecoff_sec_to_styp_flags, ecoff_styp_to_sec_flags): + Handle .lita section. + (ecoff_slurp_reloc_table): Handle RELOC_SECTION_FINI. + finish_reloc backend field renamed to adjust_reloc_in. + (ecoff_bfd_seclet_link): Adjust number of aux entries to + debug_align boundary. + (ecoff_compute_section_file_positions): If rdata_in_text put + .rdata section in text segment, not data segment. Put .pdata + section in text segment. + (ecoff_write_object_contents): Likewise. Also, call + adjust_reloc_out, and handle .lita, .xdata, .pdata, .fini and + absolute sections when writing out relocs. + * coffswap.h (coff_swap_aouthdr_out): For ALPHAECOFF, output 2 for + bldrev field, as on Alpha OSF/1. Padding field is now 2 bytes. + * coff-mips.c (mips_ecoff_swap_reloc_out): Added assertion. + (mips_adjust_reloc_in): Renamed from mips_finish_reloc. + (mips_adjust_reloc_out): New function (does nothing). + (mips_ecoff_backend_data): Initialize new fields. + (ecoff_bfd_get_relocation_section_contents): Define to be + bfd_generic_get_relocated_section_contents. + + * reloc.c (bfd_perform_relocation): Added casts to avoid Alpha + OSF/1 cc bug. + +Thu Oct 14 01:10:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * reloc.c (bfd_perform_relocation): Add comments attempting to + explain PC relative relocations. + + * coffcode.h (styp_to_sec_flags): Don't set SEC_DEBUGGING until it + is made to work. + (coff_compute_section_file_positions): Remove check for + USE_DISCARDED_SECTIONS_COUNT. + * coff-i386.c: Don't define USE_DISCARDED_SECTIONS_COUNT. Basing + it on host defines is wrong. + + * ecoff.c (ecoff_bfd_seclet_link): Don't link a .reginfo section. + (ecoff_write_object_contents): Don't require the .reginfo section + to be a particular size. + +Wed Oct 13 18:39:03 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * Makefile.in (dep-in): New rule, for editing dependencies into + Makefile.in in $(srcdir). Use move-if-change. + (.dep1, dep): Use move-if-change. + (CFILES): Add coff-apollo.c. + + Sun Oct 10 18:02:56 1993 Troy Rollo (troy@cbme.unsw.EDU.AU) + + * Makefile.in: Recognise new file, coff-apollo.o + + * coff-apollo.c: New file + + * coffcode.h: Recognise apollo magic numbers and writable text + + * coffswap.h: Swap Apollo optional header entries + + * config.bfd: Add line for Apollo + + * configure.host: Replace apollo68b and apollo68v with Apollo + + * configure.in: Recognise apollocoff_vec + + * targets.c: Likewise + + * config/apollo.mh, config/apollo.mt: New files + + * hosts/apollo68.h: Remove inclusion of strings.h + +Wed Oct 13 14:28:17 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * coff-i386.c (i3coff_object_p): Now static. + + * Makefile.in: Updated dependencies. + (.dep, .dep1, dep.sed): New targets, to make "make dep" work + better. + * dep-in.sed: New file. + + * m68klynx-cf.c (ONLY_DECLARE_RELOCS): Define, to avoid name + conflicts when "--with-targets=all". + * coff-m68k.c (m68kcoff_howto_table, m68k_rtype2howto, + m68k_howto2rtype): Rename via macros to keep namespace clean. + * configure.in: For m68klynx_coff_vec, include coff-m68k.o for + now. + +Tue Oct 12 17:03:27 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elf32-mips.c: Extensive additions to do relocations and to + handle MIPS specific sections. + * libelf.h (elf_backend_data): Pass fourth argument to + elf_backend_section_from_bfd_section to permit it to control the + section index to use. + (elf_obj_tdata): Add gp and gp_size fields. + (elf_gp, elf_gp_size): New accessor macros. + * elfcode.h: Removed a number of unused local variables. + (elf_fake_sections): Clear section header before calling + elf_backend_fake_sections, not after. + (prep_headers): Return true at end. + (elf_section_from_bfd_section): Pass retval argument to + elf_backend_section_from_bfd_section. + * elf32-hppa.c (elf32_hppa_backend_section_from_bfd_section): + Accept and ignore new retval argument. + * bfd.c: Include libelf.h. + (bfd_set_gp_size): Handle ELF targets. + * Makefile.in (bfd.o): Depends upon libelf.h. + (elf32-mips.o): Depends upon $(INCDIR)/elf/mips.h. + +Mon Oct 11 17:25:18 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_mkobject): Check bfd_make_section return value. + (ecoff_mkobject_hook): New function. + (ecoff_new_section_hook, ecoff_sizeof_headers, + ecoff_compute_section_file_positions, ecoff_set_section_contents, + ecoff_write_object_contents): Handle dummy REGINFO section. + (ecoff_get_section_contents): New function to handle reading + REGINFO section. + * libecoff.h (ecoff_get_section_contents): Change from macro + definition to function prototype. + (ecoff_mkobject_hook): New prototype. + * coff-alpha.c (alpha_ecoff_mkobject_hook): Removed. + (alpha_ecoff_backend_data): Use ecoff_mkobject_hook. + * coff-mips.c (mips_ecoff_mkobject_hook): Removed. + (mips_ecoff_backend_data): Use ecoff_mkobject_hook. + +Fri Oct 8 15:25:33 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * libbfd.c (bfd_get*32, bfd_get*64): Prevent ANSI sign extension + by casting the most significant byte to bfd_vma. + +Fri Oct 8 02:34:21 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * configure.in: Do not define SELECT_VECS, SELECT_ARCHITECTURES + if configuring --with-targets=all. + +Thu Oct 7 17:34:07 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * aoutx.h (howto_table_std): Correct the "size" field in some + entries. + + * reloc.c (reloc_howto_type): Change documentation to dispel any + notion that the "size" field is a power-of-two indicator. + +Thu Oct 7 10:50:38 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * coffswap.h: (bfd_swap_reloc_in): a symndx is signed. + + Make support for relaxing more generic. + * reloc16.c: Add new target entry - bfd_coff_reloc16_estimate, + fix bit rot. + * libcoff.h, libcoff-in.h: declarations. Prototypes + * coffcode.h (bfd_coff_std_swap_table): Add calls to + coff_reloc_16_extra_cases and coff_reloc16_estimate. + (dummy_reloc16_estimate): New function. + * coff-h8300.c (h8300_reloc16_estimate): New function + +Thu Oct 7 14:24:13 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elfcode.h (EALIGN): Define, dependent on ARCH_SIZE. + (align_file_position): New function. + (elf_locate_sh): Disabled function deleted. + (assign_file_positions_for_symtab_and_strtabs): Align position, + then place symtab, then do other sections. + (map_program_segments): Align program header. + (assign_file_positions_except_relocs): Align section headers. + (assign_file_positions_for_relocs): Align relocation sections. + +Tue Oct 5 10:44:32 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * configure.host: Recognize hppa*-*-hiux* (currently synonym for hpux). + Change other hppa entries to use -*- not -hp-. + * config.bfd: Recognize hppa*-*-hiux* (currently synonym for hpux). + + * coff-rs6000.c, cpu-rs6000.c, rs6000-core.c: Change non-ASCII + characters in comment to octal escapes. + +Sun Oct 3 12:35:15 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * coff-i386lynx.c: Removed, name too long. + * i386lynx-cf.c: New file, was coff-i386lynx.c. + * configure.in: Reflect file name changes. + * Makefile.in: Mention Lynx-related files. + + * i386lynx.c (lynx_32_swap_ext_reloc_in): get reloc bits in i386 + Lynx-specific way. + + * m68klynx-cf.c: New file, defines coff format for M68K LynxOS. + * m68klynx.c: Remove coff vector definition, now in m68klynx-cf.c. + + * coffcode.h (sec_to_styp_flags): Set section flag to STYP_INFO + for .stab, .stabstr and .debug sections, and set SEC_DEBUGGING for + sections of type STYP_INFO. (from Minh Tran-Le) + (coff_compute_section_file_positions): Add discarded_sections_count + to abfd->section_count, which helps `strip' keep the size + of the executable header constant. + * coff-i386.c (discarded_sections_count): New variable, initialized + to zero. For use by `strip'. Currently being used only in aix386 + coff, but may be useful for other coff systems. (from Minh Tran-Le) + + * coffswap.h (coff_swap_filehdr_out): Added a missing cast. + + * archive.c: Cosmetic improvements. + * opncls.c: Cosmetic improvements. + (new_bfd): Removed redundant structure slot init. + +Sat Oct 2 18:48:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config/news-mips.mh, hosts/news-mips.h: New files. + * configure.host: Use news-mips for mips-sony-bsd*. + +Fri Oct 1 13:14:17 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * configure.in: i386lynx_coff_vec requires coff-i386lynx.o. + * coff-i386lynx.c: New file, defines Lynx target vector and name, + includes coff-i386.c. + * coff-i386.c (i386coff_vec): Allow redefinition of target vector + symbol and name, if TARGET_SYM and/or TARGET_NAME are defined. + * i386lynx.c: Remove coff vector definition entirely. + (lynx_32_swap_ext_reloc_in): Define. + (lynx_32_swap_std_reloc_in): Define, get reloc bits in i386 + Lynx-specific way. + (lynx_32_swap_ext_reloc_out): Define. + (lynx_32_swap_std_reloc_out): Define. + (lynx_32_slurp_reloc_table): Define, call Lynx swapping fns. + (lynx_32_squirt_out_relocs): Define, call Lynx swapping fns. + (lynx_32_canonicalize_reloc): Define, call Lynx swapping fns. + (WRITE_HEADERS): Define, call Lynx swapping fns. + + * config/i386-lynx.mt (SELECT_VECS): Remove redundant vector. + +Thu Sep 30 17:50:52 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * reloc.c (bfd_reloc_code_type): Add linkage-table relative + relocations of size 8, 16, 32. Sort generic relocs by type rather + than size. Added a little documentation too. + + * aoutx.h (howto_table_std): Add BASE16 and BASE32 relocs. + (TABLE_SIZE): New macro. + (reloc_type_lookup): Handle BFD_RELOC_{16,32}_BASEREL for std + relocs. + (swap_std_reloc_out): Write baserel relocs correctly. + (swap_std_reloc_in): Handle r_baserel field. Assert that + r_jmptable and r_relative fields are clear, and that the computed + index does refer to a defined entry of the howto table. + +Tue Sep 28 14:47:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * section.c (bfd_make_section_anyway): New function. + * section.c: Change comments to say several sections can have + the same name. + * bfd-in2.h: Re-generate to reflect above change. + * coffgen.c (make_a_section_from_file): Call bfd_make_section_anyway + if still no section after the bfd_coff_make_section_hook. + * coffcode.h: Add comment about TWO_DATA_SECS. + +Tue Sep 28 03:22:24 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * ecoff.c (ecoff_slurp_symbolic_info): Always determine raw_size + explicitly. + * ecoff.c (ecoff_sec_to_styp_flags, ecoff_styp_to_sec_flags): Handle + .fini section. + +Mon Sep 27 18:29:18 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * config.bfd configure.host: Match on *-lynxos* for LynxOS, + add m68*-*-lynxos*. + * configure.in : Replaced i386lynx_vec with i386lynx_aout_vec + and i386lynx_coff_vec. + Added m68klynx_aout_vec and m68klynx_coff_vec. + * targets.c (target_vector): Removed i386lynx_vec, added + {i386,m68k}lynx_{aout,coff}_vec. + * i386lynx.c: Added copy of i386coff.c, renamed bfd target to + i386lynx_coff_vec. + * m68klynx.c: New file. + * config/i386-lynx.mt: Replaced i386lynx_vec with i386lynx_aout_vec + and i386lynx_coff_vec. + * config/m68k-lynx.mt: New file. + * hosts/i386lynx.h: Added definition of cfree as free (from Eichin). + * hosts/m68klynx.h: New file. + +Mon Sep 27 18:00:41 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * archive.c: Define offsetof here. + * hosts/*.h: Don't define it here. + +Mon Sep 27 19:09:27 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (bfd_section_from_shdr): Set filepos for SHT_STRTAB + section. + +Fri Sep 24 15:47:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hpux-core.c: Add comment about hpux version 7. + +Fri Sep 24 16:50:26 1993 Stu Grossman (grossman at cygnus.com) + + * lynx-core.c (lynx_core_file_p): Change per-thread register + section names from .regXXX to .reg/XXX to avoid parsing ambiguity + in gdb/corelow.c. Create alias .reg section for the currently + running thread. + +Fri Sep 24 13:22:32 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * libecoff.h (ecoff_backend_data): Removed big_magic and + little_magic fields. + * coff-alpha.c (alpha_ecoff_backend_data): Removed initialization + of big_magic and little_magic. + * coff-mips.c (mips_ecoff_bad_format_hook): Make sure magic number + matches endianess of bfd. + (mips_ecoff_backend_data): Removed initialization of big_magic and + little_magic. + * ecoff.c (ecoff_set_arch_mach_hook): Set MIPS machine number + based on magic number. Support r4000 magic numbers. + (ecoff_get_magic): New function. + (ecoff_write_object_contents): Use ecoff_get_magic, not fields in + the backend structure. + * cpu-mips.c (arch_info_struct): Added case for r6000. + + For MIPS configurations put both big and little endian versions in + the list of targets; the code is getting compiled in anyhow. + * bigmips.mt (SELECT_VECS): Define to be ecoff_little_vec. + * decstation.mt (SELECT_VECS): Define to be ecoff_big_vec. + * mipsbelf.mt (SELECT_VECS): Define to be bfd_elf32_littlemips_vec. + * mipslelf.mt (SELECT_VECS): Define to be bfd_elf32_bitmips_vec. + * riscos.mt (SELECT_VECS): Define to be ecoff_little_vec. + +Fri Sep 24 00:42:23 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * osf-core.c: New file for OSF/1 core file support. + * config/alphaosf.mh (HDEFINES): Add -DOSF_CORE. + (HDEPFILES): Set to osf-core.o. + * bfd-in2.h (union tdata): Add osf_core_data member. + * targets.c: If OSF_CORE is defined, add osf_core_vec to target list. + * Makefile.in (OPTIONAL_BACKENDS): Add osf-core.o. + (osf-core.o): New dependency. + +Thu Sep 23 21:04:53 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * TODO: Remove note about making --with-bfd-targets use canonical + target configuration name (already done); reword item about + separating reading and writing stuff to not refer to a + non-existent item. + + * ecoff.h (ecoff_set_arch_mach_hook): Accept MIPS_MAGIC_LITTLE2 + and MIPS_MAGIC_BIG2. + +Thu Sep 23 11:06:34 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * gen-aout.c (main): Output newline after end of comment, not + before. (Reported by Jonathan Stone, + jonathan@oscar.stanford.edu). + +Thu Sep 23 10:48:27 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * archive.c (compute_and_write_armap): Put weak symbols in the + armap. + + * elfcode.h (fix_up_strtabs): Set sh_entsize for the .stab + section, not the .stabstr section. Set the type of the .stabstr + section to SHT_STRTAB. + (elf_section_from_bfd_section): Handle SHT_STRTAB sections. + + * section.c (SEC_DEBUGGING): New section flag. + * elfcode.h (bfd_section_from_shdr): If section is SHT_PROGBITS, + and the name starts with .debug, .line or .stab, set + SEC_DEBUGGING. If SHT_STRTAB, check for .debug and .stab. + * elf32-target.h (TARGET_BIG_SYM, TARGET_LITTLE_SYM): Added + SEC_DEBUGGING to section_flags. + * elf64-target.h (TARGET_BIG_SYM, TARGET_LITTLE_SYM): Added + SEC_DEBUGGING and SEC_CODE to section_flags. + * bfd-in2.h: Updated. + +Wed Sep 22 16:34:14 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * bfd.c (tdata): Add lynx_core_data. + + * ecoff.c (ecoff_compute_section_file_positions): Set filepos for + sections with SEC_LOAD set, even if SEC_HAS_CONTENTS is clear. + (ecoff_write_object_contents): Don't set scnptr to zero just + because size of section is zero. Needed for Irix 4.0.5F. + +Wed Sep 22 09:49:32 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config.bfd: Use i960-bout, not i960-coff for i960-*-nindy*. + +Wed Sep 22 07:34:09 1993 Stu Grossman (grossman at cygnus.com) + + * Makefile.in (OPTIONAL_BACKENDS): Add lynx-core.o. + * bfd-in2.h (tdata): Add lynx_core_data; + * config.bfd configure.host: Get rid of superfluous netbsd and + lynxos entries. + * configure.in: Add lynx-core.o to Lynx config. + * i386lynx.c: Add defs for core file support. + * lynx-core.c: New file with Lynx core file support. + * hosts/i386lynx.h: Move lots of host specific includes to here. + Add def of HOST_LYNX. Remove unnecessary defs. + +Mon Sep 20 19:18:10 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (bfd_section_from_shdr): Only set SEC_DATA for a + SHF_PROGBITS or SHT_STRTAB section if SEC_ALLOC is set. Never set + SEC_DATA for a SHF_NOBITS section. + + * nlm32-i386.c (nlm_i386_mangle_relocs): Check SEC_LOAD rather + than SEC_CODE | SEC_DATA. Add some casts to avoid warnings. + * nlmcode.h: Add some casts to avoid warnings. + (nlm_write_object_contents): Ignore relocs for sections that are + neither code nor data. Just use the symbol value for debugging + symbols; don't offset by the section vma. + +Fri Sep 17 18:08:55 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * reloc.c (bfd_perform_relocation): Don't return an error when + performing a reloc against an undefined weak symbol. + * syms.c (bfd_print_symbol_vandf): Show value of BSF_WEAK rather + than obsolete BSF_EXPORT. + +Fri Sep 17 02:04:31 1993 John Gilmore (gnu@cygnus.com) + + * hosts/{alphaosf.h, amix.h, apollo68.h, apollov68.h, + decstation.h, delta88.h, dgux.h, dose.h, go32.h, harris.h, + hp300.h, hp300bsd.h, hppabsd.h, hppahpux.h, i386aix.h, i386bsd.h, + i386linux.h, i386lynx.h, i386v.h, i386v4.h, irix3.h, irix4.h, + mipsbsd.h, ncr3000.h, rs6000.h, rtbsd.h, solaris2.h, sparc-ll.h, + std-host.h, stratus.h, sun3.h, sysv4.h, tahoe.h, ultra3.h, + vaxult.h, vaxult2.h, we32k.h}: Make sure that "offsetof" is + defined on all hosts, now that archive.c uses it. + +Thu Sep 16 18:20:30 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (elf_map_symbols): Create section symbols for all + sections, not just allocated sections; debugging sections can have + relocs. + (elf_symbol_from_bfd_symbol): If there is an output section, use + the section index from that rather than the input section. + +Thu Sep 16 12:20:50 1993 Ken Raeburn (raeburn@cygnus.com) + + * libbfd-in.h (bfd_flush, bfd_stat): Reflect John's changes to + libbfd.h, which is regenerated from this file. + + * bfd-in.h (symtype): Deleted typedef. + +Wed Sep 15 11:48:37 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * libbfd.c (COERCExx): Cast x to bfd_signed_vma before doing the + xor and subtract. Otherwise it will not sign extend if the type + of bfd_vma is larger than int. + + * ecoffswap.h (ecoff_swap_pdr_in): Get regoffset, iopt, fregoffset + and frameoffset as signed numbers. From Peter Schauer. + +Tue Sep 14 18:20:36 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elf32-i386.c (elf_howto_table): Add bfd_elf_generic_reloc + special function for all reloc entries. + * elf32-target.h (TARGET_LITTLE_SYM): Add SEC_CODE to + section_flags. + * libelf.h (elf_symbol_type): Remove desc, type and other fields. + * Makefile.in (elf32-*.o): These depend upon elf32-target.h. + +Tue Sep 14 14:34:45 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * libbfd-in.h (struct artdata): Add armap_timestamp and + armap_datepos here too. + +Mon Sep 13 21:03:18 1993 John Gilmore (gnu@cacophony.cygnus.com) + + Improve timestamp support in BSD archive files to avoid linker + warnings. + + * libbfd.h (struct artdata): Add armap_timestamp and armap_datepos. + (bfd_flush, bfd_stat): Add prototypes. + * libbfd.c (bfd_flush): Add, does fflush on a BFD. + (bfd_stat): Add, does fstat on a BFD. + + * archive.c (_bfd_write_archive_contents): At end of file writing, + verify and possibly update the timestamp in the armap, if a BSD + archive. FIXME! Kludge recognizes BSD archive, rather than + vectoring properly. Should add to xvec. + (compute_and_write_armap): Move prototype to top, avoid PROTO. + (bsd_write_armap): Save timestamp and file location thereof, when + writing the armap in a BSD file. + (bsd_update_armap_timestamp): New function to check and + rewrite the timestamp. + + * hosts/std-host.h (offsetof): Define, if not already, for archive.c. + +Sat Sep 11 18:13:42 1993 Jim Kingdon (kingdon@poseidon.cygnus.com) + + * hosts/i386sco.h: Define a bunch of stuff for core files. + * sco-core.c: Remove, replace by trad-core.c. + * trad-core.c: If HOST_STACK_START_ADDR is defined, use it. + * config/i386sco.mh: Use trad-core not sco-core. + * hosts/i386isc.h, config/i386isc.mh: Remove. + * configure.host: Use i386sco for isc. + * config/i386-sco.mt: Remove, identical to i386-coff.mt. + * config.bfd: Use i386-coff not i386-sco. + + * config.bfd: Recognize i[34]86-*-solaris2* specifically rather + than using *-*-solaris2* (i486-unknown-solaris2 is i386-elf, not + i486-elf which doesn't exist). + +Fri Sep 10 12:56:36 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coffswap.h (coff_swap_aouthdr_out): For ALPHAECOFF, force + padding field to zero. + + * config.bfd (i[34]86-*-netbsd*): New target; use i386-netbsd. + * configure.in: Remove bogus netbsd386 handling. + + * coff-mips.c: Don't warn about overflow for MIPS_R_JMPADDR reloc. + Correct overflow detection requires matching the upper four bits + of the destination against the PC. + +Thu Sep 9 16:57:46 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * configure.in: Make 64-bit stuff work with "--with-targets=all". + +Tue Sep 7 14:17:02 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * libbfd-in.h: Removed swapping routines declarations. + * bfd-in.h: Added swapping routine declarations, and renamed them + from _do_* to bfd_*. + * libbfd.c: Renamed swapping routines from _do_* to _bfd_*. + * Changed all callers. + * libbfd.h, bfd-in2.h: Rebuilt. + +Mon Sep 6 15:28:07 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elf32-i386.c (elf_howto_table): Set pcrel_offset to true for + R_386_PC32. + +Fri Sep 3 13:06:12 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * configure.in: Reorganized setting of makefile variables so + 64-bit stuff works again. + + * libbfd-in.h (_do_get*, _do_put*): Renamed via macros to clean up + namespace. + + * libelf.h (elf32_symbol_type, elf64_symbol_type): Deleted + "native_elf_sym" field, merged to make new type "elf_symbol_type". + (struct elf_obj_tdata): Field symbols is now elf_symbol_type*. + Deleted field raw_syms. + (obj_symbols): Remove cast. + (obj_raw_syms): Deleted. + * elfcode.h (elf_slurp_symbol_table): Don't set raw_syms or + native_elf_sym fields. + * elf32-hppa.c: Changed uses of elf32_symbol_type to + elf_symbol_type. + + From Pete Hoogenboom and Jeff Law: + + * elf32-hppa.c (ELF_MAXPAGESIZE): Define. + + * elf32-hppa.c (elf_hppa_tc_symbol): If the argument relocation + bits are zero (e.g., they specify no relocations), then do not + even bother adding their entries to the symextn section. + + * elf32-hppa.c (elf_hppa_tc_symbol): Any function, regardless + of scope can have an argument relocation stub. + + * elf32-hppa.c: (Elf32_hppa_Stub_description): Rename this + structure and type to elf32_hppa_stub_description. This makes + it consistent with the GNU coding conventions. + (elf32_hppa_stub_description): Added a 'next' field to allow + linking of stub description structures. + (elf32_hppa_stub_description): Added a 'stub_listP' field to + keep track of individual stubs. + (Elf32_hppa_Stub_list, Elf32_hppa_Stub_list_struct): Removed. + Combined with the elf32_hppa_stub_description structure. + (elf32_hppa_stub_name_list): New type to keep track of + individual stubs. + (add_stub): Removed. + (add_stub_by_name): New function. + (find_stub_by_name): New function. + (hppa_elf_build_arg_reloc_stub): Allow reusing stubs that + already exist. + (hppa_elf_build_long_branch_stub): Allow reusing stubs that + already exist. + + * elf32-hppa.c: (retval_mismatches): The direction of argument + relocation was reversed. + (hppa_elf_build_arg_reloc_stub): Return address was not being + restored. + (hppa_elf_arg_reloc_needed_p): Add argument containing caller + argument relocation bits so this function can be used in the check + for plabel stubs. + (hppa_elf_stub_check): Pass caller argument relocation bits into + hppa_elf_arg_reloc_needed_p(). + (hppa_look_for_stubs_in_section): Add check for plabel stubs and + pass caller argument relocation bits into + hppa_elf_arg_reloc_needed_p(). + +Thu Sep 2 00:59:55 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * libhppa.h (hppa_field_adjust): Remove unused `init_value' variable. + + * hosts/delta88v4.h: New for SVR4. + * configure.hosts: Use it. + +Wed Sep 1 14:23:32 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * libaout.h, netbsd386.c: Change M_I386 to M_386_NETBSD. M_I386 + is an SCO pre-define. + +Tue Aug 31 12:50:19 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmcode.h (nlm_object_p): Set HAS_SYMS if there are external + references. + (nlm_swap_auxiliary_headers_{in,out}): The copyright length is + only one byte. + (nlm_get_symtab_upper_bound): Include debugging symbols in symbol + count. + (nlm_slurp_symbol_table): Make symlength unsigned. Read debugging + symbols as BFD local symbols. + (nlm_write_object_contents): Don't bother writing out exported + symbols more than once; they now appear in the symbol table more + than once (with and without a prefix) if necessary. Set offset + values to be non-zero as NLMLINK does. + +Tue Aug 31 12:07:43 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * libhppa.h: Restore #undefs of e_fsel and other e_* symbols. + +Fri Aug 27 16:43:35 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * section.c (struct sec): Move position of user_set_vma, and + document it. + (SEC_BALIGN): Disable for now. I don't think it's currently used. + + * elf32-hppa.c (elf_hppa_howto_table): Now static. + (symext_rootP, symext_lastP, global_value, GOT_value, + global_symbol, global_sym_defined, symextn_contents, + symextn_contents_real_size, elf_hppa_stub_rootP, + elf32_hppa_symextn_map, elf32_hppa_symextn_map_size): Rely on + default initialization. + (hppa_elf_gen_reloc_type): Macro "UNDEFINED" doesn't need a + trailing semicolon. + (hppa_look_for_stubs_in_section): Introduce temporaries to make + code more readable in 80 columns. + + * libhppa.h (all functions): Now inline under GNU C. + + More patches from Jeff Law: + + * elf32-hppa.c (AR_WARN): Give argument which caused the + invalid argument relocation. + (AR_UNIMP): Delete unused macro. + (hppa_elf_set_section_contents): Always return a value. + (elf32_hppa_backend_table_processing): Likewise. + (elf32_hppa_backend_section_processing: Likewise. + + * som.c: New file containing SOM specific code extracted + from hppa.c + + * som.h: New file containing SOM specific code extracted + from libhppa.h + + * hppa.c: Deleted. + + * libhppa.h: Delete SOM specific code. Add generic PA + code which can be shared by both SOM and ELF backends. + + * Makefile.in: Replace hppa.c with som.c. elf32-hppa.o + depends on libhppa.h now. + + * configure.in (hppa_vec): Needs som.o module instead of + hppa.o. + + * elf32-hppa.c: Include libhppa.h. Do not define + BYTES_IN_WORD. + + * elf32-hppa.h (hppa_reloc_field_selector_type): Delete + now lives in libhppa.h. + (hppa_reloc_field_selector_type_alt): Likewise. + + * hosts/hppabsd.h: Include and . Do not + define malloc or free. + + * config/hppa-elf.mt (SELECT_ARCHITECTURES): Don't define + SELECT_VECS. + + * elf32-hppa.c (hppa_elf_relocate_unwind_table): Delete unused + variables. + (elf_hppa_reloc_type_lookup): Likewise. + (elf_hppa_tc_make_sections): Likewise. + (hppa_elf_arg_reloc_needed_p): Likewise. + (hppa_elf_build_long_branch_stub): Likewise. + (elf_reloc_map): Delete, no longer used. + (elf_hppa_reloc_map): Likewise. + (elf32_hppa_symextn_map_max_size): Likewise. + (elf32_hppa_get_sym_extn): Abort if type is bogus. + + * elf32-hppa.c (elf32_hppa_backend_fake_sections): Add processing + of the .hppa_unwind section. + +Wed Aug 25 16:13:49 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * config.bfd: recognize m88110. + +Tue Aug 24 16:32:35 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + Merged changes from Jeff Law and Pete Hoogenboom at Utah: + + * elfcode.h (elf_section_from_bfd_section): Add detection of + SHT_NOTE sections. + + * elf32-hppa.c: + (hppa_elf_build_long_branch_stub,hppa_elf_long_branch_needed_p): + New functions for support of long branch stubs. + (hppa_elf_stub_check,hppa_look_for_stubs_in_section): Add + check for long branch stubs. + (hppa_look_for_stubs): Unused function. Removed. + (hppa_elf_set_section_contents): Implement a PA/ELF-specific + version of bfd_set_section_contents. + (hppa_elf_long_branch_needed_p): Only output debugging diagnostics + when BFD is configured for debugging. + + * elf32-hppa.c: (elf32_hppa_get_symextn_chain): New function + to return a list of symbols that have non-zero argument + relocation bits. + (hppa_elf_stub_finish): Make sure stub generation is done only + once. + + * elf32-hppa.c: (hppa_elf_stub_reloc): New function for + generation relocation entries within a stub. + (hppa_elf_build_arg_reloc_stub): Corrections to argument + relocation stubs. + + * elf32-hppa.c: New #define's for argument relocation types. + (mismatches, retval_mismatches): Updated to reflect new + argument relocation types. + (CURRENT_STUB_OFFSET): New macro. + + * elfcode.h (map_program_segments): Set the PF_X bit for data + segments. + + * elf32-hppa.c: (elf_hppa_howto_table): Add + R_HPPA_STUB_CALL_17 for support of linker stub generation. + (hppa_elf_reloc): Add support of R_HPPA_STUB_CALL_17 + relocation type. + + * elf32-hppa.h: (elf32_hppa_reloc_type): Add + R_HPPA_STUB_CALL_17 for support of linker stub generation. + + * hppa_stubs.h: Add new instructions that are used in linker + stub generation. + + * elf32-hppa.c (hppa_elf_relocate_unwind_table): The offsets in an + unwind descriptor were incorrect. + + * libelf.h (bfd_elf_find_section): Declare. + + * elf32-hppa.c: (elf32_hppa_backend_symbol_processing): New + function in place of global_sym field in elf_backend_data + structure. + (elf32_hppa_backend_symbol_table_processing, + elf32_hppa_backend_section_processing, + elf32_hppa_backend_fake_sections, + elf32_hppa_backend_section_from_shdr, + elf32_hppa_backend_section_from_bfd_section): New functions to + provide support of symbol extension sections and argument + relocation stubs. + (elf_info_to_howto): Remove call to abort(). + + * elf32-target.h: Support for special processing by the backend. + (struct elf_backend_data): Added elf_backend_symbol_processing, + elf_backend_symbol_table_processing, + elf_backend_section_processing, elf_backend_section_from_shdr, + elf_backend_fake_sections, and + elf_backend_section_from_bfd_section fields. + * elfcode.h: (bfd_section_from_shdr): Add a check for + processor-specific section types. + (elf_fake_sections): Add a check for processor-specific + section types. + (bfd_elf32_write_object_contents): Add a check to see if + there is any final section processing to be done by the + backend. + (elf_section_from_bfd_section): Add a check for + processor-specific section types. + (elf_slurp_symbol_table): Remove reference to global_sym in the + elf_backend_data structure. Replace it with a call to + elf_backend_symbol_processing. + * libelf.h: Remove global_sym field in the elf_backend_data + structure. Replace it with a series of backend-specific + functions. + + * elf32-hppa.c (hppa_elf_stub_branch_reloc): The formal argument + stub_sym should be called target_sym. + (hppa_elf_build_arg_reloc_stub): Refer to the stub bfd (abfd) + rather than the output bfd (output_bfd). + (hppa_elf_reloc): Get rid of references to the global_sym field in + the elf_backend_data structure. + + * elfcode.h (elf_fake_sections): Check the correct condition for + .bss. Also, detect the existence of a .note section. + + * elf32-hppa.c (hppa_elf_relocate_insn): r_format argument should + have been r_field. + + * hosts/hppabsd.h (HOST_MACHINE_ARCH): Reference to bfd_arch_m68k + should be a reference to bfd_arch_hppa. + + * hppa.c (hppa_vec): Replace bfd_false with _bfd_dummy_target in + the bfd_check_format structure to avoid a type mismatch. + +Mon Aug 23 1993 Sean Fagan (sef@cygnus.com) + and Jim Kingdon (kingdon@cygnus.com) + + Add NetBSD support: + * netbsd386.c: New file. + * aoutx.h: Make sym_is_debugger_info true for N_FN. + * Makefile.in, aout-target.h, config.bfd, configure.host, configure.in, + libaout.h, targets.c: Other changes. + +Fri Aug 20 17:04:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config/m88k-elf.mt: New file. + * config.bfd: Use it for m88*-*-sysv4*. + +Fri Aug 20 15:16:58 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elfcode.h (elf_build_phdrs): Unused function deleted. + (bfd_shdr_from_section): Ditto. + (write_relocs): Don't change section contents for addend. + (elf_locate_sh): Return type is now always elf_internal_shdr, + since the other types were really aliases for this type anyways. + Don't compile this function, since it is static and doesn't appear + to be used in this file. + (sym_is_global): Return non-zero for weak symbols. Abort if + section pointer is null. + (swap_out_syms): Reorder tests so function symbols can be weak. + (elf_slurp_symbol_table): Don't use BSF_EXPORT. + (elf_slurp_reloca_table): Make RELOC_PROCESSING section smaller by + extracting out some common code. Abort if BFD section symbol has + null name. + (elf_slurp_reloc_table): Translate ELF section symbols into BFD + section symbols. Don't read section contents to fill in addend + field. + + * elf32-i386.c (elf_howto_table): All partial_inplace fields + should be "true". + + * Merged from OSF: + + Tue Jun 15 14:38:32 1993 Michael Meissner (meissner@osf.org) + + * libelf.h (struct Elf_Sym_Extra): New structure to contain ELF + specific information for a symbol. Put in elf_sym_num, which + gives the external symbol number in the elf object file, since + local symbols must come before global symbols. + (elf_sym_extra): New macro. + (elf_symtab_map): Delete, in favor of using Elf_Sym_Extra. + * elfcode.h (elf_map_symbols): Use Elf_Sym_Extra to map internal + symbol number to external number. Store the address of the + Elf_Sym_Extra field for the symbol in the udata field. + (elf_write_object_contents): Use Elf_Sym_Extra to map out symbols. + + Sun Jun 20 16:30:11 1993 Michael Meissner (meissner@osf.org) + + * elfcode.h (elf_obj_tdata): Add field to count the size of the + array of pointers to section symbols. + (elf_map_symbols): Bump the max index of the section symbols so + that we don't overwrite memory. Store the max index into the + elf_obj_tdata field. + + Sat Jun 19 10:12:27 1993 Michael Meissner (meissner@osf.org) + + * elfcode.h (elf_obj_tdata): Add pointer to an array of pointers + to the section symbols we created. Remove unused field + internal_syms. + (elf_map_symbols): Fill in array of pointers to section symbols. + Only create section symbols for sections that have SEC_ALLOC set, + and have non-zero size. + (elf_symbol_from_bfd_symbol): If udata is NULL, and this is a + section symbol, look up the section in the list of section + symbols, and set the udata pointer appropriately. Otherwise, if + udata is still NULL, fail an assertion, and use 0, instead of + dropping core. + +Fri Aug 20 12:18:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config.bfd (mips-*-elfl*, mips-*-elf*): New targets, using + mipslelf and mipsbelf respectively. + * config/mipslelf.mt, config/mipsbelf.mt: New files. + * elf32-mips.c: Added some reloc information. + * configure.in: Fixed error message. + + * ecoff.c (ECOFF_LONG_SIZE): Removed. Just use constants. + +Thu Aug 19 09:45:51 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in (BFD_LIBS, ALL_MACHINES, BFD32_BACKENDS, BFD64_BACKENDS, + OPTIONAL_BACKENDS): Alphabetize entries and add a few missing ones. + * archures.c: Alphabetize decls. + + * configure.in, targets.c: Add missing vectors to the tables. + * targets.c (target_vector) [!SELECT_VECS]: Add DEFAULT_VECTOR. + Remove hp300bsd_vec due to clash with sunos_big_vec. + +Tue Aug 17 18:12:32 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hosts/i386{mach3,osf1mk}.h: New files, for Mach hosting. + * hosts/i386mach.h: removed, replaced by i386osf1mk.h. + * config/i386mach3.mt, i386mach3.c: New files, for Mach a.out format. + * Makefile.in, configure.host, config.bfd: Corresponding changes. + * hosts/decstation.h: Include not . + +Tue Aug 17 15:19:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coffgen.c (coff_section_symbol): If section's output_section is + not yet set, point to itself. This is needed because this is + called on the output file, not the input file. + + * coff-rs6000.c (dummy_reloc, RTYPE2HOWTO): Set howto field to a + dummy value, rather than leaving it NULL. + + * archures.c (bfd_default_set_arch_mach): Set bfd_error on + failure. + * aoutx.h (NAME(aout,set_arch_mach)): Check return value of + bfd_default_set_arch_mach. + +Tue Aug 17 09:42:16 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * config.bfd (cpu): Extract from canonical name with sed. + * configure.in: Don't pass it. + +Sun Aug 15 20:45:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * bfd-in.h: Remove {BYTE,WORD,LONG}_SIZE; they are pointless and + BYTE_SIZE conflicts with a Mach header. + * ecoff.c: Change LONG_SIZE to ECOFF_LONG_SIZE and define it. + + * configure.host: Make sure all OS fields end in *. + +Fri Aug 13 16:33:33 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_slurp_reloc_table): Use bfd_abs_section for + RELOC_SECTION_NONE and RELOC_SECTION_ABS. If a reloc section + doesn't exist, don't try to create it. + + * nlmcode.h (nlm_write_object_contents): procedure offsets are + from start of code segment, not start of file. + * config/i386-nlm.mt (DEFAULT_VECTOR): It's nlm32_i386_vec, not + bfd_nlm32_i386_vec. + * configure.in (SELECT_VECS switch): Likewise. + +Thu Aug 12 10:32:47 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * format.c (bfd_check_format): If the target matches the default + target, set match_count to 1, to ignore any previous matches. + + * Makefile.in (BFD32_BACKENDS): Remove srec.o, add reloc16.o. + + * configure.in: Add reloc16.o when we add + coff-h8300.o, coff-h8500.o, coff-sh.o, coff-z8k.o. + Makefile.in (BFD_LIBS): Remove reloc16.o. + + * config/u68k-coff.mt: Fix typo, DEFAULT_TARGET for + DEFAULT_VECTOR. + + * config/h8300-coff.mt, h8500-coff.mt, sh-coff.mt, st2000.mt, + z8k-coff.mt (DEFAULT_VECTOR): Define. Don't explicitly add + S-records via SELECT_VECS. + + * targets.c (target_vector), Makefile.in (BFD_LIBS): Always + support S-records, for convenience. + +Thu Aug 12 08:30:05 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-alpha.c (alpha_howto_table, alpha_finish_reloc, + alpha_ecoff_swap_reloc_{in,out}, alpha_bfd_reloc_type_lookup): + Read and write Alpha relocs. Can't process them yet. + * ecoff.c (ecoff_slurp_reloc_table): Recognize new reloc sections. + If the section does not already exist, create it. + + * ecoffswap.h (ecoff_swap_pdr_{in,out}): Handle new fields defined + on the Alpha. + + * libecoff.h (ecoff_backend_data): Added constructor_reloc and + finish_reloc fields. + * ecoff.c: Move MIPS reloc support from here... + * coff-mips.c: to here. + * ecoff.c (ecoff_set_symbol_info): Get constructor reloc howto + from backend. + (ecoff_slurp_reloc_table): Removed MIPS specific stuff. Call + finish_reloc backend function. + (ecoff_write_object_contents): Removed MIPS specific assertions. + * coff-mips.c (mips_finish_reloc): New function. + (mips_ecoff_backend_data): Fill in new fields. + * coff-alpha.c (alpha_ecoff_backend_data): Use NULL for new + fields. + * targets.c: Added extern for ecoffalpha_little_vec. + + * bfd.c (_bfd_host_big_endian): Removed. + * bfd-in.h (HOST_BYTE_ORDER_BIG_P, bfd_header_twiddle_required): + Removed. + * bfd-in2.h: Regenerated. + +Wed Aug 11 12:11:23 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * config.bfd: New file, broken out of configure.in. + * configure.in: Use it, and use standard target names for + --with-targets, replacing --with-bfd-targets. + + * archures.c (archures_init_table): Add bfd_sh_arch. + + * configure.in: Include coff-m68k.o for m68kcoffun_vec. + Include nlm32.o and nlm.o for bfd_nlm32_i386_vec. + Fix error in error message. + + * oasys.c: Make bfd_error_vector extern. + + * configure.in: Include stab-syms.o for a.out/b.out targets + and hp300{bsd,hpux}. + +Wed Aug 11 06:40:51 1993 Ian Lance Taylor (ian@cygnus.com) + + * nlmcode.h (nlm_compute_section_file_positions): Add the .bss + section before setting output_has_begun. + (nlm_set_section_contents): Remove argument names from + mangle_relocs_func prototype. + (nlm_write_object_contents): Remove shadowing local variable. + Don't write out debugging symbols if debugInfoOffset is -1. Add + the codeImageOffset to the start, exit, and check procedure + offsets. + * nlm32-i386.c (nlm_i386_write_reloc, nlm_i386_mangle_relocs): + Don't check partial_inplace field; its value is irrelevant. + + * Base use of sco-core on host, not target. + * configure.host (i[34]86-*-sco*): Use i386sco rather than i386v. + * config/i386-sco.mt (TDEFINES): Removed. + * config/i386sco.mh: New file to use sco-core. + * hosts/i386sco.h: New file; just includes hosts/i386v.h. + + * ecoffswap.h (ecoff_swap_{hdr,ext}_{in,out}): Use signed + conversions for some fields. + +Tue Aug 10 13:32:23 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_gprel_reloc): If _gp is not defined, give an + error rather than aborting. + + * libnlm.h (struct nlm_backend_data): Added mach field. + (nlm_machine): New accessor macro. + * nlm.c (nlm_mkobject): Set architecture and machine from backend + information. + * nlm32-i386.c (nlm32_i386_backend): Initialize new mach field. + +Tue Aug 10 09:31:18 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * configure.in: Replace calls to sort with shell code + to uniq the lists. + +Tue Aug 10 06:23:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * configure.in: Include aout32.o for any a.out/b.out formats. + +Mon Aug 9 09:37:18 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * config/i386-linux.mt (SELECT_VECS): Support bfd_elf32_i386_vec. + * config/m68k-elf.mt (SELECT_VECS): Support m68kcoff_vec. + * config/i386-elf.mt (SELECT_VECS): Support i386coff_vec. + * config/hppa-elf.mt (SELECT_VECS): Support hppa_vec. + * config/sparc-elf.mt (SELECT_VECS): Support sunos_big_vec. + * config/i386-sco.mt (SELECT_VECS): Don't define; Ian says it was + just a hack. + +Mon Aug 9 13:15:00 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * config/m88k-coff.mt (DEFAULT_VEC -> DEFAULT_VECTOR): renamed. + +Mon Aug 9 14:26:45 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * syms.c (BSF_EXPORT): Now same as BSF_GLOBAL. + + * bfd.c (bfd_scan_vma): New function. + +Mon Aug 9 11:29:53 1993 Ian Lance Taylor (ian@cygnus.com) + + * bfd-in.h (bfd_get_architecture, bfd_get_machine): Removed + obsolete macros. + * bfd-in2.h: Updated. + + * ecoff.c (ecoff_slurp_armap): Correct bug in initialization of + stringbase. + +Sun Aug 8 12:21:13 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * configure.in: Remove unneeded test. + +Sun Aug 8 12:41:22 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * Makefile.in ({dist,real}clean): Use $(MAKE), not make. + +Sat Aug 7 09:14:21 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * config/st2000.mt (TDEFINES): Don't define MRI; not used. + + * PORTING, TODO, config/README: Update to reflect below changes. + + * configure.in: Replace MINIMIZE and --with-minimal-bfd with + --with-bfd-targets="target1,target2,..." and the special target + "all" to get the previous default behavior. + Figure out which architecture and backend .o files are needed from + DEFAULT_VECTOR, SELECT_VECS, and SELECT_ARCHITECTURES as set in + the .mt files. Define TDEFAULTS based on them, also. + + * Makefile.in: Remove references to MINIMIZE. + * archures.c, targets.c: Ditto. + + * config/*.mt: Define DEFAULT_VECTOR, SELECT_VECS, and + SELECT_ARCHITECTURES as variables rather than as -D arguments to + TDEFAULTS. + + * config/a29k-coff.mt,alphaosf.mt, i386-sco.mt, i960-bout.mt, + i960-coff.mt (TDEFAULTS): Don't put the default vector in + SELECT_VECS manually; it's automatic now. + + * config/i386-sco.mt (TDEFAULTS): Don't put &sco_core_vec in + SELECT_VECS manually; -DSCO_CORE does it automatically now. + + * config/h8300-coff.mt,h8500-coff.mt,sh-coff.mt,st2000.mt,z8k-coff.mt + (TDEFAULTS): Don't define BFD; not used. + + * config/hppaosf.mh (HDEFINES): Don't define SELECT_ARCHITECTURES; + this is a host, not a target. + +Sat Aug 7 05:28:03 1993 Fred Fish (fnf@deneb.cygnus.com) + + * elfcode.h (elf_object_p): Add comment about what this function + does and to watch out for side effects. Add FIXME for memory leaks. + Fix comment about checking for matching byte order. Preserve + pointer to old tdata (if any), and restore it if we don't match + file with target vector. If we are going to use goto's, use them + consistently and maintainably. + * nlmcode.h (nlm_object_p): Expand comments about leaked memory + to note that the problem is even more serious than just leaked + memory. Replace goto with more traditional return. + +Fri Aug 6 12:00:03 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + Fix incorrect or useless makefile variable definitions: + * config/news.mt, config/u68k-coff.mt (TDEFAULTS): Use this to + define DEFAULT_VECTOR, instead of TDEFINES. + * config/i386aix.mh (MINIMIZE): Don't define. + * config/hppaosf.mh (MINIMIZE): Don't conditionalize. + * config/rs6000.mh (ALLOCA), + * config/i386v.mh (ALLOCA), + * config/i386linux.mh (ALLOCA), + * config/i386isc.mh (ALLOCA), + * config/go32.mh (EXTRALIBS): Don't define; not used. + * config/solaris2.mh (HDEFINES): Renamed from H_DEFINES. + * config/alphaosf.mt (TDEFINES): Set it, not HDEFINES. + * config/z8k-coff.mt (CC): Don't define. It's a target, not a host. + + * config/README: New file, explaining the variables. + + * targets.c (target_vector): Add hp300_bsd_vec. + * Makefile.in (BFD32_BACKENDS, CFILES): Add hp300bsd. + (hp300bsd.o): New rule. + +Fri Aug 6 15:13:22 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * libelf.h (NAME): Provide a default definition, that's neither + for 32 bits nor for 64. + + Tue Jun 15 14:38:32 1993 Michael Meissner (meissner@osf.org) + + * libelf.h (elf_hash): Change declaration to bfd_elf_hash, since + that is what is in elf.c. + +Fri Aug 6 12:28:38 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_set_symbol_info): Removed special handling for + scBss and scSBss symbols, since it was wrong. + + * Makefile.in (coff-mips.o, coff-alpha.o): Don't depend on + coffcode.h. + + * coffcode.h (sec_to_styp_flags): Inspired by mb@tti.COM (Michael + Bloom): Only set STYP_BSS for SEC_ALLOC sections. + + * ecoff.c (ecoff_slurp_armap): From Arne Henrik Juul + : Handle a COFF style armap. + +Fri Aug 6 09:59:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hpux-core.c: Cast return value from bfd_zalloc. + +Thu Aug 5 13:22:44 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * aoutx.h (log2): Delete i387-specific code. + + * Makefile.in (BFD_LIBS): Always include elf.o. + (BFD32_BACKENDS): Don't include elf.o here. + (ofiles): Delete references to ofiles2 and ofiles3. + (do_clean): Delete ofiles. + (BFDIN_H): Changed references to $(srcdir)/bfd-in2.h. + (stmp-bfd.h): Use bfd.h-new as temporary name, not bfd.h2. + (headers): Use bfd-in2.h-new as temporary name, not bfd.h-new. + + * bfd-in.h: Reworded comment to make it clear that bfd-in2.h is a + generated file. + + * reloc.c (enum bfd_reloc_code_real): Added i386-elf reloc types + (from Meissner's additions to bfd-in2.h). + + * elf32-i386.c (ELF_MAXPAGESIZE): Define. + + Merged: + + Wed Jun 23 06:05:58 1993 Michael Meissner (meissner@osf.org) + + * elfcode.h (elf_write_object_contents): Don't drop core if + elf_symbol_from returns a NULL pointer when processing a non-elf + symbol, use a 0 size instead. + + Tue Jun 15 14:38:32 1993 Michael Meissner (meissner@osf.org) + + * elfcode.h (elf_hash): Delete macro mapping elf_hash to + bfd_elf32_hash, since the hash table is independent of the 32/64 + bit system. + + * libelf.h (elf_hash): Change declaration to bfd_elf_hash, since + that is what is in elf.c. + + Sat Jun 19 10:12:27 1993 Michael Meissner (meissner@osf.org) + + * elf32-i386.h (reloc_type): Reformat spacing. + (elf_howto_table): Add the rest of the 386/ELF relocations. + (elf_i386_reloc_type_lookup): Ditto. + (elf_i386_info_to_howto): Ditto. + (elf_i386_info_to_howto_rel): Ditto. + +Thu Aug 5 10:07:43 1993 Fred Fish (fnf@cygnus.com) + + * nlmcode.h (nlm_get_reloc_upper_bound): Test return value + of nlm_slurp_symbol_table as boolean, not pointer. + * nlmcode.h (nlm_canonicalize_reloc): Test return value + of nlm_slurp_reloc_fixups as boolean, not pointer. + +Wed Aug 4 16:22:55 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * config/go32.mh: remove HDEFINES; since __MSDOS__ and __GO32__ + are now predefined by GCC + +Wed Aug 4 16:06:29 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * coffgen.c (coff_print_symbol): Add the section offset to the + line number address, so it's printed the same way as the function + address. Only showed up for line numbers that aren't in the first + section (.text). + +Wed Aug 4 08:33:55 1993 Ian Lance Taylor (ian@cygnus.com) + + * libnlm.h (nlm_backend_data): Added nlm_mangle_relocs. + (nlm_mangle_relocs_func): New macro. + * nlm32-i386.c (nlm_i386_write_reloc): Rewrote correctly. + (nlm_i386_mangle_relocs): New function. + * nlmcode.h (nlm_compute_section_file_positions): Move all common + symbols into the .bss section. + (nlm_set_section_contents): Call the mangle_relocs function. + (nlm_write_object_contents): Treat a reloc against any defined + symbol as an internal reloc. Fix bug in external reloc counting. + Get the offset and debugging type right for .bss symbols. Only + output debugging symbols for defined symbols. + + * coff-h8500.c (rtype2howto): Do an fprintf to stderr rather than + using printf. + * coff-z8k.c (rtype2howto): Likewise. + * coffcode.h (dummy_reloc16_extra_cases): Likewise. + * elf32-i386.c (TRACE): Likewise. + * hp300hpux.c (convert_sym_type, swap_std_reloc_in): Likewise. + * rs6000-core.c (rs6000coff_get_section_contents): Likewise. + * coffgen.c (coff_print_symbol): Do an fprintf to the file + argument rather than using printf. + +Tue Aug 3 18:17:25 1993 Ian Lance Taylor (ian@cygnus.com) + + * coffswap.h: Added macros used when accessing several fields; + default is the same as before. + (coff_swap_aouthdr_{in,out}): Handle the Alpha ECOFF fields. + * coff-alpha.c: Defined macros to use the right sizes in + coffswap.h. + * libecoff.h: Backend information is now in target vector, not + BFD. Start of backend information is COFF backend information. + * coff-alpha.c, coff-mips.c: Changed accordingly. + * ecoff.c (ecoff_mkobject): New function. + (ARMAP_START): Changed into backend information, since Alpha uses + a different name. + (ecoff_slurp_armap): Don't overlay archive header. + * bfd.c: Include libcoff.h. + +Tue Aug 3 16:33:11 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in (install): Fix sh syntax error. + + * aoutf1.h: Make bfd_error_trap extern; it's defined in bfd.c. + +Tue Aug 3 15:19:09 1993 Fred Fish (fnf@deneb.cygnus.com) + + * nlm_slurp_symbol_table: Don't use '&' on arrays. + +Tue Aug 3 11:06:28 1993 Ian Lance Taylor (ian@cygnus.com) + + * ecoff.c: New file for generic ECOFF functions. + * ecoffswap.h: New file for ECOFF swapping functions which differ + only slightly for different targets. + * libecoff.h: Added prototypes for ecoff.c functions. + (ecoff_backend_data): New structure. + (ecoff_tdata): Added backend_data field. Changed external data + pointers to be PTR rather than to a particular struct. + (ecoff_symbol_struct): Moved in from coff-mips.c. + * coff-alpha.c, coff-mips.c: Moved common functions into ecoff.c. + Added ECOFF backend structures. Include ecoffswap.h. + * coff-msym.c: Removed; superseded by ecoffswap.h. + * bfd.c: Include coff/internal.h. + * Makefile.in (BFD_LIBS): Removed coff-mips.o and coff-msym.o. + Added ecoff.o. + (BFD64_BACKENDS): Added coff-alpha.o. + (CFILES): Removed coff-msym.c. Added ecoff.c. + (bfd.o): Added dependency on $(INCDIR)/coff/sym.h. + (coff-mips.o): Added dependency on ecoffswap.h and coff/ecoff.h. + (ecoff.o, coff-alpha.o): New targets. + (coff-msym.o): Removed target. + +Mon Aug 2 23:33:38 1993 John Gilmore (gnu@cygnus.com) + + * elf32-hppa.h, hosts/*: Remove (one more time) all occurrances + of EXFUN in the BFD sources. Heave ho! + +Mon Aug 2 16:45:57 1993 Stu Grossman (grossman at cygnus.com) + + * coffcode.h (coff_set_arch_mach_hook): Add check for I386LYNXMAGIC. + +Mon Aug 2 12:18:03 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * hosts/sun3.h: remove some more conflicting decls + +Mon Aug 2 11:48:23 1993 Stu Grossman (grossman at cygnus.com) + + * i386lynx.c: Remove unnecessary def of N_HEADER_IN_TEXT, + redefine TEXT_START_ADDR to be 0. + +Sun Aug 1 22:54:08 1993 Stu Grossman (grossman at cygnus.com) + + * configure.host, configure.in, hosts/i386lynx.h: Lynx/386 + host and target info. + +Fri Jul 30 18:08:27 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlm32-i386.c: New file. First cut at i386 NLM code. + * libnlm.h: Added some more prototypes. + (struct nlm_relent): New structure. + (nlmNAME(symbol_type)): Added rcnt and relocs fields. + (struct nlm_obj_tdata): Added new fields: nlm_symbols, + nlm_text_low, nlm_data_low, nlm_reloc_fixups, + nlm_reloc_fixup_secs. + (struct nlm_backend_data): New structure, with accessor macros. + * nlmcode.h: Use NLM_HIBIT rather than MSB. + (nlm_object_p): Set SEC_RELOC for .text and .data. Don't set + SEC_DATA for .bss. Set HAS_RELOC and HAS_SYMS for abfd. Set the + architecture. + (nlm_swap_fixed_header_out, nlm_swap_variable_header_out, + find_nonzero, nlm_swap_auxiliary_headers_out): New outbound + swapping functions. + (nlm_get_symtab_upper_bound, nlm_slurp_symbol_table): Include + external references in symbol table as undefined symbols. + (nlm_get_symtab, nlm_slurp_symbol_table): Fill in alocation + argument in get_symtab rather than in slurp_symbol_table. + (nlm_slurp_symbol_table): Save symbol information in tdata. + (nlm_print_symbol): New function. + (nlm_slurp_reloc_fixups, nlm_get_reloc_upper_bound, + nlm_canonicalize_reloc): New functions to read relocs. + (nlm_compute_section_file_positions, nlm_set_section_contents, + nlm_external_reloc_compare, nlm_write_object_contents): New + functions to create NLM files. + * nlm-target.h: Define all the nlm functions here either as + default values or in terms of nlmNAME. Use JUMP_TABLE(nlm). Set + the backend_data field to TARGET_BACKEND_DATA. + * nlm32-gen.c, nlm64-gen.c: Don't define function macros here; + they are now in nlm-target.h. + (TARGET_BACKEND_DATA): Define as NULL. + * nlm.c (nlm_mkobject): Do allocate the tdata field. + (nlm_set_arch_mach): New function. + * targets.c: Added nlm32_i386_vec. + * Makefile.in (BFD32_BACKENDS): Added nlm32-i386.o. + (CFILES): Added nlm32-i386.c. + (nlm32-gen.o, nlm64-gen.o): Depend on nlm-target.h. + (nlm32-i386.o): New target. + +Thu Jul 29 20:20:39 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * hosts/sun3.h: remove some function decls that conflict w/ ANSI + C, and aren't needed anyway (return int) + +Wed Jul 28 15:46:38 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elfcode.h: Use casts with bfd_alloc and alloca. + +Tue Jul 27 12:51:43 1993 Fred Fish (fnf@deneb.cygnus.com) + + * nlm{32,64}-gen.c (JUMP_TABLE_PREFIX): Delete. + * nlm{32,64}-gen.c (JUMP_TABLE_INIT): New macro that works with + older cpp's, that don't do additional replacement on the JUMP_TABLE + macro's argument. + * nlm-target.h (JUMP_TABLE_INIT): Use new macro in place of + JUMP_TABLE macro. + +Mon Jul 26 17:39:01 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + Yet another trad-core variant: + * config/esix.mh, hosts/esix.h: New files. + * configure.hosts: Use them. + +Mon Jul 26 13:22:15 1993 Ian Lance Taylor (ian@cygnus.com) + + * reloc.c (bfd_perform_relocation): Handle the case of + complain_overflow_bitfield, rightshift > bitpos, and a negative + number. + +Mon Jul 26 14:40:10 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elfcode.h: Reimplement segment writing. + (elf_write_phdrs): Use precomputed e_phoff rather than making + assumptions. + (elf_build_phdrs): Disabled, for now. + (assign_file_position_for_section): Don't change file offset for + SHT_NOBITS. + (assign_file_positions_for_symtab_and_strtabs): New function. + (struct seg_info): New type. + (map_program_segments): New function. + (assign_file_positions_except_relocs): For executables, leave + section headers &c for last, and properly align all sections with + flag SHF_ALLOC set. + (prep_headers): No longer abort when EXEC_P is set. + (write_shdrs_and_ehdr): Deleted all code relating to program + segments. + + * elfcode.h (various): Deleted some unused code, and debugging + "malloc(0)" calls. + (write_relocs): Cache value of last symbol looked up, to save + time if the symbol is referred to repeatedly. + (elf_fake_sections): Check only SEC_RELOC flag, not number of + relocs. + (assign_section_numbers): Likewise. + + * Makefile.in (ofiles): Stars in wildcards belong outside quotes. + + * libelf.h (struct elf_backend_data): New field, maxpagesize. + (struct elf_obj_tdata): New field, phdr. + * elf32-target.h (elf32_bed): Initialize maxpagesize from + ELF_MAXPAGESIZE. + (ELF_MAXPAGESIZE): Default to 1. + * elf64-target.h (elf64_bed, ELF_MAXPAGESIZE): Likewise. + * elf32-sparc.c (ELF_MAXPAGESIZE): Define. + (elf_sparc_howto_table): All relocs should have pcrel_offset=true. + Most should have length field of `2'. + + * reloc.c (bfd_perform_relocation): Handle 64-bit relocs. + + * config/sparc-aout.mt (TARGET_BACKENDS): Define. + +Mon Jul 26 08:56:16 1993 Ian Lance Taylor (ian@cygnus.com) + + * configure.in: Don't look in ${srcdir} for ${target_makefile_frag}; + the top level script has already adjusted for it. + +Mon Jul 26 08:09:19 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * srec.c (srec_write_symbols): Get CR LF in the right order. + +Mon Jul 26 02:08:41 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hosts/vaxbsd.h: Include std-host.h. Don't include . + +Sat Jul 24 16:13:01 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * reloc.c (bfd_perform_relocation): Handle case of rightshift != + bitpos when overflow checking. + +Fri Jul 23 10:20:27 1993 Doug Evans (dje@canuck.cygnus.com) + + * bfd.c (bfd_nonrepresentable_section, bfd_undefined_symbol, + bfd_reloc_value_truncated, bfd_reloc_is_dangerous, bfd_assert): + Send error messages to stderr. + +Thu Jul 22 15:57:29 1993 Fred Fish (fnf@deneb.cygnus.com) + + * nlm{32,64}-target.h: Remove. + * nlm-target.h: New file, merged from nlm{32,64}-target.h + * libnlm.h (NLM_ARCH_SIZE): Define to ARCH_SIZE. + * nlm.c (ARCH_SIZE): Remove define to zero. + * nlm32-gen.c (ARCH_SIZE): Define to 32. + * nlm32-gen.c (JUMP_TABLE_PREFIX): Define to nlm32. + * nlm{32,64}-gen.c (nlm-target.h): Include. + * targets.c, libnlm.h, nlm.c, nlm{32,64}-gen.c, nlm{32,64}.c, + nlmcode.h: Convert prefixes from bfd_nlm to just + nlm, and use macros select size. + +Thu Jul 22 15:40:14 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * Makefile.in (Makefile): add configure.in, drop redundant + $(srcdir), drop redundant ./ + +Thu Jul 22 13:34:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * hpux-core.c: New file; backend for HP/UX style core files. + * bfd.c (struct _bfd): Renamed hppa_core_data field to + hpux_core_data. + * bfd-in2.h: Updated. + * hppa.c (make_bfd_asection, hppa_core_file_p, + hppa_core_file_failing_command, hppa_core_file_failing_signal, + hppa_core_file_matches_executable_p): Moved into hpux-core.c. + Removed from target vector. + * libhppa.h (struct hppa_core_struct and accessor macros): Moved + into hpux-core.c. + * targets.c: If HPUX_CORE is defined, add hpux_core_vec to + target list. + * config/hp300.mh (HDEFINES): Set to -DHPUX_CORE. + (HDEPFILES): Set to hpux-core.o. + * config/hppabsd.mh, config/hppahpux.mh: Likewise. + * hosts/hp300.h (HOST_HP300HPUX): Define. + * Makefile.in (OPTIONAL_BACKENDS): Added sco-core.o, + aix386-core.o, hpux-core.o. + (sco-core.o, aix386-core.o, hpux-core.o): New dependencies. + + * reloc.c (enum complain_overflow): New enumeration with the + various flavours of overflow checking. + (srtuct reloc_howto_struct): Changed complain_on_overflow field + from boolean to emum complain_overflow. Removed obsolete absolute + field. + (HOWTO): Removed absolute argument. + (bfd_perform_relocation): Do overflow checking on all types of + fields. + * bfd-in2.h: Updated accordingly. + * all targets: Updated initialization of reloc howto tables. + +Wed Jul 21 20:34:34 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * opncls.c (bfd_create): Don't use C++ keyword "template" as a C + variable name. + +Tue Jul 20 15:02:23 1993 Fred Fish (fnf@deneb.cygnus.com) + + * coff-m68k.c (m68k_howto2rtype): Make arg CONST to match callers. + + * elfcode.h: Fix several illegal pointer combination warnings for + usages of bfd_alloc and alloca. + + * libnlm.h (nlm_obj_tdata): Rename hidden struct members to avoid + apparent Sun C preprocessor recursion. Fix access macros. + * nlmcode.h: Remove spurious '&' before several array references. + +Tue Jul 20 14:36:27 1993 Jim Kingdon (kingdon@deneb.cygnus.com) + + * Rename for DOS uniqueness: coff-m68k-un.c -> coff-u68k.c + config/m68k-coffun.mt -> u68k-coff.mt. + * Makefile.in, configure.in: Corresponding changes. + +Tue Jul 20 16:21:52 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elf32-sparc.c (elf_sparc_howto_table): Don't use "&" before + function name; it's valid without, and some compilers give + warnings with it there. + +Tue Jul 20 08:21:15 1993 Fred Fish (fnf@deneb.cygnus.com) + + * bfd-in.h: Apply some of the changes that were made to bfd-in2.h. + * bfd.c (union tdata): Add nlm_obj_data; + * targets.c (enum target_flavour): Add bfd_target_nlm_flavour. + +Mon Jul 19 20:46:18 1993 Fred Fish (fnf@deneb.cygnus.com) + + * configure.in (*-*-netware, i[34]86-*-netware): New configs. + * Makefile.in (BFD32_BACKENDS): Add nlm.o, nlm32.o, nlm32-gen.o. + * Makefile.in (BFD64_BACKENDS): Add nlm64.o, nlm64-gen.o. + * Makefile.in (CFILES): Add nlm{32,64}.c, nlm{32,64}-gen.c. + * Makefile.in (nlm.o, nlm{32,64}.o, nlm{32,64}-gen.o: New targets. + * bfd-in2.h (INLINE): Defines moved here. + * {aoutx.h, elf.c, elfcode.h}: Move INLINE defines to bfd-in2.h. + * libelf.h (CAT4): Move define to bfd-in2.h. + * bfd-in2.h (CAT4): Merge CAT4 macro with other CAT macros. + * bfd-in2.h (union tdata): Add nlm_obj_data. + * bfd-in2.h (enum target_flavour): Add bfd_target_nlm_flavour. + * targets.c (bfd_nlm{32,64}_{big,little}_vec): Add prototypes. + * targets.c (target_vector): Add bfd_nlm{32,64}_{big,little}_vec. + * (libnlm.h, nlm.c, nlmcode.h, nlm{32,64}-gen.c, + nlm{32,64}-target.h, nlm{32,64}.c, config/i386-nlm.mt): New files + for NLM support. + +Mon Jul 19 15:09:01 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * configure.{hosts,in}: add i[34]86-*-lynxos* support + +Mon Jul 19 14:53:30 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * elf.c, elfcode.h, libelf.h: Serious reorganization. + Deleted `thunk' structure, merged into tdata, duplicate data + eliminated. + Rearranged functions, grouping by functionality. + Broke up many functions in elfcode.h, re-ordered many parts of + file writing to handle unpredictable state of section relocation + table as provided by various applications. + Still needs cleanup: Merge functions back together, split out + data structure with only data that is used only when writing out + object file. + + * elf.c (bfd_elf_generic_reloc): New function, taken from + coff-mips.c. + * elf32-sparc.c (elf_sparc_howto_table): Use it, to work around + bfd_perform_relocation lossage. + + * Makefile.in (BFD_LIBS): Include coff-mips.o and coff-msym.o, so + that gdb will link. + (ofiles): Don't use sort or uniq; do it with sh constructs. + +Sun Jul 18 19:42:14 1993 Jim Kingdon (kingdon@rtl.cygnus.com) + + * coffcode.h: Recognize I386PTXMAGIC. + * aoutf1.h, libaout.h: Add M_386_DYNIX. + * trad-core.c (TRAD_CORE_USER_OFFSET, TRAD_CORE_STACK_FILEPOS): + New macros; use it if defined. + * config/symmetry.mh, hosts/symmetry.h: New files. + +Fri Jul 16 14:56:31 1993 Jim Kingdon (kingdon@rtl.cygnus.com) + + * Rename elf{32,64}-generic.c to *-gen.c for 14 char filenames. + * Makefile.in: Change accordingly. + (CFILES): Add elf64-gen.c. + +Fri Jul 16 09:53:23 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c: Use MIPS_AOUT_{OZ}MAGIC rather than {OZ}MAGIC. + +Thu Jul 15 16:02:07 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-m88k.c (howto_table): Corrected bitsize for R_PCR26L from + 16 to 26. + +Wed Jul 14 15:29:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hppa.c [HOST_HPPABSD]: Use hpux-style core files. + * libhppa.h [HOST_HPPABSD]: Include hpux version of core.h + +Wed Jul 14 09:30:48 1993 Doug Evans (dje@canuck.cygnus.com) + + * configure.in: Recognize h8300h-*-*. + +Tue Jul 13 12:03:00 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * coff-h8500.c (reloc_processing, rtype2howto): New relocation + type R_H8500_HIGH_16. + * coff-sh.c (r_imm32): Get the width of the reloc right. + +Tue Jul 13 16:48:56 1993 Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr) + + * configure.in: Add new target m68k-coffun to the dpx/2. + * config/m68k-coffun.mt: New file, renamed from config/dpx2.mt. + +Mon Jul 12 10:42:49 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * reloc.c (enum bfd_reloc_code_real): Move SPARC_BASE13 reloc into + sparc-aout-specific list. + + * libelf.h (struct elf_obj_tdata): Add field `thunk'. + + * config/sparc-elf.mt (TARGET_BACKENDS): New make variable. + +Thu Jul 1 14:52:47 1993 Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr) + and Jim Kingdon (kingdon@cygnus.com) + + * elfcode.h: Use memset not bzero. + * trad-core.c: Don't include . + * i386linux.h: Include . + * coff-m68k-un.c: new file to handle names with underscores on + svr3 machines. + * coff-m68k.c (m68k_rtype2howto): added #ifdef ONLY_DECLARE_RELOCS + to not duplicate the function in the executable. + (TARGET_SYM, TARGET_NAME, NAMES_HAVE_UNDERSCORE): new macros needed + by coff-m68k-un.c. + * coffcode.h (MC68KBCSMAGIC): case added. + * targets.c: Add m68kcoffun_vec. + * configure.host: added support for Bull dpx/2. + * config/dpx2.mh, hosts/dpx2.h: new files. + * Makefile.in: added target coff-m68k-un. + +Fri Jul 9 00:43:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * aoutf1.h: Add definition of MACHTYPE_OK. + +Thu Jul 8 14:37:44 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * reloc.c (bfd_perform_relocation): Don't subtract the addend + again for coff. + + * syms.c, bfd-in2.h: Doc fix. + + * coffcode.h (CALC_ADDEND): Check for common section using the + section flag as well as the symbol flag. + +Thu Jul 8 13:43:52 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hosts/i386bsd.h: Conditionalize HOST_STACK_END_ADDR on __bsdi__. + i386bsd.c: Remove defines of N_TXT*; the versions in aout64.h should + be sufficient. Define TEXT_START_ADDR. + +Wed Jul 7 10:56:21 1993 Ian Lance Taylor (ian@cygnus.com) + + * aoutx.h (translate_from_native_sym_flags): Removed statep + argument. Just let an indirect symbol point to the next symbol + without forcing the next symbol to be undefined. Changed all + callers. + * hp300hpux.c (slurp_symbol_table): Changed call to + translate_from_native_sym_flags. + * targets.c: Added hp300hpux_vec. + * Makefile.in (hp300hpux.o): Added dependencies. + +Tue Jul 6 13:24:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * reloc.c (enum bfd_reloc_code_real): Put simple power-of-two + relocs together, and add 64-bit versions. + (bfd_generic_get_relocated_section_contents): Argument to alloca + is size_t. + + * libbfd.c (bfd_xmalloc_by_size_t): New function. + * opncls.c (bfd_cache_init, bfd_open_file): Add prototypes to + declarations. + (obstack_chunk_alloc): Use bfd_xmalloc_by_size_t. + (new_bfd): Prototype-style definition, using DEFUN. + (bfd_alloc_grow, bfd_alloc, bfd_zalloc, bfd_realloc): Size + argument is type size_t, not bfd_size_type. + * ieee.c (obstack_chunk_alloc): Use bfd_xmalloc_by_size_t. + * bfd.c (bfd_default_error_trap, bfd_error_trap, + bfd_error_nonrepresentabltrap): Prototypes. + * libbfd-in.h (bfd_alloc, bfd_zalloc, bfd_realloc, + bfd_alloc_grow): Adjusted prototypes for arg type change. + * archive.c (get_elt_at_filepos, do_slurp_bsd_armap, normalize, + do_slurp_coff_armap, bfd_construct_extended_name_table): + Prototypes. + * elfcode.h (elf_string_from_elf_strtab): Prototypes. + * libelf.h (elf_string_from_elf_section, elf_get_str_section): + Prototypes. + + * Makefile.in (ALL_MACHINES): Renamed from BFD_MACHINES. + (ofiles): New target. Build a list of unique file names, in case + any got duplicated. + (TARGETLIB): Use list of files from ofiles. + * configure.in: Set BFD_MACHINES and BFD_BACKENDS depending on + minimal-bfd flag and target makefile frag contents. + + * elfcode.h (elf_read): Delete static declaration, since function + has moved. + (elf_map_symbols): Write out section symbols for all sections, for + now. + (elf_symbol_from_bfd_symbol): Allow match if both symbols are + section symbols for the same section. + (elf_find_nearest_line): Don't print message, just return false. + + * libelf.h (bfd_elf_locate_sh): Declaration deleted. + +Mon Jul 5 16:48:11 1993 Doug Evans (dje@canuck.cygnus.com) + + * cpu-h8300.c (h8300_scan): Fix parsing of architecture string. + +Fri Jul 2 18:27:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * Makefile.in (clean): Remove bfd.h and stmp-bfd.h. + (realclean): Remove generated headers. + +Fri Jul 2 14:51:51 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * section.c (bfd_set_section_content): Deny if file is not opened with + the proper mode, set output_has_begun if file is openened for update. + * aoutx.h (aout_*_set_section_content): Remove checks that are now + done in bfd_set_section_content. + +Fri Jul 2 09:25:20 1993 Ian Lance Taylor (ian@cygnus.com) + + * hosts/std-host.h: Removed declarations of printf, fprintf, + fcntl, fread and fwrite. They are all error prone for one reason + or another. Changed declaration of memchr from char * to PTR. + + * configure.in (mips-*-riscos*): New target; use riscos. + * configure.host (mips-*-riscos*): New host; use riscos. + * config/riscos.mh (HDEFINES): Add -G 4. + + * libaout.h (GET_SWORD): Use the bfd_h_get_signed entry points + rather than casting the result of bfd_h_get. + +Fri Jul 2 10:13:48 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * configure.in, hosts/delta68.h, config/delta68.mh: Add stuff for + Motorola Delta 68. + +Wed Jun 30 06:02:43 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * targets.c (bfd_elf64_{big,little}_generic_vec): Declare, and + include in search list if BFD64 is defined. + + * libelf.h (CAT4): Added a version for Saber-C, ANSI mode. + (bfd_elf64_*): Declarations for 64-bit versions of many routines. + +Tue Jun 29 22:50:59 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elf64-target.h, elf64-generic.c: New files. + * Makefile.in (BFD64_BACKENDS): Include elf64-generic.o. + (elf64-generic.o): List dependencies. + + * Makefile.in: List target `all' explicitly before host/target + makefile fragments are included, in case they define any new + targets. + + * elfcode.h (ELF_R_INFO, ELF_R_SYM): Define as 32- or 64-bit + versions as appropriate. Uses updated. + (elf_debug_section): Declare before use. + (elf_debug_file): New function. + (bfd_section_from_shdr, bfd_shdr_from_section, elf_fake_sections): + Alignment value in section header is n_bytes, not log2. + (new_section_hook): Do nothing for now. + (bfd_section_from_shdr): Use Elf_External_Rel[a], not 32-bit + version explicitly. + (elf_core_file_p): Simplify check for correct class (word size). + (elf_make_sections, elf_fake_sections, elf_write_object_contents): + Initialize all fields when creating data structures. + (elf_locate_sh): Renamed from bfd_elfXX_locate_sh, made static. + (elf_compute_section_file_positions): Set correct class in output + file. + (elf_write_object_contents): Section symbols have empty names in + output file. + + * libbfd.c (bfd_xmalloc, zalloc): Be sure to cast malloc, memset + args to size_t before call. + (bfd_add_to_string_table): Cast zalloc arg to bfd_size_type. + +Tue Jun 29 10:49:42 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_find_nearest_line): If procedure has no line + number information, return 0 for line number. + +Mon Jun 28 10:45:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * aoutx.h (some_aout_object_p): If *oldrawptr is non-NULL, copy it + into *rawptr. + +Sun Jun 27 09:05:19 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hosts/riscos.h: Define NBPG and UPAGES. + +Sun Jun 27 16:28:26 1993 Ken Raeburn (raeburn@cygnus.com) + + * elfcode.h (elf_slurp_symbol_table): Don't use obj_raw_syms as + lvalue; it contains a cast. + +Fri Jun 25 17:09:55 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * aoutx.h (hash, compare, struct stringtab_entry, add_to_stringtab): + Use unsigned hash values for better hashing. + (hash): Hash in the string length for long strings. + +Thu Jun 24 15:47:51 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * aoutx.h (compare): Replace 3 if's with a subtraction. + (translate_to_native_sym_flags, add_to_stringtab): Reorder tests + in decreasing order of success, as an optimization. + (hash): Take a length arg; ignore chars after #25, for speed. + (add_to_stringtab): Pass length to hash. + +Thu Jun 24 17:25:51 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * elf32-sparc.c (sparc_reloc_map): Add SPARC_WDISP22 reloc. + + * elfcode.h (elf_new_section_hook): Do nothing for now. + (elf_write_object_contents): Output common symbols the way ELF + wants them. + +Wed Jun 23 16:20:07 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * libelf.h (struct elf_obj_tdata and associated macros): Moved + here from elfcode.h. A couple of size-specific structure pointers + were changed to PTR; uses fixed appropriately. + (elf32_symbol_type, elf64_symbol_type): Separated definitions. + (bfd_elf_mkobject): Renamed from bfd_elf32_mkobject. + (bfd_elf32_mkobject, bfd_elf64_mkobject, elf_mkobject): New + temporary macros to ease name change. + * elf.c (elf_read, elf_mkobject, elf_get_str_section, + elf_string_from_elf_section, bfd_elf_find_section): Moved here + from elfcode.h. + * doc/Makefile.in (libbfd.h): Process elf.c too. + * Makefile.in (elf.o): Note new dependencies. + + * elfcode.h: Lots of stuff moved elsewhere. Deleted some unused + code, tweaked some debug hooks. + (elf_slurp_reloca_table): Translate ELF section symbols into BFD + section symbols. + +Wed Jun 23 11:34:21 1993 Jim Kingdon (kingdon@cygnus.com) + + * hosts/riscos.h: New file. + +Tue Jun 22 14:35:20 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * elfcode.h (bfd_section_from_shdr, case SHT_PROGBITS): Even if + section already exists, use its pointer to fill in rawdata slot. + +Tue Jun 22 16:36:51 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hosts/std-host.h: Return value of puts and fputs is int not void. + +Tue Jun 22 14:25:58 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * aoutx.h (howto_table_ext): Comment the field names. + * reloc.c (bfd_perform_relocation): Fix max and min values. + +Mon Jun 21 18:19:14 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * elf32-target.h, elf32-hppa.c, elfcode.h: Use new + size-independent elf internal data structures. + * elfcode.h (put_word, get_word): Define as appropriate for + architecture word size. Structure swapping functions changed to + use them as appropriate. + + * configure.in: If compiling 64-bit back ends, do them before + 32-bit ones. + + * libelf.h: Use new size-independent versions of elf internal data + structures. + (symbol_type): Reordered to put any fields dependent on target + size at the end. + (elf_backend_data): Renamed from elf##_backend_data and made + size-independent. + (elf_sect_thunk): Now size-independent. + + * libbfd.c (bfd_log2): Now returns unsigned int. + +Mon Jun 21 12:30:47 1993 Jim Kingdon (kingdon@cygnus.com) + + * Rename config/m88k-aout.mt to config/noop.mt. + configure.in: Use it for mips-*-bsd*. + +Sun Jun 20 20:32:19 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * cpu-m68k.c (arch_info_struct): Eliminate "partially bracketed + initializer" warning from gcc. + * cpu-h8500.c (arch_info_struct): Likewise. + * cpu-sh.c (arch_info_struct): Likewise. + + * cpu-h8300.c (local_bfd_reloc_type_lookup, howto*_callback, + howto_*): Unused functions and variables commented out. + * cpu-z8k.c (local_bfd_reloc_type_lookup, howto*_callback, + howto_*): Likewise. + * cpu-h8500.c (compatible): Likewise. + * cpu-sh.c (compatible): Likewise. + + * hp300hpux.c (swap_std_reloc_in): Delete unused variables. + Always set a valid length value, even for invalid input. + + * srec.c (srec_write_symbols): Use sprintf_vma. + + * bfd-in.h (uint64_typeLOW, uint64_typeHIGH, int64_type, + uint64_type): Provide default definitions. + * hosts/std-host.h (int64 stuff): Remove them from here. + + * bfd-in.h (sprintf_vma): Define parallel to fprintf_vma. + + * elf32-i386.c (elf_i386_reloc_type_lookup): Delete unused + variable. Added default case to switch. + + * aoutx.h (translate_from_native_sym_flags): Before casting + pointers to integers, make sure the integer type is wide enough. + * coff-mips.c (ecoff_set_symbol_info): Ditto. + + * section.c (bfd_get_section_contents): Since `count' is unsigned, + don't bother comparing for less-than-zero. + (bfd_set_section_contents): Ditto. + + * elfcode.h (bfd_add_to_strtab): Now static. + (sym_is_global): New function. + (elf_map_symbols): Call it. Now returns void. Removed unused + local variable. + (bfd_section_from_shdr): Mark string tables other than for section + and symbol names as normal sections having contents. + (fix_up_strtabs): New function; fixes up ELF header fields for + stab sections with string tables associated. + (elf_write_object_contents): Map fix_up_strtabs over all BFD + sections. Reordered condition tests for symbol flags; default to + local-object value instead of global-object. + (elf_symbol_from_bfd_symbol): Hid conditionally-used variable + inside condition test. + (elf_print_symbol): Use fprintf_vma. + (elf_idx_of_sym, bfd_shdr_from_section): Unused functions + commented out. + + * bfd-in.h (int64_type, uint64_type): Define these if we fall + back to "long long" for HOST_64_BIT. + + * libelf.h (elfNAME, ElfNAME): New versions to get desired results + without using invalid ANSI C preprocessing tokens. + + * elf32-target.h (bfd_elf32_new_section_hook): Delete macro. + * libelf.h (bfd_elf32_new_section_hook): Declare. + * elfcode.h (new_section_hook): Define here. + + * hosts/sparc.h, hosts/std-host.h, hosts/i386bsd.h: Protect + against multiple inclusions. + + * hosts/news.h: Include hosts/std-host.h, not plain std-host.h. + + * Makefile.in (bfd.h): Generate into current directory by grabbing + 64-bit definition (if any) from sysdep.h. + * bfd-in.h: Put in marker for sysdep.h inclusion. + +Fri Jun 18 19:57:23 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * reloc.c (bfd_perform_relocation): Check for overflow on + pc-relative relocations if the howto asked for it. + +Fri Jun 18 16:00:20 1993 Jim Kingdon (kingdon@cygnus.com) + + * Makefile.in (stmp-bfd.h): Ignore nonzero exit status from grep. + +Fri Jun 18 16:54:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config/riscos.m{h,t}: New files. + * configure.{host,in}: Use them. + +Fri Jun 18 12:55:10 1993 K. Richard Pixley (rich@cygnus.com) + + * elf32-mips.c: comment change. This is a mips file, not 88k. + +Mon Jun 14 14:02:41 1993 Jim Kingdon (kingdon@cygnus.com) + + * cache.c (bfd_cache_init): Increment open_files and call close_one + if necessary. + (bfd_open_file): Don't increment open_files here. + +Fri Jun 18 10:00:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config/delta88.mh: Don't set CC. + + * Makefile.in: Add elf32-{mips,m88k,generic}. + elf32-{mips,m88k,generic}.c: New files. + targets.c (target_vector): Include bfd_elf32_{mips,m88k,generic}_vec. + elfcode.h (elf_object_p): Match elf32-generic for all machines which + don't match a different target. + +Fri Jun 18 03:12:12 1993 John Gilmore (gnu@cygnus.com) + + Eliminate "int8_type", "int16_type", "int32_type", and their + variants from the BFD universe. Leave the 64-bit types for now, + since they are in flux. + + * aoutx.h, hp300hpux.c: Eliminate needless (int32_type) casts. + * libaout.h (GET_SWORD): Convert (int32_type) to (int). + * ieee.c: Convert uint8e_type => unsigned char. + * oasys.c: Extensive changes to eliminate obsolete types. + These depend on changes in ../include/oasys.h as well. + * hosts/*.h: Remove declarations of all these types. + +Mon Jun 14 14:02:41 1993 Jim Kingdon (kingdon@cygnus.com) + + * hosts/delta88.h: #if 0 out some declarations which conflict with + system headers. + +Mon Jun 14 17:08:18 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com) + + * Makefile.in (install): remove parentdir cruft + +Mon Jun 14 19:04:09 1993 Stu Grossman (grossman@cygnus.com) + + * hppa.c (hppa_get_symbol_info): Remove redundant copy. + * Expurgate random DEFUNs that have crept in. + +Mon Jun 14 10:23:53 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_set_symbol_info): Constructor sections should + only be aligned to a 4 byte boundary. + +Sat Jun 12 16:13:17 1993 Jim Kingdon (kingdon@cygnus.com) + + * hosts/std-host.h (struct int64e_struct): Remove needless typedef + keyword. + +Fri Jun 11 14:25:34 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * aoutf1.h (sunos4_write_object_contents): set flags to 1, breaking + 1927 but fixing some other important things. + +Thu Jun 10 20:36:22 1993 Doug Evans (dje@canuck.cygnus.com) + + * hosts/std-host.h (int64e_type): Fix definition. + +Thu Jun 10 11:48:28 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_sec_to_styp_flags): Use STYP_MIPS_INIT for + section named _INIT. Don't set STYP_TEXT unless SEC_CODE is set. + (ecoff_styp_to_sec_flags): Treat a STYP_MIPS_INIT section like + a STYP_TEXT section. + +Wed Jun 9 16:48:13 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in (install, headers): don't put comments after a tab + in the actions section of a rule + +Wed Jun 9 15:00:01 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_mkobject_hook): Mark ZMAGIC files as D_PAGED. + (ecoff_write_object_contents): If not D_PAGED, don't add the + section headers to text_size. If not D_PAGED, set the magic + number to OMAGIC rather than ZMAGIC. If creating a D_PAGED + executable, the executable must fully occupy an even number of + pages. + (ecoff_set_symbol_info, make_bfd_asection, ecoff_little_vec, + ecoff_big_vec): Consistently set section alignment power to 4, + since ECOFF sections should be multiples of 16 bytes. + (ecoff_little_vec, ecoff_big_vec): Added D_PAGED to object_flags. + Made ar_pad_char and ar_max_namelen agree for both. + +Tue Jun 8 20:28:02 1993 Mark Eichin (eichin at tweedledumber) + + * elfcode.h (elf_slurp_symbol_table): subtract section vma from + symbol value, since bfd symbols are section relative, but ELF + symbols aren't. + +Tue Jun 8 12:08:27 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * cpu-i960.c, cpu-h8300.c (compatible): Make static. + +Tue Jun 8 14:27:56 1993 Jim Kingdon (kingdon@rtl.cygnus.com) + + * hosts/news.h, config/news.mh: New files. + +Tue Jun 8 12:08:27 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * bfd-in2.h, archures.c (bfd_mach_h8300[h]): new defines. + * coff-h8300.c: More addressing modes. + * coffcode.h (coff_set_arch_mach_hook): Cope with H8300 magic + number. + * cpu-h8300.c: Removed disassemble stuff. (h8300_scan): Recognise + H8/300H name. (compatible): New function. + * reloc16.c (bfd_coff_reloc16_get_relocated_sec): Cope with more + addressing modes. + +Tue Jun 8 10:30:13 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_compute_section_file_positions, + ecoff_write_object_contents): Only round to page boundaries if + D_PAGED flag is set for the output BFD. + +Fri Jun 4 15:47:52 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * coffcode.h (get_index, coff_slurp_symbol_table): Fix pointer + casts to work on machine where sizeof(long) != sizeof(int) != + sizeof(char *). + * coffgen.c (coff_get_normalized_symtab): Ditto. + * cpu-h8300.c coff-h8300.c: Support for H8/300-H. + +Fri Jun 4 15:24:27 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * coffgen.c (coff_write_symbols): For empty string table, write + out 4 in correct byte order. (from minyard@bnr.ca) + + * elf32-hppa.c: Don't include libhppa.h for now; define + BYTES_IN_WORD instead, until Utah sends a better fix. + (hppa_elf_build_arg_reloc_stub): Use xmalloc and xrealloc instead + of malloc and realloc. + +Fri Jun 4 07:49:01 1993 Ian Lance Taylor (ian@cygnus.com) + + * configure.in (mips-*-ecoffl*): New target; use decstation. + (mips-*-ecoff*): Added trailing '*'. + + * coff-mips.c (ecoff_get_debug): Get the offset from the first PDR + for the FDR, not from the first PDR in the file. + +Thu Jun 3 16:41:10 1993 Stu Grossman (grossman@cygnus.com) + + * hppa.c (hppa_get_symbol_info): New func needed for JUMP_TABLE. + +Thu Jun 3 15:33:57 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * hppa.c (hppa_get_symbol_info): New function. + +Thu Jun 3 13:07:42 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elfcode.h (elf_map_symbols): Don't crash if no symbols have been + allocated yet. + + From Peter Hoogenboom (hoogen@schafer.cs.utah.edu): + * libhppa.h (MAXCOMLEN): Define unconditionally. + (_PA_RISC_ID): Only define if not already defined. + * elf32-hppa.c: Include libhppa.h. + + From Ralph Campbell: + * hosts/mipsbsd.h (HOST_DATA_START_ADDR): Delete definition. + + * elf32-hppa.h (symext_rootP, symext_lastP): Delete decls. + +Thu Jun 3 00:23:53 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * config/go32.mh: define EXTRALIBES to -lm (for binutils), also + remove defines of __MSDOS__ and __GO32__ (these are in the + compiler now). + +Wed Jun 2 17:57:13 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + From Utah: + * hosts/hppabsd.h: Eliminate use of obsolete EXFUN. + * config/hppabsd.mh: Don't use ranlib. + +Tue Jun 1 04:15:57 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * elf.c: New file, for word-size independent code. + * elfcode.h (elf_hash): Moved to there, renamed bfd_elf_hash. + * Makefile.in: Include elf.o in standard objects. + + * bfd-in.h (CAT3): Define here. + * libaout.h, libelf.h: Not here. + + * libelf.h (struct strtab): Define here. + (bfd_elf_locate_sh): Declare here. + * elfcode.h (struct strtab): Definition deleted. + + * reloc.c (enum bfd_reloc_code_real): Added HPPA_PCREL_CALL_12. + + * Makefile.in: Make "all", not "bfd.h", be the default target. + (stmp-bfd.h): New target; prevents rebuilding world if bfd.h + hasn't really changed. + + Tue May 25 12:15:15 1993 Michael Meissner (meissner@osf.org) + + * elfcode.h (elf_hash): Provide elf standard hash function. + (various): Key off of the machines use_rela_p field to determine + whether to use REL or RELA relocations. + (elf_swap_reloc_out, elf_swap_reloc_in): New functions. + (elf_make_sections): Allocate a pointer to hold all data for a + given section, and copy each fragment into the data region. + Update the section's pointer with the REL implicit addends if the + machine uses REL relocation. + + * elf32-i386.c (elf_bfd_reloc_type_lookup): Rename to + elf_i386_bfd_reloc_type_lookup, and use cpp to map the name back + into was elf32-target.h expects. + (elf_info_to_howto): Rename to elf_i386_info_to_howto. + (elf_i386_bfd_reloc_type_lookup): Add relocation support. + (elf_i386_info_to_howto): Add minimal relocation support. + + * libelf.h (elf_backend_data): Add use_rela_p, elf_64_p, + elf_info_to_howto_rel fields. + + * elf32-target.h (elf_bed): Add support for new fields in + elf_backend_data. + + Sun May 30 16:38:24 1993 Peter Hoogenboom (hoogen@fast.cs.utah.edu) + + * elf32-hppa.c: Add symbol extension section support, fix + relocation howto table, add stub generation support. + + * elf32-hppa.h: Add symbol extension section support, fix + relocation howto table, add stub generation support. + + * elfcode.h (bfd_elf_locate_sh): New function to locate ELF + section header. + + * elfcode.h (bfd_add_to_strtab): Made non-static due to a call + from elf32-hppa.c. + + * elfcode.h (elf_idx_of_sym): Return STN_UNDEF instead of 0 when + the symbol is not found. + + * elfcode.h (elf_compute_section_file_positions): Not all section + file positions were computed. + + * elfcode.h (elf_get_sect_thunk): New function. + + * hppa.c (sign_ext): Reimplement. + + * hppa.c (round_down,round,round_up,L,R,LS,RS,LD,RD,LR,RR): Make + these functions static. + +Tue Jun 1 14:40:41 1993 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in (bfd.h): Move closer to headers - and after 'all'! + + * aoutx.h (translate_from_native_sym_flags): Don't set + BSF_DEBUGGING for constructor symbols, only BSF_CONSTRUCTOR. + * aoutx.h (translate_to_native_sym_flags): Translate + constructor symbols properly. + +Thu May 27 16:09:04 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * archures.c (bfd_default_arch_struct): use 4 byte alignment as a + minimum. + * aout-target.h (minimum_alignment): 8 byte alignment is right. + (fix ld/2680) + +Thu May 27 13:38:47 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * configure.in, Makefile.in: Build bfd-in2.h in source directory, + from bfd-in.h and .c files. Build bfd.h in build directory, + substituting in requested target word size. Insert word size into + makefile, and maybe enable 64-bit targets. + + * bfd-in.h, libbfd.c, demo64.c, targets.c: Define BFD64 if 64 bits + are available. Conditionalize on this. Assume HOST_64_BIT + will be defined if needed, so 64-bit targets are conditionalized + only in the Makefile. + +Tue May 25 14:03:56 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * libbfd.c (COERCE64): Rewrite to avoid out-of-range values. + + * coff-sh.c (rtype2howto): Put error message on stderr. + (extra_case): Delete unused variable. + + * coff-mips.c (ecoff_print_symbol): Cast bfd_vma values to long + before calling printf. + + * elfcode.h: New file, almost completely derived from old elf32.c. + * elf32.c: Now just define ARCH_SIZE and include elfcode.h. + * Makefile.in (elf64.o): List dependencies, don't build by + default. + (elf64.c): Add to list of sources. + (elf32.o): Update dependencies. + * elf32-*.c: Updated type/macro/structure names. Cleaned up + namespace pollution; rename vectors. + * targets.c, config/*-elf.mt: Updated. + * All uses of 32-bit versions of structures, routines, and macros + renamed. + + * Makefile.in (archures.o, targets.o): Depend on Makefile. + +Mon May 24 15:53:13 1993 Ken Raeburn (raeburn@cygnus.com) + + * elf32-i386.c (enum reloc_type): No comma after last enumerator. + + * elf32.c (elf_string_from_elf_section): Handle index of zero + specially. + (bfd_section_from_shdr, elf_slurp_symbol_table): Don't need to do + so here. + (elf_write_object_contents): Deleted one unused variable and + initialized another to avoid gcc warnings. + (elf_set_section_contents): Delete unused variable. + +Fri May 21 19:04:21 1993 Stu Grossman (grossman@cygnus.com) + + * i386lynx.c: New module for Lynx variant of a.out. + * Makefile.in (BFD_BACKENDS CFILES depends): Add i386lynx.c. + * gen-aout.c: Get rid of defunct endian stuff, print out true + pagesize. + * targets.c (target_vector): Add i386lynx_vec. + +Fri May 21 17:02:22 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * configure.in: Use i386-sco.mt for i[36]86-*-isc*. + +Fri May 21 13:44:18 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * aix386-core.c, aout-target.h, aoutx.h, coff-alpha.c, + coff-mips.c, coffgen.c, elf32.c, ieee.c, libaout.h, libcoff-in.h, + libelf.h, mipsbsd.c, oasys.c, sco-core.c, srec.c, tekhex.c, + trad-core.c: Define a TARGET_get_symbol_info function or macro. + Remove the bfd_print_symbol_nm case from TARGET_print_symbol. + + * bfd-in.h: Don't define bfd_print_symbol_nm. + Define symbol_info type. + (JUMP_TABLE): Set _get_symbol_info element. + + * syms.c (coff_section_type, bfd_symbol_info): New functions. + (bfd_decode_symclass): Use coff_section_type. + + * targets.c: Add bfd_get_symbol_info call. + +Wed May 19 15:30:52 1993 Stu Grossman (grossman@cygnus.com) + + * coff-i386.c (coff_i386_reloc): Use unsigned char to avoid + complaints from ancient gcc's. + +Wed May 19 15:51:19 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * trad-core.c: Check macro TRAD_CORE_EXTRA_SIZE_ALLOWED. + hosts/i386linux.h: Define it. + +Mon May 17 15:00:33 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * VERSION, bfd-in.h: Bump version number to 2.2. + + * hppa.c (assemble_3, dis_assemble_3, assemble_12, + dis_assemble_12, assemble_17, dis_assemble_17, assemble_21, + dis_assemble_21, sign_ext, ones, sign_unext, low_sign_ext, + low_sign_unext, round_down, round, round_up, L, R, LS, RS, LD, RD, + LR, RR, hppa_field_adjust): New functions. + +Mon May 17 10:04:16 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_set_symbol_info): Added support for indirect + stabs symbols, including new indirect_ptr_ptr argument. + (ecoff_slurp_symbol_table): Pass new argument in calls to + ecoff_set_symbol_info. + +Fri May 14 00:05:06 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * configure.in: For m68k sysv systems, use m68k-coff. + + * config/hppa-elf.mt (TDEFINES): Don't define DEFAULT_VECTOR here. + (TDEFAULTS): Define it here. Use the new name. + + * elf32-hppa.c (elf_hppa_backend_data): Delete; rely on default + values instead. + + * reloc.c (bfd_reloc_code_real_type): Add some HPPA reloc types. + + * aix386-core.c (NO_GETS): Fix PROTO invocation to have correct + number of arguments. + (aix386_core_file_p): Initialize core_size to correct value. + +Wed May 12 14:39:59 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (CC_FOR_BUILD): New variable, set to $(CC). + (FLAGS_TO_PASS): Pass down CC_FOR_BUILD. + + * bout.c (aout32_slurp_extended_name_table): Define to be + _bfd_slurp_extended_name_table rather than bfd_true. + + * coff-mips.c: Include libaout.h and aout/aout64.h to get + definitions for N_SET[ATDB]. + (ecoff_howto_table): Moved near top of file. + (ecoff_set_symbol_info): If a STABS symbol of type N_SET[ATDB] is + seen, cook up a constructor section of the same name and put in a + reloc pointing to the symbol. This lets the GNU linker build + global constructors and destructors without using collect. + +Tue May 11 00:33:31 1993 John Gilmore (gnu@cygnus.com) + + * coff-m88k.c (m88kbcs_vec): Symbols have underbars. + +Mon May 10 05:55:45 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * hosts/miniframe.h: New file. + * configure.host: Use it. + +Sun May 9 16:36:59 1993 Fred Fish (fnf@cygnus.com) + + * 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*-*-hpux): Change to m68*-*-hpux* + * configure.in (*-*-bsd): Change to *-*-bsd* + +Wed May 5 16:08:32 1993 Per Bothner (bothner@cygnus.com) + + * elf32-hppa.c (elf_hppa_reloc_type_lookup): Cast enums to + int, for the sake of the old Portable C Compiler. + +Mon May 3 14:37:01 1993 Stu Grossman (grossman@cygnus.com) + + * Makefile.in (CFILES): Add cpu-sh.c and coff-sh.c. + +Mon May 3 14:03:21 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * configure.in: Get target name right for m68*-*-hpux. + +Sun May 2 11:39:44 1993 Fred Fish (fnf@cygnus.com) + + * trad-core.c (NO_SIGNED_GET): New macro. + * trad-core.c (trad_core_vec): Use new NO_SIGNED_GET instead of + signed NO_GET, where appropriate. + + * configure.in (i[34]86-*-linux*): Add; bfd_target = i386-linux. + * configure.in (*-*-linux*): Remove until linux port for a + non-i386/i486 system is actually available. + +Fri Apr 30 20:04:10 1993 Stu Grossman (grossman@cygnus.com) + + * libhppa.h: #undef e_* symbols which come from + when compiling under HPUX. + +Fri Apr 30 17:25:23 1993 Stu Grossman (grossman@cygnus.com) + + * The following patches are from Jeffrey Law . + * hppa.c (hppa_core_file_p): Provide a temporary dummy routine + for HOST_HPPABSD. + * bfd/hosts/hppabsd.h: Fix declarations of malloc and free. + * bfd/libhppa.h: Include sysdep here. Conditionalize + includes based on HOST_HPPAHPUX or HOST_HPPABSD. + Provide definitions for MAXCOMLEN and _PA_RISC_ID suitable + for BSD. + +Fri Apr 30 17:34:11 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elf32-hppa.c: Don't include a.out.h. Apparently not even the + GNU version is needed. + +Fri Apr 30 09:38:59 1993 Jim Kingdon (kingdon@cygnus.com) + + * coffcode.h: use dummy_reloc16_extra_cases rather than casting abort. + +Thu Apr 29 11:30:32 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * Makefile.in: Build elf32-hppa.o. + + * syms.c (BSF_FUNCTION): New symbol flag. + + * elf32-hppa.c: Fixed to work with elf32-target.h. + + * hp300hpux.c (NAME, NAME_swap_exec_header_in): Fix for + traditional C. + * libaout.h (NAME): Don't define if already defined. + + * libelf.h: Protect against multiple inclusions. + (elf_symbol_type): Moved here, added new fields. + (struct elf_backend_data): New field `global_sym'; I suspect this + may be misplaced. + * elf32.c (elf_symbol_type): Deleted from here. + (struct elf_obj_tdata): New fields raw_syms and internal_syms, to + point to backend versions of symbols. + (obj_symbols, obj_raw_syms, obj_internal_syms): New macros. + (elf_swap_phdr_out, elf_build_phdrs, elf_write_phdrs): New + functions. + (elf_write_object_contents): Write program headers if appropriate. + (bfd_section_from_shdr): Unnamed sections get empty string for + name, not "unnamed". Handle SHT_NOBITS separately from + SHT_PROGBITS, and set some different flags. + (elf_file_p): New routine. + (elf_object_p, elf_core_file_p): Call it. + (elf_object_p): Handle EM_HPPA. + (elf_symbol_from, elf_idx_of_sym): New functions. + (elf_make_sections): Get symbol number right for relocations. Set + SHF_ALLOC, SHF_WRITE, SHF_EXECINSTR when appropriate. + (elf_fake_sections): BSS section should be SHT_NOBITS, not + SHT_PROGBITS. Always generate symtab and strtab, not only if + relocations are needed. Set SHF_* flags as appropriate. + (elf_compute_section_file_positions): Handle bfd_arch_hppa. + (elf_write_object_contents): Fix off-by-one error in symbol count. + Store a correct value for the symbol; write the size field + properly; make some guesses about the type field. Set section + type correctly for string tables. + (section_from_elf_index): Check for absolute and common sections + first. + (elf_section_from_bfd_section): Ditto. + (elf_slurp_symbol_table): Use elf_symbol_type instead of asymbol. + Use empty string instead of "unnamed" for nameless symbols. + Handle STTY_FUNC type, and weirdness with "$global$" symbol for + HPPA (only?). Don't free raw symbols; keep the pointer around for + later. + (elf_set_arch_mach): Handle bfd_arch_hppa. + (elf_find_nearest_line): Just return false. + (elf_write_object_contents, elf_set_section_contents): Set + output_has_begun field after computing file positions. + (elf_set_section_contents): Write section contents immediately, + rather than caching the whole file and writing it at close time. + + * libhppa.h (enum hppa_reloc_field_selector_type, enum + hppa_reloc_field_selector_typ_alt, enum hppa_reloc_expr_type, enum + hppa_reloc_expr_type_alt): New enumerator types. + + * config/hppa-elf.mt,. config/hppaosf.mh: HP PA/OSF support. + * configure.in, configure.host: Use them. + +Wed Apr 28 23:21:01 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elf32-target.h: Allow overrides of armap defaults. + + * elf32-hppa.c, elf32-hppa.h: New files. + + * config/hp300hpux.mt: New file. + +Tue Apr 27 05:39:40 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * aix386-core.c (NO_GETS): New macro; NO_GET for signed values. + (aix386_core_vec): Update for new fields. + + * archive.c (bfd_generic_archive_p): Call target-specific + slurp_armap code, instead of bfd_slurp_armap. + (bfd_slurp_bsd_armap_f2): New function. + * libbfd-in.h (bfd_slurp_bsd_armap_f2): Declare it. + * aout-target.h (AR_PAD_CHAR): Define it if not already defined. + (vec): Use it. + * libaout.h (struct aoutdata): New field for subformat, for + differentiating between highly similar a.out formats. + * aoutx.h (NAME_swap_exec_header_in): New macro, defaults to local + version of function. + (swap_exec_header_in): Don't define if NAME_swap_exec_header_in is + already defined. + * hp300hpux.c: New file. + * Makefile.in: Include it. + +Mon Apr 26 13:24:43 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * Makefile.in, archures.c, coffcode.h, targets.c: Support for + Hitachi SH. + +Mon Apr 26 13:55:42 1993 Jim Kingdon (kingdon@cygnus.com) + + * trad-core.c (trad_unix_core_file_p): Check the file size. + +Mon Apr 26 13:24:43 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-alpha.c: Remove duplicate function and add warnings. + +Mon Apr 26 11:25:58 1993 Ian Lance Taylor (ian@cygnus.com) + + * sco-core.c (sco_core_vec): Add initializers for new target + fields. + +Sat Apr 24 21:33:45 1993 Jim Kingdon (kingdon@cygnus.com) + + * coffcode.h [_LIT]: Recognize .lit section. + +Fri Apr 23 19:00:36 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-alpha.c, cpu-alpha.c, config/alphaosf.mt, + config/alphaosf.mt, hosts/alphaosf.h: New files. + +Fri Apr 23 16:48:46 1993 Stu Grossman (grossman@cygnus.com) + + * Merge in HPPA/BSD changes from Utah. + * hppa.c: Use this for both HPUX & BSD. + * targets.c: Enable hppa_vec for both HPUX & BSD. + * config/hppabsd.mt: TDEFINES => TDEFAULTS. + * hosts/hppabsd.h: #define HOST_HPPABSD. + +Wed Apr 21 01:50:10 1993 John Gilmore (gnu@cygnus.com) + + * libbfd.c: Whitespace changes around byteswap macros. + * libbfd-in.h: Whitespace changes around byteswap declarations. + +Tue Apr 20 15:59:07 1993 Stu Grossman (grossman@cygnus.com) + + * aoutf1.h (sunos4_core_file_p): Don't default bfd_error to + system_error anymore. It confuses bfd_check_format(). + +Mon Apr 19 23:03:08 1993 Stu Grossman (grossman@cygnus.com) + + * bfd.c: Add sgi_core_data to tdata union. + * coff-mips.c: Add Irix 4.x core file support. + * hosts/irix4.h: #define HOST_IRIX4. + +Mon Apr 19 18:52:52 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * aoutx.h (translate_from_native_sym_flags): Check that the + symbol's section does get set. + (slurp_symbol_table): Zero index means null-string name. + + * aoutx.h (struct stringtab_entry, struct stringtab_data): New + data structures. + (hash, stringtab_init, add_to_stringtab, emit_strtab, compare): + New functions. + (write_syms): Use them, to reduce string table size. + +Mon Apr 19 16:45:12 1993 Fred Fish (fnf@cygnus.com) + + * trad-core.c (trad_core_vec): Add 6 new initializers to match + new signed get/put fields. Minor reformatting to label + some fields. + +Mon Apr 19 06:09:41 1993 Jim Kingdon (kingdon@cygnus.com) + + * bfd-in.h: Insert comment about SVR3 compiler warnings. + + * hosts/{hp300,i386isc,i386v}.h: Remove unused #defines of {r,}index + (bfd uses strchr and the broken SVR3.2 cpp loses with the defines). + + * libbfd.c: bfd_put*: Remove casts to bfd_vma. + +Fri Apr 16 17:49:27 1993 Jim Kingdon (kingdon@cygnus.com) + + * aoutf1.h (internal_sunos_core): Make c_stacktop a bfd_vma. + (swapcore_sparc): Make sp a bfd_vma. + +Thu Apr 15 09:09:18 1993 Jim Kingdon (kingdon@cygnus.com) + + * libbfd.c: Add signed versions of bfd_{h_,}{get,put}_signed_. + libbfd.c, libbfd-in.h: Add _do*signed*. + targets.c, all targets: Add bfd*signed*. + bfd-in.h: Add bfd_signed_vma. Add comments. + + * bfd-in.h (bfd_error), bfd.c (bfd_errmsgs): Add file_truncated. + + * format.c (bfd_check_error): Check error return from + _bfd_check_format routines. + +Wed Apr 14 23:48:25 1993 Jim Kingdon (kingdon@cygnus.com) + + * rs6000-core.c (rs6000coff_core_p): Improve error checking and + recognize .data section if present. + +Thu Apr 15 01:00:29 1993 John Gilmore (gnu@cygnus.com) + + * aoutx.h (aout_*_adjust_sizes_and_vmas): Avoid `sanity' + check for the case where the user sets the address of the BSS + section (and the file header can't specify this). Let the user + set it wherever they want, regardless of what goes in the header. + + * ieee.c (ieee_slurp_sections): Pass all ieee section names + straight through into BFD sections. Add comments. + +Wed Apr 14 20:34:54 1993 John Gilmore (gnu@cygnus.com) + + Cleanup in preparation for better 64-bit host support. + + * bfd-in.h (bfd_64_type): Remove. + * libbfd.c (_do_getb64, _do_putb64): Use bfd_vma, not bfd_64_type. + + * bfd-in.h (bfd_size): Remove. + + * bfd-in.h (bfd_offset): Remove, after fixing ld/ldlang.[ch]. + + * bfd-in.h (bfd_word): Remove. + * reloc.c (reloc_howto_type): Replace bfd_word with bfd_vma. + + * bfd-in.h (rawdata_offset): Remove. + * reloc.c (arelent): Replace rawdata_offset with bfd_size_type. + (bfd_perform_relocation): Lint. + (enum bfd_reloc_status): Comment cleanup. + + * aout-adobe.c, cpu-h8300.c, mipsbsd.c, srec.c: lint -Wall. + +Tue Apr 13 11:19:52 1993 Jim Kingdon (kingdon@cygnus.com) + + * aoutf1.h (swapcore_sparc): Guess the right value of USRSTACK. + +Mon Apr 12 14:18:00 1993 John Gilmore (gnu@cygnus.com) + + * elf32.c: Clean up old comments. + +Fri Apr 9 10:43:20 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/sun3.h: String argument to fprintf is const. + + * coff-mips.c: Renamed PAGE_SIZE to ROUND_SIZE, to avoid confusion + on systems which define PAGE_SIZE in . + +Thu Apr 8 10:28:00 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * trad-core.c (trad_unix_core_file_failing_signal): Use new macro + TRAD_UNIX_CORE_FILE_FAILING_SIGNAL to allow host files to specify + the core file failing signal. + * hosts/decstation.h (TRAD_UNIX_CORE_FILE_FAILING_SIGNAL): Define + to supply the core file failing signal. + +Thu Apr 8 09:17:35 1993 Ian Lance Taylor (ian@cygnus.com) + + * coffcode.h (styp_to_sec_flags): Only set SEC_SHARED_LIBRARY for + a STYP_NOLOAD | STYP_BSS section if BSS_NOLOAD_IS_SHARED_LIBRARY + is defined. On many COFF targets STYP_BSS is always STYP_NOLOAD. + * coff-i386.h (BSS_NOLOAD_IS_SHARED_LIBRARY): Define. + +Wed Apr 7 11:33:06 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (PAGESIZE): Correct value. + +Tue Apr 6 12:05:44 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_find_nearest_line): Address of first PDR is + an offset (patch from Jean-Daniel Fekete ). + +Mon Apr 5 12:07:12 1993 Ian Lance Taylor (ian@cygnus.com) + + * coffcode.h (styp_to_sec_flags): Set SEC_SHARED_LIBRARY for a + STYP_NOLOAD | STYP_BSS section. Don't set SEC_NEVER_LOAD for a + STYP_INFO section. + (coff_compute_section_file_positions): Force vma and lma of _LIB + section to be zero. + (coff_set_section_contents): Count number of entries in new lma + field, not in vma. + * coffgen.c (make_a_section_from_file): Force lineno_count of + SEC_SHARED_LIBRARY section to be zero, since it is non-zero on the + SCO 3.2v4 shared library. + * seclet.c (rel): Copy over any section with contents, not just + loadable sections. + + * coff-mips.c (ecoff_make_empty_symbol): Zero out newly allocated + symbol. + + * coff-i386.c (coff_i386_reloc): New function, to generate + relocateable output correctly. + (howto_table): Use coff_i386_reloc for all reloc types. + (CALC_ADDEND): Use a more efficient hack to get the correct addend + for a common symbol. + (i386comm_value): Removed; no longer needed. + +Sun Apr 4 15:08:48 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * coffcode.h (coff_set_section_contents): Don't write out + sections without a filepos. + +Fri Apr 2 14:35:05 1993 Ian Lance Taylor (ian@cygnus.com) + + * seclet.c (seclet_dump_seclet): Correct SEC_HAS_CONTENTS test. + +Wed Mar 31 17:41:05 1993 Ian Lance Taylor (ian@cygnus.com) + + * reloc.c (bfd_reloc_code_real_type): Added BFD_RELOC_MIPS_GPREL. + * libecoff.h (ecoff_data_type): Added gp_size field. + * coff-mips.c (ecoff_mkobject_hook): Initialize gp_size to 8. + (ecoff_set_symbol_info): Compare against gp_size, not hardcoded 8. + Set flags to 0 for large common symbols. + (ecoff_gprel_reloc): Handle non-zero addend for external symbols, + which can occur for gas-generated relocs. + (ecoff_bfd_reloc_type_lookup): Added BFD_RELOC_MIPS_GPREL case. + * bfd.c (bfd_get_gp_size, bfd_set_gp_size): New functions. + * Makefile.in (bfd.o): Now depends on coff/sym.h and libecoff.h. + +Tue Mar 30 09:33:16 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * srec.c (srec_set_section_contents): Use lma field for load + address. + * section.c: Add declaration of lma field to section structure. + * coffcode.h (coff_write_object_contents): Use lma field for load + address. + * bfd-in.h (bfd_set_section_vma): Set lma along with vma. + + * aoutx.h (translate_from_native_sym_flags): Now handles indirect + symbols in a better way. (translate_to_native_sym_flag): Set the + N_INDR bit when necessary. (aout<>slurp_symbol_table): Maintain + indirect state. + * section.c: Added BFD_IND_SECTION_NAME and bfd_ind_section. + (bfd_make_section): Cope with new builtin section. + * syms.c (bfd_decode_symclass): Can now print indirect section + info. + +Wed Mar 24 13:36:33 1993 Per Bothner (bothner@rtl.cygnus.com) + + * aout-target.h (MY(object_p)): Fail if MACHTYPE_OK is + defined, and yields false. + * aout-mipsbsd.c, i386bsd.c: Define MACHTYPE_OK appropriately. + + * archive.c (snarf_ar_hdr): Add support for reading (only, + so far) BSD-4.4-style extended headers. + * archive.c: Some more comments. + +Wed Mar 24 02:05:10 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com) + + * Makefile.in: fix rule for dvi and info, so that the recursive + makes does the right thing, instead of always info + +Wed Mar 24 02:56:44 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * libbfd.c (bfd_seek): Disable optimized handling for archives and + archive members; they need more special reatment. For now, verify + that computed and actual file positions correspond. + +Tue Mar 23 08:45:33 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * mipsbsd.c: Renamed from aout-mipsbsd.c. + (set_arch_mach): Delete non-MIPS code. + (reloc_howto_type_lookup): Ditto. + * Makefile.in: Adjusted. + + * libbfd.c (bfd_tell): Update `where' field. + (bfd_seek): Don't do anything if we're not changing the file + position. If FILE_OFFSET_IS_CHAR_INDEX is defined, check `where' + field against a SEEK_SET request. Call bfd_tell to re-update + `where' field when done. + (bfd_read, bfd_write) [FILE_OFFSET_IS_CHAR_INDEX]: Maintain + `where' field. + * hosts/sparc.h: Define FILE_OFFSET_IS_CHAR_INDEX. + +Mon Mar 22 23:18:10 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: added installcheck target + +Mon Mar 22 14:57:18 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_set_symbol_info): Relocate encapsulated stabs + if the type is not stNil. + +Tue Mar 16 10:35:27 1993 Ken Raeburn (raeburn@cygnus.com) + + * elf32.c (elf_little_vec, elf_big_vec): Delete now-invalid + forward declarations. + + * elf32-sparc.c (elf_sparc_howto_table): Don't use CONST here, + it's implied by the type. + +Fri Mar 12 18:58:08 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.host: recognize sparc-sun-solaris2* instead of sparc-sun-solaris* + +Tue Mar 9 09:23:12 1993 Jim Kingdon (kingdon@cygnus.com) + + * rs6000-core.c: Add .ldinfo section. + +Fri Mar 12 11:57:52 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (MAKEOVERRIDES): Define to be empty. + +Fri Mar 12 08:32:11 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * section.c (bfd_set_section_contents): whitespace + * seclet.c (seclet_dump_seclet): Don't try and fill sections with + no contents. + +Thu Mar 11 19:26:15 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * hosts/go32.h: don't define POSIX_UTIME + +Tue Mar 9 10:52:01 1993 Fred Fish (fnf@cygnus.com) + + * elf32.c (elf_object_p): Use ELF_ARCH stored in xvec to match + against machine architecture stored in the ELF header, to resolve + ambiguities. + * elf32.c (bfd_section_from_shdr): Bfd_make_section can return + NULL, so only use results when non-NULL. + * targets.c (elf32_m68k_vec, elf32_i860_vec): Add extern decls + and add to vector of targets. + +Mon Mar 8 15:13:44 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_set_symbol_info): Encapsulated STABS symbols + are always just debugging symbols. + + * coff-mips.c (ecoff_[gs]et_sym_index): Moved macros from here... + libecoff.h (ecoff_[gs]et_sym_index): ...to here. + +Mon Mar 8 14:55:13 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * hppa.c (_PA_RISC_ID): Defined if not already defined (e.g., for + hpux 7). Patch from friedman@gnu.ai.mit.edu. + (hppa_object_p): Only check for DL_MAGIC and SHL_MAGIC if they're + defined, which they aren't in hpux 7.0. + + * aix386-core.c: Include uinfo.h and coredump.h. Patch from Minh + Tran-Le, tranle@intellicorp.com. + +Fri Mar 5 14:54:21 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_generic_reloc): If the addend is non-zero, go + ahead and do the relocation. + (ecoff_refhi_reloc): Don't to the relocation here, just remember + what needs to be done. + (ecoff_reflo_reloc): Do the REFHI relocation here. + +Thu Mar 4 14:44:01 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_bfd_reloc_type_lookup): New function. + (ecoff_write_object_contents): Added BFD_ASSERT calls to ensure + relocs are reasonable. + * coff-msym.c: Eliminated uses of DEFUN. + (ecoff_swap_tir_out): New function. + +Tue Mar 2 17:52:58 1993 Fred Fish (fnf@cygnus.com) + + (Ultrix 2.2 support from Michael Rendell ) + * configure.host (vax-*-ultrix2*): Add triplet. + * hosts/vaxult2.h: New file. + * config/vaxult2.mh: New file. + + * aoutx.h (string.h): Include for strchr and friends. + * archive.c (string.h): Include for memchr and friends. + * elf32.c (string.h): Include for strrchr and friends. + +Sat Feb 27 00:44:24 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * aoutf1.c (sunos4_reloc_type_lookup): Unused; deleted. + (MY_set_sizes): Use sunos4_set_sizes. + + * elf32.c: Renamed from elf.c. Several CPU-specific functions + deleted, as well as elf-big and elf-little targets. + * libelf.h: New file. + * elf32-sparc.c, elf32-i386.c, elf32-i860.c, elf32-m68k.c: New + files, new targets. + * Makefile.in, config/*-elf.mt, targets.c: Adjusted. + + * i386linux.c (TARGETNAME): Use hyphens instead of parentheses. + + * coffcode.h (coff_compute_section_file_positions): Don't need + variable "old_sofar" if compiling for i960. + + * reloc.c (bfd_default_reloc_type_lookup): First argument is now a + bfd pointer. + * libbfd.h: Updated. + + * ieee.c (exten, envi): "static" belongs first in declaration. + +Fri Feb 26 17:37:34 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * srec.c: add support for symbolsrec, srecords with symbols in + them. + +Thu Feb 25 11:43:30 1993 John Gilmore (gnu@cacophony.cygnus.com) + + * ieee.c: cast all arguments of ieee_write_byte to bfd_byte + to avoid lint complaints. + +Thu Feb 25 02:15:52 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elf.c (elf_write_object_contents): Section ".shstrtab" should be + type SHT_STRTAB. Don't alter file offset for section 0. + (reloc_type_names): Now an array instead of a macro. Still inside + "#if 0", since it's used only in debugging code also in "#if 0". + (struct elf_reloc_map_elt, struct elf_reloc_map): New types. + (sort_reloc_map): New function. + (sparc_reloc_map): New variable. + (elf_bfd_reloc_type_lookup): New function. + +Tue Feb 23 12:17:16 1993 Ian Lance Taylor (ian@cygnus.com) + + * bfd-in.h (JUMP_TABLE): Added bfd_reloc_type_lookup and + bfd_make_debug_symbol; they were already in the target structure. + * Adjusted all uses of JUMP_TABLE. + * coffgen.c, libcoff-in.h (coff_bfd_make_debug_symbol): Renamed + from coff_make_debug_symbol. + * libcoff.h: Updated accordingly. + + * Minor cleanups provoked by gcc warnings: + * aoutx.h (NAME(aout, reloc_type_lookup)), + cpu-h8300.c (local_bfd_reloc_type_lookup), + cpu-z8k.c (local_bfd_reloc_type_lookup): Added default case to + switches. + * archive.c (do_slurp_bsd_armap, do_slurp_coff_armap), + ieee.c (ieee_slurp_section_data), + elf.c (elf_make_sections, elf_fake_sections, + elf_compute_section_file_positions, elf_write_object_contents): + Removed unused variables. + * archures.c: Removed /* from within comment. + * bout.c (b_out_squirt_out_relocs): Initialize r_extern. + * oasys.c (oasys_write_data): Initialize i. + +Mon Feb 22 18:40:06 1993 Per Bothner (bothner@rtl.cygnus.com) + + * libcoff.h (obj_raw_syment_coun): New macro. + * coffgen.c (coff_get_normalized_symtab): Initialize + raw_syment_count. + * coffgen.c (coff_find_nearest_line): Numerous little fixes. + +Mon Feb 22 15:03:07 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (ecoff_set_symbol_info): stBlock symbols are always + debugging symbols. + (ecoff_get_debug): Offset the fdr adr by the adr of the first pdr, + for compatibility with tools from MIPS. + + * config/bigmips.mt: New file; default vector is ecoff_big_vec. + * config/irix3.mt, config/irix4.mt: Removed. + * configure.in (mips-*-ecoff): New target; uses bigmips.mt. + (mips-sgi-*, mips-big-*): Use bigmips rather than irix3. + +Wed Feb 17 23:40:41 1993 John Gilmore (gnu@cygnus.com) + + * hosts/hp300bsd.h: Add gross hack to determine whether we + are running on BSD 4.3 or BSD 4.4, and use appropriate include + files (and set other parameters) to match. + +Wed Feb 17 12:28:13 1993 K. Richard Pixley (rich@cygnus.com) + + * trad-core.c (trad_unix_make_empty_symbol): wrap PARAMS around an + ansi definition which otherwise confuses non-ansi compilers. + + * aout-adobe.c (aout_adobe_object_p): eliminate a warning from vax + ultrix cc by forward declaring getenv as is done in + bfd_find_target. + +Tue Feb 16 17:56:58 1993 K. Richard Pixley (rich@cygnus.com) + + * elf.c (elf_info_to_howto): cast an enum into unsigned char + avoiding a fatal error in vax ultrix 4.2 cc. + +Tue Feb 16 00:44:54 1993 John Gilmore (gnu@cygnus.com) + + * bfd-in.h, VERSION: Roll to version 2.1. + +Mon Feb 15 20:43:51 1993 John Gilmore (gnu@cygnus.com) + + * oasys.c (oasys_write_object_contents): Lint. + * srec.c: Whitespace cleanup. + +Fri Feb 12 14:23:07 1993 Ian Lance Taylor (ian@cygnus.com) + + * coffgen.c (coff_print_symbol): Print correct tagndx value; + cleaned up output formatting a bit. + +Fri Feb 12 08:28:56 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * coffcode.h (coff_set_arch_mach_hook): *FIXME* the H8/300 is always + relaxable. Should be moved somewhere else. + +Thu Feb 11 14:09:42 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * aout-mipsbsd.c: Eliminated uses of DEFUN. + (aout_mips_*_vec): Added seclet_link element. + + * Makefile.in (BFD_BACKENDS, CFILES, aout-mipsbsd.o): Added + support for aout-mipsbsd target. + + * bout.c (get_value): Don't truncate 32-bit addend to 16 bits. + +Fri Feb 5 08:08:43 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * cpu-h8500.c (scan_mach): return false if it's not an H8/500 + +Thu Feb 4 12:52:40 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + Add support for the H8/500 + + * coff-h8500.c, cpu-h8500.c, archures.c, coffcode.h, targets.c + +Thu Feb 4 12:35:02 1993 Ian Lance Taylor (ian@cygnus.com) + + * libecoff.h: New file. Defines ECOFF backend data for gdb. + * coff-mips.c: Now includes libecoff.h. + (ecoff_data_type): Moved to libecoff.h. + (ecoff_slurp_symbolic_info): Made globally visible so that gdb can + call it. If there is ever another ECOFF target, this and the + swapping functions should be accessed via an ECOFF specific target + vector. + * Makefile.in (coff-mips.o): Depends on libecoff.h. + +Wed Feb 3 09:14:36 1993 Ian Lance Taylor (ian@cygnus.com) + + * coffcode.h: Removed MIPS specific information, since coff-mips.c + no longer includes this file. + + * coff-msym.c (ecoff_swap_fdr_in, ecoff_swap_ext_in): Set reserved + bits to 0 to make comparison test useful. + + * config/irix3.mh, config/irix4.mh (HDEFINES): Set to -G 4 to + avoid overflowing GP accessible sections in binutils/objdump. + +Tue Feb 2 15:36:55 1993 Per Bothner (bothner@cygnus.com) + + * aoutx.h (NAME(aout,slurp_symbol_table)): Made symbol + reading more robust: Fail if string index is out of string + table range. + +Tue Feb 2 11:43:25 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * bout.c (b_out_get_relocated_section_contents, cases PCREL24 and + PCREL13): Don't take dst_address into account; the input file has + already taken care of that. + +Tue Feb 2 11:41:06 1993 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c: Completed support for linker and binutils. + +Mon Feb 1 14:45:38 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * bout.c (b_out_get_relocated_section_contents, case ABS32): Keep + original addend from section contents. + +Thu Jan 28 21:01:37 1993 John Gilmore (gnu@cygnus.com) + + Fix minor bugs reported by Carl Greco, : + * hosts/delta88.h (strtol): Fix prototype. + * config/m88k-coff.mt (SELECT_ARCHITECTURES): Fix name. + +Wed Jan 27 17:16:51 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elf.c: Get rid of "#ifdef sparc". + (RELOC_TYPE_NAMES): Never used (currently), so don't include it. + (elf_sparc_howto_table): Renamed from elf_howto_table, and always + used. + (elf_info_to_howto): Use runtime conditionals on CPU type, not + compile type conditionals on host CPU. + (elf_little_vec, elf_big_vec): Use bfd_default_reloc_type_lookup, + not null pointer. + (reloc_type, RELOC_TYPE_NAMES): Include i386 values. + +Tue Jan 26 11:43:14 1993 Ian Lance Taylor (ian@cygnus.com) + + * section.c (SEC_IS_COMMON): New section flag, needed for MIPS + ECOFF which has two common sections. + (bfd_com_section): Set SEC_IS_COMMON flag. + * bfd-in.h (bfd_is_com_section): New macro to test SEC_IS_COMMON. + * aoutx.h, archive.c, bout.c, coff-a29k.c, coff-m88k.c, + coff-mips.c, coffgen.c, ieee.c, oasys.c, reloc.c, syms.: Use + bfd_is_com_section macro rather than checking for equality to + bfd_com_section. + +Mon Jan 25 15:27:36 1993 Ian Lance Taylor (ian@cygnus.com) + + * coffcode.h (_bfd_coff_mkobject_hook): Pass aouthdr argument. + (coff_mkobject_hook): Accept aouthdr argument. + * coffgen.c (coff_real_object_p): Pass aouthdr to mkobject_hook. + Handle NULL aouthdr argument. + (coff_object_p): If there is no aouthdr, pass it as NULL to + coff_real_object_p. + * libcoff.h: Rebuilt for mkobject_hook changes. + + * coffswap.h (coff_swap_aouthdr_in, coff_swap_aouthdr_in): Swap + additional MIPS ECOFF fields. + +Sat Jan 23 18:36:20 PST 1993 Ralph Campbell (ralphc@pyramid.com) + + * configure.host: added mips-dec-bsd* + * configure.in: added mips-dec-bsd* + * aout-mipsbsd.c: new file for mips-dec-bsd* + * aout-target.h: don't define '' if 'MY_BFD_TARGET' is defined. + * aoutx.h: added mips support. + * archures.c: added mips support to bfd_default_scan(). + * cpu-mips.c: added support for R4000 (untested). + * libaout.h: added MIPS1 & MIPS2 magic numbers. + * reloc.c: fix typo's in comments. Added BFD_RELOC entries which I + hope will make it into include/bfd.h. + * targets.c: added aout_mips_*_vec. + +Wed Jan 20 17:15:52 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/decstation.mt: Set DEFAULT_VECTOR to ecoff_little_vec. + +Tue Jan 19 09:06:14 1993 Ian Lance Taylor (ian@cygnus.com) + + * bfd-in.h (bfd_asymbol_value): Add needed parentheses. + + * libcoff-in.h: Update prototype for coff_count_linenumbers. + +Fri Jan 15 18:13:17 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-msym.c (ecoff_swap_hdr_out, ecoff_swap_fdr_out, + ecoff_swap_pdr_out, ecoff_swap_sym_out, ecoff_swap_ext_out, + ecoff_swap_rndx_out, ecoff_swap_rfd_out, ecoff_swap_opt_in, + ecoff_swap_opt_out, ecoff_swap_dnr_in, ecoff_swap_dnr_out): New + functions. + * coffswap.h: If NO_COFF_RELOCS is defined, don't define + bfd_swap_reloc_in or coff_swap_reloc_out. + * coff-mips.c: Added code to link and write out symbolic debugging + information, and to swap relocs in and out. + +Thu Jan 14 15:51:58 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * libcoff.h, coffgen.c (coff_count_linenumbers), coffcode.h + (coff_write_object_contents): coff_count_linenumbers returns the + number of line number records it found. + + * coffgen.c (coff_write_linenumbers): only write out line numbers + in the section they belong to. + +Mon Jan 11 18:32:22 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * targets.c (bfd_target): Added relocateable argument to + _bfd_get_relocated_section_contents. Added _bfd_seclet_link + target vector for linker use. + * bfd.c (bfd_seclet_link): New macro. + * bfd-in.h (JUMP_TABLE): Added _bfd_seclet_link. + * seclet.c (rel, seclet_dump_seclet): Added relocateable argument + and boolean return value. Made static. + (bfd_generic_seclet_link): Renamed from seclet_dump. Added + relocateable argument. + * reloc.c (bfd_generic_get_relocated_section_contents): Added + relocateable argument (if relocateable, saves relocs). + * bout.c (b_out_get_relocated_section_contents), + reloc16.c (bfd_coff_reloc16_get_relocated_section_contents): Added + relocateable argument (if relocateable, just calls + bfd_generic_get_relocated_section_contents). + * libcoff-in.h (bfd_coff_reloc16_get_value): Added relocateable + argument to prototype. + * All targets: Set new _bfd_seclet_link vector to + bfd_generic_seclet_link. + +Sat Jan 9 21:29:32 1993 Stu Grossman (grossman at cygnus.com) + + * coffgen.c: #include seclet.h. + +Sat Jan 9 19:48:14 1993 Stu Grossman (grossman at cygnus.com) + + * hppa.c (hppa_object_setup): Get rid of all knowledge of stabs + debug info. Setup info about linker symbols only, and use + standard bfd fields to hold the info. + * (hppa_object_p): Remove unneeded decls. + * (hppa_new_section_hook): Get rid of most of this. + * libhppa.h (struct hppadata): Remove ten pounds of useless ugly + fat. Remove all knowledge of stabs, remove redundant knowledge of + linker symbols. + * Remove macros for accessing fields which are now gone. + +Fri Jan 8 15:20:00 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * coffcode.h (sec_to_styp_flags): allow SEC_NEVER_LOAD to turn on + STYP_NOLOAD bit. + * coff-z8k.c: delete unused reloc functions + +Fri Jan 8 15:47:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * bfd.c (struct _bfd): Added ecoff_tdata to tdata union. + * targets.c (enum target_flavour): Added bfd_target_ecoff_flavour. + * coff-msym.c: Use DEFUN for function definitons. + * coff-mips.c: Added code to read and print symbols, and to find + line numbers. + + * coffcode.h: Moved many generic functions into coffgen.c. Moved + swapping functions into coffswap.h for ECOFF use. Moved + relocation functions, only used by h8300 and z8k, into reloc16.c. + Added hooks for coffgen.c functions to backend data structure, and + added hook functions. Still more could be done. + * coffswap.h: New file to hold COFF swapping routines. + * coffgen.c: New file to hold generic COFF functions. + * reloc16.c: New file to hold h8300 and z8k specific relocation + functions. + * libcoff-in.h: Added declarations for functions in coffgen.c. + * libcoff.h: Rebuilt to incorporate changes. + * coff-h8300.c: Function name changes. + * coff-z8k.c: Function name changes. Use coff_reloc16_extra_cases + hook rather than defining EXTRA_CASES. + * Makefile.in: Build new files coffgen and reloc16. Added + dependencies of coff-*.o on coffswap.h and seclet.h. + +Thu Jan 7 16:16:26 1993 Per Bothner (bothner@cygnus.com) + + * ieee.c (ieee_slurp_sections): Add cast to avoid warning + about discarding const. + +Wed Jan 6 00:16:49 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * archive.c, seclet.c, elf.c use bfd_xmalloc instead of malloc + +Tue Jan 5 09:35:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * configure.in (post-target): If --with-minimal-bfd is specified, + set MINIMIZE=1. + +Mon Jan 4 07:20:01 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * srec.c (srec_write_records): one of my boards wants a CR between + records. + +Wed Dec 30 12:46:30 1992 Ian Lance Taylor (ian@cygnus.com) + + * archive.c (do_slurp_coff_armap): set symdef_count correctly + (it broke a couple of weeks ago). + +Tue Dec 29 21:41:05 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * elf.c (bfd_elf_find_section): Switch back to "struct ..." for + return type, so libbfd.h doesn't reference undefined typedefnames. + +Tue Dec 29 13:54:35 1992 Ian Lance Taylor (ian@cygnus.com) + + * coffcode.h (coff_real_object_p): use name I386AIXMAGIC rather + than I386SVMAGIC. + (coff_pointerize_aux): don't pointerize a negative tagndx + (sometimes generated by SCO 3.2v4 cc). + + * bout.c (calljx_callback, callj_callback, + b_out_get_relocated_section_contents): warn if relocating against + an undefined symbol. + +Mon Dec 28 14:30:55 1992 Stu Grossman (grossman at cygnus.com) + + * hppa.c: Get rid of DEFUN, use more conventional prolog stuff. + Make a bunch more routines be static. + * hppa.c (fill_spaces): Get rid of this, replace with much better + written setup_sections(). + * (setup_sections): New routine to create BFD sections for each + space and subspace in SOM files. + * (hppa_object_setup): Use BFD sections created by + setup_sections() to locate GDB symbol table info. + * (make_unique_section): New routine to create a BFD section. It + ensures that the given name is unique, and will generate a unique + one if necessary. + * (hppa_object_p): Become much more paranoid about file header. + * (make_bfd_asection): Call bfd_make_section to do the dirty + work. Simplify code somewhat. + * (hppa_core_file_p): Use proper name for stack section. + * libhppa.h: Remove millicode_start, millicode_end decls. + +Mon Dec 28 11:03:22 1992 Ken Raeburn (raeburn@cygnus.com) + + * Makefile.in (coff-we32k.o, coff-z8k.o): Note dependencies. + + * reloc.c (bfd_perform_relocation): For normal 2- or 4-byte + relocs, don't bother doing the adjustment if the value to add is + zero. + +Sun Dec 27 17:45:05 1992 Fred Fish (fnf@cygnus.com) + + * bfd.c (bfd_get_size): New function that gets an upper bound + on the possible size of any object in a bfd. + * elf.c (bfd_elf_find_section, elf_get_str_section, + elf_get_symtab_upper_bound): Rewrite to avoid NULL pointer + dereferences. + * elf.c (elf_big_vec, elf_little_vec): Document last three + members initialized to NULL. + +Thu Dec 24 17:49:09 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * hppa.c: change a 'const' to 'CONST', or else HP C compiler dies + +Mon Dec 21 16:33:34 1992 Per Bothner (bothner@rtl.cygnus.com) + + * hosts/std-host.h: New file. Attempt at a generic/default + set of definitions, to discourage porting to new hosts by copying. + * hosts/news.h: Removed. + * hosts/sparc.h: Use std-host.h. + * bfd-in.h: New macros bfd_asymbol_bfd and bfd_asymbol_flavour; + perhaps we can later remove the the_bfd field from each symbol. + * syms.c (struct symbol_cache_entry): Remove unused field + app_data. Add comment noting that the_bfd is almost redundant, + but not quite. + * aoutx.h, coff-a29k.c, coff-i386.c, coff-i960.c, coffcode.h: + Use new macros bfd_asymbol_bfd and bfd_asymbol_flavour. + * hppa.c (fill_spaces): Make slightly more rebust. + * configure.in: Allow std-host as the "default" host. + +Mon Dec 21 17:24:13 1992 Stu Grossman (grossman at cygnus.com) + + * bfd.c: Add struct hppa_core_data to tdata union. + * hppa.c: Conditionalize on HOST_HPPAHPUX instead of hp9000s800. + Get rid of HPPA/BSD specific code. That will go somewhere else + someday. + * (fill_spaces): Don't spin forever and die if you don't find + $MILLICODE$ subspace. + * (hppa_object_p): Make sure that we have a real honest-to-cthulu + exec file! + * (hppa_core_file_failing_signal, hppa_core_file_failing_command): + Make these work for HPUX. + * (make_bfd_asection): New routine to make section creation a + little easier. + * (hppa_core_file_p): Completely rewrite, leave out bugs. + * libhppa.h: #include the right system files. Redefine all of + the structs/macros for hacking core files to use more sensible + HPUX core file structures. + * targets.c (target_vector): Conditionalize hppa_vec on + HOST_HPPAHPUX, not hp9000s800. + * hosts/hppahpux.h: #include stdlib.h to get correct decls for + malloc and realloc. #define HOST_HPPAHPUX. + +Mon Dec 21 12:40:10 1992 Ian Lance Taylor (ian@cygnus.com) + + * Patches from Minh Tran-le . + * configure.in (i386-*-isc*, i386-*-aix*): New targets. + * configure.host (i386-*-isc*, i386-*-aix*): New hosts. + * hosts/i386isc.h, config/i386isc.mh: New files for Interactive + Unix. + * hosts/i386aix.h, config/i386aix.mh: New files for AIX on PS/2. + * aix386-core.c: New file for handling core files on AIX on PS/2. + * targets.c: if AIX386_CORE, use aix386_core_vec. + * coffcode.h (coff_real_object_p): check for I386SVMAGIC as well + as I386MAGIC. + +Fri Dec 18 10:20:27 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * aoutf1.h (sunos4_write_object_contents): set flags to 0, fixing + 1927. + +Thu Dec 17 19:35:32 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: added dvi target + +Thu Dec 17 00:36:24 1992 John Gilmore (gnu@cygnus.com) + + * bfd.c: Use right name for tekhex tdata struct. + * tekhex.c: Insert leading_char (0) into bfd_target struct. Style. + * libcoff.h: Updated to get spacing change from coffcode.h. + * trad-core.c: leading_char is 0 (no symbols!), not '_'. + +Tue Dec 15 15:40:30 1992 Per Bothner (bothner@cygnus.com) + + * archive.c (do_slurp_bsd_armap, do_slurp_coff_armap): New + functions, with the "guts" of the old bfd_slurp_bsd_armap + and bfd_slurp_coff_armap, but assuming we've already checked + if the armap is present or not. + Also, rewrite a bit to avoid keeping around obstack data + that we don't need. + * archive.c (snarf_ar_header, _bfd_slurp_extended_name_table): + Various fixes to correctly handle COFF_style archives names. + (Note that because these have a trailing '/', the names can + have embedded spaces.) + * archive.c (bfd_slurp_armap): New function, replaces old + bfd_slurp_bsd_armap and bfd_slurp_coff_armap. Recognizes + _either_ format, and calls do_slurp_bsd_armap or + do_slurp_coff_armap if either form of map is seen. + * libbfd-in.h: Changed bfd_slurp_bsd_armap and + bfd_slurp_coff_armap into macro synonyms for bfd_slurp_armap. + * elf.c (elf_slurp_armap, elf_write_armap): Fix. + * Makefile.in (AR_FLAGS): Use rc instead of non-standard qc. + +Mon Dec 14 17:08:08 1992 Stu Grossman (grossman at cygnus.com) + + * hppa.c: #include "sysdep.h", not . + * libhppa.h: Make millicode_start and millicode_end be unsigned + int to be same type as CORE_ADDR in GDB. Why are these here? + +Sat Dec 12 15:54:36 1992 Ian Lance Taylor (ian@cygnus.com) + + * coff-i386.c (CALC_ADDEND): if reloc is PC relative, add the + vaddr of the section to the addend. + * targets.c: if MINIMIZE is 1, and SCO_CORE is defined, add + SCO_CORE to SELECT_VECS. + (target_vector): add sco_core_vec. + * sco-core.c (sco_core_vec): add leading underscore initializer. + * configure.in (i[34]86-*-sco*): use target i386-sco. + * config/i386-sco.mt: new file; define SCO_CORE. + +Thu Dec 10 02:13:15 1992 John Gilmore (gnu@cygnus.com) + + * aout-adobe.c (aout_adobe_object_p): Fix !strcmp thinko. + +Fri Dec 4 14:02:49 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * coffcode.h (bfd_coff_std_swap_table): Now static and const. + +Thu Dec 3 16:54:58 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * hosts/i386linux.h: Include unistd.h. + + * aoutx.h (print_symbol): aout_stab_name returns a constant + string. + * libaout.h (aout_stab_name): Fix prototype. + * stab-syms.c (aout_stab_names): Array is now const. + (aout_stab_name): Return value is now pointer to const. + + * aoutx.h, archive.c, archures.c, coffcode.h, ctor.c, reloc.c, + syms.c: Doc fixes. + + * syms.c (asymbol): Added new field "app_data", for data + particular to the application. Some of the linker flags ought to + get moved to this field someday. + + * archures.c (bfd_default_scan): Recognize a few more numbers: + 80486, 80960, and 960. + + * bfd-in.h (COFF_SWAP_TABLE): New is just address of + bfd_coff_std_swap_table, cast to PTR. + * bfd.c (bfd_coff_swap_*): Deleted macros. + * targets.c (struct bfd_target): Deleted COFF-specific swapping + routine pointers. + * coffcode.h (type bfd_coff_backend_data): New structure type, + contains pointers to the COFF-specific swapping routines. + (bfd_coff_std_swap_table): New data structure, to be used when + NO_COFF_SYMBOLS and NO_COFF_LINENOS are not defined. + (bfd_coff_swap_*): New macros. + * coff-mips.c (mips_coff_swap_table): New data structure. + (ecoff_big_vec): Use it. + * All COFF targets: Moved COFF_SWAP_TABLE to target-specific data. + * All other targets: Deleted coff-specific vector entries. + + * trad-core.c: Fixed some `PARAMS' uses that were missing + parentheses. + +Sun Nov 29 08:37:13 1992 Fred Fish (fnf@cygnus.com) + + * aoutx.h (some_aout_object_p): Protect arg prototype in + callback_to_real_object_p with PARAMS macro for non-ANSI compilers. + +Sat Nov 28 04:01:21 1992 John Gilmore (gnu@cygnus.com) + + * aout-target.h, aoutf1.h, trad-core.c, coffcode.h, libaout.h, + libbfd-in.h, bfd-in.h: Eliminate all PROTO calls, replace with + PARAMS for readability. + + * aoutx.h: Add type to callback parameter. + * coff-mips.c: Don't call trad-core.h, not needed. + * trad-core.c: Incorporate trad-core.h declarations. Fix comments. + * trad-core.h: Eliminate, unused. + +Wed Nov 18 13:16:17 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * format.c (bfd_check_format): if default target isn't found + then look through the entire list rather than return early. + +Mon Nov 16 14:33:03 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * config/i960-coff.mt: reorder vec to match bfd_check_format (from Per) + +Thu Nov 12 17:01:41 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: pass down prefix and exec_prefix in FLAGS_TO_PASS + +Thu Nov 12 09:46:47 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-z8k.c: checkpoint, more addressing modes handled + * coffcode.h (get_value): don't truncate reloc->addend field, it's + a long now. + +Wed Nov 11 23:57:55 1992 Brendan Kehoe (brendan@cygnus.com) + + * we32k.mt (TDEFAULTS): Use we32kcoff_vec, not i386coff_vec. + +Tue Nov 10 14:04:38 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: minor tweaks to make $(CC) command lines more consistent + +Mon Nov 9 23:58:17 1992 John Gilmore (gnu@cygnus.com) + + * opncls.c (bfd_fdopenr, bfd_close): Add doc about cacheing + and about when file descriptors are closed. + +Sat Nov 7 00:42:20 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * bout.c (b_out_squirt_out_relocs): Make sure alignment relocs get + written out correctly. + +Thu Nov 5 15:34:19 1992 Ian Lance Taylor (ian@cygnus.com) + + * section.c: New section bit SEC_SHARED_LIBRARY. + coffcode.h (styp_to_sec_flags): if STYP_NOLOAD && (STYP_TEXT || + STYP_DATA), set SEC_SHARED_LIBRARY. This seems to be correct for + i386-sysv. + +Thu Nov 5 04:43:09 1992 John Gilmore (gnu@cygnus.com) + + * target.c (struct bfd_target): Eliminate the SDEF and SDEF_FMT + macros; use PARAMS to declare the function pointers involved. + + * bfd-in.h, bfd.c, libbfd.h, reloc.c, seclet.h, section.c, + targets.c: Rename struct bfd_seclet_struct to struct bfd_seclet. + +Thu Nov 5 02:59:09 1992 John Gilmore (gnu@cygnus.com) + + Cleanup: Replace all uses of EXFUN in the BFD sources, with PARAMS. + + * archures.c, reloc.c, section.c, tekhex.c: Use PARAMS in + declaring pointers to functions. + * cache.c, elf.c: Move static function decls to top, use PARAMS. + * seclet.h: Declare external function with PARAMS. + + * doc/chew.c (exfunstuff): Eliminate. + (paramstuff): Replace exfunstuff with function to generate PARAMS. + * doc/proto.str: Use paramstuff rather than exfunstuff. + + * libbfd.h: Update, based on changes in source code and chew. + +Wed Nov 4 22:47:29 1992 John Gilmore (gnu@cygnus.com) + + * libieee.h: Add FIXME about removing limit on number of sections. + * bfd-in.h: Improve comments to make it clear that bfd.h is + the wrong place to edit this file. + * Makefile.in (install): Install ansidecl.h and obstack.h in the + same places where we install bfd.h. + +Wed Nov 4 13:40:23 1992 Sean Eric Fagan (sef@cygnus.com) + + * coffcode.h (coff_swap_aux_out, coff_swap_aux_in): check for + symbol type before blindly modifying the auxent. Specifically, + only modify the endndx fields for types that need it, and don't + set the array information for non-arrays. + +Wed Nov 4 09:30:50 1992 Ken Raeburn (raeburn@cygnus.com) + + * aoutx.h (some_aout_object_p): Section list should be set up + correctly anyways; don't have to set up "next" pointers manually. + +Mon Nov 2 12:36:14 1992 Ian Lance Taylor (ian@cygnus.com) + + * config/delta88.mh, config/hp300.mh, config/hppahpux.mh, + config/i386v.mh: removed -DUSG from HDEFINES. + hosts/delta88.h, hosts/hp300.h, hosts/hppahpux.h, hosts/i386v.h: + defined USE_UTIME. + hosts/i386v.h: don't define POSIX_UTIME. + +Fri Oct 30 16:13:52 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * ieee.c (ieee_slurp_sections): make a private copy of the + section's name before truncating it. + +Thu Oct 29 08:30:50 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * hppa.c: add symbol_leading_char entry in transfer vec + +,Wed Oct 28 16:11:57 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * ieee.c (get_symbol): can now cope when two symbols of a + different class, but the same index number occur consecutively. + (get_section_entry): nicer name for sections being forward + referenced. (ieee_archive_p): don't free the filename string, + since it was never malloced. + +Wed Oct 28 13:42:09 1992 John Gilmore (gnu@cygnus.com) + + * coffcode.h (coff_write_object_contents): Zero timestamp field. + +Tue Oct 27 12:24:34 1992 Ian Lance Taylor (ian@cygnus.com) + + * coffcode.h (coff_swap_aux_out): set the fcnary info before + optionally setting the dimen info, since they are in the same + memory locations. Also zero out external auxent. + (coff_write_symbol): don't zero external auxent; now done in + coff_swap_aux_out. + +Fri Oct 23 13:55:35 1992 Ian Lance Taylor (ian@cygnus.com) + + * Check fclose return value for errors. + libbfd.h: bfd_cache_close now returns a boolean. + cache.c (bfd_cache_delete): return fclose success value. + (bfd_cache_close): return bfd_cache_delete return value. + opncls.c (bfd_close, bfd_close_all_done): return result of + bfd_cache_close. + +Fri Oct 23 10:32:36 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * seclet.c (rel): don't load sections without the SEC_LOAD bit. + +Thu Oct 15 10:16:35 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-m68k.c (m68k_howto2type, SELECT_RELOC): new function to + work out a coff relocation type from a howto's attributes rather + than using the input r_type field. This fixes PR1677 and allows + conversion of a.out relocs to coff relocs. + + * coffcode.h (coff_write_relocs): if supplied a relocation + relative to an absolute symbol, use the right symbol index. + + * reloc.c (bfd_perform_relocation): do a partial link for coff + relocs right. + +Fri Oct 23 08:15:56 1992 Ian Lance Taylor (ian@cygnus.com) + + * changes to support i386-sysv with shared libraries: + * coffcode.h (sec_to_styp_flags): if TWO_DATA_SECS is defined, + check for .data2; if _LIB is defined, check for it; map + SEC_NEVER_LOAD to STYP_NOLOAD. + (styp_to_sec_flags): map STYP_NOLOAD to SEC_NEVER_LOAD. + (make_a_section_from_file): if TWO_DATA_SECS, accept .data2. + (coff_write_object_contents): force vaddr of .lib to 0; set scnptr + if section has contents, not just if it is loadable; if + TWO_DATA_SECS, check for .data2 + (coff_set_section_contents): set vma of .lib section to number of + .lib sections. + * coff-i386.c: define TWO_DATA_SECS; use a special CALC_ADDEND; + don't define coff_write_armap to bsd_write_armap. + * hosts/i386v.h: don't include , since it is not provided + by SVR3.2. + +Thu Oct 22 22:40:20 1992 Brendan Kehoe (brendan@lisa.cygnus.com) + + * solaris2.h: Get the definition of alloca from alloca.h if we + aren't using gcc. + +Thu Oct 22 03:07:28 1992 John Gilmore (gnu@cygnus.com) + + * configure.in (i960-*-{aout,bout}): Support these. + +Wed Oct 21 03:46:34 1992 John Gilmore (gnu@cygnus.com) + + * config/a29k-aout.mt (DEFAULT_TARGET): Set to one that exists. + +Thu Oct 15 15:05:39 1992 Per Bothner (bothner@cygnus.com) + + * apollo68.h, apollov68.h, hp300.h, i386v.h, irix3.h: Remove + no-longer-used definitions of L_SET and L_INCR. + * i386linux.h: Tweaks to smooth Linux build. + +Thu Oct 15 01:32:22 1992 John Gilmore (gnu@cygnus.com) + + * seclet.h: Add enum tag to bfd_seclet_enum_type. + + * bfd-in.h (file_ptr): Update comments, make FIXME re off_t. + + * aout-adobe.c, aoutf1.h, archive.c, bout.c, coff-rs6000.c, + coffcode.h, elf.c, ieee.c, libaout.h, libbfd.c, oasys.c, + sco-core.c: Lint: Second argument of bfd_seek is always file_ptr. + Third argument is SEEK_SET or SEEK_CUR. Result is always 0 or -1. + + * aout-adobe.c, aoutf1.h, aoutx.h, bout.c coff-m68k.c, coff-z8k.c, + coffcode.h, elf.c, libaout.h, libbfd-in.h, srec.c: Lint. + +Fri Oct 9 03:46:37 1992 John Gilmore (gnu@cygnus.com) + + * configure.host: New file, contains mapping of host configs + to host support file names for bfd, binutils, opcodes. + * configure.in: Use it. + * i386aout.c: Cleanup, dump TARGET_IS_LITTLE_ENDIAN_P. + * i386bsd.c: Cleanup, reformat. + * config/i386-bsd.mt: Comment changes. + * config/i386bsd.mh: New file for core file support. + * hosts/i386bsd.h: Merge changes from Peter Schauer. + * bout.c (ALIGN): Rename to ALIGNER, since system header files + on BSD 4.4 define ALIGN (sigh!). + +Thu Oct 8 22:18:10 1992 Mark Eichin (eichin at tweedledumber.cygnus.com) + + * libaout.h (aout_backend_data): added exec_header_not_counted + field. For ZMAGIC files only, when text_includes_header is set, by + default the length of the exec header is counted in the text + section size. For go32, exec header is mapped in but does *not* + contribute to the size of section. + * aoutx.h (aout_adjust_sizes_and_vmas): if exec_header_not_counted + is not set, but ztih is, add the size of the exec header to the + recorded size of the text section. + * aoutf1.h (sunos4_aout_backend): clear exec_header_not_counted. + * i386aout.c (i386aout_backend_data): set exec_header_not_counted. + Also set text_includes_header. + * aout-target.h (*_backend_data): cleare exec_header_not_counted + by default in MY(backend_data). + +Thu Oct 8 18:12:49 1992 Ken Raeburn (raeburn@cygnus.com) + + * aout-target.h (callback): Don't define this function if it won't be + used. + + * aoutx.h (some_aout_object_p): Restore old aout_data value if this + type doesn't match. Don't lose if file sections have already been + created. + (set_arch_mach): Set reloc_entry_size. + (slurp_symbol_table): Use bfd_h_get_{16,8} for reaeding symbol data. + + * hosts/i386bsd.h: New file. + * configure.in: Recognize i[34]86-*-bsd host. + + * aout-target.h (callback, write_object_contents): Delete unused + variables. + + * aoutx.h (reloc_type_lookup): New function. + * aout-target.h (MY_reloc_howto_type_lookup): Use it as default. + * aoutf1.h (sunos4_reloc_type_lookup): Deleted. + (MY_reloc_howto_type_lookup): Don't define it. + + * aoutx.h (adjust_sizes_and_vmas): Don't bother with padding for + OMAGIC files. + (slurp_symbol_table): Use header byte order, not target byte + order, for reading symbol data. + +Thu Oct 8 17:33:39 1992 John Gilmore (gnu@cygnus.com) + + * configure.in: Undo some brain damage in the host section. + * configure.in: Reformat the target section, test many configs. + * Makefile.in (make): Remove obsolete `make make'. + * aoutx.h (some_aout_object_p): Make defines line up. + +Thu Oct 8 08:52:48 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + Now a bfd knows whether underscores are normally prepended + to symbols in its file format. + + * aout-adobe.c, aout-target.h, bout.c, coff-a29k.c, coff-h8300.c, + coff-z8k.c: targets set so they have leading underscore + * coff-i386.c, coff-i960.c, coff-m68k.c, coff-mips.c, coff-m88k.c, + coff-rs6000.c, coff-we32k.c, elf.c, ieee.c, srec.c: targets set + without leading underscore flag + * targets.c: add symbol leading char to xvec description + * bfd-in.h (bfd_get_symbol_leading_char): new macro. + +Mon Oct 5 14:32:55 1992 Per Bothner (bothner@cygnus.com) + + * archive.c: Make errno global. + * archive.c (_bfd_write_archive_contents): If read fails (and + errno!=0) set bfd_error to malformed_archive (since this probably + indicates a truncated archive), rather than system_call_error. + +Mon Oct 5 03:33:39 1992 Mark Eichin (eichin at tweedledumber.cygnus.com) + + * Makefile.in: added rules for i386bsd.c + * i386bsd.c: new file, supporting 386bsd. + * configure.in: recognize i386-*-bsd target. + * config/i386-bsd.mt: new file - 386bsd target configuration. + +Thu Oct 1 17:51:07 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: re-arrange host section to use *-*-* notation, + clean up some of the target section as well + + * seclet.c: cast result of bfd_get_relocated_section_contents to + avoid compiler warnings + +Tue Sep 29 13:24:09 1992 Ken Raeburn (raeburn@cygnus.com) + + * coffcode.h (coff_section_symbol): Create section if it doesn't + already exist. + + * bout.c: Removed some unused variables. + +Tue Sep 29 08:30:21 1992 Ian Lance Taylor (ian@cygnus.com) + + * Portability fixes from p3: + coffcode.h (coff_write_relocs): removed sanity check until it + works on all targets (per advice from sac). + config/hp9000.mh: new file to define USG. + hppa.c: #undef hppa before the JUMP_TABLE. + hosts/hppahpux.h: #define NATIVE_HPPAHPUX_COMPILER if not + __STDC__. + targets.c (bfd_target_list): if NATIVE_HPPAHPUX_COMPILER, make + local variable target volatile to avoid mysterious bug in + HP9000/700 cc. + +Sat Sep 26 03:58:49 1992 John Gilmore (gnu@cygnus.com) + + * config/hppabsd.mh, config.hppahpux.mh: Remove various bogosity. + * hosts/hppahpux.h: Remove bcopy and index circumventions. + +Fri Sep 25 22:36:52 1992 John Gilmore (gnu@cygnus.com) + + * coff-z8k.c (func_da, func_jr): Lint. + * coffcode.h: Use memset rather than bzero. + * elf.c: Use memcpy rather than bcopy. + * tekhex.c: Use memset rather than bzero. + +Fri Sep 25 19:14:48 1992 John Gilmore (gnu@cygnus.com) + + Add Adobe a.out support. + + * aout-adobe.c: New file. So far, only reads a.out.adobe. FIXME. + * config/adobe.mt: Add. + * configure.in (*-adobe-* target): Add. + * targets.c (a_out_adobe_vec): Add. + * Makefile.in: add aout-adobe.c. + + * configure.in: Put two dashes in all entries to be matched. + Add comments to remind people to do this. + Reorder all entries that match manufacturer names, to occur + last, so they will only be matched if no more specific match + occurs. Remove manufacturers `aout', `bout', `coff', and `elf'. + +Fri Sep 25 15:03:22 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * elf.c (section_from_elf_index): Return bfd_abs_section, not 0, + since we should never have a NULL section. + (elf_slurp_symbol_table): If st_shndx doesn't match any of our + tests, set the section to bfd_abs_section. + +Fri Sep 25 11:11:57 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-z8k.c: getting closer + * coffcode.h (coff_get_relocated_section_contents): allow + EXTRA_CASES hooks for different arches to provide different reloc + types. + * seclet.h: #ifndef around it to allow multiple inclusion + * srec.c: minor doc fix + +Mon Sep 21 14:33:58 1992 Ian Lance Taylor (ian@cygnus.com) + + * hosts/hp9000.h, hosts/irix3.h: changes from WRS. + +Sun Sep 20 08:48:25 1992 Fred Fish (fnf@cygnus.com) + + * configure.in: Use i386-elf for all i386/i486 sysv4 hosts, not + just ncr. + +Thu Sep 17 06:40:46 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * bout.c (b_out_slurp_reloc_table): Clear howto field before + filling in reloc, in case immediately following code doesn't set + it. + +Fri Sep 11 15:37:06 1992 Ian Lance Taylor (ian@cygnus.com) + + * coffcode.h (coff_renumber_symbols): set the last renumbered + symbol pointer to NULL, as expected by coff_write_linenumbers. + (coff_write_relocs): apparently a non-zero addend is OK for reloc + type R_IHCONST used on the 29k. + +Thu Sep 10 13:28:24 1992 John Gilmore (gnu@cygnus.com) + + * opncls.c (bfd_fdopenr): Determine whether to fdopen for + update, based on how the underlying file was opened. Obsoletes + FASCIST_FDOPEN. + * hosts/rs6000.h, hosts/tahoe.h, hosts/vaxbsd.h: Remove + all FASCIST_FDOPEN config defines. + +Tue Sep 8 21:37:58 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * sparc-opc.c: Moved to opcodes library, now that we have one. + * Makefile: Don't compile it. + +Tue Sep 8 10:10:34 1992 Ian Lance Taylor (ian@cygnus.com) + + * aoutx.h: adjust_sizes_and_vmas did not return anything. + +Thu Sep 3 19:29:04 1992 Per Bothner (bothner@rtl.cygnus.com) + + * section.c (bfd_set_section_flags): Remove a sanity check. + It is unfortunately broken, and prevents strip from working. + +Thu Sep 3 16:14:40 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * sparc-opc.c (condr): Remove extraneous, but harmless, backlash + created by last change. + +Thu Sep 3 13:52:38 1992 Per Bothner (bothner@rtl.cygnus.com) + + * reloc.c (reloc_howto_struct): Make size field be unsigned. + * bfd-in.h: Bump to version 2.0. + +Thu Sep 3 09:05:37 1992 Stu Grossman (grossman at cygnus.com) + + * bout.c, cpu-z8k.c: Use enums when initializing structs to keep + braindamaged HP/Apollo compiler happy. + +Wed Sep 2 02:53:29 1992 John Gilmore (gnu@cygnus.com) + + * format.c: Fix description of search for matching target. + * aoutx.h (some_aout_object_p): Set SEC_CODE and SEC_DATA. + * targets.c: Update description of search for matching target. + * Makefile.in (do_clean, clean): Fix infant mortality typo. + (docdir): Set to ./doc, not ${srcdir}/doc, which has no makefile. + (z8k and we32k files): `*.o: *.c': avoid Sun Make bug. + +Wed Sep 2 00:26:32 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Added mostlyclean/clean/distclean rules. + +Tue Sep 1 13:38:40 1992 Per Bothner (bothner@cygnus.com) + + * targets.c (target_vector): Take out oasys (unless that is + the default): Because there is no magic number in archives, + there can be annoying target mis-matches. + +Mon Aug 31 10:11:37 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * sparc-opc.c: Rigorously updated to match architecture manual. + +Mon Aug 31 08:07:58 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * aoutx.h (aoutswap_ext_reloc_out), bout.c + (b_out_squirt_out_relocs): fix bug 1506 where abs symbols attached + to the built-in abs_section were not written out correctly. + +Fri Aug 28 16:29:15 1992 Ian Lance Taylor (ian@cygnus.com) + + * archive.c (bfd_slurp_bsd_armap): if the symdef_count is too + large, assume we're using a swapped byte order and fail with + wrong_format rather than dumping core. + +Fri Aug 28 15:38:03 1992 Ken Raeburn (raeburn@cygnus.com) + + * Renamed opc-sparc.c to sparc-opc.c for systems with short + filename constraints. + * Makefile.in: Updated to reflect change. + +Thu Aug 27 13:05:28 1992 Brendan Kehoe (brendan@cygnus.com) + + Add preliminary support for the we32k: + + * Makefile.in, archures.c, coffocode.h, configure.in, targets.c: + Minor edits. + * coff-we32k.c, cpu-we32k.c, config/we32k.mt, hosts/we32k.h: New files. + +Wed Aug 26 14:20:16 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * bout.c: added support for relaxable alignment relocs. + + * seclet.c (rel, seclet_dump_seclet, seclet_dump): get the app to + pass down pointer to play area rather than use alloca + + * cpu-z8k.c (compatible): made static to reduce name space + polution. + +Tue Aug 25 08:39:10 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + Add basic support for the z8k: + + * Makefile.in, archures.c, coffcode.h, configure.in, reloc.c, + section.c, targets.c, + + * syms.c: move mis-inserted patch. + +Fri Aug 14 15:39:29 PDT 1992 Howard Chu (hyc@hanauma.jpl.nasa.gov) + + Documentation fixes: + * ctors.c, format.c, section.c, reloc.c: append " -" to item tags. + * reloc.c, section.c, syms.c, targets.c: add DOCDD before @node + comments. + * reloc.c: break out addend item from surrounding text. + + * doc.str (DOCDD): Defined. Adds text to output. + (bodytext): Put bulletize before kill_bogus_lines. + * chew.c (bulletize): End itemization after a blank line, to + prevent following text from being swallowed up in an item. + +Mon Aug 24 20:50:22 1992 Stu Grossman (grossman at cygnus.com) + + * configure.in: Add sparclite as a target. + +Mon Aug 24 12:06:31 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * ieee.c (ieee_get_symtab): always null terminate the symbol list, + lint. + + * coffcode.h (coff_add_missing_symbols): if symbols don't come + from a coff file (csym is null), dont deref them + + * ieee.c (parse_expression): get the answer right when adding an + abs+(sec+off), (ieee_generic_stat_arch_elt): call ieee_object_p + on elts so that filename is filled in. + +Thu Aug 20 19:05:48 1992 Ken Raeburn (raeburn@cygnus.com) + + * bout.c (howto_align_table): New set of relocs, with enough + data for "objdump -r" to work. + (b_out_reloc_type_lookup): Recognize alignment relocs. + +Tue Aug 18 12:57:45 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in: added FLAGS_TO_PASS, and used it for all recursive + invocations of make. Also, always create installation + directories. + + * config/apollov68.mh: removed -g from CC definition. + +Mon Aug 17 13:40:08 1992 Ken Raeburn (raeburn@cygnus.com) + + * config/decstation.mh (HDEFINES): Specify "-G 4" to avoid + overflowing gp-offset range. + +Mon Aug 17 11:44:28 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * srec.c (srec_set_section_contents): don't write out sections + without the LOAD and ALLOC attributes + +Mon Aug 17 11:55:07 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * archures.c, cpu-m68k.c, cpu-sparc.c: Undo 16 June changes. + * libaout.h (struct aout_backend_data): New callback "set_sizes". + * aout-target.h (callback): Don't set page/seg sizes. + (mkobject): Ditto. + (set_sizes): New routine. + (backend_data): Point to it. + * aoutf1.h (sunos4_set_sizes): Heed architecture when setting sizes. + (sunos4_aout_backend): Point to it. + * aoutx.h (set_arch_mach): Call set_sizes callback. + +Fri Aug 14 19:22:18 1992 Per Bothner (bothner@cygnus.com) + + * aout-target.h: Make _bfd_slurp_extended_name_table be + the default. Given that we *write* the suckers (for long + archive member names), we really ought to be able to read them! + * trad-core.c: Don't include . It doesn't + seem to be needed, and many machines don't have it. + +Thu Aug 13 09:53:39 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-m68k.c (vector): read and write archives in coff format. + +Tue Aug 11 12:19:42 1992 Ken Raeburn (raeburn@cygnus.com) + + * opc-sparc.c: New file. + +Sat Aug 8 23:15:35 1992 Fred Fish (fnf@cygnus.com) + + * bout.c (bfd_reloc_status_type, callj_callback): Cast void* + pointers to bfd_byte* before performing arithmetic on them. Such + use with bare void* pointers is a gcc extension. + * cache.c (bfd_cache_delete): Forward decl with prototype form. + * archive (normalize): Add to CONST to match actual usages with + CONST. + +Mon Aug 3 00:35:29 1992 Fred Fish (fnf@cygnus.com) + + * configure.in: Recognize i486 host cpu, and use i386-elf + for i486-ncr-sysv4. + +Sat Aug 1 13:49:59 1992 Fred Fish (fnf@cygnus.com) + + * config/stratus.mt (CC): Remove definition. + * elf.c (bfd_section_from_shdr): Test for the possibility that + section_from_elf_index returns NULL and don't dereference it. + +Mon Jul 20 02:46:09 1992 D. V. Henkel-Wallace (gumby@cygnus.com) + + * add hppa_data to bfd tdata (indirectly via sef). + + * config/hppahpux.mh: hpux is -DUSG (patch by sef) + +Sat Jul 18 15:50:11 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: error messages to stderr, not stdout + +Fri Jul 17 18:32:46 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * bfd.c, cache.c, coff-a29k.c, coff-i386.c, coff-i960.c, + coff-m68k.c, coff-m88k.c, demo64.c, libaout.h, libbfd.c, + oasys.c, opncls.c, sunos.c, targets.c: removed rcsid's. + +Fri Jul 17 17:06:56 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: recognize hppa* instead of hppa + +Thu Jul 16 16:39:25 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-m68k.c: added R_RELLONG_NEG reloc type, and changed + RTYPE2HOWTO to cope with same. + * reloc.c (bfd_perform_relocation): added support for size of -2 + (subtract a word reloc type). Updated doc. + +Thu Jul 16 16:28:09 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: merged changes from progressive, removed rcsid. + + * archures.c, archive.c, Makefile.dos: removed rcsid. + +Thu Jul 16 08:08:25 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * bfd-in.h : add BFD_IS_RELAXABLE flag + * bout.c (bout_swap_exec_header_[in_out]): new field in exec + header e_relaxable, major hackery in callbacks + * libaout.h : add space for a_relaxable. + * seclet.c (rel): don't relax empty sections + + +Wed Jul 15 07:57:46 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * section.c (STD_SECTION): add some casts to the initializers for + dumb compilers + +Tue Jul 14 14:06:28 1992 Stu Grossman (grossman at cygnus.com) + + * rs6000-core.c (rs6000coff_core_p): Greatly simplify expression, + and add appropriate casts to keep (picayune) aix-cc happy. + +Mon Jul 13 05:06:51 1992 John Gilmore (gnu at cygnus.com) + + * elf.c (elf_slurp_symbol_table): Now 2nd arg is where to write + symbol pointers. Punt expensive & useless bfd_realloc. Use + malloc for raw symbols, and free it before returning. + (bfd_section_from_shdr): Do not slurp symbol table until politely + asked. Do not even slurp string tables. + (elf_get_symtab_upper_bound): Count 'em without reading them. + (elf_get_symtab): This is how to politely ask. Schlurp! + This should probably just *become* elf_slurp_symbol_table, FIXME. + +Wed Jul 8 16:24:33 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * archive.c (bsd_write_armap): 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. + +Tue Jul 7 00:23:23 1992 Fred Fish (fnf@cygnus.com) + + * configure.in: Add m68k-ericsson-*. + +Sat Jul 4 03:29:41 1992 John Gilmore (gnu at cygnus.com) + + * syms.h: Define BSF_FILE, update BSF_SECTION_SYM desc. + * elf.c: Remove unconditional debug printf's. + (elf_write_object_contents, elf_slurp_symbol_table): Handle + BSF_SECTION_SYM <=> STT_SECTION, BSF_FILE <=> STT_FILE. + (elf_slurp_symbol_table): Hand out symbols in forward, not + reverse order. Simplify duplicate code. + +Fri Jul 3 20:23:34 1992 Fred Fish (fnf@cygnus.com) + + * elf.c: Remove "(void)" casts from function calls where the + return value is ignored, in accordance with GNU coding standards. + +Tue Jun 30 16:49:12 1992 Fred Fish (fnf@cygnus.com) + + * hppa.c: Apply John's standard fix to avoid "empty translation + unit" warnings from some ANSI-C compilers. + +Thu Jun 25 04:39:25 1992 John Gilmore (gnu at cygnus.com) + + * hosts/solaris2.h: Configure same as sysv4. + +Tue Jun 23 21:54:44 1992 Fred Fish (fnf@cygnus.com) + + * libbfd.h, libbfd-in.h (bfd_seek): Make prototype match definition. + * reloc.c (bfd_default_reloc_type_lookup): Make cast on return + type match actual return type. + * elf_print_symbol (section_name): Make CONST. + +Mon Jun 22 17:35:24 1992 Per Bothner (bothner@cygnus.com) + + * i386linux.c, hosts/i386linux.h, config/i386-linux.mt: + New files, for Linux (a free Unix clone for 386 machines). + * Makefile.in, configure.in, targets.c: Update accordingly. + +Fri Jun 19 20:23:21 1992 Steve Chamberlain (sac@thepub.cygnus.com) + Lints for bfd_reloc_code_type->bfd_reloc_code_real_type, and + correct calling of howto special functions and fixes from Raeburn + for gas<>bfdness + * archures.c: nuke bfd_reloc_code_type + * bout.c, cpu-h8300.c, coff-i960.c, coff-m88k.c: special function lint + * coffcode.h (styp_to_sec_flags): STYP_INFO is marked as + SEC_NEVER_LOAD, various other bfdgas newness + * reloc.c->libbfd.h: change protype of bfd_default_reloc_type_lookup + * targets.c: change jump table vector to above + + +Fri Jun 19 19:00:45 1992 John Gilmore (gnu at cygnus.com) + + * elf.c (bfd_elf_find_section): Mark as INTERNAL_FUNCTION so + its prototype will be included in libbfd.h. Change result type + to struct * (rather than equivalent typedef) so it can be used in + the prototype, where they typedef won't be known. + * libbfd.h: Updated version. + +Fri Jun 19 15:21:56 1992 Stu Grossman (grossman at cygnus.com) + + * Makefile.in, archures.c, configure.in, cpu-hppa.c, hppa.c, libhppa.h, + targets.c: HPPA merge. + +Fri Jun 19 12:21:38 1992 John Gilmore (gnu at cygnus.com) + + * configure.in: Separate Solaris2 from SYSV4 on SPARC. + * config/solaris2.mh: Kludge around Sun compiler bug. + +Wed Jun 17 14:02:46 1992 Stu Grossman (grossman at cygnus.com) + + * libaout.h (aout_backend_data): Change defs of two bitfields to + be unsigned chars instead to get around rs6000 compiler problem. + +Wed Jun 17 13:55:31 1992 Fred Fish (fnf@cygnus.com) + + * elf.c (bfd_section_from_shdr, elf_slurp_symbol_table): + Correct misconception that there can be only one symbol table. + Only call elf_slurp_symbol_table on the full symbol table, not + the dynamic one which is only a subset of the full one. + +Wed Jun 17 15:54:57 1992 Ken Raeburn (Raeburn@Cygnus.COM) + + * coffcode.h (coff_compute_section_file_positions): For I960, + don't align sections in file. + +Tue Jun 16 06:28:21 1992 Ken Raeburn (Raeburn@Cygnus.COM) + + * targets.c (struct bfd_target): Added field for target-specific + (but not file-specific) data, for distinguishing minor + characteristics between (e.g.) a.out formats. + + * section.c (struct sec): New field user_set_vma indicates vma + field should be heeded, not assumed to be unset. + (STD_SECTION): Initialize that field of standard sections to zero. + * bfd-in.h (bfd_set_section_vma): Set user_set_vma to true. + + * coffcode.h (coff_write_relocs): Write out swapped reloc, not + pre-swapped version. + + * archures.c (struct bfd_arch_info): Fixed order of comment and + field decl. New fields indicate size of page and segment for + architecture. + * cpu-m68k.c (N): Fill in values. + * cpu-sparc.c (arch_info_struct): Ditto. + + * libaout.h (struct aout_backend_data): Various bits of data (not + all used currently) with characteristics of a.out implementation. + Important field for now is text_includes_header, indicating that + the text section starts immediately after the file header, which + gets mapped in with it. + (struct aout_data): New fields indicate whether vma has been + adjusted yet (not yet used), and what magic number will be used in + the output file (should go away in favor of vma_adjusted). + (WRITE_HEADERS): Code for dealing with section sizes and related + header fields replaced with call to adjust_sizes_and_vmas. + * aoutx.h (some_aout_object_p): Fill in magic number field. + Set WP_TEXT flag for ZMAGIC as well as NMAGIC files. + (set_arch_mach): Set page size and segment size once CPU + type is known. + (adjust_sizes_and_vmas): New function; has much code moved + from set_section_contents and WRITE_HEADERS. Sets or adjusts vma + and size parameters, as well as many header fields, after deciding + on magic number for output file. Checks to ensure that this + adjustment has only been done once. + (set_section_contents): Call adjust_sizes_and_vmas instead of + doing much of the work here. + + * aout-target.h (MY_make_debug_symbol, MY_backend_data): Provide + default (null) values of these fields. + * aoutf1.h (sunos4_write_object_contents): Don't override a_text + value in exec header. + (sunos4_aout_backend, MY_backend_data): Define backend data + indicating file header is included in text section. + + * aoutf1.h (MY_reloc_howto_type_lookup): Fix typo. + + * hosts/sparc.h (abort, exit): Hide these names if compiling with + gcc version 2, to avoid warnings. + +Mon Jun 15 12:26:56 1992 Fred Fish (fnf@cygnus.com) + + * config/ncr3000.mh (INSTALL, RANLIB): Don't use /usr/ucb/install, + it's broken on ncr 3000's. Use simple "true" for RANLIB. + +Sat Jun 13 09:16:43 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * configure.in (m680[01234]0-wrs-*): Fix typo in match pattern. + +Fri Jun 12 19:48:34 1992 John Gilmore (gnu at cygnus.com) + + * section.c (STD_SECTION): Remove extra semicolon in declarations. + * configure.in: Rewrite target parsing to use simple format. + Handle sparc-sun-solaris2 configuration. + * aout64.h: Avoid ANSI C brain death warning. + * elf.c: Avoid trigraph (???) or /* in comments. + +Fri Jun 12 14:51:14 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * config/sysv4.mh: new file, RANLIB=echo + + * configure.in: handle Solaris2 as -sysv4 or -solaris2 + +Thu Jun 11 00:52:03 1992 John Gilmore (gnu at cygnus.com) + + * elf.c (elf_obj_tdata): Merge elf_obj_tdata_struct and + elf_core_tdata_struct into a single common struct. Core files + wouldn't have worked at all without this. + (bfd_elf_find_section): New function for GDB's undercover use + to find string sections that BFD hides from it. + (elf_get_str_section): Avoid multiple alloc&reads for same data; + lint. + (elf_object_p, elf_core_file_p): Allocate internal file header + storage dynamically. + * bfd.c (union {...} tdata): Remove elf_core_tdata_struct. + * demo64.c: Prevent "empty translation unit" warnings from idiots. + +Tue Jun 9 17:15:26 1992 Fred Fish (fnf at cygnus.com) + + * config/{i386v4.mh, ncr3000.mh}: Update RANLIB, add INSTALL. + +Sat Jun 6 17:02:51 1992 John Gilmore (gnu at cygnus.com) + + * configure.in: Handle Solaris2 as *-sun-sysv4 or as *-sun-sunos5. + +Sun May 31 05:45:00 1992 david d `zoo' zuhn (zoo@cygnus.com) + + * configure.in: handle m680[01234]0 as aliases for m68k + +Tue May 26 16:50:59 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-a29k.c: do byte relocs correctly + * coffcode.h (styp_to_sec_flags): never load INFO sections + * seclet.c (rel): don't relocate INFO sections + +Wed May 20 08:18:18 1992 Ken Raeburn (Raeburn@Cygnus.COM) + + * section.c (bfd_*_symbol, bfd_*_section): Initialize statically. + Make the symbols unmodifiable. + (bfd_section_init): Deleted. + * init.c (bfd_init): Don't call bfd_section_init. + + * section.c (bfd_set_section_contents): Ensure that range to be + written is within section boundaries. + (bfd_get_section_contents): Likewise. Don't bother dispatching if + size is zero. + + * libbfd.c (bfd_xmalloc): Text of error message should be const. + + * coff-i960.c (howto_table): Deleted. + (howto_rellong, howto_iprmed, howto_optcall): New vars; + interesting entries from old howto_table. + (RTYPE2HOWTO): Adjusted to use switch. + (coff_i960_reloc_type_lookup): New function. + + * coffcode.h (coff_new_section_hook): Allocate storage for aux + records for section symbol. + (make_abs_section): Unused; deleted. + (renumber_symbols): Re-order symbols so undefined symbols come + last, as COFF format desires. + (coff_write_symbol): Put C_FILE symbols in debug section always. + (coff_section_symbol): New function; creates a symbol with the + same name as a section, and sets up aux records for it. + (coff_add_missing_symbols): New function; adds section symbols to + symbol table if they aren't there already. Should someday also + add a dummy C_FILE symbol if none is present. + (coff_write_object_contents): Add missing symbols before preparing + symbol table to be written. + (coff_slurp_reloc_table): Verify that symbol indices read in are + in a reasonable range. + * libcoff-in.h (struct coff_tdata): New field conv_table_size. + (obj_conv_table_size): Accessor macro. + + * bout.c (b_out_reloc_type_lookup): New function. Handles three + reloc types on i960. + + * bfd-in.h (bfd_get_section_name): New macro. Like + bfd_section_name, but returns rvalue, not lvalue. + (bfd_get_section_vma, bfd_get_section_alignment): Similar. + (bfd_get_section_flags): Now returns rvalue. + + * reloc.c (enum bfd_reloc_code_real): Add several new values, some + general, some specific to sparc or i960. + + * aoutx.h (set_section_contents): Set VMA for each section based + on previous section. If text section VMA doesn't appear to have + been set, make a best guess from the type of file. + + * aout-target.h (MY_reloc_howto_type_lookup): Define as zero if + not defined. + (MY(vec)): Initialize reloc_type_lookup field. + + * aoutx.h (howto_table_*): Export as aout_#_*_howto_table. + (bfd_error_trap, bfd_error_vector): Extern, not common. + + * aoutf1.h (sunos4_reloc_type_lookup): New function. Handles a + few types of relocs for sparc; will need enhancement. + + * bout.c (callj_callback): Use DEFUN macro in definition. + * coff-i960.c (optcall_callback): Likewise. + + * targets.c (bfd_target): Added fields reloc_type_lookup and + _bfd_make_debug_symbol. Also minor comment changes. + * syms.c (bfd_make_debug_symbol): New dispatching macro. + * reloc.c (bfd_reloc_type_lookup): Take a BFD ptr as arg rather + than arch info, and dispatch with BFD_SEND. Callers changed. + * archures.c (struct bfd_arch_info): Deleted field + reloc_type_lookup. + * cpu-*.c: Don't initialize that field. + + * bfd-in.h (enum bfd_error): Add new value "bad_value". + * bfd.c (bfd_errmsgs): Now const; added entry for bad_value. + (bfd_errmsg): Now returns ptr to const. + * bfd-in.h (bfd_errmsg): Fix prototype. + + * cache.c (BFD_CACHE_MAX_OPEN): Fix typo in doc. + * reloc.c (bfd_generic_relax_section): Ditto. + + * section.c (Section Output doc): Improve description of use of + output_section and output_offset. + +Tue May 19 23:42:10 1992 D. V. Henkel-Wallace (gumby@cygnus.com) + + * sco-core.c: new file from net. + * aoutx.h (translate_to_native_sym_flags): bugfix from net: + Now we have the hairy linker, it's possible to move symbols from + one section into another. Actually make that work! + +Sat May 16 17:57:59 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * hosts/sun3.h: fix declaration of free. + +Tue May 12 14:08:59 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-a29k.c (perform_reloc): fix bug in jmp/call evaluation + * coff-h8300.c (reloc_processing): all relocs are relative to + section start. + * opncls.c: don't use fdopen on DOS systems + + short patches from Glenn Kasten (glenn@ready.com) + * target.c: enabled oasys support + * oasys.c: Insert . when UNDERSCORE_HACK is enabled, + fix problem where a relocation which crossed a modification byte + boundary did not work. Fix problem where a relocation near the end + of a data record did not work. + + +Tue May 5 18:11:25 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * archive.c (bfd_slurp_coff_armap): old versions of BFD wrote + archvie header string counts the endian way, this heuristic sees + how big an archive string to read by trying it one way and if the + string table is unreasonably big, trying it the other. *FIXME*. + * opncls.c (bfd_fdopenr): can't do fdopens on VMS + +Tue May 5 14:18:24 1992 Per Bothner (bothner@rtl.cygnus.com) + + * bfd-in.h: Increase version number to 1.97, for consistency + with ../binutils. + * Makefile.in: docdir is ./doc, not ${srcdir}/doc. + +Mon May 4 11:49:15 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * bfd-in.h: bump version to 1.96 + Major change; changed calling convention for + bfd_get_relocated_section_contents so that caller allocates + memory for section data. + * coffcode.h (bfd_coff_get_relocated_section_contents), reloc.c, + seclet.c, targets.c, bfd.c: reflect new convention. + * coffcode.h (styp_to_sec_flags): if styp_flags is not a special + case, then use reasonable default values for SEC_* flags. + +Fri May 1 12:58:34 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * coffcode.h (coff_write_object_contents): use RELSZ to work out + size of output reloc struct. + * targets.c, Makefile.in: comment out tekhex for the moment. + * ieee.c: if some places where null pointers were used instead of &bfd_abs_section. + * configure.in: tandem target is st2000 + * coff-m68k.c: rename static howto_table to global + m68kcoff_howto_table. + * bout.c: remove unnecessary abort + * coff-a29k.c: various changes to the way relocations work to cope + with the "new order" and latent bugs. + * coffcode.h: lint + +Wed Apr 29 12:37:07 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * aoutx.h (aout_swap_ext_reloc_out, aout_swap_std_reloc_out) + bout.c (b_out_squirt_out_relocs): treat abs sumbols the right way. + * reloc.c (bfd_perform-relocation): don't relocate refs to + absolute symbols if doing a partial link. + +Fri Apr 24 07:35:26 1992 Stu Grossman (grossman at cygnus.com) + + * configure.in: Add a29k-amd-udi. + +Thu Apr 23 18:37:55 1992 Fred Fish (fnf@cygnus.com) + + * aoutx.h (aout__swap_exec_header_in): Zero out the + internal_exec structure before initializing the fields that + are used, so that the unused fields are in a known state. + +Wed Apr 22 09:36:08 1992 Fred Fish (fnf@cygnus.com) + + * tekhex.c (struct data_struct): Convert from typedef that + typedefs nothing to a normal structure declaration. + * tekhex.c (pass_over): Prototype args for function that + second arg points to. + +Mon Apr 20 22:22:51 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: remove old style staging. Do not print recursion + lines. + + * Makefile.in: rework CFLAGS so that CFLAGS can be passed from the + Makefile command line. Remove MINUS_G. Default CFLAGS to -g. + Pass CFLAGS. + +Fri Apr 17 09:15:31 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * bfd.c, Makefile.in: added tekhex + * aoutx.h (set_section_contents): pages should be padded to the + size of a page, not the size of a segment. + * configure.in: added go32 host and i386-aout target. + * i386aout.c, libaout.h: now works for go32 target + * ieee.c: fix bit rot. + * seclet.c: support for padding seclet type. + +Wed Apr 15 18:11:58 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: added .NOEXPORT: + +Tue Apr 14 14:34:42 1992 Fred Fish (fnf@cygnus.com) + + * elf.c (bfd_add_strtab, bfd_add_2_to_strtab): CONST spreads + like ooze. + * elf.c (elf_compute_section_file_positions, + elf_write_object_contents): Return boolean, not NULL (which + can be void *). + * elf.c (bfd_section_from_shdr): Ifdef-out debugging code. + Also ifdef-out code that aborts on unhandled section types. + +Fri Apr 10 22:29:18 1992 Fred Fish (fnf@cygnus.com) + + * configure.in: Recognize ncr3000 config + * Makefile.in (MINUS_G): Pass on to recursive makes. + * hosts/ncr3000.h, config/ncr3000.mh: Add host config files. + +Thu Apr 2 17:42:45 1992 John Gilmore (gnu at cygnus.com) + + * Makefile.in: Now that we have sym.h and symconst.h, compile + coff-msym.c on all systems. + * config/{decstation.mh, irix3.mh, irix4.mh}: Remove coff-msym.o dep. + * coff-msym.c: Update include files and comments; add weakext bit. + +Wed Apr 1 23:16:38 1992 John Gilmore (gnu at cygnus.com) + + * archive.c, bfd.c, bout.c, coffcode.h, init.c, reloc.c, + section.c, srec.c, syms.c, coff-h8300.c: Lint. + +Sun Mar 29 09:37:59 1992 John Gilmore (gnu at cygnus.com) + + * bout.c, coff-a29k.c, coff-i960.c: Lint. + * configure.in: Add new host and target configs. + * elf.c (bfd_prstatus, bfd_fpregset): Avoid typename of register + structs, which vary; just use member name. + (elf_object_p, elf_core_file_p): Lint, fix comments. + * config/sparc-elf.mt, hosts/sysv4.h: New config files. + +Sat Mar 28 13:07:02 1992 Fred Fish (fnf@cygnus.com) + + * elf.c (elf_object_p, elf_core_file_p): Fix to use only a single + local, disposable, copy of the external form of section header + table and program header table entries. + +Thu Mar 26 16:59:58 1992 John Gilmore (gnu at cygnus.com) + + * Makefile.in: Set MINIMIZE back to 0 for a real release. + +Tue Mar 24 15:57:03 1992 K. Richard Pixley (rich@cygnus.com) + + * configure.in: config/irix4.m[ht], hosts/irix4.h: add support for + irix4. + +Mon Mar 23 22:37:34 1992 Stu Grossman (grossman at cygnus.com) + + * coff-msym.c (ecoff_swap_rfd_in): remove & for array ref. + +Tue Mar 17 14:12:25 1992 Per Bothner (bothner@rtl.cygnus.com) + + * bout.c (b_out_slurp_reloc_table): Use BFD_ASSERT macro, + not internal bfd_assert function (twice). + +Tue Mar 17 10:45:12 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * aout-target.h: change ar_max_namelen to 15 (the right value) + * coff-a29k, coffcode.h: more hangovers from the bfd_abs_section + change + +Mon Mar 16 14:57:22 1992 Steve Chamberlain (sac@rtl.cygnus.com) + + * archive.c (bfd_generic_archive_p): check for bout archives too. + * bout.c: make it work again. + +Sat Mar 14 17:30:40 1992 Fred Fish (fnf@cygnus.com) + + * elf.c (elf_corefile_note): Call bfd_xmalloc() instead of bare + malloc(). + * reloc.c (bfd_generic_get_relocated_section_contents): Call + bfd_xmalloc() instead of bare malloc(). + +Fri Mar 13 15:44:37 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: pass down MAKEINFO on info. + +Fri Mar 13 07:41:13 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * config/mt- now .mt, config/mh- now .mh. + host/h- now just . + * configure.in: reflect changes + +Thu Mar 12 11:15:02 1992 Per Bothner (bothner@cygnus.com) + + * libbfd-in.h (set_tdata): Make change of Feb 27 in the + actual source file, not just the generated libbfd.h. + +Sat Mar 7 10:33:41 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * coff-i960.c (icoff_little_vec): add COFF_SWAP_TABLE so we can run + gdb on little-endian 960 code. + * archive.c (compute_and_write_armap): indirect symbols should go + into the archive header too. + +Fri Mar 6 21:55:16 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: added check target. + +Thu Mar 5 23:51:42 1992 John Gilmore (gnu at cygnus.com) + + * coff-msym.c: Move this file from gdb/ecoff.c. It + handles byte-swapping for ECOFF (MIPS symbol) files. + * config/mh-decstation, config/mh-irix3: Add coff-msym.o + to the files built on MIPS-based hosts. + * Makefile.in: Add rule for coff-msym. + +Thu Mar 5 21:36:05 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: added clean-info target. MINIMIZE=1. + +Sun Mar 1 22:32:58 1992 Per Bothner (bothner@cygnus.com) + + * coff-rs6000.c: Move core file functions into separate + new file rs6000-core.c. This is needed because reading + core files depends on native include files that conflict + with ../include/coff/rs6000.h. + * config/mh-rs6000: Add rs6000-core.o to HDEPFILES. + +Thu Feb 27 22:19:55 1992 Per Bothner (bothner@cygnus.com) + + * aoutx.h (NAME(aout,print_symbol)): Don't print + symbol addresss for undefined symbols. + * coff-rs6000.c: Various updates (due to target- + independent changes). + * libbfd.h: Ditto (tdata field is now a union). + * hosts/h-sparc.h: Removed prototype for bogus function + 'emset' (presumably should have been 'memset' - which is there). + +Thu Feb 27 11:46:33 1992 John Gilmore (gnu at cygnus.com) + + * configure.in (mips-big-* target): Same is Iris. + +Thu Feb 27 09:24:56 1992 Steve Chamberlain (sac at thepub.cygnus.com) + + * aoutx.h (translate_from_native_sym_flags): when creating an + alias symbol, fill in the section as undefined, rather than + leaving it blank. If an output section can't be found for a + symbol, then don't core dump. + +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. + +Wed Feb 26 19:40:59 1992 Steve Chamberlain (sac at thepub.cygnus.com) + + * bfd.c: lint + * coff-h8300.c: fix stupid reloc subtraction bug + * coffcode.h (coff_swap_aux_out): only swap a tvndx by 2 bytes, + since that's how wide it is. (coff_slurp_symbol_table): always zero out + the symbol.flags and done_lineno fields. + +Tue Feb 25 14:29:24 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * coffcode.h (coff_write_symbol): write out the correct number of + auxents. + * cpu-h8300.c: fix disassembly bug + +Fri Feb 21 21:39:56 1992 John Gilmore (gnu at cygnus.com) + + * bfd-in.h (bfd_errmsg), coffcode.h (coff_swap_aux_in, + section_from_bfd_index), cpu-h8300.c (howto*_callback), + reloc.c, section.c (bfd_map_over_sections), targets.c + (bfd_target_list): Protolint. + * libbfd.h: Update to match a libbfd-in.h from a month ago. + +Fri Feb 21 10:57:54 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * coffcode.h (coff_swap_aux_in): lint, (coff_print_symbol): prints + out tagndx too. + * aoutx.h (swap_std_reloc_out, swap_ext_reloc_out): use the output + section of a symbol rather than the section of a reffed symbol to + determine the r_index of an emmitted reloc. + +Thu Feb 20 18:10:34 1992 Per Bothner (bothner at cygnus.com) + + * PORTING: New (preliminary) porting guide. + +Wed Feb 19 21:39:37 1992 John Gilmore (gnu at cygnus.com) + + * bout.c (callj_callback), coff-a29k.c (a29k_reloc), coff-m88k.c + (howto_hvrt16): lint. + +Mon Feb 17 12:02:17 1992 Per Bothner (bothner at cygnus.com) + + * hp300bsd.c (new), config/mt-hp300bsd: Make hp300bsd + a full configuration (with possible cross-development), + instead of using host-aout.c. + +Sun Feb 16 13:01:49 1992 Per Bothner (bothner at cygnus.com) + + * aout-target.h (MY(write_object_contents): + Set obj_reloc_entry_size (abfd). + * gen-aout.c: Change to emit a .c files, not a .h file. + +Thu Feb 13 20:11:47 1992 Fred Fish (fnf at cygnus.com) + + * elf.c (elf_slurp_symbol_table): Remove obsolete use of + BSF_ABSOLUTE and replace with bfd_abs_section reference. + +Thu Feb 13 17:22:44 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * coffcode.h (get_normalized_symtab): fixed bug where symbols + with more than one auxent can cause nasty core dumps. + + * coffcode.h, libcoff.c: added new fielded to coff_symbol_struct + "done_lineno" so that a symbol which appears twice in the symbol + table only gets it's linenumbers relocated once. Modifed + (coff_write_native_symbol) and (coff_make_empty_symbol) to make + use of it. + +Tue Feb 4 15:39:55 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * aoutx.h: (translate_from_native_sym_flags): fix constructor + stuff to use the New Order. + +Fri Jan 31 01:34:45 1992 Stu Grossman (grossman at cygnus.com) + + * ieee.c: Change type of envi[] to unsigned char. + + * configure.in: fix vax ultrix configuration. + + * elf.c (bfd_section_from_shdr): Deal with null return from + bfd_make_section(). (elf_object_p): Select endianess properly. + +Fri Jan 31 01:19:55 1992 John Gilmore (gnu at cygnus.com) + + * hosts/h-tahoe.h, h-vaxbsd.h: Fix stack in core files. + +Thu Jan 30 23:51:07 1992 John Gilmore (gnu at cygnus.com) + + * Makefile.in: host-aout.c doesn't depend on aout-params.h. + * aout-target.h: Use TARGET_BIG_ENDIAN_P to set up vector. + * host-aout.c: Don't use aout-params.h; configure these systems + in their xm files, not in a randomly generated file. + * hosts/h-hp300bsd.h, h-tahoe.h, h-vaxbsd.h, h-vaxult.h: + Specify byte order. + * hosts/h-vaxbsd.h: Define the form of exec and core files. + +Thu Jan 30 13:02:41 1992 Per Bothner (bothner at cygnus.com) + + * config/mt-tahoe, config/mt-vax: Change DEFAULT_VECTOR to + host_aout_vec here as well. + +Thu Jan 30 11:41:45 1992 Stu Grossman (grossman at cygnus.com) + + * host-aout.c: Change TARGETNAME to "a.out" to be compatible with + gdb. config/mt-hp300bsd: Change DEFAULT_VECTOR to host_aout_vec + to prevent undefined symbol. + +Thu Jan 30 07:26:53 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + Various lints found on PersSony + * aoutx.h: cast an enum + * coff-a29k.c: many ints in reloc structure turned to enum + * coffcode.h: more enums + * cpu-h8300.c: more enums + * opncls.c: more enums + +Thu Jan 30 01:19:56 1992 John Gilmore (gnu at cygnus.com) + + * configure.in: Make Tahoe configuration work again. + * bfd-in.h: Remove trailing comma from enum declaration. + * ieee.c: Can't put byte values >0x7F into a signed char. + +Tue Jan 28 21:10:51 1992 Fred Fish (fnf at cygnus.com) + + * Makefile.in: Add dependencies for various coff-*.o files. + + * elf.c: Remove extraneous paren from core_prpsinfo and + core_prpstatus macros, rename core_prpstatus to core_prstatus. + Replace references to old section "size" member with new + "_raw_size" member. Implement elf_make_empty_symbol, which + is now used. + +Tue Jan 28 14:51:40 1992 Stu Grossman (grossman at cygnus.com) + + * trad-core.c, bfd.c, ../include/bfd.h: Various fixes for PMAX + core reading. + +Tue Jan 28 10:46:32 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * coffcode.h (bfd_coff_relax_section): now static. + (bfd_coff_get_relocated_section_contents): various type lints. + +Mon Jan 27 19:44:08 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + New entry point in the transfer vector - bfd_relax_section. + + * aout-target.h: add to vector, call generic_relax + * bfd-in.h: add to vector + * bfd.c: add #define for vector + * bout.c: add to vector, call generic_relax + * coffcode.h: add to vector, also now has coff specific relax code + for the relaxable H8/300 relocs. Also clean up abs section cruft. + * elf.c: call generic_relax + * ieee.c: call new vector, clean up some bugs due to the creation + of bfd_abs_section + * libbfd.h: add bfd_generic_relax_section EXFUN + * oasys.c: call generic_relax + * reloc.c: implement generic_relax + * seclet.c: moved much of this into coffcode.h + * srec.c: call generic_relax + * targets.c: define new transfer vector + +Fri Jan 24 14:40:17 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * everything: now modified to use smaller reloc type. Self hosts + on sun3 & sun4. + +Sat Jan 18 17:00:16 1992 Fred Fish (fnf at cygnus.com) + + * config/mh-stratus, config/mt-i860-elf, hosts/h-stratus: + New files for stratus. + + * configure.in: Add configuration fragments for stratus. + +Wed Jan 15 10:02:43 1992 Fred Fish (fnf at cygnus.com) + + * aoutx.h (NAME(aout,find_nearest_line)): Declare various filename + variables as CONST since they are set to point to a const char + string. Fixes compiler complaints. + +Fri Jan 10 17:44:53 1992 Fred Fish (fnf at cygnus.com) + + * hosts/h-amix.h hosts/h-i386v4.h: Change abort() to a function + returning void. + +Fri Jan 10 14:33:32 1992 Per Bothner (bothner at cygnus.com) + + * aoutx.h (NAME(aout,find_nearest_line)): Recognize N_SOL + symbols, so that we can emit the correct file name even + if it's an include file. + +Thu Jan 2 16:43:34 1992 John Gilmore (gnu at cygnus.com) + + * coff-i960.c: Add COFF_SWAP_TABLE to little_vec as well as big_vec. + (Reported by john@labtam.labtam.oz.au (John Carey)). + +Wed Jan 1 04:23:06 1992 Fred Fish (fnf at cygnus.com) + + * elf.c: Change all '#if HAVE_PROCFS' to '#ifdef HAVE_PROCFS'. + + * config/mh-amix, config/mh-i386v4: Remove HDEFINES that was + being used to -DHAVE_PROCFS. + + * hosts/h-amix, hosts/h-i386v4: Add '#define HAVE_PROCFS'. Move + '#include "fopen-same.h"' to end of file to match other h-* files. + +Fri Dec 20 12:06:17 1991 Fred Fish (fnf at cygnus.com) + + * configure.in: Change svr4 references to sysv4. Add case + "unknown" for target vendor and infer some targets based + on the specified operating system. + +Wed Dec 18 17:17:59 1991 Stu Grossman (grossman at cygnus.com) + + * bfd-in.h, libaout.h: ANSIfy enums. + +Wed Dec 18 16:12:25 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + * archive.c (normalize): created version for VMS which removes the + VMS directory crap from the front and end of a filename, eg turn + [-.foo]bar.obj;123 into bar.obj + (bfd_construct_extended_name_table): now writes index into an + extended name table in decimal - the same base used to read an + extended name table. + +Wed Dec 18 14:40:39 1991 Per Bothner (bothner at cygnus.com) + + * aout-encap.c: Fix to use aout-target.h. + * aoutf1.h: Use standard MY_object_p and MY_callback + in aout-target.h. Remove target-specific versions. + * host-aout.c: Re-write to use aout-target.h. + * gen-aout.c: New files use with host-aout.c to generate + host-specific a.out-related parameters. + * Makefile.in: host-aout.o depends on aout-params.h, which is + generated by gen-aout. + * aout-target.h: Make a little more flexible. + * libaout.h, aout-target.h: Removed WORK_OUT_FILE_POSTIONS + macro. Instead, inline it in aout-target.h. + * newsos3.c: Define N_SHARED_LIB(x) as 0 to avoid + a gcc -Wall warning. + * archive.c: Add missing commas in DEFUN macro (2 places). + * elf.c, coffcode.h, aoutf1.h: Use ANSI functions instead of + Berkeley ones, now that libiberty has them: + bcopy->memcpy, bzero->memset, bcmp->memcmp. + * aoutx.h: Various touch-ups: Re-formatting, fix a cast, + remove unused variable. + +Tue Dec 17 19:48:59 1991 Fred Fish (fnf at cygnus.com) + + * elf.c (elf_core_file_matches_executable_p): Enclose corename + and execname inside HAVE_PROCFS ifdef since they are unused + when it is not defined. + +Mon Dec 16 12:00:10 1991 Fred Fish (fnf at cygnus.com) + + * elf.c: Flag all sections as either code or data. We can't + be sure what they are anyway, since ELF doesn't fit the + traditional model of text+data+bss very well. Add new local + function elf_read() to simplify code. Record entry point in + the bfd structure. + +Thu Dec 12 21:01:22 1991 John Gilmore (gnu at cygnus.com) + + * hosts/h-*.h: Configure fopen using ../include/fopen-*.h + rather than N copies of the same lines. + +Wed Dec 11 16:39:45 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + * cpu-h8300.c: disassemble branch displacements correctly + * coff-h8300.c: put reloc offsets out in 32bits + + * makefile.dos, configdj.bat: New files from DJ + * cache.c: fopen with new macros is needed for DOS. + * ieee.c: environ renamed to envi to stop an include file + conflict. + * opncls.c, coff-rs6000.c: more fopens with macros. + +Tue Dec 10 04:07:24 1991 K. Richard Pixley (rich at rtl.cygnus.com) + + * Makefile.in: infodir belongs in datadir. + +Sat Dec 7 16:39:23 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + * Makefile.in: fix where docdir lives + + * aoutx.h, archive.c, archures.c, bfd.c, cache.c, coff-m88k.c, + coffcode.h, core.c, ctor.c, elf.c, format.c, ieee.c, init.c, + libbfd.c, libbfd.h, libcoff.h, opncls.c, reloc.c, section.c, + srec.c, syms.c, targets.c : all new documentation and lint + removal. + + +Sat Dec 7 07:22:09 1991 John Gilmore (gnu at cygnus.com) + + * coffcode.h, srec.c: Lint. + +Fri Dec 6 22:58:48 1991 K. Richard Pixley (rich at rtl.cygnus.com) + + * Makefile.in: install using INSTALL_DATA, added standards.text + support. + + * configure.in: mark directory as target dependent. configure + nows works in objdir always so make file existence checks + against ${srcdir}. + +Thu Dec 5 22:46:19 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. + +Wed Dec 4 10:14:17 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + * aoutf1.h (sunos__object_p, sunos4_callback): moved the + computation of arch and machine type so it's worked out before + some_aout_object_p is called. + * aoutx.h: (some_aout_object_p): don't set arch and mach to + unknown. + * archures.c: add extra field 'section_align_power' to hold + default section alignment in object files. + * cpu-a29k.c, cpu-h8300.c, cpu-i386.c, cpu-i960.c, cpu-m68k.c, + cpu-m88k.c, cpu-mips.c, cpu-rs6000.c, cpu-sparc.c, cpu-vax.c: + initialize the new field. + * bout.c (b_out_callback): replace the text size, since aout + fries them. + * aoutx.h: Documentation in the new style + +Wed Dec 4 02:00:30 1991 John Gilmore (gnu at cygnus.com) + + * bfd.c (bfd_get_mtime): Don't cache mtime any more; only + use the saved value if mtime_set is already set (intended + for archive files, though apparently not used yet). + +Tue Dec 3 22:54:50 1991 John Gilmore (gnu at cygnus.com) + + * targets.c: Revise comments about how to configure the target + vector, to match reality. Remove mention of obsolete methods. + Remove long lists of capitalized macros that turn into the same + thing in lowercase. Normal vector simply lists all known + lowercase xvec names; all other cases are handled by SELECT_VECS. + + * config/mt-i386-coff: Set DEFAULT_VECTOR to real identifier, + not macro name. + + * config/mt-i960-{coff,bout}: Use SELECT_VECS to make a short + list of supported targets. + +Tue Dec 3 14:06:15 1991 Per Bothner (bothner at cygnus.com) + + * archive.c (bsd_write_armap): The pad byte sometimes added to + the string table in a __.SYMDEF member is now + counted as part of the size of the string table. + This is compatible with the old ranlib, as well as Sun's. + +Tue Dec 3 10:53:30 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + * srec.c: Rewrote to fix many bugs; now gets the record type + right, doesn't choke on input, sets the start address in an S9 and + fills in the filename on an S0. + +Sat Nov 30 21:19:15 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + * cpu-h8300.c: Add support for MEMIND addressing mode + + * coff-a29k.c: defined RELOC_PROCESSING to take the #ifdef out of + coffcode.h + * coffcode.h: use the new macro if available + + * elf.c (elf_corefile_note): cast malloc to avoid warning. + * Makefile.in: Fixed dependencies due to file rename + + * aout-encap.c, aoutf1.h, aoutx.h, archive.c, bout.c, coff-a29k.c, + coff-h8300.c, coff-i386.c, coff-i960.c, coff-m68k.c, coff-m88k.c, + coff-mips.c, coff-rs6000.c, cpu-h300.c, elf.c, i386aout.c, + newos3.c, stab-syms.c, syms.c: All these files have had their + #includes altered to point to the new places. + +Fri Nov 29 20:04:49 1991 Fred Fish (fnf at cygnus.com) + + * config/mh-i386v4, config/mh-i386-elf, hosts/h-i386v4.h: New files. + + * configure.in: Add vendor "ncr" as supported per-target vendor. + Add svr4 case for i386 per-host case. + + * elf.c (elf_object_p, elf_core_file_p): Add missing "break" to + ELFDATA2LSB cases. + +Fri Nov 29 12:16:51 1991 Per Bothner (bothner at cygnus.com) + + * syms.c (bfd_decode_symclass): Return 'A' + for symbols that are both absolute and global. + * archive.c (bfd_special_undocumented_glue): Return NULL + if bfd_ar_hdr_from_filesystem returns NULL. + +Tue Nov 26 09:10:55 1991 Steve Chamberlain (sac at cygnus.com) + + * Makefile.in: added coff-h8300 + * configure.in: now h8 is a coff target + * cpu-h8300.c: fix various disassembly problems + * libcoff.h: took out some code which has been #0ed for a long + time. + * targets.c: added h8 coff + * coff-a29k.c, coff-i386.c, coff-i960.c, coff-m68k.c, coff-m88k.c + added new macro RTYPE2HOWTO to take a load of #ifdefs out of + coffcode.h + * coffcode.h: Started to change the way machine dependencies are + handled, from the nest of #ifdefs to macros defined in the + including coff-.c + +Fri Nov 22 08:11:42 1991 John Gilmore (gnu at cygnus.com) + + * aoutx.h (some_aout_object_p): Set the `executable' bit + if the entry point is contained in the text segment, even if the + text segment is at location 0. + + * coff-mips.c, coffcode.h: Peter Schauer's patch to kludge in + nonstandard MIPS sections (.rdata, .sdata, etc). + + * aoutx.h, bfd.c, coffcode.h, ieee.c, oasys.c, targets.c: CONST lint. + * libbfd-in.h, libbfd.h, aoutx.h, coffcode.h, elf.c, libaout.h: + Rename ALIGN to BFD_ALIGN to avoid conflict with BSD . + * libbfd.c: Lint. + * host-aout.c, trad-core.c: Fix write_armap prototypes. Lint. + +Thu Nov 21 19:56:40 1991 Per Bothner (bothner at cygnus.com) + + * stab-syms.c, syms.c: Moved bfd_stab_name() and bfd_stab_names[] + from syms.c to new file stab-syms.c. Also, since GNU extended + type codes such as N_SETT are no longer in ../include/stab.def, + include them manually. + * stab-syms.c, aoutx.h: Renamed bfd_stab_name() and + bfd_stab_names[] to aout_stab_name() and aout_stab_names[]. + * libaout.h: Added prototype for aout_stab_name(). + * Makefile.in: Update Makefile for new stab-syms.[co]. + +Thu Nov 21 11:50:49 1991 John Gilmore (gnu at cygnus.com) + + * libaout.h (WORK_OUT_FILE_POSITIONS): One more try at this + rather complicated seeming problem. Eliminate LOGICAL_ versions, + just make N_XXX work by excluding the header from the text segment. + * aoutx.h: Fix comments to match. + +Tue Nov 19 18:49:01 1991 Per Bothner (bothner at cygnus.com) + + * libaout.h (WORK_OUT_FILE_POSITIONS): Use new LOGICAL_TXTADDR, + LOGICAL_TXTOFF, LOGICAL_TXTSIZE macros to figure out numbers + for the "logical" text segment (i.e. never consider the exec + header to be part of the text segment). This change is + needed for consistency with various other parts of bfd and ld. + * aoutx.h (NAME(aout,soe_aout_object_p)): Fix comment, + and move calculation of obj_textsec(abfd)->size to libaout.h. + * bfd-in.h: Removed bogus ';'. + + * Makefile.in: Add MINIMIZE flag to select lean + or bloated target_vector. + * targets.c: Use new MINIMIZE macro, and add trad_core if needed. + * newsos3.c: Fixes to ../include/aout64.h remove need + for special N_TXTOFF macro, but require N_HEADER_IN_TEXT. + +Mon Nov 18 12:00:59 1991 Per Bothner (bothner at cygnus.com) + + * aout-target.h, aoutf1.h, newsos3.c: Make aout-target.h + handle both little and big-endian targets, with little + the default unless TARGET_IS_BIG_ENDIAN_P is defined. + * host-aout.c: Add FIXME note. + +Sun Nov 17 13:29:39 1991 Per Bothner (bothner at cygnus.com) + + * targets.c: Make the default target_vector contain + just &DEFAULT_VECTOR. This makes executables a lot smaller. + Old behavior can be gotten by defining ALL_TARGETS. + * aoutf1.h, demo64.c, i386aout.c, newsos3.c, sunos.c: + Factored out common code into new file aout-target.h. + Saves a lot of duplicate code for a.out variants. + +Fri Nov 15 13:00:43 1991 Per Bothner (bothner at cygnus.com) + + Get 'make headers' to work when configured with +subdirs. + * Makefile.in: Add $(subdir) to docdir path. + * doc/Makefile.in (protos): Add $(srcdir) prefix + to name of sed scripts. + +Thu Nov 14 19:49:10 1991 Per Bothner (bothner at cygnus.com) + + * aoutx.h (NAME(aout,print_symbol)): Fix thinko. + * syms.c (bfd_stab_names): Turn on new GNU_EXTRA_STABS macro + to include names of N_SETT etc. + +Thu Nov 14 19:11:13 1991 Fred Fish (fnf at cygnus.com) + + * elf.c: Add minimal support for ELF symbol tables. Generates + canonical bfd symbol tables from ELF symbol tables. Change the + name of some functions from bfd_ to elf_. + + * syms.c: Trivial fix to comment to remove a redundant "to". + +Wed Nov 13 17:02:01 1991 John Gilmore (gnu at cygnus.com) + + * coff-{i386,m68k,m88k}.c: Change name of file format to standard + form that GDB recognizes as COFF. + +Wed Nov 13 09:09:41 1991 Steve Chamberlain (sac at cygnus.com) + + * ieee.c (ieee_object_p): cast NULL correctly. + * configure.in: added harris host + + * coff-a29k.c: Lots of changes, most from David Wood. + +Tue Nov 12 07:21:41 1991 John Gilmore (gnu at cygnus.com) + + * coff-m88k.c (coff_write_armap): Just #undef it. + +Mon Nov 11 20:30:18 1991 Steve Chamberlain (sac at cygnus.com) + + * Makefile.in: standardize on MINUS_G to disable debugging + * coff-m88k.c: create coff armaps instead of bsd ones. + * opncls.c (bfd_close_all_done), (bfd_close): Mask out random bits + when calling chmod. + +Mon Nov 11 19:07:32 1991 Fred Fish (fnf at cygnus.com) + + * elf.c: Additions to support ELF format core files. + * config/mh-amix: Add -DHAVE_PROCFS to HDEFINES, since host + has support for /proc (all the include files in particular). + +Mon Nov 11 18:36:47 1991 Per Bothner (bothner at cygnus.com) + + * aoutx.h (NAME(aout,find_nearest_line)): Handle the case + of two N_SO stabs, one for directory, and one for filename. + + * bfd-in.h (print_vma): Factor out duplicate definition. + + Exit a little more gracefully when malloc returns NULL. + * libbfd.c: New function bfd_xmalloc (malloc wrapper). + * opncls.c, syms.c, bout.c, aoutx.h: Replace malloc by bfd_xmalloc. + * libbfd.h: Rre-generated due to libbfd.c update. + +Sat Nov 9 13:45:01 1991 Fred Fish (fnf at cygnus.com) + + * config/mt-m68k-elf: Define DEFAULT_VECTOR as elf_big_vec. + + * elf.c (elf_object_p): Don't try to create a bfd section for + the first ELF section header. It is just a placeholder. + +Sat Nov 9 03:04:26 1991 John Gilmore (gnu at cygnus.com) + + * coff-rs6000.c, config/mh-rs6000: Make it work on archive and + core files, when compiling native. + * hosts/h-rs6000.h: Define FASCIST_FDOPEN for bfd_fdopenr. + + FIXME: The aoutf1.h change below needs to be reversed back + to the way it was. + +Thu Nov 7 11:03:55 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + * coffcode.h: Defined new macros [PUT|GET]LINENO_LNNO for + manipulation of lnno fields in lineno structs in a coff-.h + independent way. Override it in coff-.h to your favourite + number if you don't have a 16bit lnno field. (coff_swap_lineno_in) + (coff_swap_lineno_out): modified to use the new macros. + +Mon Nov 4 11:38:33 1991 Steve Chamberlain (sac at cygnus.com) + + * aoutf1.h (sunos4_callback): Now defaults to 68020 rather than + unknown arch when the magic number doesn't specify the + architecture, since some OSs (eg old sun3s) don't set the number, and + 020 is probably the right answer anyway. + +Sun Nov 3 12:07:08 1991 Per Bothner (bothner at cygnus.com) + + * hosts/h-news.h, hosts/h-rtbsd.h: + Get rid of MISSING_VFPRINTF, since libiberty provides one. + * bfd-in.h (bfd_print_symbol_type_hopw enum): Add new option + bfd_print_symbol_nm, for use by nm. + * aoutx.h (NAME(aout,print_symbol)): Add code for new + bfd_print_symbol_nm option, to print in nm format. + * coffcode.h (coff_print_symbol), ieee.c (ieee_print_symbol) + oasys.c (oasys_print_symbol): Provide stub implementations + for bfd_print_symbol_nm. + * syms.c: New function bfd_decode_symclass, used by nm printer. + New function bfd_stab_name to look up string name of stab code. + +Sat Nov 2 14:26:03 1991 Steve Chamberlain (steve at cygnus.com) + + * Makefile.in: Added ctor.c + * archures.c (bfd_default_arch_struct) added + bfd_default_reloc_type_lookup. + * coffcode.h: removed a load of #if 0ed code. + (coff_compute_file_section_positions): now works out the section + alignment and size correctly in all cases. + (coff_get_symtab): looks for constructor symbols and calls the + right function when they're found. (coff_canonicalize_reloc): + knows when a section is full of constructors and does the right + thing. + * cpu-m88k.c: Added default_reloc_type lookup to the architecture + description. + * libbfd-in.h: (bfd_default_reloc_type_lookup) defun added. + * libcoff.h: removed #if 0ed code + * reloc.c: (bfd_reloc_code_real_type) added BFD_RELOC_CTOR for + arch independent constructor relocation type. + (bfd_reloc_type_lookup): removed the comment "this will go away" + since it won't. (bfd_howto_32): stolen from 88k, this is a 32bit + reloc which is used when BFD_RELOC_CTOR falls through to give a + default 32bit reloc for constructors. + (bfd_default_reloc_type_lookup): added. + * aoutf1.h: fixed SEGMENT_SIZE typo. + +Thu Oct 31 18:23:06 1991 John Gilmore (gnu at cygnus.com) + + * coff-rs6000.c: Change name to "aixcoff-rs6000", to avoid + matching prefix "coff". + * coffcode.h (coff_swap_aux_in, coff_swap_aux_out): Handle + rs/6000 csect records. + +Sun Oct 27 16:56:58 1991 Steve Chamberlain (steve at cygnus.com) + + * coff-m88k.c, targets.c: change name of m88k_bcs to m88kbcs + * configure.in: add motorola delta88 cases + * libbfd.h, libbfd-in.h, archive.c, ieee.c, elf.c, srec.c: fix + write_armap prototype + * libbfd.c: add doc on bfd_write_bigendian_4byte_int + +Fri Oct 25 02:48:19 1991 John Gilmore (gnu at cygnus.com) + + * Rename COFF-related files in `coff-ARCH.c' form. + coff-a29k.c, coff-i386.c, coff-i960.c, coff-m68k.c, coff-m88k.c, + coff-mips.c, coff-rs6000.c to be exact. + + * Makefile.in: Only supply TARGET_DEFAULTS to targets.c, reducing + make output clutter. + * config/mt-*: Ditto. + +Thu Oct 24 22:40:07 1991 John Gilmore (gnu at cygnus.com) + + RS/6000 support, by Metin G. Ozisik, Mimi Phûông-Thåo Võ, and + John Gilmore. Archive support from Damon A. Permezel. + + * Makefile.in: Add cpu-rs6000.c and rs6000coff.c. + * configure.in: Add rs6000 case. + * targets.c: Add rs6000 vector. + * archures.c: Add rs6000, fix comment on romp. + * bfd-in.h (enum bfd_error): Add no_debug_section error. + * libcoff-in.h (struct coff_tdata): Remove unused string_table. + * bfd.c (bfd_errmsgs): Add no_debug_section error message. + * section.c (bfd_make_section): Return NULL on attempt to create + a section twice. + * coffcode.h (bfd_swap_reloc_in): Handle r_type and r_size. + (bfd_swap_aouthdr_in): Handle lots more members. + (make_a_section_from_file): If section has already been seen, + just return false rather than overwriting it. + (coff_real_object_p): Understand incoming magic numbers. + (coff_set_flags): Understand outgoing magic numbers. + (coff_compute_section_file_positions): outgoing aouthdr magic #. + (build_debug_section): Add fn for reading debug string section. + (get_normalized_symtab): Handle symbol names in debug string section. + Remove unused obj_string_table. + (coff_slurp_symbol_table): Handle rs6000-specific storage classes. + * aoutx.h (translate_from_native_sym_flags, N_SET*): Check for + existing section before making one. + * cpu-rs6000.c: New file. + * rs6000coff.c: New file. + +Thu Oct 24 02:03:24 1991 Fred Fish (fnf at cygnus.com) + + * elf.c: Add partial support for ELF format corefiles. Still needs + support for extracting registers from corefiles. + + * config/t-m68k-elf: Set DEFAULT_VECTOR to elf_big_vec. + + * config/{h-amix,h-dgux,h-irix3,h-ultra3}: For systems where + RANLIB is defined as echo, send the output to /dev/null to help + reduce clutter in the output from doing a make. + +Mon Oct 21 17:48:48 1991 John Gilmore (gnu at cygnus.com) + + * hosts/h-vaxult.h: Remove malloc/free decls covered in stdlib.h. + Fix HOST_PAGE_SIZE and HOST_SEGMENT_SIZE. From David Taylor. + +Mon Oct 21 09:34:11 1991 Steve Chamberlain (steve at rtl.cygnus.com) + + * coffcode.h (coff_compute_section_file_positions): make it pad + section size out if there are alignment restrictions so that the + image will be ok on a system where section positions are worked + out by accumulating sizes rather than from the section headers. + * targets.c (proto write_armap). Changed orl_count to unsigned. + * opncls.c (bfd_close_all_done). Added so that generative + programs like gas can close a bfd without causing bfd confusion. + * libbfd.h (changed becuase of protos) + * amdcoff.c: messed with the way that jmp displacements are + calcualated. This may not yet be totally correct. + * archive.c (coff_write_armap): rewrote the way that ranlibs are + written out. + * coffcode.h (fixup_symbol_value): now doesn't core dump if a non + abs symbol has no section (like a register symbol). + (coff_write_symbol) now zeros auxent before filling it up to help + with sensitive applications. + * libbfd.c (bfd_write_bigendian_4byte_int): added. + +Wed Oct 16 22:58:45 1991 John Gilmore (gnu at cygnus.com) + + * bfd.c: Make sure we don't get a macro strerror(). + * opncls.c (bfd_fdopenr): If FASCIST_FDOPEN, use "r", not "r+". + * trad-core.c (trad_unix_core_file_failing_command): Suppress + attempt to recover command, ifdef NO_CORE_COMMAND. + * hosts/h-tahoe.h: Add FASCIST_FDOPEN and NO_CORE_COMMAND; + revamp HOST_*, etc. + * hosts/h-i386v.h: Use , not , unlike POSIX. + +Wed Oct 16 12:43:49 1991 Per Bothner (bothner at cygnus.com) + + * archive.c (bsd_write_argmap): The size of the ranlib structures + should not include the size field itself. + * aoutx.h, libaout.h (NAME(aout, sizeof_headers)): Use + adata(abfd)->exec_bytes_size field instead of constant macro, + because aoutx.h compiles to a simple .o file shared by + all 32-bits a.out targets. + +Wed Oct 16 11:11:05 1991 John Gilmore (gnu at cygnus.com) + + * configure.in: Allow i386-sco-sysv. + * bout.c: Remove unused i960_align; lint dummy core file handlers. + * cpu-h8300.c: lint. + + * host-aout.c: New strategy. We use common code, include files, + and data structures to handle the file, but set a few parameters + from the host's config file (page size, text start addr, etc). + * libaout.h: Define HP BSD machine types. + * aoutf1.h: Handle reading a.outs with these types. + + * trad-core.c: Pass the u.u_ar0 value as the negative of the + virtual-memory-address of the .reg section. We can't just make a + section for "all the regs and nothing else" because only GDB knows + exactly where the regs are (scattered around the upage and stack). + Clean up memory allocation. Remove big- and little-endian + vectors, replace with single vector; this only runs on the host, + in host byte order. Replace byteswap routines with aborts in case + anyone calls them. + * targets.c: There's only one trad_core_vec now. + * aoutf1.h (sunos_core_file_p): VMA of .reg* now needs to be 0. + +Tue Oct 15 08:29:03 1991 John Gilmore (gnu at cygnus.com) + + * hosts/h-amix.h (free): Fix prototype. + + * aoutx.h: Don't use NULL as an integer, for braindead systems + that declare it as (void *)0. (From Peter Schauer.) + +Mon Oct 14 17:20:47 1991 Per Bothner (bothner at cygnus.com) + + * opncls.c (bfd_fdopenr): Add parentheses to avoid reported + problem with bad Ultrix system headers. + * aoutx.h (NAME(aout,set_section_contents)): Try to handle the + various kinds of alignments for the various kinds of + magic numbers. + +Mon Oct 14 14:23:10 1991 John Gilmore (gnu at cygnus.com) + + * doc/Makefile: Don't assume . is on the path (from James Clark). + +Fri Oct 11 22:45:14 1991 John Gilmore (gnu at cygnus.com) + + * Makefile.in: Avoid Sun Make VPATH bugs. + * targets.c: Declare trad_core vectors extern. + +Fri Oct 11 13:03:02 1991 Per Bothner (bothner at cygnus.com) + + * coffcode.h: Moved ALIGN macro to libbfd.h. Removed i960_align. + * libbfd.h: Moved ALIGN macro here. + * bout.c (b_out_callback): Replace i960_align by align_power. + + * libaout.h (struct aoutdata): Added fields page_size, + segment_size and exec_bytes_size. These help generic code + (in aoutx.h and libaout.h) to figure out where to align + the various segments in a demand paged file. + * libaout.h (WRITE_HEADER): Use new (struct aoutdata) fields + to decide if the exec header counts in a_text (text segment size). + Also, assume D_PAGED flag is set; don't set it here. + * bout.c (b_out_callback): Add initialization of + adata fields page_size, segment_size, and exec_bytes_size. + * host-aout.c (NAME(host_aout, callback) and + NAME(host_aout,mkobject): Ditto. + * i386aout.c (aout386_callback) and new aout386_mkobject): Ditto. + * newos3.c (newsos3_callback) and new newsos_mkobject): Ditto. + * aoutf1.c (sunos4_callback) and new sunos_mkobject): Ditto. + * aoutx.h (NAME(aout,some_aout_object_p)): Don't subtract + EXEC_BYTES_SIZE from the a_test size; this is only appropriate + for some systems (mainly sunos), so do it in the callback instead. + Same routine: Add stuff to the THIS_IS_ONLY_DOCUMENTATION comment. + * aoutx.h (NAME(aout,set_section_contents): Change the way + filepos and size of sections are carried out to support + older styles of demand paged executables. + + +Fri Oct 11 12:33:36 1991 Steve Chamberlain (steve at cygnus.com) + + * bfd-in.h: Added more macros to COFF_SWAP_TABLE. + * bfd.c: Added macros to enable gas to swap coff records. + * coffcode.h: Make the coff_swap_*_out routines return the number + of bytes swapped, and cleaned up their prototypes. + * configure.in: Added ebmon/coff support + * ecoff.c: Changed null definitions of coff_swap_*_out to conform + to new prototypes + * targets.c: Added new entry points for coff swapping + +Fri Oct 11 03:01:52 1991 John Gilmore (gnu at cygnus.com) + + Restructure configuration scheme for bfd, binutils, ld. + + * include/sys/h-*.h: Move to bfd/hosts/h-*.h. + * configure.in: Revise to symlink sysdep.h to hosts/h-xxx.h. + Change some config names to match other dirs. + * *.c: Include bfd.h before sysdep.h, so ansidecl and PROTO() + get defined first. + * Makefile.in: Use -I. to get sysdep.h. Remove refs to + ../include/sysdep.h. + * cpu-i960.c: Strncmp needed a length arg. + * ecoff.c: Don't ever call trad_unix_core_file_p from here. + * i386aout.c: Remove dead N_TXTOFF override. + * trad-core.c: Don't disable the whole file if SUN4_SYS. + * config/: Rename some config files to match up h-*.h names. + Remove all the HOST_SYS definitions from the config files. + * hosts/h-amix.h, h-i386v.h: Define POSIX_UTIME, not USG. + * hosts/h-hp9000.h: Remove USG comment. + * hosts/h-rs6000.h: Include for malloc. + * hosts/h-news.h, h-sparc-64.h: New config files that had + previously been kludged in the file. + +Thu Oct 10 17:54:08 1991 John Gilmore (gnu at cygnus.com) + + * config/*: trad-core support is HOST dependent, not target + dependent. Target config files only set DEFAULT_VECTOR and/or + other vector elements. Exception: when host-aout.c is in use, + in which case we're forced to assume we're native (hp, vax, + tahoe). Rename XDEPFILES to HDEPFILES. + * Makefile.in: Rename XDEPFILES. + * config/h-sun*: Don't force static linking. + * trad-core.c: Document how to use it nowadays. + * i386aout.c, newsos3.c: Clean up. + * i386coff.c: Allow 386 coff files to be used as core files too + (for reading core files from embedded systems). + +Tue Oct 8 15:30:39 1991 John Gilmore (gnu at cygnus.com) + + * Add i386aout.c for a.out support on the i386. + +Tue Oct 8 12:18:54 1991 Roland H. Pesch (pesch at cygnus.com) + + * reloc.c, section.c, syms.c, targets.c: correct info-node + structure in *doc* comments. + doc/Makefile: stop hiding complaints from makeinfo. + +Sun Oct 6 19:10:06 1991 John Gilmore (gnu at cygnus.com) + + * aoutx.h (...some_aout_object_p): Take a third parameter, + the internal_exec struct, and avoid ever looking at an + external_exec. All callers changed to read the entire + external_exec struct, swap and check its magic number, + swap in the whole structure, and pass the swapped-in version to + some_aout_object_p. + * bout.c: Bring into modern era. Use single _object_p routine + for big- aand little-endian. Provide internal and external + exec header structs. Use separate swap-in and swap-out routines. + + * libaout.h: Move struct internal_exec from ../include/aout64.h + to here. Add obj_symbol_entry_size to struct aoutdata. + * aoutx.h (...some_aout_object_p): Set obj_symbol_entry_size. + + * ../include/aout64.h: Change EXTERNAL_LIST_SIZE to + EXTERNAL_NLIST_SIZE. Callers changed. + +Fri Oct 4 18:18:46 1991 John Gilmore (gnu at cygnus.com) + + * bfd.c: Remove strerror() to libiberty. + + * elf.c: Remove elf_set_section_contents, use generic one. Lint. + * libbfd-in.h, libbfd.c: Add bfd_generic_set_section_contents. + * libbfd.c (bfd_generic_{get,set}_section_contents): Check that + last byte of transfer, not first byte, is within the section. + + * host-aout.c: Remove `BSD' archive support. Lint. + + * archures.c: Rename `struct bfd_arch_info_struct' to `struct + bfd_arch_info'. Rename `typedef bfd_arch_info_struct_type' to + `bfd_arch_info_type'. All uses changed. + * reloc.c: Rename `bfd_reloc_status_enum_type' to + `bfd_reloc_status_type'. Rename `bfd_reloc_code_enum_real_type' + to `bfd_reloc_code_real_type'. (This seems to be a misnomer, + it needs a better name.) All uses changed. + * targets.c: Rename `enum target_flavour_enum' to `enum + target_flavour', and remove the `_enum' from all of the enum + values themselves. All uses changed. + + * configure.in, config/h-i386mach: i386 mach host. + * config/t-i386-aout: Use host-aout.c. + + * trad-core.c: Give it its own xvec's to make it independent + of other file formats. + * ecoff.c, host-aout.c: Remove refs to trad-core. + * config/t-dec3100, t-hp300bsd, t-tahoe, t-vax: Define TRAD_CORE. + * targets.c: #ifdef TRAD_CORE, include it in the vector. + +Fri Oct 4 17:38:03 1991 Steve Chamberlain (steve at cygnus.com) + + * reloc.c: Extended NEWHOWTO macro + * ieee.c: Changed the way 8bit pcrel is done + * cpu-h8300.c: got the registers in the right order + +Thu Oct 3 19:39:55 1991 John Gilmore (gnu at cygnus.com) + + * bfd-in.h: enum boolean => enum bfd_boolean for SVR4. Gumby's + prediction is vindicated! + + * bfd-in.h, libbfd-in.h, doc/Makefile, doc/tolibbfd, doc/intobfd: + Remove refs to howto.c, since Steve forgot. + +Thu Oct 3 07:49:21 1991 Steve Chamberlain (steve at cygnus.com) + + * elf.c: took the abort out of set_arch_mach so that objdump -i will + still work. Now allows any architecture/machine to be set. + +Wed Oct 2 13:50:35 1991 Steve Chamberlain (steve at cygnus.com) + + * howto.c deleted and moved code to reloc.c + + * libbfd.h, libbfd-in.h removed $id stuff for real + + * cpu-h8300.c Made it match various different spellings of h8300. + + * archures.c: Took out the first char filter which made it only + look for a cpu/arch match when the first chars of supplied and + tested names were the same. + + * targets.c removed oasys stuff, pending someone to fix the bugs + in it. + + +Tue Oct 1 12:29:44 1991 John Gilmore (gnu at cygnus.com) + + * Makefile.in, configure.in, targets.c, elf.c: Add preliminary + ELF support good enough for GDB. + * configure.in, config/h-amix, config/t-m68k-elf: Handle + m68k-cbm-svr4 host and target. + * config/t-m68k-coff, t-m88k-coff, t-m88k-aout: Make files nonempty + so `diff' and `patch' can cope. + +Tue Oct 1 11:24:31 1991 Steve Chamberlain (steve at cygnus.com) + + * archures.c: removed texinfo error + + * init.c: added texinfo hooks, and removed initialization error + message. + + * libcoff-in.h, libbfd-in.h removed $id field so cvs can merge + without complaints. + +Tue Oct 1 05:02:53 1991 John Gilmore (gnu at cygnus.com) + + * cpu-i960.c: Avoid numerical count of initializers. + + Vax Ultrix changes from David Taylor : + * host-aout.c: Make little-endian vector really little-endian. + * configure.in: Separate vax and tahoe cases, handle ultrix. + * config/t-vax: Add trad-core.o. + * config/h-vaxult: New host system. + +Mon Sep 30 15:13:46 1991 Steve Chamberlain (steve at cygnus.com) + + * bfd-in.h VERSION, change version number to 0.18, this makes a + gap, but now is the same as the linker version number. + + * cpu-a29k.c, cpu-i386.c, cpu-m68k.c, cpu-mips.c, cpu-vax.c, + cpu-h8300.c, cpu-i960.c, cpu-m88k.c, cpu-sparc.c: added. These + files will eventually contain processor specific bits for bfd, + like strange relocation information and dis/assembly. So far only + the H8 has been even partially done. This work also ties in with + the change in handling architectures. + + * amdcoff.c: (a29k_reloc) fix error message. + + * aout-f1.h: (choose_reloc_size) now calls bfd_get_arch to + discover the architecture of the bfd. (sunos4_callback) calls the + function bfd_set_arch_mach rather than stuffing stuff directly + into the bfd. (sunos4_write_object_contents), changed names of + accessor functions. + + * aoutx.h: (set_arch_mach) now calls bfd_default_set_arch_mach to + setup the environment. + + * archive.c: (bfd_slurp_coff_armap) coff archives always have the + headers in big endian format, regardless of the endianess of the + host or target. + + * archures.c: totally changed. Now an architecture is represented + with a pointer to an info structure rather than an enumerated type + and a long. The old info is available as two elements in the + structure. Future enhancements to architecure support will + involve pointers to methods being placed into the info structure. + + * bfd.c: changed the definition of the bfd structure for the new + architecture stuff. + + * bout.c: (b_out_set_arch_mach) changed to use the new + architecture mechanism. + + * coffcode.h: (coff_set_arch_mach, coff_set_flags) changed to use + the new architecture mechanism. + + * configure.in: added h8 stuff. + + * ieee.c: too many changes to note. Now ieee files written with + bfd gas and ld can be read by gld and ieee only linkers and + simulators. + + * libbfd.c, libbfd.h: changed prototype of bfd_write. + + * newsos3.c: (newos3_callback) now calls bfd_set_arch_mach rather + than fixing the structure directly. + + * oasys.c: (oasys_object_p) now calls bfd_default_set_arch_mach rather + than fixing the structure directly. + + * opncls.c: (new_bfd) makes sure that bfd_init has been called + before opening a bfd. + + * srec.c: (srec_set_arch_mach) now calls bfd_default_set_arch_mach + rather than fixing the structure directly. + + * targets.c: (target_vector) now by defining SELECT_VECS (perhaps + in the t/hmake file) a user can select which backends they want + linked with bfd without changing the source. + + * init.c: new, looks after initializing modules. + + * howto.c: for future use, will allow an application to work out + what cookie to use as a handle on a relcoatio howto. + +Mon Sep 30 13:31:15 1991 John Gilmore (gnu at cygnus.com) + + * srec.c: Better error checking, partly from Peter Schauer. + (srec_object_p): Avoid assuming any file that starts with 'S' is + an S-record file! (Check for 3 uppercase-hex digits after it.) + (ISHEX): Define new macro for checking supposedly hex characters. + (pass_over): Treat as EOF any S-record line that: + * doesn't have hex in either size character + * produces a size larger than 0x7F + * has an unrecognized type number + +Thu Sep 26 15:27:29 1991 John Gilmore (gnu at cygnus.com) + + * aoutf1.h, aoutx.h, bout.c, coffcode.h, host-aout.c, oasys.c, + opncls.c: Lint (saber actually). + +Thu Sep 26 11:24:24 1991 Per Bothner (bothner at cygnus.com) + + * libaout.h (WRITE_HEADERS): Set header's a_text field always. + * newsos3.c: Fixed two types: newos3 -> newsos3. + * reloc.c (bfd_perform_relocation): Fix pc-relative relocation + to use correct segment. + +Mon Sep 23 18:24:34 1991 Per Bothner (bothner at cygnus.com) + + * aoutx.h (print_symbol): Handle missing symbol->name. + +Fri Sep 20 12:26:01 1991 Stu Grossman (grossman at cygnus.com) + + * aoutf1.h (swapcore_sparc): Change name of USRSTACK, fix comment + at top of routine. + +Tue Sep 17 17:23:49 1991 Stu Grossman (grossman at cygnus.com) + + * oasys.c, configure.in, config/h-irix3, config/t-irix3: + add sgi/irix support. + +Thu Sep 12 14:29:09 1991 John Gilmore (gnu at cygint.cygnus.com) + + Changes for the AMD 29000 Ultracomputer port from David Wood. + (wood@nyu.edu). + + * opncls.c (bfd_fdopenr): Handle NO_FCNTL. + + * Makefile.in: Make subdirs work by using $(INCDIR) in the + crude dependencies. + + * coffcode.h (coff_real_object_p): Pass information about the + current file's coff symbol format to BFD via the coff_data struct. + (coff_find_nearest_line): obj_icof => coff_data. + (coff_swap_sym_{in,out}): Check that SYMNMLEN == E_SYMNMLEN. + (coff_swap_aux_{in,out}): Check that FILNMLEN == E_FILNMLEN + and DIMNUM == E_DIMNUM. + * configure.in: Handle a29k-*-* hosts, and targets + a29k-*-coff, a29k-*-aout, and a29k-*-sym1. + * libcoff-in.h: Add local_n_btmask, local_n_btshft, + local_n_tmask, local_n_tshift, local_symesz, local_auxesz, + local_linesz to `coff_data' (tdata) struct. + (coff_data, coff_data_type, coff_tdata): Rename struct icofdata. + * config/h-ultra3: Handle a29k-*-* hosts as Ultracomputers. + +Thu Sep 12 14:07:22 1991 Roland H. Pesch (pesch at cygint.cygnus.com) + + * Makefile.in: $(MAKE) for make, $(docdir) for doc + * doc/Makefile: redundant dependencies for Sun-make VPATH bug + +Tue Sep 10 20:34:12 1991 John Gilmore (gnu at cygint.cygnus.com) + + * aoutf1.h (sunos4_core_file_p): Release the right storage in + error case. + (sunos4_core_file_matches_executable_p): Fix header comparison. + * aoutx.h: Avoid shifts of 32 bits, undefined in C. Lint. + * bout.c, icoff.c, ieee.c, libbfd.c, oasys.c: gcc -O -W lint. + +Wed Sep 4 00:44:52 1991 John Gilmore (gnu at cygint.cygnus.com) + + Allow GDB to patch object files. + + * aoutf1.h (sunos_core_file_p): Set SEC_HAS_CONTENTS on all sections. + * trad-core.h (trad_unix_core_file_p): Ditto. + * aoutx.h (aout_set_section_contents): On first output, check + abfd->direction and complain if erroneous. + + * Makefile.in: Add crude dependencies. + +Tue Sep 3 13:46:19 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * config/* aoutx.h configure* shortened all the h/tmake-xxxx + to h/t-xxxx files so that everything will work on System V. + +Fri Aug 23 13:51:06 1991 John Gilmore (gnu at cygint.cygnus.com) + + * aoutx.h: Add information on host-aout.c and how to configure + to use it, to the manual. + * configure.in: Tix typo. + * ecoff.c: If compiling for DEC3100, use trad_unix core files, + else dummy out the core file support. + * trad-core.c (trad_unix_core_file_p): If HOST_DATA_START_ADDR is + specified, use it to locate the data section. + * coffcode.h (coff_write_symbols): Declare buffer as bfd_bytes + rather than as chars (lint). + +Thu Aug 22 22:20:19 1991 Stu Grossman (grossman at cygint.cygnus.com) + + * aoutx.h, coffcode.h: saberized. + +Thu Aug 22 11:27:06 1991 Roland H. Pesch (pesch at cygint.cygnus.com) + + * bfd.texinfo: some cleanup, reincorporated more intro matter from + bfd.doc + bfd.c, targets.c: minor rewording of doc segments + + +Wed Aug 21 19:13:22 1991 John Gilmore (gnu at cygint.cygnus.com) + + * trad-core.c (trad_unix_core_file_p): Use HOST_TEXT_START_ADDR, + etc, rather than TEXT_START_ADDR. + * host-aout.c: Remove #if 0 around whole thing. + Update to modern (32/64-bit) a.out naming conventions. + Include a large chunk of ../include/a.out.gnu.h to get macros that + are not defined by the system include files. + (host_aout_{32,64}_write_object_contents): Use the WRITE_HEADERS + macro used by the other a.out implementations. + * Makefile.in: Give dependencies to OPTIONAL_BACKENDS. + +Wed Aug 21 14:33:06 1991 Roland H. Pesch (pesch at cygint.cygnus.com) + + * Makefile.in: use targets "bfd.dvi" and "bfd.ps" instead of + texdoc and psdoc; make these depend on generated .texi's + + * scanit, (new) unPROTO: turn PROTO macros into ANSI declarations in + doc + + * bfd.c, reloc.c, syms.c: minor spelling/wording fixes in doc + portions + + * Makefile.in, awkscan-ip, awkscan-p, intobfd, + libbfd.h, libcoff.h, tolibcoff; new bfd-in.h, libbfd-in.h, + libcoff-in.h: (a) use separate files for invariant parts of bfd.h, + libbfd.h, and libcoff.h; (b) in generated parts of same, use less + obtrusive marks indicating .c origins. + + * bfd.texinfo: generalize most references to linker + +Tue Aug 20 15:18:02 1991 Roland H. Pesch (pesch at cygint.cygnus.com) + + * Makefile.in: include core.p in PROTOS (building better bfd.h) + * archures.c: remove empty foo() definition (crept in at vn1.9) + +Mon Aug 19 13:48:22 1991 Roland H. Pesch (pesch at cygint.cygnus.com) + + * bfd.texinfo: use @setchapternewpage on instead of lots of + @page's; minor rephrasing in Introduction. + + * aoutx.h, archive.c, archures.c, bfd.c, bfd.texinfo, cache.c, + coffcode.h, core.c, format.c, ieee.c, libbfd.c, libbfd.h, libcoff.h, + oasys.c, opncls.c, reloc.c, section.c, syms.c, targets.c (documentation + segments): used BFD (caps) more consistently as a name in + discourse, fixed a few other minor typos and uses of fonts + + +Thu Aug 8 16:47:43 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * coffcode.h: fixed bug where string table size wasn't being swapped. + +Thu Aug 1 16:35:28 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * section.c: added SEC_CONSTRUCTOR_TEXT|DATA|BSS flags + + * syms.c: added BSF_CONSTRUCTOR, BSF_WARNING and BSF_INDIRECT + flags. (bfd_print_symbol_vandf) now knows what to do with the + above flags. + + * aoutx.h: made translate_from_native_sym_flags and + translate_to_native_sym_flags produce the above flags. + + +Wed Jul 31 09:53:52 1991 John Gilmore (gnu at cygint.cygnus.com) + + * all files: update copyright notices for GPL version 2. + Install header comments and attribute most modules to their + authors. BFD's name is now officially "Binary File Descriptor", + so remove any conflicting pejoratives. + archures.h: Consists solely of comments; remove it. + +Fri Jul 26 18:11:34 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * Makefile.in, bfd.c: Made it compile again. + +Fri Jul 19 08:17:09 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * newsos3.c, targets.c, coffcode.h: new patches from David Wood + + +Mon Jul 15 16:27:42 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * aoutf1.h archive.c bfd.c coffcode.h core.c ecoff.c ieee.c + bfd.texinfo oasys.c opncls.c reloc.c srec.c: More documentation on + lint fixes. + + * amdcoff.c bfd.texinfo Makefile.in : Folded in changes for amd + 29k coff by David Wood (wood@lab.ultra.nyu.edu). + +Thu Jul 4 09:53:16 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * Everything: created some new files, core.c format.c, reloc.c, + section.c and syms.c to split the functionality a bit better. + Cleaned up the rest of the files a bit, and added some + documentation. + + +Mon Jul 1 13:29:47 1991 David Wood (wood at david.ultra.nya.edu) + + * opncls.c, ../include/sys/h-sun3.h ../include/sys/h-sun4.h: fcntl + really takes 3 arguments, patched code and ammended prototypes. + +Fri Jun 14 13:19:40 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * ../include/bfd.h (struct bfd_target): Added new field + "align_power_min" which contains the minimum alignment for a + section. This is used in coff_new_section_hook. The field + insertion necessitates an update of all backends.. + + * aoutf1.h jump table field inserted + + * archive.c(snarf_ar_hdr)(bfd_slurp_coff_armap) can now parse dgux style extended + filenames too. + + * bout.c(b_out_squirt_out_relocs) fix to assertion tests. Jump + table field inserted. + + * coffcode.h(just about everything) Now patches up symbol tables + using a different mechanism. The Intel major bug has been fixed, + and the linker can self host on the Aviion and be debugged with + gdb. + + * ecoff.c: new include and jump table patch, i386coff.c: new + include and jump table patch, icoff.c: new include and jump table + patch, ieee.c: can now read archives containing ieee modules., + libcoff.h: added (combined_entry_type), libieee.h: uped max + sections to 20, m68kcoff.c: new include and jump table patch, + m88kbcs.c: new include and jump table patch, oasys.c: various bugs + fixed. opncls.c: added bfd_alloc_grow and bfd_alloc_finish. + srec.c: jump table patch. trad-code.c fixed #IF typeo + +Fri Jun 7 12:35:46 1991 Sean Fagan (sef at cygint.cygnus.com) + + * coffcode.h (coff_swap_aux_in): added else case to deal with + filenames less than 9 characters. + + +Thu Jun 6 18:27:38 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * ../include/oasys.h oasys.c (oasys_archive_p): fixed so it works + + * srec.c: now allows any number of sections to be created in a + file. Outputs addresses of the right length. + +Thu May 30 15:30:10 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * bfd.c (bfd_check_format): Fixed problem where when a defaulted + target didn't match, the format got set to the attempted match, + breaking a future test. + + *../include/i386coff.h : fixed typo in type field with size + + * i386coff.c icoff.c m88k-bcs.c ecoff.c ../include/bfd.h : Added + support in the jump table for the swapping routines exported to + gdb. Now gdb works with the 386. + +Tue May 28 17:21:43 1991 John Gilmore (gnu at cygint.cygnus.com) + + * Merge in changes from gdb-3.95 release. + Makefile.in: Allow hmake and tmake files to add OFILES. + aoutf1.h: + bfd.c: support specific targets as well as searching. When + searching, take default target in preference to others. + bfd.doc: typos + ieee.c, oasys.c: Avoid using the "tdata" macros left of assignment. + liba.out.h: Don't hard-code file offsets; use N_ macros for them. + libbfd.h: Support specific targets as well as searching. + opncls.c: Support specific targets as well as searching. + targets.c: Search is short-circuited if default target matches. + liboasys.c, libieee.c: Undo bothner changes that make macros + work to the left of assignment, but which depend on the + representations of different pointer types being the same. + +Fri May 24 18:56:52 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * i386coff.c: created. + * coffcode.h: added support for 386. + * Makefile.in: added support for 386. + * ../include/i386coff.h: created + +Wed May 22 07:26:38 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * coffcode.h: removed all put_x_ + * libbfd.c: Changed #ifdef __GNUC__ to #ifdef HOST_64_BIT, Added + DEFUNS + + +Tue May 21 08:58:58 1991 Steve Chamberlain (steve at cygint.cygnus.com) + (bothner) + * opncls.c: Changed obstack_chunk_alloc use xmalloc + +Mon May 20 17:12:17 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * everything: Removed sysdep.h from bfd.h and put back into files + from which it was split out. Now 64 bit version is built with a + -DHOST_64_BIT="long long" on the compile line. + +Fri May 17 19:35:26 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + Changed all the [get|put][name] routines to use [get|put]_[size + in bytes]. + + Put in support for 64 bit work. Now two versions of bfd may be + generated, according to the state of TARGET_64_BIT, one which is + 32 bit only, and one which is 64/32 bits. + Created new back end 'demo64' to test 64 bit functionality. + + Renamed some files to work on DOS. + + * archive.c: lint * bfd.c: prototypes and lint. * ecoff.c: added + 64bit transfer * icoff.c: added 64bit transfer * ieee.c: name + chage, 64 bit transfer. * liba.out.h: Split out common code from + sunos and newsos into liba.out. Name changes and prototype mods. * + libbfd.c: lint and prototypes, extra 64bit swaps. * libbfd.h: + prototypes for new functions. * libcoff.h: lint * libieee.h: make + work on DOS * liboasys.h: make work on DOS * m88k-bcs.c: Name + change and 64bit stuff.* newsos3.c: common code removed, new jump + table. * oasys.c: Name change * opncls.c: Portability fixes * + srec.c: Name changes * sunos.c: Removed comon code. * targets.c: + Added demo * aout32, aout64.c include aoutx.h * bout.c: used to + be called b.out.c * coffcode.h: used to be called coff-code.h, now + 64bit ized. * demo64.c: 64 bit a.out back end + +Thu May 16 16:02:07 1991 Steve Chamberlain (steve at cygint.cygnus.com) + from bothner + * libieee.h: Make ieee_data and ieee_ar_data macros usable + on LHS of assignment, even when using old compilers. + * liboasys.h: Ditto for oasys_data and oasys_ar_data. + * m68kcoff.c: Add enum-to-int casts to accomodate old compilers. + * newsos3.c: Fix definitions of SEGMENT_SIZE and TEXT_START_ADDR. + * opncls.c: Define S_IXUSR, S_IXGRP, S_IXOTH if undefined. + * targets.c: Add declaration of newsos3_vec. + +Mon May 13 10:03:29 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * aout.c: fixxed some of the problems with filepos calculation. + (swap_ext_reloc): fixed problem with creation of relocs. + (aout_set_section_contents): fixed filepos problem + + * coff-code.h: (swap_filehdr_in, swap_filehdr_out) add. + (swap_filehdr) delete. Changed all the usage of bfd_h_put_x. + (swap_aouthdr_in, swap_aouthdr_out) add. (swap_aouthdr) delete. + (coff_real_object_p) cleaned up, added MIPS. (coff_object_p) + cleaned up. (coff_write_object_contents) cleaned up. + + * ecoff.c: Totally different. Now supports ecoff fully. + + * icoff.c: fixed problems in relocation callout. + + * libcoff.h: (struct icofdata) removed hdr structure from tdata. + + * m68kcoff.c: updated target vector. + + * sunos.c: (choose_reloc_size) added: (sunos4_callback) calls + choose_reloc_size. (sunos4_write_object_contents) now calls + choose_reloc_size so outputs relocs correctly, also calculates the + size of the sections correctly. + + + +Fri May 10 16:58:53 1991 John Gilmore (gnu at cygint.cygnus.com) + + Merge Per Bothner's changes to modularize BFD a.out a bit. + + * libbfd.h, libbfd.c (bfd_generic_get_section_contents): Add. + * ieee.c: Cast enums to int before comparing them, for brain- + dead compilers. + * coff-code.h: Remove coff_get_section_contents, and use the + generic one instead. + + * aout.c: Derive new module from sunos.c, containing generic + support code for all kinds of a.out files. + + * sunos.c: Remove all code that goes in aout.c. Split out + machine dependent followup in sunos4_object_p into + sunos4_callback. Use JUMP_TABLE(aout) for the transver vector, + and redefine only the names we CHANGE, not all the names. Drop + the little-endian vector, and rename the vector as sunos4 rather + than generic. + + * b.out.c: Use aout.c routines for most of the work. Slight + changes for the new regime. Remove close_and_cleanup and + get_section_contents in favor of generics. New transfer vector + regime. + + * newsos.c: New support for Sony NEWS, another a.out format. + + * ecoff.c: Remove close_and_cleanup. New tvec regime. + * icoff.c, m88k-bcs.c: Add write_contents to tvec. + * ieee.c, oasys.c: Remove close_and_cleanup, add write_contents + to tvec. + * opncls.c (bfd_close): Call format-dependent write_contents + routine, if writing, before calling target-dependent + close_and_cleanup routine (which is now always generic, I think). + * srec.c: Use bfd_alloc instead of malloc. Remove + close_and_cleanup and move code from it to + srec_write_object_contents. Add write_contents to tvec. + * targets.c: Remove a.out little vector, replace a.out big + vector with SunOS vector. FIXME: Need Vax support again now. + + * libbfd.h: Add write_contents format-dependent-vector to the + bfd_target vector. Supply a generic close_and_cleanup routine. + * liba.out.h: Handle the new aout.c split. Add prototypes for + all routines defined in aout.c. Rename "sunos" things to "aout" + things. Add a few fields where needed for various formats. + * Makefile.in: Add aout.c and newsos.c. + + * archive.c, ieee.c, oasys.c: Lint. + +Fri May 10 12:34:48 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * ../include/bfd.h + changed forward declaration struct stat; to reduce warnings. Changed + comment on bfd_h__x. + + * ../include/m68kcoff.h, ../include/intel-coff.h, + ../include/m88k-bcs.h + Now there are two incarnations of relocs, linenos and syments. One for + internal digestion, and one full of char arrays for I/O. The original + names have gone to detect errors. + + * Makefile.in, m68kcoff.c, targets.c + Test new structure code with a 68k coff implementaion + + * coff-code.h, icoff.c, coffswap.c, libcoff.h + Fixed all the places where there were problems with the size and + alignments of structures on disk and structures in memory. #ifed out + all the code in coffswap.c, since it should be done using the target + swap routines now. + +Thu May 9 11:00:45 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * ieee.c (do_one, ieee_slurp_section_data): now supports the load + multiple reloc command. + + * sunos.c (sunos4_set_section_contents): Made it so that sections + are always padded to their alignment size. + +Sat May 4 15:49:43 1991 John Gilmore (gnu at cygint.cygnus.com) + + * archive.c, bfd.c, coff-code.h, opncls.c, sunos.c, trad-core.c: + Clean up types and such (saber C problems). + * ecoff.c: Clean up types and such. Remove routines that are + not used. Fix up reading and swapping of shorts from files. + + Notes on bfd-0.5.2-patch1a, from Per Bothner: + + * a.out.vax.c: Remove two bogus "static" from prototypes. + + * ecoff.c: Got rid of lots of non-working junk (that had + been copied directly from coff-code.h). + Updated to be consistent with updates to icoff.c and coff-code.h. + + * libbfd.h: Added definitions for S_IXUSR, S_IXGRP, and S_IXOTH + if they're missing (as they are in (BDS-4.3-based) NewsOS-3). + + * sunos.c (n_txtoff): (Re-)Add support for sony. This is a kludge, + but until the target_vector is automatically generated, + it's as good as any. Note that the text offset is the only + difference between NewsOS and SunOs (including magic numbers). + (Most of the sunos_* routines should to renamed bsd_* + and move to a bsd.c file. Then (and when the target_vector + is automatically generated) it might make sense to create + a separate Sony target.) + + * sysdep.h: Don't declare fread and fwrite. Causes trouble + on some systems, and doesn't help on others. + Similarly, only define X_OK if not already defined. + + * trad-core.c: Don't include sys/stat.h - at least + on NewsOS 3, it has already been included. + +Tue Mar 5 01:47:57 1991 John Gilmore (gnu at cygint.cygnus.com) + + * coff-code.h (bfd_coff_swap_sym, bfd_coff_swap_aux, + bfd_coff_swap_lineno): Export the routines that byte-swap COFF + symbol tables if necessary when reading them in, so gdb can use + them. Add "bfd_coff_" to the names so they won't conflict with + names in calling programs. FIXME-soon: if coff-code.h is + included in two BFD modules, this will cause duplicate + definitions; the routines should be exported to a separate, + common, module (probably along with a mess of other ones). + +Sat Mar 2 12:11:26 1991 John Gilmore (gnu at cygint.cygnus.com) + + Improve modtime support. + + * bfd.h: Add boolean mtime_set, and declare bfd_get_mtime. + Remove #define for bfd_get_mtime. Remove gratuitous comment. + * bfd.c (bfd_get_mtime): New fn, caches mtime, gets if not cached. + BUG: archive members still do not get correct mod times. + + Improve floating point support for core files. + + * sunos.c (struct core): Change void *fpa_dummy to double fp_stuff. + (sunos4_core_file_p): Create a second registers section in the + core file, called ".reg2", for the float registers. + +Thu Feb 14 15:49:06 1991 Gumby Vinayak Wallace (gumby at cygint.cygnus.com) + + * many changes to improve archive handling; found a logic flaw in + bfd_check_format which only just happened to work by cooncidence. + +Thu Feb 14 07:53:16 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * bfd.c (bfd_perform_relocation): fixed to use output_offsets + correctly. + + * bfd.h: changed type of udata in asymbol to void *, like it + should be. Added bfd_reloc_dangerous enum member. + + * coff-code.h: Fixed it so that internally generated symbols get + their values relocated correctly in all cases. Removed calls to + xmalloc. + + * icoff.c: Not understanding the destination symbol of a reloc is + not a failure any more, just 'dangerous'. This allows linking of + b.out and coff images. + + * sunos.c: Cleaned up the way that ZMAGIC section sizes are + calculated. + + +Tue Feb 12 13:25:46 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * sunos.c (translate_to_native_sym_flags): fixed + sym_pointer->n_value so that symbols on the way out get their + section relative values calculated correctly. + + * coff-code.h (mangle_symbols): fixed problem where tags were not + being relocated for structs, enums, unions. Also various lints. + +Mon Feb 11 19:52:26 1991 Gumby Vinayak Wallace (gumby at cygint.cygnus.com) + + * archive.c (get_elt_at_filepos): system_call_error returned + incorrectly. + +Sun Feb 10 23:18:40 1991 Gumby Vinayak Wallace (gumby at cygint.cygnus.com) + + * Resolve the use of no_error and system_call_error. + The bfd library itself now will never set bfd_error to + no_error. + + The code still needs to be combed to make sure all the error + codes are correct. I suspect they are not always set correctly. + + * The names of all the messages have _ prepended because the sun + bundled compiler can't distinguish from a macro which takes an + argument and the same identifier in a non-macro context. + + * The reason for the above being that entry points which used to + be trampoline functions are now just macros which expand to a + direct call through the bfd's xfer vector. + + * (../include/intel-coff.h) F_AR32WR: fix this constant. Why + must gas have its own version of everything (the gas version + had the correct value) + +Tue Feb 5 11:46:53 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + * b.out.c: Added patches supplied by chrisb@mipon2.intel.com to + properly support i960 architecture and output correct reloc stuff. + + * bfd.h: added prototype for bfd_printable_arch_mach, added + BFD_FAIL + + * coff-code.h: Applied patches from chrisb to support i960 + architecture, zero relocs and swap them correcly and conditionally + compiled the timestamp. + + * sunos.c: Made the default section alignment 2^3 so that doubles + are done properly. Fixed the same reloc bug that was in b.out.c + + * sysdep.h: Now compiles on a Posix box + +Wed Jan 30 21:36:26 1991 John Gilmore (gnu at cygint.cygnus.com) + + * icoff.c: Fix comment on big-endian version. + * coff-code.h: Make HAS_RELOC really work (it's backwards from + F_RELFLG). Set F_AR32WR in output files if little endian + architecture. + +Tue Jan 29 20:56:10 PST 1991 steve@cygnus.com + + * archures.c fixed =/== typo + + * sunos.c added architecture stuff for output. Fixed + bug where files where vma(data) != size(text) + were processed wrong. + + * coff-code.h added a lint cast + + * (../include/a.out.sun4.h) fixed it so zmagic + worked + +Mon Jan 28 19:15:29 PST 1991 steve@cygnus.com + + * archive.c removed loads of includes, and fixed bug where string + table didn't have a null at the end. + + * bfd.c fixed includes, added symbols argument to + canonicalize_reloc entry point. + + * libbfd.c fixed includes and added some lint patches. + + * targets.c added both sorts of intel coff. + + * b.out.c fixed included, changed was the canonical + relocs were done. + + * icoff.c added support for callj and big and little + enidian tables. + + * opncls.c added chmod+xing for files with EXEC_P set. + + * sunos.c fixed includes. Changed default section + alignement to words. Fixed relocation stuff to work with + new scheme + + * bfd.h various new types added, prototype for new + reloc calls, changed bfd->iostream to a void * + to including files don't need stdio.h. + + * libcoff.h added conversion table to tie relocs to + canonical symbols + + * sysdep.h created + + * coff-code.h fixed includes. Added code to support + big and little endian formats. Various lints. Better + processing of symbols. Changed reloc stuff to new + order + + * libbfd.h fixed includes + + +Mon Jan 21 11:53:51 PST 1991 steve@cygnus.com + + * bfd.h changed name of alignment entry in sec_struct to + alignment_power, because of conflicting uses within bfd. + Now it should be obvious that it's a 2**n alignment + specifier. Removed start_pad, end_alignment, block, minsize, + output_file_alignment, subsection_alignment and original_vma fields. + Added align_power() macro. Fixed bfd_section_alignment + acessor macros. Added bfd_symbol_same_target macro. + + * b.out.c (b_out_write_object_contents) fixed to use + new alignment member. Fixed (callj_callback) to use section + relative symbols properly. + + * sunos.c (sunos4_object_p) fixed to use new alignment_power. + Fixed (translate_from_native_sym_flags) to correctly make + symbols section relative. + + * bfd.c (bfd_errmsg) fixed various enum cast problems. + (bfd_make_section) took out initialization of obsolete members. + (bfd_print_symbol_vandf) added + + * opncls.c (bfd_create) created. + + * coff-code.h (coff_new_section_hook) took away refs + to obsolete members. (make_a_section_from_file) added + conversion between alignment types. (coff_symbol_from) + added. (coff_count_linenumbers) only counts linenumbers + if symbol is of coff-type. (coff_mangle_symbols) only + heavily mangles symbols if symbol is coff-type. + (coff_write_symbols) various lints. (coff_write_object_contents) + various lints and modification for alignment conversion. + (coff_slurp_relocs) fixed for use with new asection shape. + +Sat Jan 19 16:10:42 PST 1991 steve@cygnus.com + + * archive.c lots of lint + + * b.out.c added callj relocation support, upgrated reloc howto. + Fixed so that asymbol and reloc records are output + correctly. + + * bfd.c lots of lint, support for new bfd entry point + bfd_print_symbol. + + * bfd.h changed definition of asymbol to contain pointer to + owning bfd, removed target dependencies. + + * cache.c took out print statements, put in BFD_ASSERT calls. + + * coff-code.h various lints, corrected linenumber output + functionality. Added support for new style asymbols and + bfd_print_symbol. Fixed so that asymbol and + reloc records are handled correctly. Added timestamp. + + * icoff.c Added support for new howto shape. + + * liba.out.h Added support for new asymbol shape + + * libbfd.c various lints + + * libbfd.h various lints + + * libcoff.h added support for new asymbol shape. + + * sunos.c various lints. Added support for new asymbol shape + and bfd_print_symbol. + +Wed Jan 16 21:38:09 PST 1991 steve@cygnus.com + + * b.out.c removed prototype of sunos4_ennativate_symtab, lots of + pointer lint. Added support for callj relocation. Fixed bug where + the last 32 bytes of the text section were overwritten by data. Fixed bug + where archives of b.out didn't work due bfd_slurp_extended_name_table + returning false. + + * sunos.c added support for n_other field. Braced the howto table so + that it won't be affected by any lengthing of the howto struct typedef. + Various lints + + * bfd.h added support for n_other field, added special_function + reloc type, modified bfd_perform_relocation prototype. Added bfd_h_get_x + macros. + + * bfd.c upgraded bfd_perform_relocation, various lints. + +Wed Jan 16 01:55:53 1991 John Gilmore (gnu at rtl) + + * ChangeLog: Started ChangeLog for BFD. + * ToDo: Create file for suggestions. + + * Makefile: Support easy loading into Saber C. + Add dependencies for icoff.o and bcs88kcoff.o. + Rename coff.c to coff-code.h. Change callers. + + * bfd.c (bfd_check_format): Allow the check_format routines + to return the desired target vector, rather than just a Boolean. + bfd.h (bfd_check_format): Change function pointer return type. + archive.c (bfd_generic_archive_p): change callee. + b.out.c (b_out_little_object_p, b_out_big_object_p, + b_out_real_object_p): change callee. + libbfd.c (_bfd_dummy_target): Dummy routine replacing bfd_false + in check_format transfer vectors that need a filler. + libbfd.h (bfd_generic_archive_p, _bfd_dummy_target): Fix decls. + bcs88kcoff.c: change callee. + coff-code.h (coff_real_object_p, coff_big_object_p): change callee. + icoff.c: change callee. + sunos.c (sunos4_object_p, sunos4_core_file_p): change callee. + + * libbfd.c (zalloc): It should actually zero the storage! + This was commented out for some reason. + + * libbfd.h: Add malloc, xmalloc, memcpy, and fatal decls. + This is so callers can avoid which doesn't exist + on older systems. + + * bfd.c (map_over_sections): Add debugging code, since I + noticed the section count for sunos core files was bad, but only + GDB had detected the problem. + (bfd_set_section_lineno_size, bfd_set_section_linenos, + bfd_get_section_linenos): Remove obsolete functions. + (bfd_apply_relocations): Use longs, not ints, for the math. + + * bfd.h: Declare enum boolean and struct bfd_target as well + as typedefs for them. Remove obsolete + bfd_get_section_lineno_size. + + * cache.c: Make the "fdopen" support work. Keep better track + of how many files are open. Centralize the opening of files + and be sure bfd_open[rw] actually try to open the file. Evade + linked list initialization problems. + + * b.out.c, coff-code.h, opncls.c, sunos.c: lint. + + * coff-code.h (coff_slurp_symbol_table): Null-terminate symtab names. + + * cplus-dem.c: Delete file, since it is not part of BFD. + + * opncls.c (bfd_openr): Eliminate misplaced #if 0 code. + (bfd_openr, bfd_openw): Actually open the file, give error now. + + * sunos.c (sunos4_core_file_p): Set section count. + (sunos4_set_section_linenos, stab_names, fprint_name): Eliminiate + obsolete definitions. + (_write_symbol_table): Initialize counter. + (foop): Eliminate debugging code. + +Local Variables: +mode: indented-text +left-margin: 8 +fill-column: 74 +version-control: never +End: diff --git a/gnu/usr.bin/binutils/bfd/ChangeLog.2 b/gnu/usr.bin/binutils/bfd/ChangeLog.2 new file mode 100644 index 00000000000..dc8e16c2757 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/ChangeLog.2 @@ -0,0 +1,8830 @@ +Thu Aug 31 16:00:53 1995 steve chamberlain + + * Makefile.in: Update dependencies. + * aout-target.h (MY_bfd_print_private_bfd_data): New. + * bfd-in.h (PE STUFF): Deleted. + * bfd.c (tdata->pe_obj_data): New. + (bfd_print_private_bfd_data): New. + * coff-i386.c, coff-arm.c (coff_*-rtype_to_howto): Get image base from + new place. + * libcoff.h, libbfd.h, bfd-in2.h: Rebuilt. + * coffcode.h (pe_value): Delete + (coff_mkobject, coff_mkobject_hook): Conditionally build. + (coff_compute_section_file_positions): Look in new place. + (add_data_entry, fill_pe_header_info): Deleted. + (coff_write_object_contents): Remove PE stuff. + (coff_bfd_print_private_bfd_data): New. + * coffswap.h: Remove PE stuff. + * elfxx-target.h (bfd_elfNN_bfd_print_private_bfd_data): New. + * libbfd-in.h (_bfd_generic_bfd_print_private_bfd_data): New. + * libcoff-in.h (pe_data_type): New. + * libecoff.h (_bfd_ecoff_bfd_print_private_bfd_data): New. + * targets.c (_bfd_print_private_bfd_data): New. + * peicode.h: New file. + +Thu Aug 31 11:49:21 1995 Ian Lance Taylor + + * bfd-in.h: Add extern "C" if __cplusplus. + * bfd-in2.h: Rebuild. + + * coff-mips.c (mips_relocate_section): Don't convert a reloc + against an absolute symbol into a reloc against a section. + +Thu Aug 31 08:00:14 1995 steve chamberlain + + * coff-arm.c (coff_arm_reloc): Fix common size problem. + (i3coff_object_p): Delete. + +Wed Aug 30 20:41:27 1995 steve chamberlain + + * coff-arm.c (deletemeacoff_arm_reloc): Deleted. + (arm26): Not partial inplace. + * coffcode.h (coff_compute_section_file_positions): Don't + do page aligning if COFF_PAGE_SIZE isn't defined. + * coffswap.h (coff_swap_scnhdr_in): Update image base correctly. + +Tue Aug 29 13:50:21 1995 steve chamberlain + + * coffcode.h (coff_compute_section_file_positions): + Compile even if COFF_PAGE_SIZE isn't defined. + * cofflink.c (_bfd_coff_generate_reloc_section): Write + base file info as rvas. + * coff-arm.c (coff_rtype_to_howto): Deal with reloc 11. + * coffcode.h (coff_write_object_contents): Remove #if0ed code + Only remove empty sections in PE inmage files. + * libbfd.h, bfd-in2.h: regenerated. + * coff-arm.c (aoutarm_std_relo): New entry at 11. + (arm_reloc_type_lookup) : Understand type 11. + * coff-i386.c (howto_table): fix name of rva type. + (coff-i386_rtype_to_howto): Understand R_IMAGEBASE type. + * coffcode.h (sec_to_styp_flags): .edata is data. + (coff_compute_section_file_positions): Get page size right for PE. + Pagesize info is only valid in PE image files. + (fill_pe_header_info): Fix fields. + (coff_write_object_contents): Remove end_of_image calc. + (_bfd_coff_generate_reloc_section): Remove orphaned comment. + * coffswap.h (coff_swap_scnhdr_in): Don't always add IMAGE_BASE. + Swap in PE header. + (coff_swap_scnhdr_out): Setup PE flags correctly. + * reloc.c (BFD_RELOC_RVA): New field. + +Thu Aug 24 17:49:59 1995 Ian Lance Taylor (ian@cygnus.com) + + * cofflink.c (coff_link_input_bfd): Don't include line numbers for + a section if its output section has no contents. + +Wed Aug 23 16:48:52 1995 Ian Lance Taylor (ian@cygnus.com) + + * ecoff.c (_bfd_ecoff_slurp_symbolic_info): Add parentheses to FIX + expression to avoid compiler bug on HP-UX 9.01. + +Wed Aug 23 09:49:39 1995 Steve Chamberlain + + * coffcode.h (pe_value): Unansify. + +Mon Aug 21 17:49:28 1995 steve chamberlain + + * bfd-in.h (bfd_link_subsystem): Turn enum into #defines. + (bfd_link_pe_info_dval): New + (bfd_link_stack_heap): Renamed and massaged into bfd_link_pe_info. + * bfd-in2.h: rebuilt. + * bfd.c (NT_subsystem, NT_stack_heap): Deleted. + * coffcode.h (pe_value): New function. + (fill_pe_header_info): New function. + (coff_write_object_contents): Use new function. + (coff_write_object_contents): Initialze link_data if not set. + * cofflink.c (coff_final_link_info): Remove pe randomness. + (dores_com): Update info in bfd_link_pe_info_dval. + (process_embedded_commands): Use the bfd_link_pe_info_dval. + (_bfd_coff_final_link): Remove PE stuff, initialize + coff_data->link_info. + * coffswap.h (coff_swap_[aout|filehdr]_out): Use indirect PE pointer. + (coff_swap_scnhdr_out): Use real imagebase. + * libcoff-in.h (coff_data_type.link_info): New field. + +Mon Aug 21 11:10:32 1995 Ian Lance Taylor + + * linker.c (link_action): If an undefined reference follows an + undefined weak reference, change the type to undefined. + * elflink.h (elf_link_add_archive_symbols): Don't record an + undefined weak reference as defined, in case it turns into a real + undefined reference later in the same archive. + +Thu Aug 17 16:29:09 1995 Ken Raeburn + + * coff-sh.c (sh_relax_section): Cast value for used_by_bfd field + to PTR, not coff_section_tdata pointer, since PTR is the real type + of the field. + * cofflink.c (_bfd_coff_read_internal_relocs): Ditto. + +Thu Aug 17 14:44:26 1995 Ian Lance Taylor + + Add support for linking SPARC SunOS PIC compiled code. + * sunos.c (SPARC_PLT_PIC_WORD0): Define. + (SPARC_PLT_PIC_WORD1, SPARC_PLT_PIC_WORD2): Define. + (struct sunos_link_hash_entry): Add got_offset and plt_offset + fields. + (struct sunos_link_hash_table): Add dynamic_sections_created and + dynamic_sections_needed fields. + (sunos_link_hash_newfunc): Initialize new fields. + (sunos_link_hash_table_create): Initialize new fields. + (sunos_create_dynamic_sections): New static function, broken out + of sunos_add_dynamic_symbols. + (sunos_add_dynamic_symbols): Call sunos_create_dynamic_sections. + (sunos_add_one_symbol): Call sunos_create_dynamic_sections. + (bfd_sunos_size_dynamic_sections): Call sunos_scan_relocs before + checking whether we need to set up the dynamic link information. + Define __GLOBAL_OFFSET_TABLE if anything referred to it. + (sunos_scan_std_relocs): Call sunos_create_dynamic_sections. Use + plt_offset field; only put symbol in .plt if it is not defined by + a regular object. + (sunos_scan_ext_relocs): Likewise. Handle base relative relocs. + (sunos_scan_dynamic_symbol): Store dynobj in local variable. + (sunos_write_dynamic_symbol): Check plt_offset rather than + checking whether symbol is in .plt section. If symbol is defined + in a regular object file, use SPARC_PLT_PIC_WORD[012], and don't + add a JMP_TBL reloc. + (sunos_check_dynamic_reloc): Add contents and relocationp fields. + If plt_offset is set, redirect relocation to PLT. If this is a + base relative reloc, redirect relocation to GOT. Check + dynamic_sections_needed field rather than whether dynobj is set. + (sunos_finish_dynamic_link): Check dynamic_sections_needed field + rather than whether dynobj is set. Don't die if .need and .rules + sections were not created. + * aoutx.h (howto_table_ext): Mark PC10, PC22, and JMP_TBL entries + PC relative. Mark PC10 complain_overflow_dont. Mark PC22 and + JMP_TBL complain_overflow_signed. + (NAME(aout,final_link)): If info->shared is set, set DYNAMIC. + (aout_link_input_section_std): Call check_dynamic_reloc for all + relocs. Pass contents and &relocation. Don't warn about an + undefined symbol until check_dynamic_reloc has been called. Don't + warn about an undefined symbol for a base relative reloc. + (aout_link_input_section_ext): Likewise. For a base relative + reloc, always treat r_index as an index into the symbol table. + * libaout.h (struct aout_backend_data): Add contents and + relocation argument to check_dynamic_reloc entry point. + (struct aoutdata): Add local_got_offsets field. + +Wed Aug 16 01:03:07 1995 Ian Lance Taylor + + * elf32-i386.c (elf_i386_check_relocs): Fix bug in last change. + +Mon Aug 14 11:39:24 1995 Ian Lance Taylor + + * aoutx.h (NAME(aout,machine_type)): Handle a machine of + bfd_mach_sparc or bfd_mach_sparc64. + + * elflink.h (elf_link_add_object_symbols): If a symbol is a weak + definition, add it to the dynamic symbol table if any dynamic + object mentions it. If we do add it, make sure we add the + corresponding real symbol. + (elf_adjust_dynamic_symbol): Adjust a weak defined symbol which we + put in the dynamic symbol table, even if no regular object refers + to it. + * elf32-i386.c (elf_i386_check_relocs): When creating a shared + library, don't allocate space for a PC relative reloc against a + local symbol. + * elf32-m68k.c (elf_m68k_check_relocs): Likewise. + * elf32-sparc.c (elf32_sparc_check_relocs): Likewise. + * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Change assertion + to accept symbol with weakdef set. + * elf32-m68k.c (elf_m68k_adjust_dynamic_symbol): Likewise. + * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise. + * elf32-m68k.c (elf_m68k_relocate_section): When creating a shared + libary, don't copy over a PC relative reloc against a local + symbol. + * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. + +Sun Aug 13 00:40:58 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.h (R_HPPA_BEGIN_BRTAB): Define. + (R_HPPA_END_BRTAB): Likewise. + * som.c (som_write_fixups): Handle R_BEGIN_BRTAB and R_END_BRTAB. + +Thu Aug 10 15:53:29 1995 Ian Lance Taylor + + * coffswap.h (coff_swap_aux_in): Swap the array dimensions + whenever x_fcnary is not being used for something else, rather + than only for an array. + (coff_swap_aux_out): Likewise. + +Tue Aug 8 16:34:57 1995 steve chamberlain + + * cofflink.c (_bfd_coff_generic_relocate_section): Remove most + of special case stuff for PE. Now handled by relocs. + * coff-i386.c (coff_i386_reloc): Special case of PE type 7s. + (howto_table): Type 7 is dir32-rva. + +Tue Aug 8 10:15:43 1995 Jeffrey A. Law + + * configure.host: Recognize aix4 explicitly. + * rs6000-core.c (CORE_DATA_SIZE_FIELD): New macro to get a the size + of a core dump's data section. Provide alternate definition for aix4. + (SAVE_FIELD): Similarly for save state field (register info). + (STACK_END_ADDR): Provide definition suitable for aix4. + * config/{aix4.mh,aix4.mt}: New configuration files. + * hosts/aix4.h: Likewise. + +Mon Aug 7 23:03:21 1995 Ian Lance Taylor + + * som.c (som_bfd_copy_private_symbol_data): Cast initializations + to avoid warnings. + +Mon Aug 7 14:51:08 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_decode_symclass): Handle absolute symbols by checking + the SOM type (since they will rarely if ever be in the absolute + section). + +Wed Aug 6 09:12:50 1995 Doug Evans + + * archures.c (bfd_mach_sparc, bfd_mach_sparc64): Define. + * bfd-in2.h: Regenerated. + * cpu-sparc.c (sparc_arch_info): Renamed from arch_info_struct. + (sparc64_arch_info): New static variable. + (bfd_sparc_arch): Link in sparc64_arch_info. + * elf64-sparc.c (sparc64_elf_xxx): Renamed from elf64_xxx. + (sparc64_elf_object_p): New static function. + (elf_backend_object_p): Define. + * config/sparc64-elf.mt (SELECT_VECS): Add bfd_elf32_sparc_vec. + +Sat Aug 5 00:04:08 1995 Jeff Law (law@snake.cs.utah.edu) + + * som (som_get_reloc_upper_bound): Return -1 on error. Compute + return value with sizeof (arelent *), not sizeof (arelent). + +Wed Aug 2 12:32:21 1995 Ian Lance Taylor + + * elf.c (bfd_section_from_shdr): If the section pointed to by the + sh_link field of a reloc section is not a symbol table, and the + file contains a single symbol table, clobber the sh_link field of + the reloc section to point to the symbol table. + +Tue Aug 1 10:09:01 1995 Doug Evans + + * coff-arm.c (howto reloc ARM26): Change size from 3 to 2. + (howto reloc ARM26D): Likewise. + +Mon Jul 24 14:17:50 1995 Ian Lance Taylor + + * aoutx.h (NAME(aout,find_nearest_line)): Use the line just before + the offset, not the one just after. Break out of the loop after + finding a function past the offset, not merely when finding a + function with a line defined. + + * ecofflink.c (_bfd_ecoff_locate_line): When handling stabs: + correct setting of sym_ptr_end to consider symbols skipped when + setting sym_ptr; don't leave loop early unless an N_FUN is found + with a larger value. + + * coff-sh.c (sh_coff_howtos): Mark R_SH_PCDISP8BY2 and R_SH_PCDISP + as PC relative. Describe R_SH_IMM16. Add entries for + R_SH_SWITCH16, R_SH_SWITCH32, R_SH_USES, R_SH_COUNT, and + R_SH_ALIGN. + (SWAP_IN_RELOC_OFFSET): Define. + (SWAP_OUT_RELOC_OFFSET): Define. + (CALC_ADDEND): Define. + (sh_reloc): Change sym_value and addr to type bfd_vma. Skip reloc + types other than R_SH_IMM32 and R_SH_PCDISP on an external symbol. + (coff_bfd_relax_section): Define. + (coff_bfd_get_relocated_section_contents): Define. + (sh_relax_section): New static function. + (sh_relax_delete_bytes): New static function. + (sh_relocate_section): Handle R_SH_PCDISP on an external symbol. + (sh_coff_get_relocated_section_contents): New static function. + + * cofflink.c (coff_link_add_object_symbols): Call + _bfd_coff_get_external_symbols, not coff_link_get_symbols. Call + _bfd_coff_free_symbols, not coff_link_free_symbols. Call + _bfd_coff_read_string_table, not coff_read_string_table. + (coff_link_check_archive_element): Likewise. + (coff_link_input_bfd): Likewise. + (coff_link_get_symbols): Move to coffgen.c. + (coff_read_string_table): Likewise. + (coff_link_free_symbols): Likewise. + (_bfd_coff_internal_syment_name): New static function. + (coff_link_check_ar_symbols): Use _bfd_coff_internal_syment_name. + (coff_link_add_symbols): Likewise. + (coff_link_input_bfd): Likewise. + (_bfd_coff_generic_relocate_section): Likewise. + (_bfd_coff_read_internal_relocs): New function. + (coff_link_input_bfd): Use cached section contents if available. + Use _bfd_coff_read_internal_relocs. + * coffcode.h (coff_slurp_symbol_table): Don't call bfd_seek. + (coff_bfd_get_relocated_section_contents): Only define if not + already defined. + (coff_bfd_relax_section): Likewise. + * coffgen.c (build_string_table): Remove. + (_bfd_coff_get_external_symbols): New function, moved in from old + coff_link_get_symbols in cofflink.c. + (_bfd_coff_read_string_table): New function, moved in from old + coff_read_string_table in cofflink.c. + (_bfd_coff_free_symbols): New function, moved in frmo old + coff_link_free_symbols in cofflink.c. + (coff_get_normalized_symtab): Use _bfd_coff_get_external_symbols + rather than reading the symbols directly. To free them, call + _bfd_coff_free_symbols. Use _bfd_coff_read_string_table rather + than build_string_table. + * libcoff-in.h (obj_coff_keep_syms): Define. + (obj_coff_keep_strings): Define. + (coff_data_type): Add fields keep_syms and keep_strings. + (coff_section_tdata): Define new structure. + (coff_section_data): Define. + (_bfd_coff_get_external_symbols): Declare. + (_bfd_coff_read_string_table): Declare. + (_bfd_coff_free_symbols): Declare. + (_bfd_coff_read_internal_relocs): Declare. + * libcoff.h: Rebuild. + +Fri Jul 21 22:32:54 1995 Michael Meissner + + * elf32-ppc.c (ppc_elf_howto_raw): Add support for R_PPC_SDAREL + relocation. + (ppc_elf_reloc_type_lookup): Ditto. + (ppc_elf_got16_inner): Ditto. + (ppc_elf_relocate_section): Ditto. + +Thu Jul 20 19:19:06 1995 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (hppa_elf_gen_reloc_type): Add new (ignored) + argument. + * elf32-hppa.h: Corresponding change. + +Thu Jul 20 19:01:07 1995 Ken Raeburn + + * libaout.h (set_aout_section_data): New macro. + * sunos.c (sunos_scan_relocs): Use it. + + * aout-ns32k.c (MY_swap_std_reloc_out): Undef KEEPIT before + defining it. + +Thu Jul 20 13:48:00 1995 Fred Fish + + * hosts/i386v4.h (getgid, getuid): Change prototypes to be + compatible with Unixware 1.x and Unixware 2.x, and probably other + i386 svr4 versions as well. + +Thu Jul 20 13:41:21 1995 Ken Raeburn + + * targets.c (bfd_target_vector): Since armpe and armpei have been + split into big- and little-endian variants, list all of them, + instead of the now-nonexistant armpe[i]_vec. + +Thu Jul 20 00:06:39 1995 Ian Lance Taylor + + * elf.c (bfd_section_from_phdr): Set lma based on p_paddr. + (elf_fake_sections): Set sh_addr based on lma, not vma. + +Wed Jul 19 15:52:01 1995 Doug Evans + + * coff-arm.c (TARGET_LITTLE_SYM, TARGET_BIG_SYM): Replaces TARGET_SYM. + * configure.in (armpe_vec, armpei_vec): Add bi-endian support. + * configure: "regenerated". + * pe-arm.c (TARGET_LITTLE_SYM, TARGET_BIG_SYM): Replaces TARGET_SYM. + (TARGET_LITTLE_NAME, TARGET_BIG_NAME): Replaces TARGET_NAME. + * pei-arm.c (TARGET_LITTLE_SYM, TARGET_BIG_SYM): Replaces TARGET_SYM. + (TARGET_LITTLE_NAME, TARGET_BIG_NAME): Replaces TARGET_NAME. + * targets.c (armpe_vec, armpei_vec): Deleted. + (armpe_little_vec, armpe_big_vec, armpei_little_vec, armpei_big_vec): + Added. + * config/arm-pe.mt (DEFAULT_VECTOR): Default is armpe_little_vec. + (SELECT_VECS): Add bi-endian support. + +Wed Jul 19 10:47:25 1995 Ian Lance Taylor + + * coff-sh.c: Clean up and comment. + (r_imm32): Remove. + (sh_coff_howtos): New static array. + (SH_COFF_HOWTO_COUNT): Define. + (get_symbol_value): Make relocation bfd_vma rather than long. + (RTYPE2HOWTO): Rewrite to use sh_coff_howtos. + (coff_relocate_section): Define to sh_relocate_section. + (sh_relocate_section): New static function. + +Sat Jul 15 01:02:53 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * configure.host: Add support for generic m68k SVR4 host. + +Fri Jul 14 13:13:55 1995 Ian Lance Taylor + + * aoutx.h (KEEPIT): Change definition to udata.i. + (KEEPITTYPE): Remove. + (NAME(aout,reloc_type_lookup)): Add cases to the + extended reloc type switch: SPARC_GOT10, SPARC_GOT13, SPARC_GOT22, + SPARC_PC10, SPARC_PC22, SPARC_WPLT30. + (NAME(aout,swap_std_reloc_out)): Don't bother to use stoi when + retrieving KEEPIT value. + (NAME(aout,swap_ext_reloc_out)): Likewise. Also, only add in + output section VMA for section symbols, and check BSF_SECTION_SYM + to control whether to set r_extern to 1. + + * syms.c: Fix comments so that `make info' works. + + * elf32-mips.c (mips_elf_find_nearest_line): Set SEC_HAS_CONTENTS + in .mdebug section, in case backend linker has cleared it. + +Fri Jul 14 11:58:34 1995 Michael Meissner + + * elf32-ppc.c (ppc_elf_addr16_ha_inner): Rewrite to take just one + argument, the final relocated address. + (ppc_elf_addr16_ha_inner): Adjust ppc_elf_addr16_ha_inner caller. + (ppc_elf_relocate_section): Ditto. + +Thu Jul 13 17:22:03 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (hppa_som_gen_reloc_type): Choose a reasonable field + selector relocation for the difference of two symbols. + +Thu Jul 13 10:33:25 1995 Ian Lance Taylor + + * aoutx.h (NAME(aout,slurp_reloc_table)): Cast argument to size_t + for malloc. + * coff-mips.c (mips_relocate_section): Likewise, for memmove. + (mips_relax_section): Likewise, for malloc. + * cofflink.c (process_embedded_commands): Likewise. + (_bfd_coff_final_link): Likewise. + * ecoff.c (_bfd_ecoff_write_object_contents): Likewise. + (ecoff_final_link_debug_accumulate): Likewise. + (ecoff_indirect_link_order): Likewise, for memcpy and malloc. + (ecoff_reloc_link_order): Likewise, for malloc. + * ecofflink.c (ecoff_align_debug): Likewise, for memset. + (ecoff_write_symhdr): Likewise, for malloc. + * elf32-hppa.c (elf32_hppa_read_symext_info): Likewise. + * elf.c (assign_file_positions_except_relocs): Likewise, for + qsort. + * elf32-mips.c (mips_elf_read_ecoff_info): Likewise, for malloc. + * elfcode.h (elf_slurp_reloc_table): Likewise. + * elfcore.h (elf_corefile_note): Likewise. + * elflink.h (elf_link_add_object_symbols): Likewise. + (elf_link_read_relocs): Likewise. + (NAME(bfd_elf,size_dynamic_sections)): Likewise, for memset. + * i386linux.c (bfd_linux_size_dynamic_sections): Likewise. + * ieee.c (do_with_relocs): Likewise. + * linker.c (default_indirect_link_order): Likewise, for malloc. + * nlmcode.h (nlm_object_p): Likewise. + (nlm_write_object_contents): Likewise. + * oasys.c (oasys_set_section_contents): Likewise, for memcpy. + * reloc.c (bfd_generic_get_relocated_section_contents): Likewise, + for malloc. + * section.c (bfd_get_section_contents): Likewise, for memcpy. + * srec.c (srec_get_section_contents): Likewise. + (srec_set_section_contents): Likewise. + * sunos.c (bfd_sunos_size_dynamic_sections): Likewise, for + realloc and memset. + (sunos_scan_relocs): Likewise, for malloc. + (sunos_scan_dynamic_symbol): Likewise, for realloc. + * syms.c (_bfd_generic_read_minisymbols): Likewise, for malloc. + * versados.c (versados_get_section_contents): Likewise, for + memcpy. + + * libbfd.c (real_read): Add prototype. Change argument types from + int to size_t. + (bfd_read): Cast real_read argument to size_t, not int. + (bfd_write): Cast fwrite argument to size_t, not int. + + * elf64-gen.c (elf_info_to_howto): Fix definition for recent elf.c + changes. + + * configure.in: Fix typo: change {$enableval} to ${enableval}. + * configure: Rebuild. + + * Makefile.in (BFD32_BACKENDS): Add elflink.o. + + * targets.c (bfd_target): Add fields _read_minisymbols and + _minisymbol_to_symbol. + (BFD_JUMP_TABLE_SYMBOLS): Add _read_minisymbols and + _minisymbol_to_symbol. + (bfd_read_minisymbols): Define. + (bfd_minisymbol_to_symbol): Define. + * syms.c (_bfd_generic_read_minisymbols): Define. + (_bfd_generic_minisymbol_to_symbol): Define. + * libbfd-in.h (_bfd_nosymbols_read_minisymbols): Define. + (_bfd_nosymbols_minisymbol_to_symbol): Define. + (_bfd_generic_read_minisymbols): Declare. + (_bfd_generic_minisymbol_to_symbol): Declare. + * bfd-in2.h: Rebuild. + * libbfd.h: Rebuild. + * aoutx.h (MINISYM_THRESHOLD): Define. + (NAME(aout,read_minisymbols)): New function. + (NAME(aout,minisymbol_to_symbol)): New function. + * libaout.h (NAME(aout,read_minisymbols)): Declare. + (NAME(aout,minisymbol_to_symbol)): Declare. + * aout-target.h (MY_read_minisymbols): Define. + (MY_minisymbol_to_symbol): Define. + * All targets: Define read_minisymbols and minisymbol_to_symbol. + +Wed Jul 12 17:55:55 1995 Ken Raeburn + + * elflink.h (elf_link_add_object_symbols): Cast return value from + bfd_alloc. + + * elfcode.h (size_info): Don't use "&" before function names. + +Wed Jul 12 00:16:48 1995 Ken Raeburn + + * libelf.h (elf_backend_data): Use unsigned, not unsigned char, + for bitfields. + +Tue Jul 11 15:19:53 1995 Ian Lance Taylor + + * elf.c (bfd_section_from_shdr): In case SHT_REL[A], only get the + BFD section for the sh_link section if it is a SYMTAB section. + + * aoutx.h (NAME(aout,link_add_symbols)): Don't bother to check + that archives hold a.out objects. + * cf-i386lynx.c (coff_bfd_link_add_symbols): Don't define. + (lynx_link_add_symbols): Remove. + * cf-m68klynx.c (coff_bfd_link_add_symbols): Don't define. + (lynx_link_add_symbols): Remove. + * elflink.h (elf_bfd_link_add_symbols): Don't bother to check that + archives hold ELF objects. + + * archive.c (bfd_generic_archive_p): If the archive has a map, and + the target was defaulted, but the first object in the archive can + not be matched with that target, then return a bad format error. + + * elf64-sparc.c (elf_sparc_howto_table): Set howto for WDISP16 to + elf64_wdisp16_reloc. + (elf64_wdisp16_reloc): New static function. + (elf64_sparc_relocate_section): New static function. + (elf_backend_relocate_section): Define. + + * libelf.h (struct elf_size_info): Change type of last argument to + swap_symbol_out from char * to PTR. + (bfd_elf32_swap_symbol_out): Update declaration. + (bfd_elf64_swap_symbol_out): Likewise. + * elfcode.h (elf_swap_symbol_out): Change type of cdst from char * + to PTR. + * elf.c (swap_out_syms): Cast to PTR, not char *, when calling + swap_symbol_out routine. + * elflink.h (NAME(bfd_elf,size_dynamic_sections)): Likewise. + (elf_link_output_sym): Likewise. + (elf_link_output_extsym): Likewise. + * elf32-sparc.c (elf32_sparc_finish_dynamic_sections): Likewise. + +Tue Jul 11 12:29:49 1995 Rick Sladkey + + * elf.c (_bfd_elf_find_nearest_line): Handle the simple case where + there is no debugging information. + +Mon Jul 10 11:45:55 1995 Ken Raeburn + + * makefile.dos (OBJS): Add binary.o and tekhex.o. From DJ + Delorie. + +Mon Jul 10 11:09:58 1995 Ian Lance Taylor + + * linker.c (set_symbol_from_hash): bfd_link_hash_new case: Don't + abort; it can happen for constructor symbols when not building + constructors. + + * coff-i960.c (coff_i960_relocate): Correct typo: use ! on strcmp, + not on string. + * cofflink.c (_bfd_coff_generic_relocate_section): Remove unused + local i. + * coff-arm.c (coff_arm_rtype_to_howto): Don't declare. + (PCRELOFFSET): Define if not already defined. + * Makefile.in: Rebuild dependencies. + (BFD32_BACKENDS): Add coff-arm.o + (CFILES): Add coff-arm.c, pe-arm.c, pei-arm.c. + + * aoutx.h (NAME(aout,link_hash_table_create)): Allocate hash table + using bfd_alloc, not malloc. + * cofflink.c (_bfd_coff_link_hash_table_create): Likewise. + * ecoff.c (_bfd_ecoff_bfd_link_hash_table_create): Likewise. + * i386linux.c (linux_link_hash_table_create): Likewise. + * linker.c (_bfd_generic_link_hash_table_create): Likewise. + * sunos.c (sunos_link_hash_table_create): Likewise. + + Based on patches from Eric Youngdale : + * elflink.h (NAME(bfd_elf,size_dynamic_sections)): If -Bsymbolic, + output a DT_SYMBOLIC dynamic entry. + (elf_adjust_dynamic_symbol): If -Bsymbolic, don't require a PLT + entry for a locally defined symbol. + * elf32-i386.c (elf_i386_relocate_section): If -Bsymbolic, do warn + about undefined symbols, and fill in the GOT entry for a symbol + defined in a regular object file. + (elf_i386_finish_dynamic_symbol): If -Bsymbolic, output a RELATIVE + reloc rather than a GLOB_DAT reloc for a symbol defined in a + regular object file. + * elf32-m68k.c (elf_m68k_relocate_section): If -Bsymbolic, do warn + about undefined symbols, and fill in the GOT entry for a symbol + defined in a regular object file. + (elf_m68k_finish_dynamic_symbol): If -Bsymbolic, output a RELATIVE + reloc rather than a GLOB_DAT reloc for a symbol defined in a + regular object file. + * elf32-sparc.c (elf32_sparc_relocate_section): If -Bsymbolic, do + warn about undefined symbols, and fill in the GOT entry for a + symbol defined in a regular object file. + (elf32_sparc_finish_dynamic_symbol): If -Bsymbolic, output a + RELATIVE reloc rather than a GLOB_DAT reloc for a symbol defined + in a regular object file. + + * config/m68k-coff.mt (SELECT_VECS): Rename from SELECT_VECTORS. + Correct elements to be actual BFD vector names. + + * Makefile.in (Makefile): Don't depend upon @frags@. + (config.status): Depend upon @frags@. + +Fri Jul 7 17:36:44 1995 Ian Lance Taylor + + * coffgen.c (coff_renumber_symbols): Sort defined symbols that are + neither BSF_FUNCTION not BSF_NOT_AT_END just before undefined + symbols. + * coffcode.h (coff_slurp_symbol_table): Set BSF_FUNCTION as well + as BSF_NOT_AT_END. + +Fri Jul 7 17:16:15 1995 Ken Raeburn + + * Makefile.in (do_mostlyclean): Remove config.log. + (do_distclean): Remove config.cache. + +Thu Jul 6 14:37:43 1995 Ian Lance Taylor + + * elf32-i386.c (elf_i386_relocate_section): Revert May 24 patch. + Don't copy PC32 reloc against section into shared object. + + * Makefile.in: Rebuild dependencies. + (CFILES): Added elflink.c. + (Makefile): Depend upon config.status, not configure.in. + (config.status): New target; depend upon configure configure.host + and config.bfd. + +Wed Jul 5 20:17:14 1995 Ken Raeburn + + * elfcore.h, elflink.h, elfcode.h, elf.c, elflink.c: Moved some + primarily size-independent code from elfcode.h to elf.c and new + file elflink.c; moved out other core- or linker-related routines + into other new .h files for clarity. Renamed many routines to + start with bfd_elf or _bfd_elf. Added a structure of + size-dependent but target-independent info to elfcode.h. + * Makefile.in: Build elflink.o. Update dependencies. + * libelf.h: Updated some declarations. Added a definition for the + new structure in elfcode.h. Added more fields to elf backend data + structure. + * elfxx-target.h: Refer to the appropriate size-dependent info. + * elf32-*.c: Changed some function names. Moved common + create_dynamic_sections code from m68k, sparc, and i386 support + into elflink.c. Define some new macros to fill in new fields of + back end data. Also clean up some "gcc -Wall" warnings regarding + unused or uninitialized variables. + + * Makefile.in (BFD_LIBS): No, don't put elflink.o here. + * configure.in: Include it here whenever elf.o is specified. + +Wed Jul 5 10:31:47 1995 Ian Lance Taylor + + * elf32-mips.c (mips_elf_object_p): Unconditionally set + elf_bad_symtab, since sometimes the symbol table is messed up and + the last symbol is global. + + * ecoff.c (_bfd_ecoff_bfd_is_local_label): New function. + * libecoff.h (_bfd_ecoff_bfd_is_local_label): Declare. + * elf32-mips.c (mips_elf_is_local_label): New static function. + (bfd_elf32_bfd_is_local_label): Define. + + * configure.in: Use $ac_config_sub, not $configsub. + * configure: Likewise. + + Permit --enable-targets=ieee: + * config.bfd (*-*-ieee*): New target. + * config/ieee.mt: New file. + +Wed Jul 5 04:16:35 1995 Ken Raeburn + + * config/i386aix.mh (HDEFINES): Remove -DFASCIST_FDOPEN. + + Autoconfiscation: + * configure.in, Makefile.in, doc/Makefile.in: Switch from Cygnus + configure to autoconf ways of processing --enable arguments, + setting up symlinks, incorporating makefile fragments, printing + messages at configuration time, setting variables in Makefile. + Deleted some unused variables. Check for ranlib via autoconf. + For now, configure script removes doc/config.status. + * configure: New file. + * dep-in.sed: Use @SRCDIR@ instead of @srcdir@, so Makefile.in + line doesn't get broken by configure. + * doc/configure.in: Removed. + +Tue Jul 4 12:22:21 1995 Ian Lance Taylor + + * archive.c (_bfd_construct_extended_name_table): If + BFD_TRADITIONAL_FORMAT is set, limit the length of all file names + to ar_max_namelen. + (bfd_dont_truncate_arname): If BFD_TRADITIONAL_FORMAT is set, call + bfd_bsd_truncate_arname. + (_bfd_write_archive_contents): Revert June 1 change. + + * elfcode.h (NAME(bfd_elf,record_link_assignment)): Add provide + argument. + * bfd-in.h (bfd_elf32_record_link_assignment): Update prototype. + (bfd_elf64_record_link_assignment): Likewise. + * bfd-in2.h: Rebuild. + + * libelf.h (struct elf_link_hash_table): Add needed field. Remove + saw_needed field. + * elfcode.h (elf_link_add_object_symbols): If elf_dt_needed_name + is an empty string, don't make a DT_NEEDED entry in the output + file. Record all DT_NEEDED entries found in input dynamic + objects. + (elf_link_output_extsym): Don't check saw_needed when issuing + warnings. + * elf.c (_bfd_elf_link_hash_table_init): Initialize needed, not + saw_needed. + (bfd_elf_get_needed_list): New function. + * bfd-in.h (struct bfd_elf_link_needed_list): Define. + (bfd_elf_get_needed_list): Define. + * bfd-in2.h: Rebuild. + + * ecoff.c (_bfd_ecoff_find_nearest_line): Also initialize + find_buffer and fdrtab_len fields of newly allocated + find_line_info structure. + +Mon Jul 3 17:03:52 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (hppa_som_gen_reloc_type): New argument "sym_diff", + nonzero when we're generating relocations for an expression + using the difference of two symbols. All callers changed. + Handle difference of symbols for both R_HPPA and R_COMPLEX + cases. + (som_write_fixups): Handle R_COMP1, R_COMP2 and R_CODE_EXPR + fixups. + +Mon Jul 3 13:55:18 1995 Steve Chamberlain + + * config.bfd (win32): New configuration. + * configure.host (pe): Changed to i386win32. + * config/i386pe.mh: Deleted. + * config/i386win32.mh: New file. + +Mon Jul 3 11:30:45 1995 Ian Lance Taylor + + * ecoff.c (_bfd_ecoff_find_nearest_line): If we allocate + find_line_info, clear the fdrtab field. + + * targets.c (enum bfd_flavour): Add bfd_target_msdos_flavour here, + rather than in bfd-in2.h. + + * bfd.c (enum bfd_error): Define bfd_error_no_armap. + (bfd_errmsgs): Add string for bfd_error_no_armap. + * bfd-in2.h: Rebuild. + * ecoff.c (ecoff_link_add_archive_symbols): If an archive has no + armap, set bfd_error_no_armap rather than bfd_error_no_symbols. + * elfcode.h (elf_link_add_archive_symbols): Likewise. + * linker.c (_bfd_generic_link_add_archive_symbols): Likewise. + + * elfcode.h (elf_link_add_object_symbols): Permit common and + indirect symbols in weakdefs BFD_ASSERT. + * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Simplify + BFD_ASSERT to permit some legal, but odd, cases. + * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise. + * elf32-m68k.c (elf_m68k_adjust_dynamic_symbol): Likewise. + + * Makefile.in: Rebuild dependencies. + (BFD32_BACKENDS): Add versados.o. + (CFILES): Add pe-i386.c, pei-i386.c, and versados.c. + +Sun Jul 2 17:49:32 1995 Ian Lance Taylor + + * cofflink.c (_bfd_coff_generic_relocate_section): Cast base_file + to FILE * before using it. + * stab-syms.c: Revert yesterday's patch. + +Sat Jul 1 12:10:42 1995 Fred Fish + + * stab-syms.c (stdio.h): Include prior to libaout.h, which + includes bfdlink.h, which now uses FILE. + +Sat Jul 1 00:11:08 1995 Ken Raeburn + + * elfxx-target.h: New file. + + * libelf.h (struct elf_backend_data): Remove elf_64_p field. + * elfxx-target.h (elfNN_bed): Don't set it. + + * elf32-target.h, elf64-target.h: Deleted. + * Makefile.in (elf32-target.h, elf64-target.h): Build them from + elfxx-target.h. + +Fri Jun 30 16:07:18 1995 Steve Chamberlain + + * cofflink.c (_bfd_coff_generic_relocate_section): Compare + the full text of .reloc or .edata section names. + +Fri Jun 30 15:47:37 1995 Fred Fish + + * cofflink.c (_bfd_coff_generic_relocate_section): + Remove extra '+'. + +Thu Jun 29 17:24:52 1995 Steve Chamberlain + + * coff-h8300.c (COFF_LONG_FILENAMES): Define. + +Wed Jun 28 18:04:42 1995 Steve Chamberlain + + * Makefile.in: versados.o is now conditionally built. + * coffcode.h (add_data_entry): New function. + (coff_write_object_contents): Clean up. Calculate + data entries. + * cofflink.c (_bfd_coff_generic_relocate_section): + .reloc and .edata sections are IMAGE_BASED too. + If there's a base_file then write out base information. + * configure.host (i386-*-pe): New. + * syms.c (coff_section_type): Only scan prefixes. + * targets.c (bfd_target_vector): Versados is now conditionally + built. + * config/m68k-coff.mt: Build versados.o + * hosts/i386pe.h: New file. + +Mon Jun 26 13:53:49 1995 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hpa.c (elf32_hppa_relocate_section): Close comment before + R_PARISC_DPREL21L handling. + +Thu Jun 22 19:28:36 1995 Ken Raeburn + + Sun May 7 11:53:41 MDT 1995 Bryan Ford + + * config/i386-moss.mt: created. + +Thu Jun 22 08:56:10 1995 Steve Chamberlain + + * reloc.c (bfd_perform_relocation): Add case for -ve words. + +Wed Jun 21 13:13:49 1995 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (elf32_hppa_relocate_section): Don't try to apply a + relocation against an undefined symbols. + +Wed Jun 21 10:16:10 1995 Steve Chamberlain + + * versados.c: Second pass/rewrite. + +Mon Jun 19 08:40:45 1995 Steve Chamberlain + + * syms.c (coff_section_type): Compare only the front part + of a section name. + +Sat Jun 17 09:40:44 1995 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (elf32_hppa_size_stubs): Set the size of the stub + section if we get an error. + + * elf32-hppa.c (elf32_hppa_bfd_final_link_relocate): Don't mess + with the operands of an R_PARISC_DPREL21L relocation if the insn + is not "addil ,%r27". + +Fri Jun 16 15:04:47 1995 Stan Shebs + + * bfd-in.h (NT_subsystem, NT_stack_heap): Declare but don't + define. + * bfd-in2.h: Rebuilt. + * bfd.c (NT_subsystem, NT_stack_heap): Define. + +Fri Jun 16 00:07:25 1995 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (elf32_hppa_bfd_link_link_relocate): Use the right + type field (there are two!) when checking to see if $global$ is + defined. + +Thu Jun 15 14:03:47 1995 Stan Shebs + + * bfd-in.h, bfd-in2.h (bfd_boolean): Rename bfd_true, bfd_false + to bfd_tttrue, bfd_fffalse so as not to conflict with functions. + * coffswap.h (coff_swap_scnhdr_out): Remove version that was + hacked for MPW C. + * mpw-config.in: Set shell vars instead of pasting to makefile + for each configuration, edit coffswap.h to make MPW C not choke. + (i386-unknown-coff, sh-hitachi-hms): Recognize. + * mpw-make.in (BFD_LIBS): Add versados.c.o. + + * versados.c (versados_scan): Properly cast results from bfd_alloc. + +Wed Jun 14 15:27:32 1995 Steve Chamberlain + + * cofflink.c (process_embedded_commands): New function + reads and handles .drectve sections for PE. + (coff_link_input_bfd): Call new function if PE. + +Mon Jun 12 12:09:39 1995 Jeff Law (law@snake.cs.utah.edu) + + * bfd-in.h (bfd_set_section_vma): Case true to a boolean. + (bfd_set_cacheable): Likewise. + * bfd-in2.h: Rebuilt. + +Fri Jun 9 12:20:28 1995 Steve Chamberlain + + * elfcode.h (elf_sort_hdrs): Rewrite to be symmetrical. + +Fri Jun 9 12:49:00 1995 Jeff Law (law@snake.cs.utah.edu) + + * targets.c: Add copy_private_symbol_data and link_split_section + to the target vector. + * libbfd-in.h (_bfd_generic_bfd_copy_private_symbol_data): Define. + (_bfd_nolink_bfd_link_split_section): Likewise. + (bfd_generic_link_split_section): Declare. + * syms.c (bfd_copy_private_symbol_data): Define. + * linker.c (bf_link_split_section): Likewise. + * som.c (som_bfd_copy_private_symbol_data): New function + (som_bfd_link_split_section): Likewise. + * All other targets updated with default versions of new routines. + + * Take out my braindamaged bfd_true/bfd_false changes from earlier + today. Replace with just: + * bfd-in.h: (TRUE_FALSE_ALREADY_DEFINED): Define this if + compiling with g++-2.6 or later. + * bfd-in2.h: Rebuilt. + +Fri Jun 9 07:54:29 1995 Steve Chamberlain + + * versados.c (struct esd, get_4): Lint; use unsigned chars. + + * coff-i960.c (coff_i960_relocate): Compare output section names + when converting for vxworks. + +Wed Jun 7 19:01:30 1995 Ken Raeburn + + * elfcode.h (elf_fake_sections): Permit .scommon or COMMON + sections as random SHT_NOBITS sections, in case a linker script is + strange. + +Tue Jun 6 17:29:32 1995 Steve Chamberlain + + * bfd-in.h (NT_subsystem, NT_stack_heap): Moved from pe.h + * coff-i386.c (coff_i386_rtype_to_howto): Get PE relocs right. + * coffcode.h (coff_mkobject): Set pe tdata bit when using PE. + * cofflink.c (COFF_WITH_PE code): Test on obj_pe bit rather + than conditional compile. + * configure.in: Fix PE dependencies. + * libcoff-in.h (obj_pe): New. + (coff_tdata): Added pe entry. + * libcoff.h: Regenerated. + +Mon Jun 5 09:07:13 1995 Steve Chamberlain + + * coff-a29k.c (coff_a29k_adjust_symndx): Completely parenthesize + macro. + +Mon Jun 5 02:15:20 1995 Ken Raeburn + + Linker support for m68k-elf from Andreas Schwab + : + * elfcode.h (elf_link_add_object_symbols): Check for NULL when + looping through the symbol hashes. + (elf_bfd_final_link): When looking for _init and _fini don't use + the symbol if it is imported from another object. + * elf32-m68k.c: Relocation type changed from REL to RELA. Regular + and dynamic linking support functions added, similar to other elf + targets. + + * config.bfd (i[345]86-*-gnu*): Use ELF configuration. + +Fri Jun 2 18:54:59 1995 Steve Chamberlain + + * versados.c: New file. + * bfd-in2.h (struct _bfd): New field. + * bfd.c (struct _bfd): New field. + * configure.in (versados_vec): New field. + * targets.c (bfd_flavor): Added versados. + +Thu Jun 1 13:51:49 1995 Steve Chamberlain + + * coffcode.h (sec_to_styp_flags, styp_to_sec_flags, + coff_new_section_hook): Any section that starts ".stab" + is now marked as debugging. + +Thu Jun 1 16:15:16 1995 Ken Raeburn + + * archive.c (_bfd_write_archive_contents): Disable extended name + table until it can be made optional, so that native AR has half a + chance on SunOS and HP/UX. + + * linker.c (_bfd_generic_link_output_symbols, case + bfd_link_hash_indirect): Add cast to correct pointer types. + +Sat May 27 21:37:31 1995 J.T. Conklin + + * config.bfd (m68k-bull-sysv*): Added strip_underscore=yes. + (m68k-est-coff): Removed. target does not effect object format. + +Wed May 24 10:52:01 1995 Steve Chamberlain + + * linker.c (_bfd_generic_link_output_symbols): Cope with + indirect symbols. + + * elf32-i386.c (elf_i386_relocate_section): Give error + message when linking to a shared reloc which isn't there. + +Wed May 24 10:40:00 1995 Steve Chamberlain + + Support for ARM-PE. + + * Makefile.in, coffcode.h, config.bfd, configure.in, pe-arm.c, + pei-arm.c, coff-arm.c, reloc.c, targets.c, config/arm-pe.mt: + Support for ARM COFF/PE. + +Tue May 23 19:24:58 1995 Ken Raeburn + + * bfd.c (bfd_get_relocated_section_contents): Now a function, + tries calling routine from input bfd target vector for + bfd_indirect_link_order. Put a declaration into the header file. + * bfd-in2.h: Regenerated. + * elf32-mips.c (gprel16_with_gp): New function, split out from + mips_elf_gprel16_reloc. + (mips_elf_gprel16_reloc): Call it. If output bfd target vector + isn't elf flavoured, abort, since it's assumed to be elf in some + of this code, including the code that looks up the gp value. + (elf32_mips_get_relocated_section_contents): New function, + modified from bfd_generic_get_relocated_section_contents to deal + with passing gp to gprel16_with_gp. + (bfd_elf32_bfd_get_relocated_section_contents): New macro. + * elf32-target.h (bfd_elf32_bfd_get_relocated_section_contents): + Don't define if already defined. + +Tue May 23 15:58:15 1995 Jeff Law (law@snake.cs.utah.edu) + + * Makefile.in: Install bfdlink.h too. + +Sun May 21 22:25:09 1995 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (elf32_hppa_relocate_section): Handle undefined and + notsupported return codes from final_link_relocate (used when + $global$ is undefined or nonexistant). + (elf32_hppa_bfd_link_link_relocate): If $global$ exists, but is + not defined,then return bfd_reloc_undefined. + +Fri May 19 10:00:14 1995 Steve Chamberlain + + * coffswap.h: (IMAGE_BASE): Define to 0 if not. + +Thu May 18 04:24:01 1995 Ken Raeburn + + Wed May 10 14:28:16 1995 Richard Earnshaw (rearnsha@armltd.co.uk) + + * aoutx.h (aout_link_input_section_standard): If defined, call + MY_relocatable_reloc before doing a partial relocation. + + * aout-arm.c: (WRITE_HEADERS): Delete. + (NAME): Define version to override default in aoutx.h + (MY(howto_table)): Reformat. Alter some entries slightly. + (RELOC_ARM_BITS_NEG_{BIG,LITTLE}): Define. + (MY(reloc_howto), MY(put_reloc), MY(relocatable_reloc)): New functions. + (MY_reloc_howto, MY_put_reloc, MY_relocatable_reloc): Define. + (MY(fix_pcrel_26)): Renamed from aoutarm_fix_pcrel_26, return + bfd_reloc_ok not bfd_reloc_continue. + (MY(fix_pcrel_26_done)): Likewise. + (MY(bfd_reloc_type_lookup)): Renamed from aoutarm_reloc_type_lookup. + (MY_bfd_link_hash_table_create, MY_bfd_link_add_symbols, + MY_bfd_final_link): Delete. + (MY_swap_std_reloc_in, MY_swap_std_reloc_out, MY_get_section_contents): + Define. + (aoutx.h): Include it. + (MY(swap_std_reloc_{in,out})): New functions. + Use RELOC_ARM_BITS_NEG_{BIG,LITTLE} to extract negative reloc bit. + (aoutarm_squirt_out_relocs): Delete. + + From: David Taylor (dtaylor@armltd.co.uk) + * config/arm[lb]-aout.mt: New files. + * aout-arm.c: New file. + * config.bfd: Handle arm{,e[lb]}-*-aout + * configure.in: Add vetor for aout_arm_{big,little}_vec. + * reloc.c: New relocation types for the ARM. + * targets.c (aout_arm_{big,little}_vec): declare. + +Tue May 16 10:29:51 1995 Jim Kingdon + + * libbfd.c (bfd_stat): If bfd_cache_lookup returns an error, + return an error to the caller. Call bfd_set_error on errors. + +Tue May 16 14:44:45 1995 Ken Raeburn + + * libcoff-in.h (coff_renumber_symbols): Modified prototypes in + accordance with 11 May libcoff.h change. + +Thu May 11 16:43:14 1995 Steve Chamberlain + + tekhex.c (first_phase): Understand type 0 symbols. + (tekhex_write_object_contents): Fix typo in final record. + +Thu May 11 16:43:14 1995 Steve Chamberlain + + * coff-i960.c (optcall_callback): don't try and optimize + undefined refs. + (coff_write_relocs): Search for broken relocs on the way + out and fix them up. + (coff_renumber_symbols): Calculate and return index of + first undefined symbol. + (coff_write_object_contents): Call coff_renumber_symbols + and coff_write_relocs with the new args. + * libcoff.h: (coff_renumber_symbols, coff_renumber_symbols): + Modified prototypes. + +Thu May 11 16:43:14 1995 Steve Chamberlain + Tom Griest + + Initial support for PE format. + + * Makefile.in, targets.c, configure.in, config.bfd: + Add support for i386-*-winnt and i386-*-pe. + * archive.c (do_slurp_coff_armap): Understand NTPE format + archives. + (_bfd_slurp_extended_name_table): Turn \ in a filename + into /. + * bfd-in.h (bfd_link_subsystem, _bfd_link_stack_heap): New. + * coff-i386.c (howto_table): Conditionalize PCRELOFFSET. + * coffcode.h (IMAGE_BASE): New. + (coff_compute_section_file_positions): Throw away .junk + sections for PE, align symbols. + (coff_write_object_contents): Throw away .junk sections + for PE. Remember info on .idata and .rsrc sections. + Fill in the PE header. + (coff_slurp_symbol_table): PE uses C_SECTION class. + * cofflink.c (_bfd_coff_final_link): Keep PE info up to date. + (_bfd_coff_generic_relocate_section): Cope with PE relocs. + * coffswap.h (coff_swap_{aout/file/scn/sym}hdr_{in/out}): + New code for PE headers. + +Tue May 9 17:01:38 1995 Michael Meissner + + * config.bfd: Add little endian PowerPC support. + * configure.in: Ditto. + * targets.c: Ditto. + * config/ppcle-elf.mt: New file, for little endian PowerPC + support. + * config/ppc-elf.mt: Add little endian powerpc to the BFD + selection vectors. + * elf32-ppc.c (ppc_elf_merge_private_bfd_data): Complain if + linking a different endian object than we expect. + (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME): Define, to provide little + endian support. + +Tue May 2 16:32:24 1995 Jeff Law (law@snake.cs.utah.edu) + + * config.bfd (hppa*-*-lites*): Treat just like hppa*-*-*elf*. + +Tue Apr 25 19:38:43 1995 Ken Raeburn + + * coffgen.c (make_a_section_from_file): Initialize lma same as + vma. + +Tue Apr 25 11:03:21 1995 Jason Molenda (crash@phydeaux.cygnus.com) + + * hosts/std-host.h: #include ansidecl.h 'cause PTR is used in + std-host.h. + +Mon Apr 24 23:56:44 1995 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * hosts/i386linux.h (HAVE_PROCFS): Don't define it. Added lengthy + comment explaining why. + +Mon Apr 24 10:34:02 1995 Michael Meissner + + * hosts/i386linux.h (HAVE_PROCFS): If NO_PROCFS is defined, don't + define HAVE_PROCFS. + +Mon Apr 24 08:33:12 1995 Michael Meissner + + * elf32-ppc.c (ppc_elf_relocate_section): Do not continue + processing unknown symbols to prevent a cascade of errors. + +Fri Apr 21 12:48:48 1995 Ken Raeburn + + Patches from H.J. Lu for Linux ELF core file support. + * elfcode.h (elf_core_file_matches_executable_p) [HAVE_PROCFS]: + Use prpsinfo_t instead of struct prpsinfo, for consistency. + * hosts/i386linux.h (HAVE_PROCFS): Define. + +Thu Apr 20 09:07:39 1995 Steve Chamberlain + + * linker.c (link_action): Do the right thing when a undefined + strong symbol appears after an undefined weak symbol. + +Fri Apr 14 16:51:17 1995 Michael Meissner + + * elf32-ppc.c (ppc_elf_relocate_section): New function to relocate + a whole section for the linker, bypassing bfd_perform_relocation. + (ppc_elf_reloc_type_lookup): New function to map the BFD + enumeration code into a howto structure. + (ppc_elf_howto_raw): Rename from ppc_elf_howto_table. + (ppc_elf_howto_table): New array that maps PowerPC relocation + numbers to howto structures without a linear search. Change from + using bfd_elf_generic_reloc to use ppc_elf_std_reloc. + (ppc_elf_howto_init): Initialize ppc_elf_howto_table from + ppc_elf_howto_raw. + (ppc_elf_reloc_type_lookup): Use a case statement instead of a + loop. + (ppc_elf_std_reloc): Replacement for bfd_elf_generic_reloc. + (ppc_elf_unsupported_reloc): Print a real error message, instead + of calling abort. + (ppc_elf_addr16_ha_inner): Abstract getting adjustment from + ppc_elf_addr16_ha_reloc, so ppc_elf_relocate_section can use it + too. + (ppc_elf_addr16_ha_reloc): Call it. + (ppc_elf_got16_inner): Abstract getting adjustment from + ppc_elf_got16_reloc, so ppc_elf_relocate_section can use it too. + (ppc_elf_got16_reloc): Call it. + (ppc_elf_info_to_howto): Rename from powerpc_info_to_howto. + + * elfcode.h (elf_symbol_from_bfd_symbol): Omit space in debugging + output. + (elf_symbol_flags): Add debug function to decode flags so that + defining DEBUG to be 4 will compile again. + (elf_debug_section): Fix typo in debug output. + +Fri Apr 14 16:03:04 1995 Ken Raeburn + + * config.bfd: Add m68*-*-elf*. + * elf32-m68k.c: Filled out implementation, except for dynamic + linking support. + * reloc.c (enum bfd_reloc_code_real): Added *_GOT_PCREL, *_GOTOFF, + *_PLT_PCREL, *_PLTOFF, *_68K_* relocations for ELF. + * libbfd.h, bfd-in2.h: Regenerated. + +Thu Apr 13 14:28:04 1995 Torbjorn Granlund + + * coff-m68k.c (COFF_DEFAULT_SECTION_ALIGNMENT_POWER): Change from + 1 to 2. + (bfd_target): Change minimum section alignment from 1 to 2. + +Wed Apr 12 12:40:04 1995 Ken Raeburn + + * aoutx.h (machine_type, case bfd_arch_mips): Treat R8000 like + R6000 and R4000 for now. + +Tue Apr 4 12:28:25 1995 Stan Shebs + + * mpw-config.in: New file, MPW version of configure.in. + * mpw-make.in: New file, MPW version of Makefile.in. + * hosts/mpw.h: New file, MPW host definitions. + * ecoffswap.h (ecoff_swap_pdr_in, ecoff_swap_pdr_in) [MPW_C]: + Alternate versions without ECOFF_64 that chokes MPW C. + * coffswap.h (coff_swap_scnhdr_out): Add alternative version with + partly-expanded macros. + +Thu Mar 30 14:56:21 1995 Ian Lance Taylor + + * reloc.c (bfd_perform_relocation): Don't bother to check for + overflow if the symbol is undefined. + +Thu Mar 30 14:32:26 1995 H.J. Lu (hjl@nynexst.com) + + * config.bfd: Change linux to default to elf. Using + i[345]86-*-linuxaout will build a library which defaults to a.out. + * config/i386-laout.mt: Rename from old config/i386-linux.mt. + * config/i386-linux.mt: Rename from old config/i386-lelf.mt. + Comment out EXTRALIBS. + * config/i386-lelf.mt: Remove. + +Wed Mar 29 12:01:30 1995 Ian Lance Taylor + + * coff-i960.c (coff_i960_relocate): Cache the section symbol in + the used_by_bfd field of the section, to avoid looping for each + reloc. + + * cpu-h8500.c (arch_info_struct): Change name from "H8/300" to + "h8300" for consistency with other cpu-* files. + +Tue Mar 28 15:14:11 1995 Ian Lance Taylor + + * bout.c (b_out_canonicalize_reloc): Handle SEC_CONSTRUCTOR + sections. + (b_out_get_reloc_upper_bound): Likewise. + + * linker.c (generic_link_add_symbol_list): Skip constructor + symbols which the main linker code did not do anything with. + (_bfd_generic_link_output_symbols): Use udata.p if it is set, + rather than looking the symbol up in the hash table. Just pass + through constructor symbols for which udata.p is not set. If the + linker defined the symbol, clear the constructor flag. + +Tue Mar 21 10:50:32 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_set_reloc_info): Sign extend constants from + R_DATA_OVERRIDE fixups. + * libhppa.h (sign_extend): Renamed from sign_ext. Fix. + (low_sign_extend): Likewise. + +Mon Mar 20 22:39:10 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_slurp_symbol_table): Tighten test to determine + what symbols are section symbols. + +Sat Mar 18 01:54:45 1995 Ian Lance Taylor + + * elfcode.h (elf_bfd_link_add_symbols): An empty archive is OK. + +Fri Mar 17 16:29:02 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_copy_private_section_data): Just return true when + either the input or output section isn't attached to a SOM BFD. + (som_bfd_copy_private_bfd_data): Similarly for BFD private data. + +Fri Mar 17 11:50:34 1995 Ian Lance Taylor + + * elfcode.h (elf_link_add_object_symbols): Check whether a dynamic + object has already been included, and ignore it the second time. + +Wed Mar 15 11:56:40 1995 Ian Lance Taylor + + * elf32-sparc.c (elf_sparc_howto_table): Change R_SPARC_GOT13 from + complain_overflow_bitfield to complain_overflow_signed. + + * libelf.h (bfd_elf32__write_relocs): Don't declare. + (bfd_elf64__write_relocs): Don't declare. + +Tue Mar 14 05:54:33 1995 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * stab-syms.c (aout_stab_name): Moved aout_stab_names to be local + to this function. Recoded function to stop using table, to + improve performance (on i486-netbsd host). Left old version + intact under "#if 0" for further performance testing. + +Mon Mar 13 13:48:49 1995 Ian Lance Taylor + + * elfcode.h (write_relocs): Make static. Use PTR argument as a + pointer to a boolean variable set to true if something fails. + Cast to PTR rather than void *. + (sym_is_global): Rewrite for clarity. + (map_program_segments): If the program header size is too small, + call _bfd_error_handler and return failure rather than aborting. + (NAME(bfd_elf,write_object_contents)): Pass boolean variable when + calling write_relocs. + (elf_symbol_from_bfd_symbol): Use BFD_ASSERT rather than abort. + (struct elf_info_failed): Define. + (NAME(bfd_elf,size_dynamic_sections)): Declare variables in inner + blocks. Pass elf_info_failed structure when calling + elf_export_symbol and elf_adjust_dynamic_symbol. + (elf_export_symbol): Treat data argument as elf_info_failed rather + than bfd_link_info. Set failed field on error. + (elf_adjust_dynamic_symbol): Likewise. + (struct elf_finfo_failed): Define. + (elf_bfd_final_link): Pass elf_finfo_failed structure when calling + elf_link_output_extsym. Use BFD_ASSERT rather than abort. + (elf_link_output_extsym): Treat data argument as elf_finfo_failed + rather than elf_final_link_info. Set failed field on error. + (elf_link_input_bfd): Use BFD_ASSERT rather than abort. + (elf_reloc_link_order): Likewise. + + * elf32-sparc.c (elf32_sparc_size_dynamic_sections): Only write + out PLTRELSZ, PLTREL and JMPREL relocs if there is a .rela.plt + section. Solaris 2.4 apparently does not handle empty reloc + information correctly. + + * archive.c (bsd_write_armap): Cast getuid and getgid results to + long, and print with %ld. + + +Fri Mar 10 16:41:05 1995 Ian Lance Taylor + + * aoutx.h (translate_to_native_sym_flags): Always use the output + section if it is not NULL. + +Thu Mar 9 15:06:25 1995 Ian Lance Taylor + + * coffswap.h (coff_swap_scnhdr_out): If the line number count or + the reloc count does not fit, print an error and return 0. + * coffcode.h (coff_write_object_contents): Check return value of + coff_swap_scnhdr_out. + * ecoff.c (_bfd_ecoff_write_object_contents): Check return value + of bfd_coff_swap_scnhdr_out. + + * bfd.c: Include or , depending upon + ANSI_PROTOTYPES. + (bfd_error_handler_type): New global type. + (_bfd_error_program_name): New static variable. + (_bfd_default_error_handler): New static function. + (_bfd_error_handler): New BFD private global variable. + (bfd_set_error_handler): New globally visible function. + (bfd_set_error_program_name): New globally visible function. + * libbfd-in.h (_bfd_error_handler): Declare. + * bfd-in2.h, libbfd.h: Rebuild. + + * aoutx.h (NAME(aout,swap_ext_reloc_in)): Add symcount parameter, + and use it instead of bfd_get_symcount. Check r_index after + setting r_extern based on whether this is a base relative reloc. + (NAME(aout,swap_std_reloc_IN)): Add symcount parameter, and use it + instead of bfd_get_symcount. + (NAME(aout,slurp_reloc_table)): Pass bfd_get_symcount to reloc + swap routines. + * libaout.h (NAME(aout,swap_ext_reloc_in)): Add symcount parameter + to declaration. + (NAME(aout,swap_std_reloc_in)): Likewise. + * sunos.c (sunos_canonicalize_dynamic_reloc): Pass + info->dynsym_count to reloc swap routines. + * aout-ns32k.c (MY_swap_std_reloc_in): Add symcount parameter. + * hp300hpux.c (MY(swap_std_reloc_in)): Likewise. + (MY(slurp_reloc_table)): Pass bfd_get_symcount to reloc swap + routine. + * i386lynx.c (NAME(lynx,swap_ext_reloc_in)): Add symcount + parameter. + (NAME(lynx,swap_std_reloc_in)): Likewise. + (NAME(lynx,slurp_reloc_table)): Pass bfd_get_symcount to reloc + swap routines. + +Thu Mar 9 12:04:05 1995 Michael Meissner + + * bfd.c (bfd_merge_private_bfd_data): New function vector to be + called by the linker to merge any private bfd data of the input + files and the output file. Used by the PowerPC ELF support to + check whether -mrelocatable is used for all modules. + (bfd_set_private_flags): New function vector to be called by the + assembler to set private flags. Used by the PowerPC ELF support + to set that a particular object file was assembled with the + -mrelocatable option. + + * targets.c (BFD_JUMP_TABLE_COPY): Add intiialization of the + bfd_merge_private_bfd_data and bfd_set_private_flags function + vectors. + + * bfd-in2.h, libbfd-in.h: Rebuild with bfd.c and targets.c + changes. + + * elf32-ppc.c (ppc_elf_set_private_flags): New function to set the + ELF e_flags field. + (ppc_elf_copy_private_bfd_data): Copy the e_flags field from the + input file to the output file. + (ppc_elf_merge_private_bfd_data): Check for a mismatch between the + e_flags field of all of the linker input files. + + * libelf.h (elf_obj_tdata): Add ppc_flags_init field so that the + PowerPC support can check if compataible e_flags are present. + + * aout-target.h: Add NOP for the bfd_merge_private_bfd_data + and bfd_set_private_flags function vectors. + * coffcode.h: Ditto. + * elf32-target.h: Ditto. + * elf64-target.h: Ditto. + * libbfd.h: Ditto. + * libecoff.h: Ditto. + * som.c: Ditto. + +Wed Mar 8 00:53:54 1995 Ian Lance Taylor + + * cpu-mips.c (arch_info_struct): Add mips:8000 entry. + + * elfcode.h (swap_out_syms): Mark an undefined BSF_WEAK symbol as + STB_WEAK rather than STB_GLOBAL. + + +Tue Mar 7 12:23:47 1995 Ian Lance Taylor + + * coffcode.h (bfd_coff_backend_data): Add new field + _bfd_coff_adjust_symndx. + (bfd_coff_adjust_symndx): Define. + (coff_adjust_symndx): Define as NULL if not already defined. + (bfd_coff_std_swap_table): Initialize new field to + coff_adjust_symndx. + * cofflink.c (coff_link_input_bfd): Call coff_adjust_symndx if it + is defined. + * coff-a29k.c (coff_a29k_adjust_symndx): New static function. + (coff_adjust_symndx): Define before including coffcode.h. + * libcoff.h: Rebuild. + + * format.c (bfd_check_format_matches): Skip binary_vec when + searching through bfd_target_vector. + + * elfcode.h (elf_sort_hdrs): Check SHT_NOBITS before checking + sh_size. + +Mon Mar 6 23:31:36 1995 Doug Evans + + * elfcode.h (elf_sort_hdrs): Keep SHT_NOBITS sections after + !SHT_NOBITS ones. + +Mon Mar 6 09:53:08 1995 Jeff Law (law@snake.cs.utah.edu) + + * cpu-hppa.c (arch_info_struct): Support both PA1.0 and PA1.1 + machine types. + (bfd_hppa_arch): Link in both PA1.0 and PA1.1 architecture info + structures. + * libhppa.h (enum pa_arch): New enumeration to describe the + different variants of the PA architecture. + * som.c (som_object_setup): Use new enumeration to set machine + type. + (som_finish_writing): If the machine type is PA1.1, then use the + PA1.1 machine identifier in the output file. + +Thu Mar 2 15:58:24 1995 Ian Lance Taylor + + * aoutx.h (NAME(aout,swap_ext_reloc_in)): Treat the index of a + base relative reloc as an index into the symbol table, regardless + of the setting of r_extern. + (NAME(aout,swap_std_reloc_in)): Likewise. + + * aoutx.h (NAME(aout,set_section_contents)): Double check that the + caller is writing to a valid section. + +Thu Mar 2 14:37:57 1995 Bryan Ford + + * binary.c: Add support for reading binary files. Loads the raw + contents of the file into a data section and wraps some symbols + around it. The symbols `_binary__start' and + `_binary__end' indicate the start and end of the data, + while `_binary__size' is an absolute symbol whose value + is the size of the data. is the name of the binary + input file, with all non-alphanumeric characters converted to + underscores. + + * archures.c (bfd_arch_get_compatible): Assume users knows what + they're doing if one of the architectures is bfd_arch_unknown. + +Wed Mar 1 17:30:46 1995 Michael Meissner + + * elf32-ppc.c (elf_powerpc_howto_table): For relocation + R_PPC_GOT16, change complain_on_overflow to be + complain_overflow_signed. + +Wed Mar 1 11:52:55 1995 Jason Molenda + + * configure.host: Recognize powerpc-*-aix*. + +Wed Mar 1 11:57:39 1995 Ian Lance Taylor + + * coff-i960.c (COFF_PAGE_SIZE): Define. + + * configure.in: Rewrite output of TDEFAULTS to avoid relying on + semantics of single quotes in parameter substitution. + +Tue Feb 28 12:53:09 1995 Ian Lance Taylor + + * elfcode.h (elf_sort_hdrs): Sort empty sections before non-empty + sections, if they have the same VMA. + + * config.bfd (i[345]86-*-linuxelf*): New target. Use i386-lelf. + (i[345]86-*-gnuelf*): New target. Use i386-gelf. + * config/i386-lelf.mt: New file. + * config/i386-gelf.mt: New file. + +Mon Feb 27 12:58:25 1995 Kung Hsu + + * config.bfd: add a29k-*-vxworks configuration. + +Wed Feb 22 14:40:26 1995 Ian Lance Taylor + + * libaout.h (NAME(aout,slurp_reloc_table)): Change declaration to + use reloc_howto_type rather than const struct reloc_howto_struct. + +Tue Feb 21 18:19:22 1995 Ian Lance Taylor + + * bout.c (b_out_slurp_reloc_table): Don't return an error if asked + for relocations for the .bss section. + +Tue Feb 21 15:13:05 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_ar_write_symbol_stuff): Handle objects with odd + lengths. + +Fri Feb 17 12:34:36 1995 Michael Meissner + + * elf32-ppc.c (ppc_elf_got16_reloc): Make GOT style relocs add + 32768, so the GOT pointer can point to 16384 pointers, instead of + 8192. + +Fri Feb 17 11:45:38 1995 Ian Lance Taylor + + * hosts/sysv4.h: Include , , and . + Only define SEEK_SET and SEEK_CUR if they are not already defined. + Remove all external function declarations. + + * syms.c (bfd_decode_symclass): Return 'W' for a weak symbol. + + * coffgen.c (coff_real_object_p): Set start address and flags + before calling coff_mkobject_hook. Restore them on failure. + * ecoff.c (_bfd_ecoff_mkobject_hook): If not ECOFF_AOUT_ZMAGIC, + clear D_PAGED. + + * coffgen.c: Reindented. + +Thu Feb 16 14:37:23 1995 Doug Evans + + * reloc.c (bfd_perform_relocation): Don't use bitpos in overflow + calculations. + (bfd_install_relocation): Likewise. + +Thu Feb 16 13:22:29 1995 Ian Lance Taylor + + * hosts/std-host.h: Remove all function declarations which return + int or void, except the one for free. + +Wed Feb 15 14:54:18 1995 Michael Meissner + + * elf32-ppc.c (elf_powerpc_howto_table): Use a destination mask of + 0xffffffff for R_PPC_REL32, not 0. + (powerpc_reloc_map): Add low 16 bit, high 16 bit, and high 16 bit + adjusted relocations. + +Tue Feb 14 17:47:17 1995 Ian Lance Taylor + + * elf32-mips.c (struct mips_elf_find_line): Define. + (mips_elf_find_nearest_line): New static function. + (bfd_elf32_find_nearest_line): Define. + * libelf.h (struct elf_obj_tdata): Add find_line_info field. + + * ecoff.c (_bfd_ecoff_swap_tir_in): Move to ecofflink.c. + (_bfd_ecoff_swap_tir_out): Likewise. + (_bfd_ecoff_swap_rndx_in): Likewise. + (_bfd_ecoff_swap_rndx_out): Likewise. + (cmp_fdrtab_entry): Likewise. + (mk_fdrtab): Likewise. + (lookup): Likewise. + (_bfd_ecoff_find_nearest_line): Just call _bfd_ecoff_locate_line + to do most of the work. Allocate find_line_info if necessary. + * ecofflink.c: Include "aout/stab_gnu.h". + (_bfd_ecoff_swap_tir_in): Move in from ecoff.c. + (_bfd_ecoff_swap_tir_out): Likewise. + (_bfd_ecoff_swap_rndx_in): Likewise. + (_bfd_ecoff_swap_rndx_out): Likewise. + (cmp_fdrtab_entry): Likewise. Use PTR instead of void *. + (mk_fdrtab): Move in from ecoff.c. Add debug_info, debug_swap, + and line_info arguments, and use them instead of ecoff_data. + (fdrtab_lookup): Move in from lookup in ecoff.c. Remove abfd + argument, add line_info argument. Use it instead of ecoff_data. + (_bfd_ecoff_locate_line): New function, mostly from the old + _bfd_ecoff_find_nearest_line in ecoff.c. + * libecoff.h (ecoff_data_type): Remove find_buffer, fdrtab_len and + fdrtab fields, replacing them find_line_info field. + (_bfd_ecoff_swap_tir_in): Declare. + (_bfd_ecoff_swap_tir_out): Declare. + (_bfd_ecoff_swap_rndx_in): Declare. + (_bfd_ecoff_swap_rndx_out): Declare. + * libbfd-in.h (_bfd_ecoff_locate_line): Declare. + * libbfd.h: Rebuild. + * configure.in: Don't use ecoff.o for bfd_elf32_bigmips_vec or + bfd_elf32_littlemips_vec. + * Makefile.in: Rebuild dependencies. + +Tue Feb 14 14:04:22 1995 Michael Meissner + + * libelf.h (elf_backend_data): Add fields elf_machine_alt1 and + elf_machine_alt2 which provide alternate versions of the machine + code. + + * elf32-ppc.c (ELF_MACHINE_ALT1, ELF_MACHINE_ALT2): Define to + recognize old versions of the PowerPC machine code. + + * elf32-target.h (elf32_bed): Initialize alternate machine code + fields defined by ELF_MACHINE_ALT1 and ELF_MACHINE_ALT2. + + * elf64-target.h (elf64_bed): Initialize alternate machine code + fields defined by ELF_MACHINE_ALT1 and ELF_MACHINE_ALT2. + + * elfcode.h (elf_object_p, elf_core_file_p): In addition to the + main machine code field, check the two alternate machine code + fields. + +Tue Feb 14 12:46:48 1995 Ian Lance Taylor + + * aoutf1.h (MACHTYPE_OK): Don't define if already defined. Don't + accept M_SPARC if bfd_arch_sparc is not in the list of supported + architectures, and don't accept a 680x0 machine type if + bfd_arch_m68k is not in the list of supported architectures. + * aout0.c (MACHTYPE_OK): Define. + +Mon Feb 13 23:25:38 1995 Ian Lance Taylor + + * aoutx.h (NAME(aout,swap_ext_reloc_in)): Don't return a pointer + to garbage if the symbol index is out of range. + (NAME(aout,swap_std_reloc_in)): Likewise. + + +Thu Feb 9 18:36:52 1995 Ken Raeburn + + * Makefile.in (BFD32_BACKENDS): Add i386msdos.o. + +Thu Feb 9 12:02:35 1995 Ian Lance Taylor + + * i386linux.c (NEEDS_SHRLIB): Define. + (linux_tally_symbols): Crash if a NEEDS_SHRLIB symbol is + undefined. From hjl@nynexst.com (H.J. Lu). + +Wed Feb 8 17:26:00 1995 Ian Lance Taylor + + * linker.c (generic_link_check_archive_element): Allocate common + symbol information structure. Don't bother to check for common + symbol size overflow. + (_bfd_generic_link_add_one_symbol): Likewise. + * aoutx.h (aout_link_check_ar_symbols): Likewise. + * linker.c (generic_link_check_archive_element): Adjust references + to common symbol information for new structure. + (_bfd_generic_link_add_one_symbol): Likewise. + * aoutx.h (aout_link_check_ar_symbols): Likewise. + (aout_link_add_symbols): Likewise. + * ecoff.c (ecoff_link_add_externals): Likewise. + * elfcode.h (elf_link_add_object_symbols): Likewise. + (elf_link_output_extsym): Likewise. + * sunos.c (sunos_add_one_symbol): Likewise. + +Wed Feb 8 09:53:42 1995 Doug Evans + + * elfcode.h (elf_sort_hdrs): Put SHT_NOBITS sections after !SHT_NOBITS. + +Tue Feb 7 16:27:33 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_find_nearest_line): Just return false, don't + abort. + +Tue Feb 7 14:43:33 1995 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * ecoff.c: Reformatted some comments and brace constructs in + recent changes to GNU style. + (cmp_fdrtab_entry, mk_fdrtab, lookup): Use old-style function + definitions. + +Tue Feb 7 14:21:28 1995 Ian Lance Taylor + + * ecoffswap.h (ecoff_swap_pdr_in): Zero out intern before setting + any of the fields. + +Mon Feb 6 20:01:24 1995 Ken Raeburn + + Sat Feb 4 14:20:24 1995 David Mosberger-Tang + + * ecoffswap.h (ecoff_swap_pdr_in, ecoff_swap_pdr_out): added + internalizing/externalizing new "prof" field. + + * libecoff.h (ecoff_tdata): added fdrtab. + + * ecoff.c (_bfd_ecoff_find_nearest_line): Fixed. + +Mon Feb 6 14:25:24 1995 Ian Lance Taylor + + * libelf.h (struct elf_link_hash_table): Add saw_needed field. + * elfcode.h (elf_link_add_object_symbols): Set saw_needed if + DT_NEEDED seen in .dynamic section. + (elf_link_output_extsym): Warn if an undefined symbol is + only referenced from a dynamic object, and not making a shared + object, and saw_needed is false. + * elf.c (_bfd_elf_link_hash_table_init): Initialize saw_needed. + + * libelf.h (ELF_LINK_HASH_DEFINED_WEAK): Don't define. + * elfcode.h (elf_link_add_object_symbols): Don't clear or set + ELF_LINK_HASH_DEFINED_WEAK. + (elf_link_output_extsym): Don't check ELF_LINK_HASH_DEFINED_WEAK. + + Distinguish a weak defined symbol from a regular defined symbol. + * linker.c (enum link_action): Add DEFW. + (link_action): Add bfd_link_hash_defweak column. + (_bfd_generic_link_add_one_symbol): Add DEFW case. Handle + bfd_link_hash_defweak in a few other cases. + * Many files (bfd_link_hash_undefweak): Renamed from + bfd_link_hash_weak. + * aoutx.h (aout_link_write_symbols): Handle bfd_link_hash_defweak. + (aout_link_write_other_symbol): Likewise. + (aout_link_input_section_std): Likewise. + (aout_link_input_section_ext): Likewise. + * bout.c (get_value): Likewise. + * coff-a29k.c (coff_a29k_relocate_section): Likewise. + * coff-alpha.c (alpha_convert_external_reloc): Likewise. + (alpha_relocate_section): Likewise. + * coff-mips.c (mips_relocate_section): Likewise. + (mips_relax_section): Likewise. + (bfd_mips_ecoff_create_embedded_relocs): Likewise. + * cofflink.c (coff_write_global_sym): Likewise. + (_bfd_coff_generic_relocate_section): Likewise. + * ecoff.c (ecoff_link_add_externals): Likewise. + (ecoff_link_write_external): LIkewise. + * elf32-hppa.c (elf32_hppa_relocate_section): Likewise. + (elf32_hppa_size_stubs): Likewise. + * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Likewise. + (elf_i386_relocate_section): Likewise. + (elf_i386_finish_dynamic_symbol): Likewise. + * elf32-mips.c (mips_elf_output_extsym): Likewise. + (mips_elf_relocate_section): Likewise. + * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise. + (elf32_sparc_relocate_section): Likewise. + * elfcode.h (elf_link_add_object_symbols): Likewise. + (elf_adjust_dynamic_symbol): Likewise. + (elf_bfd_final_link): Likewise. + (elf_link_output_extsym): Likewise. + * i386linux.c (linux_add_one_symbol): Likewise. + (linux_tally_symbols): Likewise. + (linux_finish_dynamic_link): Likewise. + * linker.c (_bfd_generic_link_output_symbols): Likewise. + (set_symbol_from_hash): Likewise. + * reloc16.c (bfd_coff_reloc16_get_value): Likewise. + (bfd_perform_slip): Likewise. + * sunos.c (sunos_add_one_symbol): Likewise. + (sunos_scan_std_relocs): Likewise. + (sunos_scan_ext_relocs): Likewise. + (sunos_scan_dynamic_symbol): Likewise. + (sunos_write_dynamic_symbol): Likewise. + +Mon Feb 6 03:20:17 1995 Ken Raeburn + + Changes from Bryan Ford, baford@schirf.cs.utah.edu: + * config.bfd (i[345]86-*-msdos*): New target. + * configure.in (i386msdos_vec): Handle it. + * i386msdos.c: New file. + * config/i386-msdos.mt: New file. + * bfd.c (enum bfd_error): Added new value bfd_error_file_too_big. + (bfd_errmsgs): Added string to table. + * libaout.h (reloc_type-lookup): Declare it. + * targets.c (enum bfd_flavour): Added bfd_target_msdos_flavour. + (i386msdos_vec): Declare. + (bfd_target_vector): Add it to the list. + * bfd-in2.h: Regenerated. + +Wed Feb 1 01:32:14 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_set_reloc_info, case R_DATA_ONE_SYMBOL): If there's + nothing in R_DATA_OVERRIDE, then try to find the addend in the + section's contents. + (som_write_fixups): Ignore the addend in a R_DATA_ONE_SYMBOL fixup. + + * som.c (som_object_setup): More heruistics to detect the + braindamaged HP OSF1 linker. + (setup_sections): Don't forget to free subspace_sections if we get + an error. + (som_slurp_string_table): Allocate strings on this bfd's obstack + rather than directly out of the heap. + (som_slurp_symbol_table): Likewise for the saved copy of the + canonical symbols. + (som_slurp_reloc_table): Likewise for the saved copy of the + canonical relocations. Free the native relocations when we're + done with them. + +Tue Jan 31 21:53:28 1995 Doug Evans + + * libelf.h (struct elf_obj_tdata): New member program_header_size. + * elfcode.h (get_program_header_size): New parameters sorted_hdrs, + count, and maxpagesize. All callers updated. + If sorted_hdrs is non-NULL, use it to compute the number of segments. + Save result in case called again. + (assign_file_positions_except_relocs): Sort headers before calling + get_program_header_size. + +Tue Jan 31 15:27:53 1995 Ian Lance Taylor + + * elfcode.h (map_program_segments): Add sorted_hdrs parameter. + Search through it rather than through unsorted section headers. + (assign_file_positions_except_relocs): Pass sorted_hdrs to + map_program_segments. + +Mon Jan 30 22:04:53 1995 Ken Raeburn + + * ecoff.c (_bfd_ecoff_find_nearest_line): Fix problems in range + checking. Expect argument OFFSET to be section-relative. From + David Mosberger-Tang, davidm@piston.cs.arizona.edu. + +Mon Jan 30 11:22:11 1995 Ian Lance Taylor + + * elfcode.h (NAME(bfd_elf,record_link_assignment)): Don't do + anything if we are not linking an ELF file. + (NAME(bfd_elf,size_dynamic_sections)): Likewise. + +Sat Jan 28 12:48:57 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (compare_subspaces): New function to sort subspaces by + their location in the object file. + (setup_sections): When computing the index for each subspace, + handle case where setup_sections reads the subspaces in a + different order that they appear in the object file. + (som_is_space): Also examine the output section for the containing + section. + (som_is_subspace, som_is_container): Likewise. + (som_begin_writing): Don't prepare or write fixups here. When + writing the symbol strings, use the unsorted symbol table. + (som_write_object_contents): Don't write the symbol table here. + (som_finish_writing): Prepare and write the fixups here. Likewise + for the symbol table. + (som_bfd_derive_misc_symbol_info): Undefined symbols always have + type SS_UNSAT regardless of BSF_EXPORT. + (som_set_reloc_info): Unpack and attach argument location + information for R_PCREL_CALL and R_ABS_CALL relocations. + + * som.c (som_object_setup): New heuristic to determine if the + entry and flags fields are switched in the exec header. + +Sat Jan 28 00:16:01 1995 Ian Lance Taylor + + * elfcode.h (elf_link_add_object_symbols): Use *sym_hash instead + of h if we might not be doing an ELF link. + +Fri Jan 27 16:13:42 1995 Ian Lance Taylor + + * elf32-mips.c (mips_elf_final_link): If the size of an input + .reginfo section is zero, force it to the correct size, since the + linker emulation code may have clobbered it. + + * elfcode.h (elf_sort_hdrs): Correct SHF_ALLOC test. + (assign_file_positions_except_relocs): Free sorted_hdrs. + +Thu Jan 26 09:00:12 1995 Steve Chamberlain + + * srec.c (srec_set_section_contents): Fix off by + one end address calculation. + + * config.bfd: (m68*-est-coff): New configuration. + +Thu Jan 26 11:39:21 1995 Ian Lance Taylor + + * elfcode.h (elf_link_add_object_symbols): Only examine weakdef if + we are using an ELF hash table. + + * aoutx.h (NAME(aout,some_aout_object_p)): Always set EXEC_P if + the start address is in the .text section, even if STAT_FOR_EXEC + is set. Just use STAT_FOR_EXEC as an additional test. + +Thu Jan 26 11:12:54 1995 Michael Meissner + + * elfcode.h (prep_headers): Use EM_PPC instead of + EM_CYGNUS_POWERPC. + + * elf32-ppc.c (reloc_type): Add all System V.4 and eABI + relocations currently defined. + (powerpc_reloc_map): Adjust to new relocation names. + (elf_powerpc_howto_table): Add most of the new relocations. + (ELF_MACHINE_CODE): Use EM_PPC instead of EM_CYGNUS_POWERPC. + + * config.bfd: Add support for powerpc-*-eabi. + + * config/ppc-elf.mt: Add rs6000 architecture support to the + PowerPC. Also add XCOFF support. + +Wed Jan 25 23:26:13 1995 Ian Lance Taylor + + * coff-sh.c (CALC_ADDEND): Don't define. + (coff_sh_relocate_section): Remove. + (coff_relocate_section): Use _bfd_coff_generic_relocate_section. + +Tue Jan 24 14:22:47 1995 Ian Lance Taylor + + * elf32-mips.c (mips_elf_output_extsym): Set the value of the + ECOFF symbol from the hash table entry. + +Mon Jan 23 14:53:35 1995 Steve Chamberlain + + * coff-sh.c (coff_sh_relocate_section): Don't subtract + vma twice. + +Mon Jan 23 13:33:18 1995 Ian Lance Taylor + + * coff-sh.c (sh_reloc): Don't ignore the previous contents of an + R_SH_IMM32 reloc. + + * config.bfd (i[345]86-*-gnu*): Set bfd_name to i386-gnu. + * config/i386-gnu.mt: New file. Include ELF support. + + * opncls.c (bfd_openstreamr): Call bfd_cache_init. + +Fri Jan 20 11:44:45 1995 Ian Lance Taylor + + * sunos.c (sunos_add_one_symbol): Only set the sunos specific + fields if we are doing a sunos link. + +Wed Jan 18 12:28:17 1995 Ian Lance Taylor + + * cpu-h8300.c (h8300_info_struct): Change name from "H8/300" to + "h8300" for consistency with other cpu-* files. + (h8300h_info_struct): Change name from "H8/300H" to "h8300h". + * coff-h8300.c (special): Remove unused variable diff. + +Tue Jan 17 10:52:32 1995 Ian Lance Taylor + + * bfd-in.h (bfd_byte, reloc_howto_type): Define here, not... + * reloc.c (bfd_byte, reloc_howto_type): here. + * Changed all occurrences of ``const struct reloc_howto_struct'' + to be ``reloc_howto_type'' instead. + * bfd-in2.h, libbfd.h, libcoff.h: Rebuilt. + + * opncls.c (bfd_openstreamr): New function. + * bfd-in2.h: Rebuilt. + + * elf32-mips.c (enum reloc_type): Define new relocs used on Irix. + (elf_mips_howto_table): Add entries for new relocs. + (mips_elf_section_from_shdr): Handle SHT_MIPS_MSYM, + SHT_MIPS_DWARF, and SHT_MIPS_EVENTS. + (mips_elf_fake_sections): Handle sections named .msym, .debug_* + and .MIPS.events.*. + + * srec.c (srec_init): Remove unused local variable i. + +Sat Jan 14 19:09:48 1995 Steve Chamberlain + + * archures.c, Makefile.in, targets.c, bfd-in2.h, coffcode.h, + config.bfd, configure.in, config/w65.mt: Initial support for the W65. + +Sun Jan 15 13:57:45 1995 Steve Chamberlain + + * opncls.c (bfd_fdopenr): Configure for WIN32. + +Thu Jan 12 16:30:47 1995 Ken Raeburn + + * Makefile.in (diststuff): Include `headers'. + + * sunos.c (m68k_plt_first_entry, sparc_plt_first_entry): Now + const. + * tekhex.c (digs): Ditto. + * elf32-i386.c (elf_i386_plt0_entry, elf_i386_plt_entry): Ditto. + + * srec.c, tekhex.c: Include libiberty.h. Delete static array + hex_value and replace references to it with references to + hex_init, hex_p, and hex_value. + * Makefile.in: Updated dependencies. + + * archures.c (archures_init_table): Now const. + (bfd_arch_init): Adjusted type of local var `ptable'. + +Thu Jan 12 09:33:24 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * hosts/symmetry.h: Redefine `shared' to enable compilation + with the native Dynix cc compiler. + * i386dynix.c: Include aoutx.h instead of using routines + from aout32.c. + +Wed Jan 11 21:31:41 1995 Ken Raeburn + + * reloc.c (reloc_howto_type): Make typedef include `const'. + * aout-ns32k.c, aoutx.h, bout.c, cf-m68klynx.c, coff-i386.c, + coff-i960.c, coff-m68k.c, cofflink.c, cpu-ns32k.c, ecoff.c, + elf32-hppa.c, elf32-i386.c, elf32-mips.c, elf32-sparc.c, + elfcode.h, libbfd-in.h, linker.c, mipsbsd.c, nlm32-ppc.c, oasys.c, + reloc.c, som.c: Don't use `const' in combination with + `reloc_howto_type'. + * bfd-in2.h, libbfd.h: Regenerated. + + * ecoff.c (ecoff_type_to_string): Local variable `buffer1' doesn't + need to be static. + +Wed Jan 11 14:36:41 1995 Ian Lance Taylor + + * sunos.c (sunos_add_one_symbol): Don't core dump if a multiple + definition of an absolute symbol is encountered. + + * linker.c (_bfd_generic_link_add_one_symbol): Ignore + redefinitions of an absolute symbol to the same value. + +Mon Jan 9 15:51:32 1995 Ian Lance Taylor + + * elfcode.h (elf_link_add_object_symbols): It's reasonable for no + flags to be set, so don't insist otherwise. + +Fri Jan 6 16:39:40 1995 Ian Lance Taylor + + * elfcode.h (elf_slurp_symbol_table): Don't set BSF_GLOBAL for an + undefined or common symbol. + (elf_link_add_object_symbols): Likewise. + +Wed Jan 4 14:14:05 1995 Jeff Law (law@snake.cs.utah.edu) + + * som.c (bfd_section_from_som_symbol): Only return sections which + correspond to subspaces. + + * som.c (som_begin_writing): Don't forget to bump the + total_subspaces when writing the unloadable subspaces. + +Wed Dec 28 20:54:47 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_write_fixups): Use SEC_HAS_CONTENTS to identify + bss-like sections. + (som_get_section_contents): Likewise. + (som_set_section_contents): Likewise. + +Tue Dec 27 14:03:47 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (setup_sections): Turn off SEC_HAS_CONTENTS for bss-like + sections. + +Tue Dec 20 15:30:12 1994 Ken Raeburn + + * coffgen.c (bfd_debug_section): Deleted. + (coff_section_from_bfd_index): Return absolute section for debug + symbol. + (coff_write_symbol): Set BSF_DEBUGGING for C_FILE symbols. If + BSF_DEBUGGING is set, set section to N_DEBUG. + (coff_bfd_make_debug_symbol): Use absolute section. + + * elfcode.h (assign_file_positions_except_relocs): In assertion, + force all values to the same type. + +Tue Dec 20 11:11:58 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coff-h8300.c (howto_table): All relocs get a special function. + (special): Never do anything when linking -r. + +Tue Dec 20 13:58:01 1994 Ian Lance Taylor + + * i386linux.c (linux_add_one_symbol): Don't do anything Linux + specific if this is not a Linux hash table. From Eric Youngdale + . + + Patches from kkojima@mix.or.jp (Kazumoto Kojima): + * mipsbsd.c (mips_howto_table_ext): Change sizes of memory relocs + apply to from two bytes to four bytes. + * MY(reloc_howto_type_lookup): Handle BFD_RELOC_CTOR. + + * elf32-i386.c (elf_i386_relocate_section): Correct and expand the + list of cases for which relocation need not be computed. + * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. + + +Mon Dec 19 23:09:16 1994 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (elf32_hppa_read_symext_info): Delete do_locals and + do_globals arguments, always read symbol extension information for + globals and locals. All callers changed. + (elf32_hppa_size_stubs): Rework to only read symbol extension + information once for each input bfd. 10% improvement in linker + performance. + +Fri Dec 16 12:28:46 1994 Ian Lance Taylor + + * elfcode.h (elf_section_from_bfd_section): Check + bfd_is_abs_section, etc., only after checking for the section in + the BFD and after calling the backend routine. + +Wed Dec 14 20:21:58 1994 Ian Lance Taylor + + * elfcode.h (elf_map_symbols): Only use section symbols whose + value is the start of the section, checking output_offset when + using output_section. When creating a new symbol, set the value + to 0, since BFD symbol values are section relative. + +Tue Dec 13 13:31:06 1994 Ian Lance Taylor + + * cpu-z8k.c (arch_info_struct): Make z8002 the default + architecture. + +Fri Dec 9 12:43:05 1994 Ian Lance Taylor + + * elfcode.h (elf_bfd_link_add_symbols): If the first object in the + archive is not an ELF object, pass the archive to the add_symbols + entry point appropriate for the first object. From Eric Youngdale + . + * aoutx.h (NAME(aout,link_add_symbols)): Similar change if the + first object is not an a.out object. + + * elf32-i386.c (elf_i386_relocate_section): Don't compute + relocation in cases where we won't use it. + * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. + +Thu Dec 8 14:19:41 1994 Ken Raeburn + + * pc532-mach.c (NAME): Define to use ns32kaout prefix. + * ns32knetbsd.c (NAME): Ditto. + (ns32kaout_32_get_section_contents): Define to standard aout-32 + version. + +Fri Dec 2 13:56:49 1994 Ian Lance Taylor + + * coff-mips.c (mips_read_relocs): New static function, broken out + of mips_relax_section. + (mips_relax_section): Call mips_read_relocs. + (bfd_mips_ecoff_create_embedded_relocs): New function. + * bfd-in.h (bfd_mnips_ecoff_create_embedded_relocs): Declare. + * bfd-in2.h: Rebuild. + +Wed Nov 30 14:12:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-sh.c: Use _bfd_dummy_target instead of no_archive. + + +Tue Nov 29 14:00:19 1994 J.T. Conklin + + * config.bfd (i[345]86-*-freebsd*): Use i386-bsd as bfd_name. + * configure.host (i[345]86-*-freebsd*): Use i386bsd as my_host. + +Mon Nov 28 15:36:04 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * config/m68k-nbsd.mt (DEFAULT_VECTOR): set to m68knetbsd_vec. + * Makefile.in: Rebuilt dependancies. + (CFILES): Added m68knetbsd.c. + (HFILES): Added netbsd.h. + +Wed Nov 23 19:21:41 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coff-sh.c (shlcoff_vec): New target vector. + (no_archive): New function. + * coffcode.h (coff_set_arch_mach_hook, coff_set_flags): Handle + little endian SH. + * configure.in: Handle shl. + * targets.c (bfd_target_vector): Add shlcoff_vec. + * config/sh-coff.mt (SELECT_VECS): Handle shl_coff_vec. + +Wed Nov 23 10:50:13 1994 Jeff Law (law@snake.cs.utah.edu) + + * elfcode.h (write_relocs): Do not subtract the section's vma from + the reloc's offset when writing .o's. Instead add the section's + vma to the reloc's offset when writing an executable or shared + library. + +Tue Nov 22 23:34:37 1994 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (elf32_hppa_bfd_final_link_relocate): Do not add + input_section->vma to the relocation's offset. + +Mon Nov 21 12:37:25 1994 Ian Lance Taylor + + * srec.c (srec_get_reloc_upper_bound): Define. + (srec_canonicalize_reloc): Define. + (srec_bfd_reloc_type_lookup): Define. + (srec_vec, symbolsrec_vec): Use BFD_JUMP_TABLE_RELOCS (srec). + +Sat Nov 19 03:10:51 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * configure.host (i[345]86-*-solaris*): Use solaris2 to + enable extraction of procfs info from core file for GDB. + +Thu Nov 17 17:37:39 1994 Ken Raeburn + + * reloc.c (bfd_reloc_code_type): Add new value BFD_RELOC_12_PCREL. + * bfd-in2.h, libbfd.h: Rebuilt. + +Thu Nov 17 13:12:08 1994 Jeff Law (law@snake.cs.utah.edu) + + * bfd/elf32-hppa.c (elf32_hppa_bfd_final_link_relocated): Use the + vma from the output_section containing $global$ when computing + global_vlaue. + +Thu Nov 17 14:29:13 1994 Ian Lance Taylor + + * archive.c (_bfd_write_archive_contents): Round up the archive + header size of the extended name table to an even number. + +Wed Nov 16 16:08:06 1994 Ken Raeburn + + * coff-sh.c: Deleted some code that was commented out or inside + "#if 0". + (COFF_LONG_FILENAMES): Define. + + * cpu-sh.c (arch_info_struct): Convert name to lowercase, for + consistency with other architectures. + +Sat Nov 12 23:50:10 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (elf_export_symbol): Also export symbols which are + referenced by a regular file. + +Fri Nov 11 14:29:31 1994 Ian Lance Taylor + + * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Add + export_dynamic argument, and handle it. + (elf_export_symbol): New function. + * bfd-in.h (bfd_elf32_size_dynamic_sections): Update declaration. + (bfd_elf64_size_dynamic_sections): Update declaration. + * bfd-in2.h: Rebuild. + +Fri Nov 11 10:35:33 1994 Jeff Law (law@snake.cs.utah.edu) + + * hpux-core.c (hpux_core_struct): Delete handles for the + data, reg and stack sections. They're never used. Delete + accessor macros. + (make_bfd_asection): Use bfd_make_section_anyway since debugging + cores from dynamic executables may have several sections with the + same logical name. + (hpux_core_core_file_p): Don't save handles to data, reg and + stack sections. Handle CORE_TEXT, CORE_MMF and CORE_SHM. + +Tue Nov 8 13:03:30 1994 Ian Lance Taylor + + * bout.c (callj_callback): Add new argument shrinking. Change all + callers. Handle relocs against section symbols correctly. If not + shrinking, don't subtract out dstidx; the subtraction is already + in the object file. + +Sun Nov 6 12:52:00 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.h: Conditionally include and . + +Thu Nov 3 18:19:13 1994 Ken Raeburn + + * Makefile.in (ALL_MACHINES): Include m68knetbsd.o. + + * config/i386linux.mh (EXTRALIBS): Include -lm. + + Patches from DJ Delorie: + * coff-go32.c: Replacement file, uses coff-i386.c with minor + changes. + * coff-i386.c (TARGET_UNDERSCORE): allow other files to override + underscore also + * makefile.dos: del ctor.o, add cofflink.o and elf32.o + + * aoutx.h (adjust_o_magic): If user set data section vma, use it + to determine the default bss vma. Patch from Takada Hiroaki, + hiro@is.s.u-tokyo.ac.jp. + (machine_type, case bfd_arch_vax): Set *unknown to false. Patch + from John David Anglin . + + * configure.in (tb): Rename ns32knetbsd_vec to pc532netbsd_vec, + since that's what it's called. + +Wed Nov 2 15:24:51 1994 Ian Lance Taylor + + * archive.c (normalize): Change to take a BFD as an argument. + Change VMS version to use bfd_alloc rather than malloc, so that we + don't lose the memory forever. + (_bfd_construct_extended_name_table): Check the name of an archive + entry which is not being extended, and correct it if it is wrong. + This is necessary in case the archive was constructed by another + program which put an entry in the extended name table which we + don't plan to put in ourselves. From jjc@jclark.com (James + Clark). + (bfd_dont_truncate_arname): Check return value of normalize. + +Mon Oct 31 14:19:08 1994 Ian Lance Taylor + + * elf32-hppa.c (ELF32_PARISC_SX_SIZE): Define. + (ELF32_PARISC_SX_GET, ELF32_PARISC_SX_PUT): Define. + (symextn_entry): Don't define. + (symext_chain_size): Change type to bfd_size_type. + (symextn_contents): Change type to bfd_byte *. + (elf32_hppa_backend_begin_write_processing): Use + ELF32_PARISC_SX_SIZE instead of sizeof (symext_entryS). + (elf32_hppa_size_symext): Likewise. Also, change type of sizep to + bfd_size_type *. + (elf_hppa_tc_make_sections): Cast symextn_contents assignment to + bfd_byte *. Use ELF32_PARISC_SX_PUT instead of direct assignment. + (elf32_hppa_backend_symbol_table_processing): Use + ELF32_PARISC_SX_SIZE instead of sizeof (symext_entryS). Use + ELF32_PARISC_SX_GET insetad of direct assignment. + (elf32_hppa_read_symext_info): Change type of contents, and its + assignment cast, to bfd_byte *. Use ELF32_PARISC_SX_SIZE instead + of sizeof (symextn_entry). Use symext_entryS instead of + symextn_entry. Use ELF32_PARISC_SX_GET instead of direct + assignment. + + * archive.c (bfd_dont_truncate_arname): Add the ar padding + character, if there is room for it, even if the name is the + maximum length. + + * elfcode.h (assign_file_positions_except_relocs): Sort the ELF + headers by section address when assigning file positions. + (elf_sort_hdrs): New static function. + +Sun Oct 30 18:56:58 1994 Ian Lance Taylor + + * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Create DT_INIT + and DT_FINI dynamic entries based on the existence of _init and + _fini symbols, not on the .init and .fini sections. This is + compatible with some SVR4 linkers. + (elf_bfd_final_link): Corresponding change. + +Sat Oct 29 12:18:10 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Don't move a + symbol with a PLT entry into the .plt section if it is defined in + a regular file. + * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise. + + * linker.c (_bfd_generic_link_add_archive_symbols): It's not an + error if an empty archive has no symbol table. + * ecoff.c (ecoff_link_add_archive_symbols): Likewise. + * elfcode.h (elf_link_add_archive_symbols): Likewise. + +Fri Oct 28 10:08:41 1994 J.T. Conklin (jtc@rtl.cygnus.com) + + NetBSD/m68k support, based on work by mikeb@snow.datametrics.com: + * config.bfd (m68*-*-netbsd*): Use m68k-nbsd as bfd_name. + * configure.in (m68knetbsd_vec): Added. + * targets.c (bfd_m68knetbsd_vec): Added. + * hosts/m68knbsd.h, config/m68k-nbsd.mt, m68knetbsd.c: New files. + * Makefile.in (BFD32_BACKENDS, CFILES): Add m68knetbsd.c. + + miscellaneous cleanup required by all netbsd targets, based on work + by Andrew Cagney : + * netbsd.h (N_MAGIC, N_SET_MAGIC, N_GETMAGIC, N_GETMAGIC2, N_TXTADDR, + N_TXTOFF, N_ALIGN, N_DATADDR, N_DATOFF): Removed. Generic a.out + definitions work. + * i386nbsd.c, ns32knbsd.c, sparcnbsd.c (__LDPGSZ): Removed. + (MY(write_object_contents)): Use NetBSD's magic numbers + +Thu Oct 27 16:59:52 1994 Ian Lance Taylor + + * libelf.h (struct bfd_elf_section_data): Add field dynindx. + * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Don't finalize + the .dynsym, .dynstr or .hash sections until after the backend + size_dynamic_sections routine, so that it can add dynamic symbols + if it wants to. + * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Don't define the + symbol to be in the .plt section when generating a shared library + if it is a defined symbol. + * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise. + (elf32_sparc_size_dynamic_sections): When generating a shared + library, allocate space for a dynamic symbol for each output + section, storing the index in the dynindx field of the ELF section + data. Adjust the other dynindx fields to account for this. + (elf32_sparc_adjust_dynindx): New static function. + (elf32_sparc_relocate_section): When copying a reloc into a shared + library, use the original addend as appropriate. Convert an + R_SPARC_32 reloc into an R_SPARC_RELATIVE reloc. Use the dynamic + symbol index of the output section, not the normal symbol index. + (elf32_sparc_finish_dynamic_sections): Don't die if a section does + not exist when setting the value of the dynamic tags. Write out + a dynamic symbol for each output section. + +Wed Oct 26 01:15:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (aout_link_input_section): Don't bother to read or write + the relocs if there aren't any. + +Tue Oct 25 11:44:38 1994 Ian Lance Taylor + + * Makefile.in (ALL_MACHINES): Add tekhex.o. + * targets.c (bfd_target_vector): If SELECT_VECS is not defined, + include tekhex_vec. + * tekhex.c (NIBBLE, ISHEX): Cast array arguments to unsigned char. + (getvalue, getsym, out): Likewise. + (find_chunk): Remove unused variable s. + (first_phase): Remove unused variable s. + (pass_over): Remove unused variable address. + (tekhex_object_p): Remove unused variable section. + (move_section_contents): Change return type from boolean to void. + (tekhex_write_object_contents): Remove unused variables tdata and + list. + + * linker.c (enum link_action): Add CIND. + (link_action): Change COMMON_ROW\indr from MDEF to CREF. Change + INDR_ROW\common from MDEF to CIND. + (_bfd_generic_link_add_one_symbol): In CREF case, handle an + existing symbol which is indirect rather than defined. Add new + CIND case. + +Mon Oct 24 15:33:16 1994 Ian Lance Taylor + + Change S-record backend to use multiple sections to handle gaps in + file. + * srec.c (srec_data_list_struct): Move field next from last place + to first. Change type of data to bfd_byte *. + (struct srec_symbol): Define. + (tdata_type): Remove done_symbol_read, count, strings, symbol_idx, + string_size, string_idx. Change type of symbols to struct + srec_symbol *. Add symtail and csymbols. + (low, high): Remove. + (size_symbols, fillup_symbols, size_srec, fillup): Remove. + (white, skipwhite, pass_over, object_p): Remove. + (srec_mkobject): Call srec_init. Adjust tdata initialization for + field changes. + (srec_get_byte, srec_bad_byte): New static functions. + (srec_new_symbol, srec_scan): New static functions. + (srec_object_p): Change type of b to bfd_byte. Explicitly set + wrong_format error. Call srec_mkobject and srec_scan instead of + object_p. + (symbolsrec_object_p): Likewise. Also, change b to be only two + bytes. + (srec_read_section): New static function. + (srec_get_section_contents): Call srec_read_section rather than + pass_over. Handle zero length section correctly. + (set_set_arch_mach): Change from function to macro. + (srec_set_section_contents): Change data to bfd_byte *. + (srec_write_record): Change data, end and src to bfd_byte *. + (srec_write_header): Change buffer and dst to bfd_byte *. + (srec_write_section): Change location to bfd_byte *. + (srec_write_terminator): Change buffer to bfd_byte *. + (srec_get_symtab_upper_bound): Don't call + srec_get_section_contents. + (srec_get_symtab): Rewrite. + + * ecoff.c (ecoff_set_symbol_info): Set udata.i to 0, not NULL. + +Fri Oct 21 16:43:13 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * libaout.h (machine_type): added M_68K_NETBSD and M_SPARC_NETBSD. + * i386netbsd.c, ns32knetbsd.c, sparcnetbsd.c: removed RCS Id's. + changed how PAGE_SIZE and SEGMENT_SIZE are defined so they are + consistant with each other. + * netbsd.h (N_HEADER_IN_TEXT, TEXT_START_ADDR): NetBSD fits its + header into the start of its text segment. + +Fri Oct 21 17:13:07 1994 Ian Lance Taylor + + * targets.c (BFD_JUMP_TABLE_ARCHIVE): Add case for + _construct_extended_name_table. + (bfd_target): Add _bfd_construct_extended_name_table. + * archive.c (_bfd_archive_bsd_construct_extended_name_table): New + function. + (_bfd_archive_coff_construct_extended_name_table): New function. + (_bfd_construct_extended_name_table): Renamed by adding a leading + underscore, and made externally visible. Added trailing_slash + argument, and used it instead of elf_style. Changed type of + tablen to bfd_size_type *. + (_bfd_write_archive_contents): Use BFD_SEND to call + construct_extended_name_table. Use the returned name. + * libbfd-in.h (_bfd_construct_extended_name_table): Declare. + (_bfd_noarchive_construct_extended_name_table): Define. + (_bfd_archive_bsd_construct_extended_name_table): Declare. + (_bfd_archive_coff_construct_extended_name_table): Declare. + * bfd-in2.h: Rebuild. + * libbfd.h: Rebuild. + * som.c (som_construct_extended_name_table): New static function. + * aout-target.h (MY_construct_extended_name_table): Define. + * coff-rs6000.c (rs6000coff_construct_extended_name_table): + Define. + * ieee.c (ieee_construct_extended_name_table): Define. + * libecoff.h (_bfd_ecoff_construct_extended_name_table): Define. + * oasys.c (oasys_construct_extended_name_table): Define. + + Fix the ELF linker to not require an interpreter if no dynamic + objects were seen, even when linking PIC code. + * libelf.h (ELF_LINK_HASH_NEEDS_PLT): Define. + (struct elf_link_hash_table): Add field dynamic_sections_created. + * elfcode.h (elf_link_record_dynamic_symbol): Create dynstr if it + doesn't already exist. + (elf_link_add_object_symbols): Create dynamic sections based on + dynamic_sections_created field, not dynobj field. Don't bother to + set dynobj. + (elf_link_create_dynamic_sections): If dynamic sections were + already created, don't do anything. If dynobj is already set, use + it; otherwise, set it to the bfd argument. Don't initialize + dynsymcount. Only create dynstr if it does not exist. Set + dynamic_sections_created to true. + (NAME(bfd_elf,size_dynamic_sections)): Skip most of this function + if no dynamic objects were seen. + (elf_adjust_dynamic_symbol): If a symbol has the + ELF_LINK_HASH_NEEDS_PLT flag set, let the backend adjust it. + (elf_bfd_final_link): Change most decisions based on dynobj to + check dynamic_sections_created instead. + (elf_link_output_extsym): Only handle dynamic symbols if a dynamic + object was seen. + * elf.c (_bfd_elf_link_hash_table_init): Initialize new field + dynamic_sections_created. Set dynsymcount to 1, not 0. + * elf32-i386.c (elf_i386_create_dynamic_sections): Call + elf_i386_create_got_section rather than creating the .got and + .got.plt sections. + (elf_i386_create_got_section): New static function. + (elf_i386_check_relocs): Just call elf_i386_create_got_section if + a GOT table is needed, not bfd_elf32_link_create_dynamic_sections. + Only create the .rel.got section, and only make space for a reloc, + for a global symbol or when generating a shared object. For a + R_386_PLT32 reloc, just set the ELF_LINK_HASH_NEEDS_PLT flag. + (elf_i386_adjust_dynamic_symbol): Rework initial assertion to + permit ELF_LINK_HASH_NEEDS_PLT non dynamic symbols. Create a + procedure linkage table entry for such symbols. But, if no + dynamic objects were seen, never create a PLT entry. + (elf_i386_size_dynamic_sections): If no dynamic objects were seen, + skip most of this function, and force the size of the .rel.got + section to zero. + (elf_i386_relocate_section): For a R_386_GOT32 reloc against a global + symbol when no dynamic object was seen, initialize the contents of + the .got section. For a R_386_GOT32 against a local symbol, only + create a R_386_RELATIVE reloc when generating a shared object. + Treat a R_386_PLT32 reloc against a symbol for which we did not + create a PLT entry as a R_386_PC32 reloc. + (elf_i386_finish_dynamic_sections): Only fiddle with the dynamic + entries and the PLT if we saw a dynamic object. + * elf32-sparc.c (elf_sparc_howto_table): Fix R_SPARC_PC22 by + setting rightshift to 10. Fix R_SPARC_WPLT20 by setting + rightshift to 2, size to 2, bitsize to 30, and dst_mask to + 0x3fffffff. + (elf32_sparc_create_dynamic_sections): Don't set the size of the + .plt section. Call elf32_sparc_create_got_section rather than + creating the .got section. + (elf32_sparc_check_relocs): Call elf32_sparc_create_got_section if + a GOT table is needed, not bfd_elf32_link_create_dynamic_sections. + Only create the .rela.got section, and only make space for a + reloc, for a global symbol or when generating a shared object. + Set the alignment of the .rela.got section to 2. For a + R_SPARC_WPLT30 reloc, just set the ELF_LINK_HASH_NEEDS_PLT flag. + (elf32_sparc_adjust_dynamic_symbol): Rework initial assertion to + permit ELF_LINK_HASH_NEDS_PLT non dynamic symbols. Create a + procedure linkage table for such symbols. But, if no dynamic + objects were seen, never create a PLT entry. Initialize the size + of the .plt section. + (elf32_sparc_size_dynamic_sections): If no dynamic objects were + seen, skip most of this function, and force the size of the + .rela.got section to zero. Strip empty reloc sections, and strip + an empty .plt section. + (elf32_sparc_relocate_section): For a GOT reloc against a global + symbol when no dynamic object was seen, initialize the contents of + the .got section. For a GOT reloc against a local symbol, only + create a R_SPARC_RELATIVE reloc when generating a shared object. + Treat a R_SPARC_WPLT30 reloc against a symbol for which we did not + create a PLT entry as a R_SPARC_WDISP30 reloc. + (elf32_sparc_finish_dynamic_sections): Only fiddle with the + dynamic entries and the PLT if we saw a dynamic object. + +Thu Oct 20 13:28:45 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (elf_map_symbols): Don't worry about section symbols + in a section not owned by any BFD. + (elf_section_from_bfd_section): Separate out loop which calls + backend routine. Check bfd_section and call the backend routine + even for a section not owned by any BFD. + * elf32-mips.c (mips_elf_section_from_bfd_section): Handle + .acommon section. + +Wed Oct 19 13:28:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * coffgen.c (coff_print_symbol): Make names for section number and + storage class slightly more verbose. It's not clear how many + characters I can justify using up, but before this change they + both were abbreviated "sc" which is (IMHO) clearly unacceptable. + +Wed Oct 19 01:26:39 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * binary.c (binary_set_section_contents): Set the base file + position from the lowest section VMA, not the start address. + + * aoutx.h (NAME(aout,slurp_symbol_table)): Don't return an error + if there are no symbols. + * coffgen.c (coff_get_normalized_symtab): Likewise. + * hp300hpux.c (MY(slurp_symbol_table)): Likewise. + +Tue Oct 18 12:56:43 1994 Ian Lance Taylor + + * aout-target.h (MY_bfd_copy_private_section_data): Only copy + subformat to another bfd_target_aout_flavour file. + + * binary.c: New file for raw binary output format. + * Makefile.in (BFD_LIBS): Add binary.o. + (CFILES): Add binary.c. + * targets.c (binary_vec): Declare. + (bfd_target_vector): Include binary_vec. + + * srec.c (tdata_type): Add field tail. + (srec_mkobject): Initialize tail. + (srec_set_section_contents): Sort S record list by address. + +Mon Oct 17 11:38:16 1994 Ian Lance Taylor + + * elfcode.h (elf_map_symbols): Sort the symbols into a new array, + rather than messing with Elf_Sym_Extra. Store the symbol index in + the udata.i field. + (swap_out_syms): Use outbound_syms as a pointer rather than as an + array. Don't worry about elf_sym_num. + * libelf.h (struct elf_sym_extra): Don't define. + (Elf_Sym_Extra): Don't define. + (struct elf_obj_tdata): Remove sym_extra field. + (elf_sym_extra): Don't define. + * elf32-hppa.c (elf32_hppa_backend_final_write_processing): Use + udata.i rather than elf_sym_extra array. + + * syms.c (asymbol): Change udata field into a union. + * bfd-in2.h: Rebuild. + * aoutx.h (NAME(aout,translate_symbol_table)): Use udata.p rather + than just udata. + * bout.c (perform_slip): Likewise. + * hp300hpux.c (MY(slurp_symbol_table)): Likewise. + * ieee.c (ieee_slurp_external_symbols): Likewise. + * linker.c (generic_link_add_symbol_list): Likewise. + (default_indirect_link_order): Likewise. + * oasys.c (oasys_slurp_symbol_table): Likewise. + * reloc16.c (bfd_perform_slip): Likewise. + * srec.c (fillup_symbols): Likewise. + * coffcode.h (get_index): Use udata.i rather than just udata. + (coff_slurp_symbol_table): Likewise. + * coffgen.c (set_index): Likewise. + * ecoff.c (ecoff_set_symbol_info): Likewise. + * elfcode.h (elf_symbol_from_bfd_symbol): Likewise. + * libecoff.h (ecoff_get_sym_index, ecoff_set_sym_index): Likewise. + * som.c (compare_syms): Likewise. + (som_prep_for_fixups): Likewise. + (som_write_fixups): Likewise. + + Use a hash table when writing out ELF symbol names. + * elfcode.h (elf_stringtab_init): New static function. + (bfd_new_strtab, bfd_add_to_strtab, bfd_add_2_to_strtab): Remove. + Change all callers to use elf_stringtab_init or + _bfd_stringtab_add, and get stringtab lengths using + _bfd_stringtab_size. + (elf_fake_sections): Change ignored argument to pointer to + boolean, and set the boolean to true if an error occurs. If an + error has already occurred, don't do anything. + (assign_section_numbers): Just set sh_size, not contents. + (elf_compute_section_file_positions): Pass the address of a + boolean to elf_fake_sections. Pass the address of a + bfd_strtab_hash to swap_out_syms. Write out the .strtab section. + (prep_headers): Change shstrtab to bfd_strtab_hash. + (swap_out_syms): Take a pointer to a bfd_strtab_hash as an + argument. Set it to the symbol names. + (NAME(bfd_elf,write_object_contents)): Write out the section + header names using _bfd_stringtab_emit. + (elf_debug_section): Remove first argument; get the section name + via the bfd_section pointer. Change caller. + (elf_bfd_final_link): Write out the symbol names using + _bfd_stringtab_emit. Likewise for the .dynstr section contents. + Free the symbol names at the end of the function. + (elf_link_input_bfd): Remove the last argument, output_names, + from relocate_section. Save the old symbol contents before + calling elf_link_output_sym, and restore them afterward. + * libelf.h (struct elf_link_hash_table): Change dynstr field to + struct bfd_strtab_hash. + (struct elf_backend_data): Remove last argument, output_names, + from elf_backend_relocate_section field. + (struct strtab): Don't define. + (struct elf_obj_tdata): Change strtab_ptr field to struct + bfd_strtab_hash. + * elf32-hppa.c (elf32_hppa_relocate_section): Remove last + argument, output_names. + * elf32-i386.c (elf_i386_relocate_section): Likewise. + * elf32-mips.c (mips_elf_relocate_section): Likewise. + * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. + + * libbfd-in.h (DEFAULT_STRING_SPACE_SIZE): Don't define. + (bfd_add_to_string_table): Don't declare. + * libbfd.h: Rebuild. + * libbfd.c (bfd_add_to_string_table): Remove. + + * elfcode.h (elf_swap_shdr_in): Use bfd_section, not rawdata. + Clear contents field. + (bfd_section_from_shdr): In SHT_STRTAB case, check bfd_section, + not rawdata. Don't set rawdata if e_shstrndx. Use bfd_section + rather than rawdata in commented out code. In SHT_REL[A] case, + don't bother to check elf_section_data of section returned by + section_from_elf_index. + (elf_fake_sections): Set bfd_section, not rawdata. Don't set + size. + (elf_map_symbols): Don't set elf_num_section_syms. Don't create + section symbols that already exist. + (assign_file_position_for_section): Use bfd_section, not rawdata. + (section_from_elf_index): Just check bfd_section field. + (elf_section_from_bfd_section): Likewise. + (elf_debug_section): Don't print rawdata, contents, or size. + (elf_link_add_object_symbols): Don't error out if + section_from_elf_index returns NULL. + (elf_bfd_final_link): Check return value from + section_from_elf_index against NULL, not bfd_is_abs_section. + (elf_link_input_bfd): Don't check section_from_elf_index return + value. + * libelf.h (struct elf_obj_tdata): Remove num_section_syms field. + (elf_num_section_syms): Don't define. + * elf.c (elf_get_str_section): Store section contents in contents + field rather than rawdata field. + (elf_string_from_elf_section): Likewise. + (_bfd_elf_make_section_from_shdr): Store BFD section pointer in + bfd_section field rather than rawdata field. + * elf32-hppa.c (elf32_hppa_read_symext_info): Use bfd_section + rather than rawdata. + (elf32_hppa_size_stubs): Likewise. + (elf32_hppa_backend_symbol_table_processing): Don't set + symextn_hdr->size; just use sh_size. + * elf32-mips.c (mips_elf_final_write_processing): Use bfd_section + rathern than rawdata. + (mips_elf_section_from_shdr): Likewise. + (mips_elf_section_processing): Likewise. + (mips_elf_section_from_bfd_section): Remove rawdata check. + + * srec.c (pass_over): Set the start address for S7, S8 or S9. + +Fri Oct 14 19:15:46 1994 Ken Raeburn + + * VERSION: Updated to 2.5. + +Fri Oct 14 11:07:50 1994 Ian Lance Taylor + + * bfd.c (bfd_scan_vma): Cast end to be non const before passing it + to strtoul. + +Thu Oct 13 14:40:41 1994 Ian Lance Taylor + + * bfd.c (bfd_scan_vma): Pass end argument on to strtoul. + +Wed Oct 12 16:46:43 1994 Ken Raeburn + + * opncls.c (bfd_realloc): Deleted, since it's broken and fixing it + would make it slow. Besides, it isn't used much. + * elfcode.h (elf_map_symbols): Always allocate new storage for the + symbol table. + +Wed Oct 12 11:54:37 1994 Ian Lance Taylor + + * ecoff.c (ecoff_set_symbol_info): Mark local stProc, stLabel or + stabs symbols as BSF_DEBUGGING. + + * rs6000-core.c (rs6000coff_core_file_matches_executable_p): Make + str1 and str2 const pointers. + + * Makefile.in (INSTALL): Use top level install.sh script. + * config/README (INSTALL): Remove. + * config/delta88.mh (INSTALL): Remove. + * config/i386v4.mh (INSTALL): Remove. + * config/irix4.mh (INSTALL): Remove. + * config/irix5.mh (INSTALL): Remove. + * config/ncrt3000.mh (INSTALL): Remove. + +Tue Oct 11 13:57:56 1994 Eric Youngdale (eric@andante.aib.com) + + * elf32-i386.c (elf_i386_check_relocs): Make sure that a symbol + with a global offset table entry or a procedure linkage table + entry is added to the dynamic symbol table. + * elf32-sparc.c (elf32_sparc_check_relocs): Likewise. + * elf32-i386.c (elf_i386_adjust_dynamic_symbol): If a symbol has + already gotten a procedure linkage table entry, change the + definition to the PLT entry. + * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise. + +Tue Oct 11 17:12:00 1994 Ian Lance Taylor + + * lynx-core.c (lynx_core_file_p): SPARC Lynx appears to start + dumping the .data section in a core file at a page boundary. + +Mon Oct 10 16:24:44 1994 Ken Raeburn + + * cofflink.c (_bfd_coff_final_link): Cast argument to bfd_h_put_32 + to correct type. + (coff_read_string_table): Cast argument to bfd_h_get_32 to correct + type. + * elfcode.h (elf_link_output_extsym): Cast argument to + bfd_elf_hash to correct type. + + * elf32-sparc.c (elf_sparc_howto_table): The PC10, PC22, and + WPLT30 relocations are PC-relative. + +Thu Oct 6 12:57:26 1994 Richard Earnshaw (rwe@pegasus.esprit.ec.org) + + * aoutx.h (adjust_o_magic): Correctly initialize vma if the vma of + the text section was user-defined. + +Wed Oct 5 14:42:12 1994 Ian Lance Taylor + + * archive.c (bfd_construct_extended_name_table): SVR4 uses slash + newline at the end of the file name, not just newline. + +Tue Oct 4 11:23:12 1994 Ian Lance Taylor + + * ecoff.c (_bfd_ecoff_new_section_hook): Default section alignment + power to 4, rather than using align_power_min. + + * coffcode.h (coff_new_section_hook): Don't use align_power_min; + use COFF_DEFAULT_SECTION_ALIGNMENT_POWER instead. Force the .stab + and .stabstr sections to be aligned to no more than 2. Remove + COFF_SPARC special cases. + * coff-a29k.c: Define COFF_DEFAULT_SECTION_ALIGNMENT_POWER. + * coff-apollo.c, coff-go32.c, coff-h8300.c: Likewise. + * coff-h8500.c, coff-i386.c, coff-i960.c, coff-m68k.c: Likewise. + * coff-m88k.c, coff-rs6000.c, coff-sh.c, coff-sparc.c: Likewise. + * coff-we32k.c, coff-z8k.c: Likewise. + + * configure.in: Use ${config_shell} when running config.bfd. + + * cofflink.c (coff_link_input_bfd): Don't try to convert a long + filename if the offset field is zero. + + * elfcode.h (swap_out_syms): If the alignment of a common symbol + was not set, use a sensible default rather than zero. + +Mon Oct 3 16:04:29 1994 H.J. Lu (hjl@nynexst.com) + + * opncls.c (bfd_close): Honor umask when setting execution bits. + (bfd_close_all_done): Likewise. + +Mon Oct 3 04:41:49 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * rs6000-core.c (rs6000coff_core_p): Set SEC_HAS_CONTENTS flag + for .stack and .ldinfo sections. Cast coredata.c_tab to a + file_ptr to avoid warnings from gcc. + +Fri Sep 30 13:11:38 1994 Ian Lance Taylor + + * elfcode.h (elf_bfd_final_link): Remove assertion when a non + SEC_IN_MEMORY section is found in dynobj. This can happen when + linking PIC compiled code. + +Thu Sep 29 15:21:44 1994 Ken Raeburn + + * reloc.c (bfd_install_relocation): Change type of "data" to + bfd_byte *, to go along with yesterday's change. + + * elf.c (bfd_elf_print_symbol): Moved here from elf_print_symbol + in elfcode.h. (case bfd_print_symbol_all): Print symbol's size + field, except for common symbols; print their alignment. + * elfcode.h (elf_print_symbol): Deleted. + * libelf.h (bfd_elf_print_symbol): Declare. + (bfd_elf{32,64}_print_symbol): Replace declarations with macros. + + * syms.c (bfd_print_symbol_vandf): Show BSF_LOCAL and BSF_GLOBAL + in one column. Use the column freed up to show BSF_FUNCTION and + BSF_FILE. + +Thu Sep 29 12:29:01 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * syms.c (stt): Add .rdata and .rodata. + +Wed Sep 28 13:35:05 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * reloc.c (bfd_install_relocation): Cast data_start to bfd_byte * + before trying to add values to it. + +Tue Sep 27 16:47:58 1994 Ken Raeburn + + * elf32-hppa.c (elf32_hppa_backend_final_write_processing): Cast + return value from elf_sym_extra. + (elf32_hppa_build_stubs): Cast return value from bfd_zalloc. + (elf32_hppa_size_stubs): Cast return value from malloc. + + * gen-aout.c (main): Declare and initialize "arch". + + * cofflink.c (coff_link_add_symbols): Cast return value of + bfd_hash_allocate. + + * riscix.c (riscix_callback): Use PARAMS macro in prototype. + + * reloc.c (bfd_install_relocation): New function, mostly copied + from bfd_perform_relocation, adjusted for the assembler's needs. + * bfd-in2.h: Regenerated. + +Mon Sep 26 11:00:14 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * elfcode.h (assign_file_positions_except_relocs): Align the + section VMA and the file position even if D_PAGED is not set. + + * bfd-in.h (bfd_seek): Change declaration to not mark fp const. + * bfd-in2.h: Rebuild. + * libbfd.c (bfd_seek): Don't mark parameters const, to avoid + conflicts with declaration. + +Fri Sep 23 15:15:31 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * elfcode.h (map_program_segments): Don't abort if we allocated + too much space for the program header, only if we allocated too + little. + (assign_file_positions_except_relocs): Similar change. + +Tue Sep 20 13:17:07 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * libaout.h: Fix comment. + * ns32knbsd.h: Changed M_NS32K_NETBSD to M_532_NETBSD to match + libaout.h. + +Tue Sep 20 15:23:21 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * Makefile.in: Rebuilt dependencies. + (BFD32_BACKENDS): Add sparcnetbsd.o. + (CFILES): Add ns32knetbsd.c and sparcnetbsd.c. + * targets.c: ns32knetbsd_vec was renamed to pc532netbsd_vec. + + * coff-sh.c (rtype2howto): Remove; unused. + (coff_sh_relocate_section): Remove unused local variable rstat. + (reloc_processing): Comment out; unused. + +Fri Sep 16 12:12:27 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * aoutx.h (aout_link_write_other_symbol): If h->indx is -2, then + always write it out even if it would normally be stripped. + (aout_link_input_section_std): If we find a reloc against a + stripped global symbol, force it to be written out rather than + merely calling unattached_reloc. + (aout_link_input_section_ext): Likewise. + (aout_link_reloc_link_order): Likewise. + +Wed Sep 14 15:37:19 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.h (struct somdata): New field sorted_syms. + (obj_som_sorted_syms): Accessor macro. + * som.c (som_object_setup): Initialize sorted_syms to NULL. + (som_prep_for_fixups): Sort a copy of the BFD's symbol table; + store the sorted symbol table in sorted_syms. + (som_write_fixups): Initalize tmp_reloc to NULL to make GCC happy. + (som_begin_writing): Similarly for exec_header. Pass the sorted + symbol table to som_write_symbol_strings. + (som_build_and_write_symbol_table): Use the sorted symbols rather + than the canonical symbol table. + + * som.h (som_symbol_type): Add "stringtab_offset" field. + * som.c (som_write_symbol_strings): Use "stringtab_offset" + rather than destroying the "name" field in the BFD symbol. + (som_build_and_write_symbol_table): Likewise. + +Wed Sep 14 15:06:55 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * aoutx.h (aout_link_write_symbols): Rename skip_indirect to + skip_next. If we find an N_WARNING symbol which has already been + written out, set skip_next. + + * libecoff.h (struct ecoff_tdata): Add field find_buffer. + * ecoff.c: Include aout/stab_gnu.h. + (ecoff_find_nearest_line): Handle stabs debugging information. + + * elfcode.h (elf_link_output_extsym): Keep a symbol marked as weak + even if it is referenced by another object. + +Tue Sep 13 17:57:00 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_fixup_formats): Case R_ENTRY (0xb3), set both + 'T' and 'U' to grab all the unwind information. + (som_set_reloc_info): Make 'U' unwind bits persist across + multiple SOM relocations. Set the addend field of an R_ENTRY + relocation to the value in 'T'; set the addend field on an + R_EXIT relocation to the value in 'U'. + + * som.h (som_symbol_type): Delete unwind field. + + * som.c (som_write_fixups): For R_ENTRY fixups, get 32bits of + unwind information from the addend field of the R_ENTRY, get the + other 32bits from the addend field of the R_EXIT. + (bfd_som_attach_unwind_info): Delete function and all references. + + * som.h (som_symbol_type): Delete unused a.out-related fields. + + * som.c (bfd_section_from_som_symbol): Use bfd_abs_section_ptr + instead of &bfd_abs_section. + + * som.c (som_object_setup): Handle exec_entry and exec_flags being + switched in executables created by the OSF1 linker. + (som_write_fixups): Handle R_EXIT just like the R_{F,L,R}SEL + fixups. Support R_ALT_ENTRY (handle just like R_EXIT). + +Tue Sep 13 16:04:07 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * cofflink.c (coff_link_input_bfd): syment_base is unsigned + so can't compare -ve numbers with it. + +Mon Sep 12 20:31:17 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * configure.in (shcoff_vec): Use cofflink.o now. + * coff-sh.c: Rewritten to use new fast coff backend. + +Tue Sep 13 16:23:57 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * aoutx.h (NAME(aout,final_link)): Don't assume that all the input + files are a.out. + +Tue Sep 13 11:09:39 1994 J.T. Conklin (jtc@rtl.cygnus.com) + + * configure.host (sparc-*-netbsd): use sparcnbsd. + (ns32k-*-netbsd): use ns32knbsd. + + * hosts/{nbsd,i386nbsd,ns32knbsd,sparcnbsd}.h: New files, NetBSD + host support. + + * sparcnetbsd.c: New file, adds support for NetBSD/sparc. + * config/sparc-nbsd.mt: Likewise. + + * netbsd.h: New file, definitions common to all netbsd ports. + * i386netbsd.c: Use it. + * ns32knetbsd.c: Use it. + + * Makefile.in, configure.in, targets.c, config/i386-nbsd.mt, + config/ns32k-nbsd.mt: canonicalize netbsd targets to conform to + file/variable naming conventions. + * i386netbsd.c: New file, renamed from netbsd386.c. + * ns32knetbsd.c: New file, renamed from netbsd532.c. + +Mon Sep 12 21:56:20 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_reloc_skip): Correct off-by-one error for 4-byte + R_NO_RELOCATION fixups. + (bfd_section_from_som_symbol): Return the absolute section if the + symbol isn't contained in any section in the output file. + (som_slurp_symbol_table): ST_PRI_PROG and ST_SEC_PROG symbols are + not function symbols (they are magic code labels which *can* be the + targets of cross space branches). $START$ is not a section symbol. + +Mon Sep 12 11:43:08 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * coff-alpha.c (ecoffalpha_little_vec): Add SEC_CODE and SEC_DATA + to section_flags. + * coff-mips.c (ecoff_little_vec, ecoff_big_vec): Likewise. + + * elfcode.h (swap_out_syms): Set the type of an undefined symbol + to STT_FUNC if the BSF_FUNCTION flag is set. + + * cofflink.c (coff_link_input_bfd): If r_symndx is -1, don't + change it. + (_bfd_coff_generic_relocate_section): If r_symndx is -1, it is an + absolute reloc. Don't dump core using r_symndx as an array index. + * cf-m68klynx.c (coff_bfd_link_add_symbols): Define. + (lynx_link_add_symbols): New static function (copy of function in + coff-i386.c). + (coff_m68k_lynxrtype_to_howto): sym argument may be NULL. + * coff-i386.c (coff_i386_rtype_to_howto): Likewise. + * coff-a29k.c (coff_a29k_relocate_section): Handle an r_symndx + value of -1, meaning an absolute reloc. + + * ctor.c: Remove; obsolete. + * Makefile.in: Rebuild dependencies. + (BFD_LIBS): Remove ctor.o. + (CFILES): Remove ctor.c. + * libbfd.h: Rebuild. + +Mon Sep 12 01:58:47 1994 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (elf32_hppa_relocate_section): If there was a link + error of some sort (for example, undefined symbols), then do not + apply any relocs, just notify the user of the errors. + (elf32_hppa_backend_begin_write_processing): Do not build a symbol + extension section for an executable (it's useless). + (elf32_hppa_link_output_symbol_hook): Do nothing if there was a + link error of some sort (for example, undefined symbols). + (elf32_hppa_read_symext_info): Kludge. Turn off SEC_HAS_CONTENTS + for all the input symbol extension sections to keep the generic + BFD code happy. Temporarily turn it on to read the contents of + the symbol extension section. + +Sun Sep 11 21:58:59 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/hppaosf.mh (RANLIB): Do not set. + * config/hppabsd.mh (RANLIB): Likewise. + +Sun Sep 11 22:50:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * cf-i386lynx.c: Remove #if 0 code. + (i386_lynxos_coff_object_p): Remove unused function. + (coff_bfd_link_add_symbols): Define. + (lynx_link_add_symbols): New static function. + * coffcode.h (coff_bfd_link_hash_table_create): If + coff_relocate_section is defined, only define this if not already + defined. + (coff_bfd_link_add_symbols, coff_bfd_final_link): Likewise. + + * linker.c (_bfd_generic_final_link): Handle + bfd_indirect_link_order explicitly, rather than via + _bfd_default_link_order. + (set_symbol_from_hash): New static function, broken out of + _bfd_generic_link_write_global_symbol. + (_bfd_generic_link_write_global_symbol): Symbol setting code moved + to set_symbol_from_hash; call it. + (default_indirect_link_order): Add generic_linker argument. + Change all callers. If false, set the generic symbols based on + the hash table entries. + +Fri Sep 9 11:51:49 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * coffgen.c (coff_get_symtab): Reindented. Removed commented out + call to bfd_constructor_entry. + + Convert m68k COFF to use new COFF backend linker. + * coff-m68k.c (coff_relocate_section): Define. + * cf-m68klynx.c (coff_rtype_to_howto): Define. + (coff_m68k_lynx_rtype_to_howto): New static function. + * configure.in (m68kcoff_vec): Build cofflink.o. + (m68kcoffun_vec, m68klynx_coff_vec): Likewise. + +Thu Sep 8 16:20:38 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coff-h8300.c (h8300_reloc16_extra_cases, case RELBYTE): Flag + overflows correctly. + +Wed Sep 7 19:01:42 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * libelf.h (struct elf_backend_data): Change second argument of + elf_backend_final_write_processing hook to boolean. + (struct elf_obj_tdata): Add linker field. + * elfcode.h (NAME(bfd_elf,write_object_contents)): Pass value of + tdata linker field to final_write_processing, rather than NULL. + (elf_bfd_final_link): Don't call final_write_processing hook. Set + tdata linker field to true. + * elf32-mips.c (mips_elf_final_write_processing): Change type of + second argument to boolean. + * elf32-hppa.c (elf32_hppa_backend_final_write_processing): + Likewise. + + * coff-go32.c (RTYPE2HOWTO): Fully parenthesize arguments. + * coff-i960.c (RTYPE2HOWTO): Likewise. + * coff-m88k.c (RTYPE2HOWTO): Likewise. + * coff-we32k.c (RTYPE2HOWTO): Likewise. + + Make i386 COFF use new COFF backend linker. + * coff-i386.c (RTYPE2HOWTO): Fully parenthesize arguments. + (coff_relocate_section): Define. + (coff_i386_rtype_to_howto): New function. + * configure.in (i386coff_vec): Use cofflink.o. + (i386lynx_coff_vec): Likewise. + + * coffcode.h (bfd_coff_backend_data): Add new field + _bfd_coff_rtype_to_howto. + (bfd_coff_rtype_to_howto): Define. + (coff_rtype_to_howto): Define to use RTYPE2HOWTO, if not already + defined. + (bfd_coff_std_swap_table): Initialize new field. + * cofflink.c (_bfd_coff_final_link): Allocate section_count + 1 + section_info structures, since the target_index is 1 based. + (coff_link_input_bfd): Set *secpp to bfd_com_section_ptr for a + common symbol. Adjust rel_hash by the output reloc count. + (_bfd_coff_generic_relocate_section): New function. + * libcoff-in.h (_bfd_coff_generic_relocate_section): Declare. + * libcoff.h: Rebuild. + * coff-alpha.c (alpha_ecoff_backend_data): Initialize new field. + * coff-mips.c (mips_ecoff_backend_data): Likewise. + +Tue Sep 6 23:28:52 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_derive_misc_symbol_info): Treat undefined code + symbols and undefined symbols which no type in the same manner + if the associated BFD symbol has BSF_FUNCTION set. For a defined + symbol which no type, select a SOM type based on the flags of the + section containing the symbol. + (som_slurp_symbol_type): Set BSF_FUNCTION for undefined ST_STUB + or ST_CODE symbols (importing a non-function code symbol is + meaningless in SOM). + (som_set_reloc_info): Don't set "offset" to the section's vma; it + should always start at zero. + +Tue Sep 6 14:51:11 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + Add new style linker support to COFF backend. a29k only for now. + * cofflink.c: New file. + * libcoff-in.h: Include bfdlink.h. + (obj_coff_external_syms, obj_coff_strings): Define accessor macro. + (obj_coff_sym_hashes): Define accessor macro. + (struct coff_tdata): Add fields external_syms, strings, and + sym_hashes. + (struct coff_link_hash_entry): Define. + (struct coff_link_hash_table): Define. + (coff_link_hash_lookup, coff_link_hash_traverse): Define. + (coff_hash_table): Define. + (_bfd_coff_link_hash_table_create): Declare. + (_bfd_coff_link_add_symbols, _bfd_coff_final_link): Declare. + * coffcode.h (bfd_coff_backend_data): Add fields _bfd_relsz, + _bfd_coff_swap_reloc_in, _bfd_coff_sym_is_global, + _bfd_coff_compute_section_file_positions, + _bfd_coff_relocate_section. + (bfd_coff_relsz, bfd_coff_swap_reloc_in): Define. + (bfd_coff_sym_is_global): Define. + (bfd_coff_compute_section_file_positions): Define. + (bfd_coff_relocate_section): Define. + (coff_mkobject_hook): Initialize obj_raw_syment_count and + obj_conv_table_size. + (coff_compute_section_file_positions): Set target_index of all + sections. Set output_has_begun field. + (coff_write_object_contents): Don't set target_index; now done by + coff_compute_section_file_positions. Remove obsolete handling of + scn_base and data_base. Don't bother to check that target_index + is positive, since it always is. Remove use of pad, which is + always zero. Check obj_raw_syment_count, not bfd_get_symcount, + for the number of symbols, but only write them out if + bfd_get_symcount is non-zero. Don't check obj_raw_syment_count + until after coff_write_symbols is called. + (coff_slurp_symbol_table): Use obj_raw_syment_count, not + bfd_get_symcount for the number of symbols. Don't set + obj_conv_table_size. + (coff_sym_is_global): New static function or macro. + (coff_slurp_reloc_table): Call coff_swap_reloc_in, not + bfd_swap_reloc_in. + (coff_bfd_link_hash_table_create): If coff_relocate_section is + defined, define as _bfd_coff_link_hash_table_create. + (coff_bfd_link_add_symbols): Similar change. + (coff_bfd_final_link): Similar change. + (coff_relocate_section): Define as NULL if not defined. + (bfd_coff_std_swap_table): Initialize new fields. + * coffgen.c (coff_real_object_p): Don't set obj_raw_syment_count + and obj_conv_table_size here. + (coff_count_linenumbers): Reindent. If bfd_get_symcount is zero, + add up the line numbers from the sections. + (coff_write_symbols): Set obj_raw_syment_count, not + bfd_get_symcount. + (coff_pointerize_aux): Don't pointerize a nonpositive x_endndx + field. + (coff_get_normalized_symtab): Use obj_raw_syment_count, not + bfd_get_symcount. + (coff_print_symbol): If auxp->fix_end, print x_endndx value. + * coffswap.h (coff_swap_reloc_in): Rename from bfd_swap_reloc_in. + Reindent. Change argument type to PTR. + * coff-a29k.c (coff_a29k_relocate_section): New static function. + (coff_relocate_section): Define. + * configure.in (a29kcoff_big_vec): Compile cofflink.o. + * coff-alpha.c (alpha_ecoff_backend_data): Initialize new fields. + * coff-mips.c (mips_ecoff_backend_data): Likewise. + * libcoff.h: Rebuilt. + * Makefile.in: Rebuilt dependencies. + (BFD32_BACKENDS): Add cofflink.o. + (CFILES): Add cofflink.c. + +Tue Sep 6 14:00:45 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * coffgen.c (coff_print_symbol, case bfd_symbol_print_all): Check + for section symbol, and print its aux fields with appropriate + labels. + + * Makefile.in (ALL_MACHINES): Added cpu-arm.o. + +Sun Sep 04 17:58:10 1994 Richard Earnshaw (rwe@pegasus.esprit.ec.org) + + * aoutx.h (NAME(aout,machine_type)): Recognize the ARM processor. + * archures.c, config.bfd, configure.host, libaout.h, reloc.c, + targets.c: Add support for the ARM. + * cpu-arm.c, riscix.c, config/riscix.mh, config/riscix.mt: New files. + + * aoutx.h (add_to_stringtable): Check that str isn't a NULL pointer. + +Fri Sep 2 14:10:30 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * reloc.c (enum bfd_reloc_code_real): Rewrote definition to use + new "chew" commands for simultaneous definition of enumerator and + enumerator name table. + (bfd_get_reloc_code_name): New function, for retrieving a symbolic + name associated with an enumerator. + * libbfd.h, bfd-in2.h: Regenerated. + +Tue Aug 30 21:24:54 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_write_fixups, case R_ENTRY): Handle case where no + unwind descriptor information is available. + +Tue Aug 30 11:43:30 1994 Eric Youngdale (ericy@cais.cais.com) + + * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Add soname + argument, and use it to set DT_SONAME dynamic entry. + * bfd-in.h (bfd_elf32_size_dynamic_sections): Update prototype. + (bfd_elf64_size_dynamic_sections): Update prototype. + * bfd-in2.h: Rebuilt. + +Fri Aug 26 15:47:57 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * coffgen.c (coff_real_object_p): Set obj_raw_syment_count. + (coff_get_normalized_symtab): Verify obj_raw_syment_count, rather + than setting it. + +Thu Aug 25 10:44:53 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * archive.c (bsd_write_armap): Remove host dependencies. + + * aoutx.h (add_to_stringtab): Check for _bfd_stringtab_add error + before adding BYTES_IN_WORD. + + * coffgen.c (coff_find_nearest_line): Look for the best C_FILE, + not merely the first. + + * coffgen.c (coff_write_alien_symbol): If we are not using the + symbol, clear the name so that it is not put in the string table. + From Antti.Miettinen@ntc.nokia.com. + +Wed Aug 24 11:49:19 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * coffgen.c (coff_print_symbol): Cast pointer different to long + and use %ld to print it. + * osf-core.c (osf_core_core_file_p): Remove unused variable + dseccnt. + * ecoffswap.h (ecoff_swap_ext_out): If ECOFF_64, clear remaining + bytes in bits2. + + * configure.host, config.bfd: Change i[34]86 to i[345]86. + * coffgen.c (coff_real_object_p): Set obj_conv_table_size here, + rather than waiting until coff_slurp_symbol_table. + (coff_write_alien_symbol): Just ignore BSF_DEBUGGING symbols. + From Antti.Miettinen@ntc.nokia.com. + + * section.c (bfd_make_section_anyway): Fix failure check of + bfd_make_empty_symbol. From Antti.Miettinen@ntc.nokia.com. + + * aoutx.h (translate_to_native_sym_flags): Use the output_section + (and output_offset) if there is one. + + * aoutx.h (aout_link_check_archive_element): Discard the symbols + if the archive element was not needed. + + * aoutx.h (aout_get_external_symbols): Ensure that a zero string + index yields an empty string. + (aout_link_write_symbols): If info->keep_memory is false, use name + from original hash table entry, not from entry in *sym_hash. + + * aoutx.h (struct aout_final_link_info): Add fields contents, + relocs, symbol_map and output_syms. + (NAME(aout,final_link)): Work out the largest section size, reloc + size, and number of symbols. Use them to preallocate buffers that + are large enough for all cases. + (aout_link_input_bfd): Use preallocated symbol_map. + (aout_link_write_symbols): Remove symbol_map argument; use + preallocated symbol_map instead. Change all callers. Use + preallocated output_syms. + (aout_link_input_section): Remove symbol_map argument. Change all + callers. Use preallocated contents and relocs. + (aout_link_input_section_std): Remove symbol_map argument; use + preallocated symbol_map instead. Change all callers. + (aout_link_input_section_ext): Likewise. + +Tue Aug 23 10:51:09 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * archive.c (_bfd_write_archive_contents): Don't update the + symbol map timestamp if there is no symbol map. From + schwab@issan.informatik.uni-dortmund.de (Andreas Schwab). + +Mon Aug 22 12:26:42 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * targets.c (BFD_JUMP_TABLE_ARCHIVE): Add _update_armap_timestamp. + (bfd_target): Add field _bfd_update_armap_timestamp. + * bfd.c (bfd_update_armap_timestamp): Define. + * bfd-in2.h: Rebuilt. + * libbfd-in.h (_bfd_noarchive_update_armap_timestamp): Define. + (_bfd_archive_bsd_update_armap_timestamp): Declare. + (_bfd_archive_coff_update_armap_timestamp): Define. + * libbfd.h: Rebuilt. + * archive.c (_bfd_write_archive_contents): Call + bfd_update_armap_timestamp instead of checking for a BSD archive + and calling bsd_update_armap_timestamp. + (_bfd_archive_bsd_update_armap_timestamp): Rename from + _bsd_update_armap_timestamp. Don't assume that armap_datepos is + already set. + * aout-target.h (MY_update_armap_timestamp): Define if not already + defined. + * coff-rs6000.c (rs6000coff_update_armap_timestamp): Define. + * ieee.c (ieee_update_armap_timestamp): Define. + * libecoff.h (_bfd_ecoff_update_armap_timestamp): Define. + * oasys.c (oasys_update_armap_timestamp): Define. + * som.c (som_update_armap_timestamp): Define. + + * hash.c: Copy string hash functions from aoutx.h. + * aoutx.h: String hash functions moved to hash.c. Retain + simplified versions of add_to_stringtab and emit_stringtab. + Change all callers to use new function and structure names. + * libbfd-in.h (_bfd_stringtab_init, _bfd_stringtab_free): Declare. + (_bfd_stringtab_size, _bfd_stringtab_add): Declare. + (_bfd_stringtab_emit): Declare. + * libbfd.h: Rebuilt. + +Mon Aug 22 10:49:37 1994 Eric Youngdale (ericy@cais.cais.com) + + * i386linux.c (linux_add_one_symbol): Create a fixup for any + defined absolute symbol, not just GOT or PLT symbols. + (linux_tally_symbols): Correct handling of references to defined + symbols. + +Thu Aug 18 16:29:57 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + Get ld -x -r to handle a.out set symbols correctly. + * aoutx.h (adjust_o_magic): If the .bss VMA was set outside of + BFD, pad the .data section up to the VMA of the .bss section. + (aout_link_add_symbols): If a set symbol does not get modified, + treat it as a local symbol. + (aout_link_write_symbols): Set the value of set symbols + correctly. Don't discard set symbols even if discarding local + symbols. + (aout_link_write_other_symbol): Don't abort on bfd_link_hash_new, + since it can now happen for set symbols. + + * elfcode.h (elf_fake_sections): Just check for ".rela" and + ".rel", not ".rela." and ".rel."; make this work by checking + use_rela_p. + * elf32-i386.c (elf_i386_check_relocs): Just check for ".rel", not + ".rel." + (elf_i386_size_dynamic_sections): Likewise. + (elf_i386_relocate_section): Likewise. + * elf32-sparc.c (elf32_sparc_check_relocs): Just check for + ".rela", not ".rela." + (elf32_sparc_size_dynamic_sections): Likewise. + (elf32_sparc_relocate_section): Likewise. + +Wed Aug 17 16:54:18 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * linker.c (_bfd_generic_link_add_archive_symbols): Initialize + PASS to the old value + 1. + + * coffgen.c (coff_get_normalized_symtab): If a C_FILE symbol has + no aux entries, use the symbol name as the file name. + (coff_find_nearest_line): Look for the right C_FILE symbol, rather + than always using the first one. If there is a debugging symbol + after a function symbol, skip it. Add the section VMA to the line + offset, since it was subtracted out in coff_slurp_line_table. + +Tue Aug 16 16:53:00 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_prep_headers): If writing some form of an executable, + allocate and attach an exec header to the BFD private data. + (som_begin_writing): Don't fill fields of the exec header based + on BFD private data here (like the exec flags). Do not write + the exec header here. + (som_write_headers): Instead do it here. + * som.h (struct somdata): New field "exec_hdr" for the executable + file header. + (obj_som_exec_hdr): New accessor macro. + +Tue Aug 16 00:12:31 1994 Eric Youngdale (ericy@cais.cais.com) + + * i386linux.c (linux_link_create_dynamic_sections): Create section + named .linux-dynamic, not .dynamic. + (linux_add_one_symbol): Use .linux-dynamic, not .dynamic. + (bfd_linux_size_dynamic_sections): Likewise. + (linux_finish_dynamic_link): Likewise. + +Mon Aug 15 12:16:56 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * coffgen.c (STRING_SIZE_SIZE): Define. + (coff_fix_symbol_name): Use STRING_SIZE_SIZE, not 4. + (coff_write_symbols, build_string_table): Likewise. + (coff_get_normalized_symtab): Likewise. + + * libcoff-in.h (obj_symbol_slew): Don't define. + (struct coff_tdata): Remove unused fields index_slew, raw_linenos, + and flags. + * libcoff.h: Rebuilt. + * coffcode.h (coff_mkobject): Don't initialize raw_linenos. + (coff_mkobject_hook): Don't initialize flags. + + * aout-target.h (MY_zmagic_contiguous): Define as 0 if not already + defined. + (MY(backend_data)): Use MY_zmagic_contiguous, not hardcoded 0. + * i386linux.c (MY_zmagic_contiguous): Define. + + * elfcode.h (bfd_section_from_shdr): If a SHT_SYMTAB section in a + shared object has SHF_ALLOC set, create a BFD section for it. + (elf_section_from_bfd_section): There may be a BFD section for a + SHT_SYMTAB section. + + * coffcode.h (styp_to_sec_flags): Add name argument. If no flags + are recognized, chose section flags based on the name. + (bfd_coff_backend_data): _bfd_styp_to_sec_flags_hook field: Add + name argument. + (bfd_coff_styp_to_sec_flags_hook): Add name argument. + (coff_compute_section_file_positions): Don't adjust the section + position by COFF_PAGE_SIZE unless SEC_ALLOC is set. + * libcoff.h: Rebuilt. + * coffgen.c (make_a_section_from_file): Pass section name to + bfd_coff_styp_to_sec_flags_hook. + * ecoff.c (_bfd_ecoff_styp_to_sec_flags): Add unused name + argument. + * libecoff.h (_bfd_ecoff_styp_to_sec_flags): Add name argument to + prototype. + +Fri Aug 12 11:22:40 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * elfcode.h (section_from_elf_index): Correct check for invalid + section index. + + * elfcode.h (elf_link_add_object_symbols): If there is no symbol + table, try using the dynamic symbol table. From Eric Youngdale + . + + * configure.host (sparc-*-solaris2*): Use solaris2, not sysv4. + The linker depends upon configuring for solaris2. + * hosts/solaris2.h: New file; include hosts/sysv4.h. + * config/solaris2.mh: New file; copy of config/sysv4.mh. + +Wed Aug 10 13:09:38 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * aoutx.h (adjust_z_magic): Make sure data section is padded to + page boundary when the VMA is set by the calling program. From + Eric Youngdale . + +Mon Aug 8 17:18:49 1994 Stan Shebs (shebs@andros.cygnus.com) + + Update to ns32k support, from Ian Dall (dall@hfrd.dsto.gov.au). + * aout-ns32k.c: Add declarations that were in aout-ns32k.h, change + declarations to traditional form. + (MY_reloc_howto, MY_put_reloc): Change from macro to function. + (ns32k_relocate_contents): New function. + * aout-ns32k.h: Remove. + * cpu-ns32k.c: Add declarations that were in aout-ns32k.h, change + declarations to traditional form. + (ns32k_final_link_relocate): Call ns32k_relocate_contents. + * netbsd532.c: Reformat to standards, add copyright notice. + (ARCH): Don't define. + (aout-ns32k.h): Don't include. + * pc532-mach.c: Ditto. + +Mon Aug 8 17:55:52 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * coff-i960.c (coff_i960_relocate): Don't try to convert relocs + against common symbols. + +Sat Aug 6 22:27:30 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * irix-core.c (irix_core_core_file_p): Ignore sections that + are not contained in the core file. + +Thu Aug 4 11:32:23 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * coff-m68k.c (m68k_reloc_type_lookup): New function. + (coff_bfd_reloc_type_lookup): Define. + * cf-m68klynx.c (_bfd_m68kcoff_reloc_type_lookup): Define. + + * elfcode.h (elf_bfd_final_link): Force the vma of sections which + do not have SEC_ALLOC set to be 0. This is needed to handle + relocs against debugging sections. + +Wed Aug 3 16:45:41 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * coff-i960.c (coff_i960_relocate): Rewrote to change relocs + against locally defined symbols into relocs against section + symbols, for VxWorks 5.1. + +Wed Aug 3 10:34:37 1994 Eric Youngdale (ericy@cais.cais.com) + + * i386linux.c (linux_add_one_symbol): Only handle + SHARABLE_CONFLICTS specially if BSF_CONSTRUCTOR is set. Set hashp + for a GOT or PLT symbol. Set jump field of fixup for a PLT symbol. + (linux_tally_symbols): Check section of real symbol. When looking + for a builtin fixup, check builtin and jump flags. Create no more + than one fixup, and always create one if the real symbol is in the + absolute section. Only strip absolute symbols. + +Wed Aug 3 05:08:24 1994 D. V. Henkel-Wallace (gumby@cygnus.com) + + * coffcode.h (coff_write_object_contents): set internal_a.magic to + LYNXCOFFMAGIC whenever 68k, SPARC or i386 LynxOS + (yes, they have the same magic number!) + +Tue Aug 2 10:43:21 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * hp300hpux.c (BMAGIC): Define as HPUX_DOT_O_MAGIC, to make test + in aoutx.h work correctly. + + * coff-i960.c (coff_i960_relocate): New function. + (howto_rellong, howto_iprmed): Use it as special_function. + + * libbfd-in.h: Move declarations of bfd_read, bfd_write, bfd_seek, + bfd_tell, bfd_flush, and bfd_stat from here... + * bfd-in.h: ...to here, to make them visible to programs which + know more about the object file format than BFD does. + * libbfd.h, bfd-in2.h: Rebuilt. + +Mon Aug 1 17:55:53 1994 Fred Fish (fnf@cygnus.com) + + * ptrace-core.c (ptrace_unix_core_file_p): Convert zalloc usage + to bfd_zalloc. + +Mon Aug 1 12:04:40 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * elf64-sparc.c (ELF_MAXPAGESIZE): Define. + + ELF linker patches from Eric Youngdale . + * elfcode.h (elf_link_create_dynamic_sections): Set type of + _DYNAMIC to STT_OBJECT. + (NAME(bfd_elf,record_link_assignment)): Always create hash table + entry. Set type to STT_OBJECT. + (elf_link_output_extsym): Don't set type of weak defined symbol to + STB_WEAK if symbol was referenced. + (map_program_segments): Check DYNAMIC as well as EXEC_P. + (assign_file_positions_except_relocs): Likewise. + * elf32-i386.c (elf_i386_create_dynamic_sections): Set type of + _GLOBAL_OFFSET_TABLE to STT_OBJECT. + (elf_i386_check_relocs): Ignore local PLT32 relocs. + (elf_i386_relocate_section): Treat local PLT32 relocs as PC32. + + * elfcode.h (elf_adjust_dynamic_symbol): Correct weak symbol + handling again. + + * elfcode.h (elf_slurp_reloc_table): Don't try to read the relocs + if there aren't any. + + * configure.host (sparc-*-solaris2*): Use sysv4, not solaris2. + * hosts/solaris2.h: Remove. + * config/solaris2.mh: Remove. + +Sun Jul 31 14:27:04 1994 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.c, elf32-hppa.h: Update comment reflecting which + HPPA ELF spec the code implements. + +Tue Jul 26 17:38:01 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * cpu-i960.c (MAX_ARCH): New macro. + (compatible): Use it in computing array bounds. Put comma after + last entry in array, for regularity. + (arch_info_struct): Adjust spacing for easier reading. + + * coff-i960.c (howto_rellong, howto_iprmed, howto_optcall): Use + HOWTO macro. + + +Tue Jul 26 11:04:00 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * elfcode.h (elf_adjust_dynamic_symbol): When handling a weak + symbol, correct check to see whether the equivalent normal symbol + was referenced. + + Add support for creating shared libraries under i386 ELF and SPARC + ELF. Based on patches by Eric Youngdale . + * libelf.h (struct elf_link_hash_entry): Remove copy_offset field. + Add got_offset and plt_offset fields. + (ELF_LINK_HASH_REF_DYNAMIC_MULTIPLE): Don't define. + (ELF_LINK_HASH_DEF_DYNAMIC_MULTIPLE): Don't define. + (ELF_LINK_HASH_NEEDS_COPY): Define. + (struct elf_backend_data): Add check_relocs field. + (struct bfd_elf_section_data): Change relocs from PTR to + Elf_Internal_Rela *. + (struct elf_obj_tdata): Add local_got_offsets field. + (elf_local_got_offsets): Define accessor macro. + (bfd_elf32_link_create_dynamic_sections): Declare. + (bfd_elf32_link_record_dynamic_symbol): Declare. + (bfd_elf64_link_create_dynamic_sections): Declare. + (bfd_elf64_link_record_dynamic_symbol): Declare. + * elfcode.h (elf_slurp_reloc_table): Don't use the section data + relocs field. + (elf_link_record_dynamic_symbol): Make globally visible. Use + macro to rename to NAME(bfd_elf,link_record_dynamic_symbol). + (elf_link_add_object_symbols): If creating a shared library, put + make all local symbols dynamic. Don't bother with the + DYNAMIC_MULTIPLE flags. Call the check_relocs backend function if + it is defined. + (elf_link_create_dynamic_sections): Make globally visible. Use + macro to rename to NAME(bfd_elf,link_create_dynamic_sections). If + creating a shared library, make sure that _DYNAMIC is added as a + dynamic symbol. + (elf_link_read_relocs): New function. + (NAME(bfd_elf,record_link_assignment)): If creating a shared + library, always create symbols, and always make them dynamic. + (elf_bfd_final_link): Permit creation of shared libraries. + (elf_link_input_bfd): Use elf_link_read_relocs to get the relocs. + * elf.c (_bfd_elf_link_hash_newfunc): Don't initialize + copy_offset. Initialize got_offset and plt_offset. + * elf32-target.h (elf_backend_check_relocs): Define as 0 if not + defined. + (elf32_bed): Initialize check_relocs field. + * elf64-target.h (elf_backend_check_relocs): Define as 0 if not + defined. + (elf64_bed): Initialize check_relocs field. + * elf32-i386.c (elf_howto_table): Change R_386_PLT32 and + R_386_GOTPC to be pc_relative and pcrel_offset. + (elf_i386_pic_plt0_entry): Define. + (elf_i386_pic_plt_entry): Define. + (elf_i386_create_dynamic_sections): Create a .got.plt section, and + define _GLOBAL_OFFSET_TABLE_ at the start of it. If creating a + shared library, make sure that _GLOBAL_OFFSET_TABLE_ is added as a + dynamic symbol. Don't create .rel.bss if creating a shared + library. + (elf_i386_check_relocs): New function. + (elf_i386_adjust_dynamic_symbol): Don't make a PLT entry if the + symbol already has one. When making a PLT entry, set plt_offset. + Don't create a copy reloc when creating a shared library. Don't + set copy_offset, just set ELF_LINK_HASH_NEEDS_COPY. + (elf_i386_allocate_dynamic_section): Remove. + (elf_i386_size_dynamic_sections): Look through all the sections + rather than assuming we know their names. Remove any empty reloc + or plt sections. Only add a DT_DEBUG entry if not creating a + shared library. Only add a DT_PLTGOT entry if there is a PLT. + Add a DT_TEXTREL entry if required. + (elf_i386_relocate_section): Permit undefined symbols when + creating a shared library. Handle the special relocation types + specially. + (elf_i386_finish_dynamic_symbol): Create a PLT entry if plt_offset + is set. If creating a shared library, produce a PIC PLT entry. + Only mark a PLT symbol as undefined if it was not defined by a + regular object file. Create a GOT entry if got_offset is set. + Create a copy reloc if ELF_LINK_HASH_NEEDS_COPY is set. + (elf_i386_finish_dynamic_sections): Change the handling of + DT_RELSZ to simply subtract out the size of .rel.plt. If creating + a shared library, produce PIC PLT code. + (elf_backend_check_relocs): Define. + * elf32-sparc.c (elf_sparc_howto_table): Change R_SPARC_GOT10, + R_SPARC_GOT22, and R_SPARC_PC10 to not warn about reloc overflow. + (elf32_sparc_create_dynamic_sections): If creating a shared + library, make sure that _GLOBAL_OFFSET_TABLE_ is added as a + dynamic symbol, and set the type to STT_OBJECT. Likewise for + _PROCEDURE_LINKAGE_TABLE_. Don't create .rel.bss if creating a + shared library. + (elf32_sparc_check_relocs): New function. + (elf32_sparc_adjust_dynamic_symbol): Don't make a PLT entry if the + symbol already has one. When making a PLT entry, set plt_offset. + Don't create a copy reloc when creating a shared library. Don't + set copy_offset, just set ELF_LINK_HASH_NEEDS_COPY. + (elf32_sparc_allocate_dynamic_section): Remove. + (elf32_sparc_size_dynamic_sections): Look through all the sections + rather than assuming we know their names. Only add a DT_DEBUG + entry if not creating a shared library. Add a DT_TEXTREL entry if + required. + (elf32_sparc_relocate_section): Permit undefined symbols when + creating a shared library. Handle the special relocation types + specially. + (elf32_sparc_finish_dynamic_symbol): Create a PLT entry if plt_offset + is set. Only mark a PLT symbol as undefined if it was not defined + by a regular object file. Create a GOT entry if got_offset is + set. Create a copy reloc if ELF_LINK_HASH_NEEDS_COPY is set. + (elf32_sparc_finish_dynamic_sections): Store dynobj in a local + variable. + (elf_backend_check_relocs): Define. + +Mon Jul 25 12:21:07 1994 Stan Shebs (shebs@andros.cygnus.com) + + * configure.in (pc532mach_vec): Change to pc532machaout_vec. + * config.bfd (ns32k-*-netbsd*): Use ns32k-nbsd as bfd_name. + * Makefile.in (ALL_MACHINES): Add cpu-ns32k.o. + (BFD32_BACKENDS): Add aout-ns32k.o, netbsd532.o, m88kmach3.o, + pc532-mach.o. + * targets.c (pc532machaout_vec): Use instead of pc532mach_vec. + * config/pc532-mach.mt (DEFAULT_VECTOR): Ditto. + (SELECT_VECS): Remove. + * config/ns32k-nbsd.mt: New file, was ns32k-netbsd.mt. + * config/ns32k-netbsd.mt: Remove, name too long. + +Fri Jul 22 11:07:14 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * linker.c (generic_link_check_archive_element): When changing a + symbol to common, set the alignment. + (_bfd_generic_link_add_one_symbol): When creating a common symbol, + set the alignment. + * aoutx.h (aout_link_check_ar_symbols): When changing a symbol to + common, set the alignment. + (aout_link_add_symbols): Restrict the alignment of a common symbol + to the alignment power given by the architecture. + * libelf.h (struct elf_link_hash_entry): Remove align field. Add + copy_offset field. + * elfcode.h (elf_link_add_object_symbols): Store alignment in + new bfd_link_hash_entry field, not in elf_link_hash_entry field. + (elf_link_output_extsym): Similar change when getting alignment. + * elf.c (_bfd_elf_link_hash_newfunc): Don't initialize align. Do + initialize copy_offset. + * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Use copy_offset + field rather than align field. Get alignment using bfd_log2 + rather than switch. + * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise. + * elf32-i386.c (elf_i386_finish_dynamic_symbol): Use copy_offset, + not align. + * elf32-sparc.c (elf32_sparc_finish_dynamic_symbol): Likewise. + + * aoutx.h (NAME(aout,some_aout_object_p)): Just check + STAT_FOR_EXEC, don't check MACH. + * m88kmach3.c (MACH): Don't define. + * config/i386-mach3.mt (TDEFINES): Define STAT_FOR_EXEC. + * config/m88k-mach3.mt (TDEFINES): Likewise. + * config/mips-mach3.mt (TDEFINES): Likewise. + +Thu Jul 21 17:24:31 1994 Stan Shebs (shebs@andros.cygnus.com) + + * i386mach3.c: Reverted to version from before Jul 5 1994 changes. + +Thu Jul 21 12:26:01 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * reloc.c (struct reloc_howto_struct): Remove special_function1. + It's the wrong way to do things. + (HOWTO): Change accordingly. + (HOWTO2): Remove. + (_bfd_final_link_relocate): Remove references to + special_function1. + * bfd-in2.h: Rebuilt. + * aoutx.h (aout_link_input_section_std): Remove references to + special_function1. + (aout_link_reloc_link_order): Likewise. + +Wed Jul 20 15:46:44 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Add rpath + argument. If it is not NULL, use it to set DT_RPATH. + * bfd-in.h (bfd_elf32_size_dynamic_sections): Update prototype. + (bfd_elf64_size_dynamic_sections): Likewise. + * bfd-in2.h: Rebuilt. + +Sat Jul 16 21:10:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * elfcode.h (elf_get_dynamic_symtab_upper_bound): If there is no + dynamic symtab, return error. + + * libelf.h (ELF_LINK_HASH_DEFINED_WEAK): Define. + * elfcode.h (elf_link_add_object_symbols): If symbol is defined as + weak, set ELF_LINK_HASH_DEFINED_WEAK. + (elf_link_output_extsym): If symbol is defined as weak, mark it + STB_WEAK. + + * libelf.h (struct bfd_elf_section_data): Add relocs field. + (shdr_name): Remove; unused. + * elfcode.h (elf_slurp_reloc_table): Rewrote to handle both REL + and RELA relocs. Free up the unswapped relocs. Permit the relocs + to be cached in the section_data. Correct the reloc address. + (elf_slurp_reloca_table): Remove. + (elf_canonicalize_reloc): Rewrote. + (elf_link_input_bfd): Permit the relocs to be cached in the + section data. + +Sat Jul 16 13:55:38 1994 Stan Shebs (shebs@andros.cygnus.com) + + * config.bfd (m88*-harris-cxux*): Recognize. + * hosts/harris.h (POSIX_UTIME, HAVE_PROCFS): Define. + + * configure.host (m68*-atari-sysv4*): New host. + (m68*-cbm-sysv4*): Use m68kv4 instead of amix. + * hosts/amix.h: Remove. + * hosts/m68kv4.h: New file, was amix.h. + +Thu Jul 14 15:12:24 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * reloc.c (enum bfd_reloc_code_real, bfd_type, struct + reloc_howto_struct, reloc_howto_type, HOWTO, HOWTO2): Copied + changes over from bfd-in2.h so they get generated properly next + time someone runs "make headers". + * bfd-in2.h: Rebuilt. + + * targets.c (netbsd532_vec, pc532mach_vec): Declare const. + (m88kmach3_vec): Restore deleted declaration. + + * configure.in: Alphabetize target vector names. + + * config/pc532mach.mh: New file. + (HDEPFILES, HDEFINES): Define here. + * config/pc532-mach.mt (HDEPFILES, HDEFINES): Deleted. + * config/ns32k-netbsd.mt (HDEPFILES, HDEFINES): Deleted. + + Sun Jul 10 00:04:20 1994 Ian Dall (dall@hfrd.dsto.gov.au) + + * pc532-mach.c: New File. pc532-mach a.out format. + + * netbsd532.c: New file. pc532-netbsd532 a.out format. + + * hosts/pc532mach.h: New file. pc532-mach host support. + + * cpu-ns32k.c: New file. ns32k support cpu specific code rather + than format specific code. + + * config/pc532-mach.mt: New file. Support for pc532-mach target. + + * config/ns32k-netbsd.mt: New file. Support for netbsd532 target. + + * aout-ns32k.c, aout-ns32k.h: New files supporting aout format for + ns32k series. + + * targets.c: Add netbsd532_vec and pc532machaout_vec into + bfd_target_vector array. Move netbsd386_vec to alphabetic order + location. + + * reloc.c (_bfd_final_link_relocate) Add support for + special_function1 in howto. + + * libaout.h: add M_NS32032, M_NS32532, M_532_NETBSD entries in + machine_type enum. + + * configure.in: add pc532mach_vec and netbsd532_vec entries. + + * config.bfd: add pc532mach host entries. Use for both + ns32k-pc532-mach and ns32k-pc532-netbsd. + + * config.bfd: it doesn't work to use i386-mach3 for ns32k*-*-mach. + add ns32k-pc532-mach* and ns32k-*-netbsd* entries. + + * bfd-in2.h: Add ns32k specific relocations to bfd_reloc_code_real + enum. + + * bfd-in2.h: Add special_function1 to struct howto. Change HOWTO + and NEWHOWTO macros to make special_function1 NULL. Neww HOWTO2 + macro. + + * bfd-in2.h: Split definition of struct reloc_howto_struct + and corresponding typedef into two statements. + + * bfd-in2.h: Add entry bfd_arch_ns32k to bfd_architecture enum. + + * archures.c: Add bfd_ns32k_arch prototype, and entry in + archures_init_table. + + * aoutx.h (aout_link_reloc_link_order): Allow for target dependent + MY_put_reloc macro. Allow for target dependent special_function1 + to apply the relocation. + + * aoutx.h (aout_link_input_section_std): Allow for target + dependent determination of reloc howto. Allow for target dependent + special_function1 to apply the relocation. + + * aoutx.h (get_reloc_upper_bound): Detect bss and return 0. + + * aoutx.h (slurp_reloc_table): Detect bss and succesfully read + zero reloc entries. + + * aoutx.h (machine_type): Add bfd_arch_ns32k case. + + * aoutx.h: Stat to determine executable status if STAT_FOR_EXEC + is defined (not just MACH). Use fstat instead of stat and check + for fstat error. + + * aoutx.h: Allow target dependent swap_std_reloc_{in,out}. + + * aoutx.h: Allow CTORS reloc info to be in target dependent reloc + table. + + * aout-target.h: Apply SWAP_MAGIC (if defined) after + swap_exec_header_in, otherwise we have magic in the wrong order. + +Thu Jul 14 11:47:27 1994 Stan Shebs (shebs@andros.cygnus.com) + + * coff-sparc.c (sparccoff_vec): Have leading underscores. + +Tue Jul 12 12:08:10 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * aix386-core.c, aoutf1.h, cisco-core.c, elfcode.h, hppabsd-core.c, + hpux-core.c, irix-core.c, lynx-core.c, osf-core.c, ptrace-core.c, + rs6000-core.c, trad-core.c: Remove SEC_ALLOC flag from .reg + sections, .reg sections are not allocated and contain debug + information only. + * osf-core.c (make_bfd_asection, osf_core_core_file_p): Use + bfd_make_section_anyway instead of building unique section names. + +Tue Jul 12 11:41:22 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * libelf.h (bfd_elf32_swap_symbol_in): Declare. + (bfd_elf32_swap_symbol_out): Declare. + (bfd_elf64_swap_symbol_in, bfd_elf64_swap_symbol_out): Declare. + * elf32-hppa.c (elf32_hppa_args_hash_table_init): Correct cast. + + * aout-encap.c (ARCH): Don't define. Obsolete. + * aout0.c, aoutx.h, gen-aout.c, hp300bsd.c, hp300hpux.c: Likewise. + * i386aout.c, i386bsd.c, i386dynix.c, i386linux.c: Likewise. + * i386lynx.c, m68klynx.c, mipsbsd.c, netbsd386.c: Likewise. + * newsos3.c, sparclynx.c, sunos.c: Likewise. + +Mon Jul 11 20:08:23 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * section.c (STD_SECTION): Make the sixth argument boolean, not + the seventh. From gary@tuva.pacsemi.oz.au (gary kopff). + +Sun Jul 10 09:12:02 1994 D. V. Henkel-Wallace (gumby@cygnus.com) + + * aoutx.h (bfd_free_cached_info): Change name of FREE to BFCI_FREE + in order not to collide with LynxOS's definition of FREE in + /usr/include/sys/proc.h + +Thu Jul 7 14:18:06 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * reloc.c (bfd_perform_relocation): Don't clobber the relocation + value for coff-Intel-little or coff-Intel-big. Hack upon hack. + +Thu Jul 7 10:10:34 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * aoutx.h (howto_table_std): Add entry for GOT relocations + which are present in sun3 shared libraries, to avoid assertions + when reading the dynamic relocations. + +Thu Jul 7 10:19:20 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.h (R_HPPA_COMPLEX): Fix dumb typo. + +Wed Jul 6 19:21:57 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * hosts/sysv4.h (qsort, strtol): Don't declare. + + * elfcode.h (elf_link_output_sym): Don't call output_symbol_hook + if it is NULL. + + * elf32-mips.c (mips_elf_final_write_processing): Add ignored info + argument to correspond to recent libelf.h change. + +Wed Jul 6 00:48:57 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * coff-alpha.c (alpha_ecoff_mkobject_hook): New hook to + additionally copy object type information from the alpha file + header to the BFD flags. + (alpha_ecoff_backend_data): Use it. + (ecoffalpha_little_vec): Add DYNAMIC to object_flags. + * aout64.c: Fix typo in conditional QMAGIC definition. + +Wed Jul 6 00:13:17 1994 Jeff Law (law@snake.cs.utah.edu) + + * hppabsd-core.c (hppabsd_core_core_file_p): Sanity check the + value of clicksz to help weed out non HPPA BSD core files. + +Tue Jul 5 13:26:02 1994 Stan Shebs (shebs@andros.cygnus.com) + + Mach 3 support. + * config.bfd (m88*-*-mach3*, mips*-dec-mach3*, mips*-*-mach3*): + New targets. + * configure.host (i[34]86-*-mach3*, ns32k-*-mach3*): Recognize + "mach3" instead of "mach". + (m88*-*-mach3*, mips*-dec-mach3*, mips*-*-mach3*): New hosts. + * targets.c (m88kmach3_vec): New target vector. + (bfd_target_vector): Add i386mach3_vec and m88kmach3_vec, but + inside #if 0. + * aoutx.h (some_aout_object_p) [MACH]: Recognize executables by + checking for execute permission, instead of looking at entry + point. + * i386mach3.c: Update, define MACH, N_TXTOFF, N_TXTADDR, + N_SHARED_LIB, don't include aout/*.h files, etc. + * m88kmach3.c: New file, m88k Mach 3 target. + * config/m88k-mach3.mt, config/mips-mach3.mt: New files, target + makefile fragments. + * config/i386mach3.mh, config/m88kmach3.mh, config/mipsmach3.mh: + New files, host makefile fragments. + * hosts/m88kmach3.h, hosts/mipsmach3.h: New files, host definitions. + +Tue Jul 5 13:56:52 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * elfcode.h (swap_out_syms): Get alignment of common symbol from + st_value field of saved ELF symbol information, if there is any. + +Mon Jul 4 19:13:32 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.h (R_HPPA_COMPLEX): Define. + * elf32-hppa.h (R_HPPA_COMPLEX): Define. + (elf32_hppa_reloc_type): Delete R_PARISC_STUB_CALL_17. + +Fri Jul 1 12:07:41 1994 Jeff Law (law@snake.cs.utah.edu) + + * Support code for enabling the new style linker for PA ELF. + * elfcode.h (swap_symbol_in, swap_symbol_out): Externalize. + (elf_compute_section_file_positions): Pass link_info to + the begin_write_processing hook. + (bfd_elf_write_object_contents): Pass NULL for new link_info + argument to final_write_processing hook. + (elf_link_output_sym): Accept new "input_section" argument for + the symbols's input section. All callers changed. Call the + link_output_symbol_hook if it's defined. + (elf_bfd_final_link): Call the final_write_processing hook if + it's defined. + * libelf.h (elf_backend_link_output_symbol_hook): Declare. + (elf_backend_begin_write_processing): Add new "info" argument. + (elf_backend_final_write_processing): Likewise. + * elf32-target.h (elf_backend_link_output_symbol_hook): Provide + a default definition. + (elf32_bed): Add elf_backend_link_output_symbol_hook. + * elf64-target.h: Likewise. + + * Major rework of the PA ELF code. Uses the new style BFD + linker, major cleanups. + * hppa_stubs.h: Rewrite from scratch. Much smaller and simpler. + * elf32-hppa.h: Delete all symbol extension related code. + (hppa_look_for_stubs_in_section): Delete decl. + (elf32_hppa_size_stubs, elf32_hppa_build_stubs): New decls. + * elf32-hppa.c: Symbol extension stuff moved form elf32-hppa.h + into elf32-hppa.c. Do not include aout64.h. + (typdef hppa_stub_type): Delete. + (elf32_hppa_stub_name_list_struct): Delete. + (elf32_hppa_stub_description_struct): Delete. + (arg_reloc_type): Use simpler enumerations. All references changed. + (arg_location, arg_reloc_relocation): Likewise. + (elf32_hppa_symextn_map_struct): Delete. + (get_symbol_value): Delete. + (elf32_hppa_get_sym_extn): Delete. + (find_stubs, new_stubs, type_of_mismatch): Delete. + (find_stub_by_name, add_stub_by_name): Delete. + (hppa_elf_stub_finish, hppa_elf_stub_reloc): Delete. + (hppa_elf_arg_reloc_needed): Renamed. Simplify. + (hppa_elf_build_linker_stub, hppa_elf_create_stub_sec): Delete. + (hppa_elf_long_branch_needed_p): Delete. + (hppa_look_for_stubs_in_section): Delete. + (hppa_elf_get_section_contents): Delete. + (elf32_hppa_backend_symbol_processing): Delete. + (elf32_hppa_backend_section_processing): Delete. + (elf32_hppa_backend_section_from_shdr): Delete. + (elf32_hppa_backend_fake_sections): Delete. + (elf32_hppa_backend_section_from_bfd_section): Delete. + (NEW_INSTRUCTION): Delete. + (CURRENT_STUB_OFFSET): Delete. + (elf32_hppa_relocate_section): New function. + (elf32_hppa_bfd_final_link_relocate): New function. + (elf32_hppa_size_symext): New function. + (elf32_hppa_link_output_symbol_hook): New function. + (elf32_hppa_read_symext_info): New function. + (elf32_hppa_add_symbol_hook): New function. + (elf32_hppa_name_of_stub): New function. + (elf32_hppa_size_of_stub): New function. + (elf32_hppa_build_one_sub): New function. + (elf32_hppa_build_stubs): New function. + (elf32_hppa_size_stubs): New function. + (linker, stub and argument hash tables): Add appropriate + structures, definitions and functions to implement all three + hash tables. + (hppa_elf_relocate_insn): Don't need argument location information + in this function. + (add_entry_to_symext_chain): Accept a symbol's argument location + information rather than the symbol itself. All callers changed. + (hppa_elf_gen_reloc_type): Simplify. + (hppa_elf_set_section_contents): Stub section is no longer special. + (hppa_elf_reloc): Greatly simplify. + (elf32_hppa_begin_write_processing): Accept link_info argument. + Handle being called from the BFD backend linker. + (elf32_hppa_final_write_processing): Likewise. + (elf_hppa_tc_make_sections): No longer call stub_finish. + +Mon Jun 27 18:07:06 1994 Steve Chamberlain (sac@cirdan.cygnus.com) + + * section.c (bfd_get_section_contents): Put in parens to get + precedence right. + +Sun Jun 26 18:08:29 1994 Jeff Law (law@snake.cs.utah.edu) + + * libelf.h (relocate_section): New argument "output_names" added + to prototype. + * elfcode.h (elf_link_input_bfd): New argument "output_names" + added to prototype of relocate_section. Pass the output symbol + names to relocate_section. + * elf32-i386.c (elf_i386_relocate_section): Use "output_names" to + determine the name of a local symbol. + * elf32-mips.c (mips_elf_relocate_section): Likewise. + * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. + +Fri Jun 24 08:15:42 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + Add Solaris BCP (the part of Solaris which allows it to run + SunOS4 a.out files) core file handling. + * aoutf1.h (external_solaris_bcp_core, swapcore_solaris_bcp): + New structure and its swap in function. + (internal_sunos_core): New member c_data_addr, to receive the + start address of the data section in the core file. + (swapcore_sun3, swapcore_sparc, sunos4_core_file_p): Use it. + (sunos4_core_file_p): Recognize Solaris BCP core file. + (sunos4_core_file_matches_executable_p): Always indicate match + for Solaris BCP core files. + +Thu Jun 23 15:31:28 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + Preliminary support for generating shared libraries, from Eric + Youngdale . + * elfcode.h (prep_headers): If DYNAMIC, set e_type to ET_DYN. + (elf_link_add_object_symbols): If generating a shared library, + create dynamic sections for first input BFD with the right format. + (elf_link_create_dynamic_sections): Don't create .interp section + if creating a shared library. + (elf_link_input_bfd): Skip dynamic sections in input file. + (elf_bfd_final_link): If creating a shared library, it's OK for + dynobj to have sections which are not SEC_IN_MEMORY. + * elf32-i386.c (elf_i386_size_dynamic_sections): Only set .interp + section if not creating a shared library. + * elf32-sparc.c (elf_sparc_size_dynamic_sections): Likewise. + + * elfcode.h (elf_object_p): Don't set DYNAMIC just because there + is an SHT_DYNAMIC section. + + * cf-i386lynx.c (i386coff_vec): Don't include DYNAMIC in + object_flags. + * coff-sparc.c (sparccoff_vec): Likewise. + * hppabsd-core.c (hppabsd_core_vec): Likewise. + + * aoutx.h (NAME(aout,some_aout_object_p)): Don't set SEC_RELOC + just because DYNAMIC is set. + +Thu Jun 23 12:53:41 1994 David J. Mackenzie (djm@rtl.cygnus.com) + + * configure.in: Change --with-targets to --enable-targets and + --with-64-bit-bfd to --enable-64-bit-bfd. + * Makefile.in, mpw-make.in, targets.c: Change comments. + +Wed Jun 22 17:59:59 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config.bfd (powerpc-*-elf*): New target, just like + powerpc-*-sysv4*. + + * linker.c (FAIL): Undefine macro before defining as enum. + +Wed Jun 22 10:52:47 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * linker.c (_bfd_generic_link_add_archive_symbols): Initialize + pass from abfd->archive_pass, and save it there as well. + + * hash.c (bfd_hash_allocate): Don't call bfd_set_error if + obstack_alloc returns NULL unless the size is non-zero. + + * linker.c (archive_hash_allocate): Define. + (_bfd_generic_link_add_archive_symbols): Use archive_hash_allocate + rather than obstack_alloc, for clarity. + + * elfcode.h (elf_get_reloc_upper_bound): Correct. + + * aout64.c (BMAGIC, QMAGIC): Define if not already defined. From + Peter Schauer . + + Linux ZMAGIC support from Eric Youngdale . + * libaout.h (struct aoutdata): Add field zmagic_disk_block_size. + * aout-target.h (MY(callback)): Only set alignment according to + architecture if the section sizes are aligned to that alignment, + for backward compatibility. + (MY(set_sizes)): Initialize zmagic_disk_block_size field. + * aoutx.h (adjust_z_magic): Set ztih if using q_magic_format. Set + text section filepos to zmagic_disk_block_size if not ztih. Use a + different padding algorithm if not ztih. + * i386linux.c (MY_text_includes_header): Don't define. + + * aoutx.h (aout_link_check_ar_symbols): Just skip N_STAB and N_FN + symbols; don't look them up in the hash table. From + ralphc@pyramid.com (Ralph Campbell). + +Tue Jun 21 11:47:20 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * coff-go32.c (go32coff_archive_p): Remove unused function. + + * section.c (bfd_abs_section): Make const. + (bfd_abs_section_ptr, bfd_is_abs_section): Define. + (bfd_und_section): Make const. + (bfd_und_section_ptr, bfd_is_und_section): Define. + (bfd_com_section): Make const. + (bfd_com_section_ptr): Define. + (bfd_ind_section): Make const. + (bfd_ind_section_ptr, bfd_is_ind_section): Define. + (bfd_abs_symbol, bfd_com_symbol): Make const. + (bfd_und_symbol, bfd_ind_symbol): Likewise. + (global_syms): Cast initialization of section field. + (STD_SECTION): Define as const, and cast initializations. + * bfd-in2.h: Rebuilt. + * Many files: Change uses of bfd_abs_section, etc., to use + bfd_abs_section_ptr or bfd_is_abs_section, etc. + +Mon Jun 20 11:06:27 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * Many files: change all bfd_target vectors to be const. Change + all uses of bfd_target * to be const bfd_target *. Change + bfd_target_vector and bfd_default_vector arrays to be const + bfd_target * const *. + + * ecoff.c, libecoff.h, ecoffswap.h, coff-alpha.c, coff-mips.c, + elf32-mips.c: Renamed all externally visible ECOFF routines which + are local to BFD to start with _bfd_ecoff instead of just ecoff. + + * ecoff.c (ecoff_swap_tir_in): Change input argument to const. + (ecoff_swap_tir_out): Likewise. + (ecoff_swap_rndx_in, ecoff_swap_rndx_out): Likewise. + (ecoff_slurp_symbolic_info): Add new arguments to correspond to + read_debug_info entry point in ecoff_debug_swap structure. + Change all calls. + * libecoff.h (ecoff_slurp_symbolic_info): Change declaration. + * ecoffswap.h (ecoff_swap_tir_in, ecoff_swap_tir_out): Declare. + (ecoff_swap_rndx_in, ecoff_swap_rndx_out): Declare. + * coff-alpha.c (alpha_ecoff_backend_data): Initialize new + ecoff_debug_swap fields. + * coff-mips.c (mips_ecoff_backend_data): Likewise. + * elf32-mips.c (mips_elf_read_ecoff_info): Undefine READ. + (mips_elf_ecoff_debug_swap): Initialize new ecoff_debug_swap + fields. + * configure.in (bfd_elf32_bigmips_vec): Use ecoff.o and + ecofflink.o. + (bfd_elf32_littlemips_vec): Likewise. + (ecoff_big_vec, ecoff_little_vec): Likewise. + (ecoffalpha_little_vec): Likewise. + * Makefile.in (BFD_LIBS): Remove ecoff.o and ecofflink.o. + (BFD32_BACKENDS): Add ecoff.o and ecofflink.o. + + * aoutx.h (NAME(aout,final_link)): Check flavour of sub, not abfd, + when computing reloc sizes. From Eric Youngdale + . + * elfcode.h (elf_bfd_final_link): Don't try to compute maximum + reloc count or size for a non-ELF file. + + * mipsbsd.c (MY_final_link_callback): Define to avoid warning. + + * hp300hpux.c (MY_final_link_callback): Define to avoid warning. + (BMAGIC, QMAGIC): Define; used by aoutx.h. + (MY(slurp_symbol_table)): Change translate_from_native_sym_flags + calls to use new parameters. + +Fri Jun 17 14:45:32 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aout-target.h (MY(callback)): Set the alignments of the text, + data and bss sections after determining the architecture. + + * sunos.c (sunos_add_one_symbol): Treat a common symbol from a + dynamic object as being in the .bss section of the object, rather + than as being undefined. + +Fri Jun 17 11:16:50 1994 Jeff Law (law@snake.cs.utah.edu) + + * libhppa.h (bfd_hppa_insn2fmt, hppa_rebuild_insn): Make INLINE. + + * elf32-hppa.h (elf_hppa_final_processing): Delete decl. + +Thu Jun 16 23:36:23 1994 Jeff Law (law@snake.cs.utah.edu) + + * elfcode.h (elf_link_input_bfd): Don't try to read local symbols + if there aren't any in the input file. + +Thu Jun 16 14:25:22 1994 Eric Youngdale (ericy@cais.cais.com) + + * i386linux.c: Many new functions and definitions for linker + support for Linux shared libraries. + * bfd-in.h (bfd_linux_size_dynamic_sections): Declare. + * bfd-in2.h: Rebuild. + +Thu Jun 16 14:23:46 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config.bfd: If second argument is ``_'', then, instead of + echoing config file name, echo whether target uses leading + underscores on symbol names. Add appropriate settings to + different cases. Used by binutils/configure.in to set default for + c++filt. + + * elfcode.h (elf_bfd_final_link): If trying to generate a shared + object, warn and return false. + + * aoutx.h (NAME(aout,some_aout_object_p)): Accept BMAGIC objects + and treat them as OMAGIC. + +Wed Jun 15 18:02:21 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + Enable sparc v9 support for release. Note that this is still a + work in progress, pending release of an ABI specification. + * config.bfd, configure.in: Include sparc v9 elf config. + * elfcode.h (prep_headers): Handle sparc v9 (64 bit). + * reloc.c (bfd_reloc_code_real): New reloc types. + * elf64-sparc.c: Implement elf64-sparc target. + * Makefile.in, targets.c: Updated. + +Wed Jun 15 01:34:07 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * libelf.h (struct elf_obj_tdata): New field dt_needed_name. + (elf_dt_needed_name): New accessor macro. + * elfcode.h (elf_link_add_object_symbols): If elf_dt_needed_name + is set, use that instead of the filename for the DT_NEEDED dynamic + entry. + * elf.c (bfd_elf_set_dt_needed_name): New function. + * bfd-in.h (bfd_elf_set_dt_needed_name): Declare. + * bfd-in2.h: Rebuilt. + + * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Add sinterpptr + argument, and set it to the .interp section. + * bfd-in.h (bfd_elf32_size_dynamic_sections): Update prototype. + (bfd_elf64_size_dynamic_sections): Likewise. + * bfd-in2.h: Rebuilt. + + * coff-sparc.c (SWAP_OUT_RELOC_EXTRA): Define to clear the r_spare + field of the reloc rather than letting it be garbage. + + * archive.c (bfd_slurp_armap): Recognize __.SYMDEF/ as well as + __.SYMDEF; the former was used in old Linux archives. From + jrs@world.std.com (Rick Sladkey). + + * i386linux.c (i386linux_write_object_contents): Define; like + MY(write_object_contents) in aout-target.h, but set MACHTYPE to + M_386. From jrs@world.std.com (Rick Sladkey). + (MY_write_object_contents): Define. + + * aoutx.h (translate_from_native_sym_flags): Treat N_SETV symbols + as N_DATA symbols. + (aout_link_add_symbols): Likewise. + + * aoutx.h: Rewrite symbol duplicate elimination to use BFD hash + tables. + (struct stringtab_entry, struct stringtab_data): Remove. + (HASHMAXLEN, HASH_CHAR, hash, compare, log2, emit_strtab): Remove. + (struct strtab_hash_entry, struct strtab_hash): Define. + (strtab_hash_newfunc, strtab_hash_lookup): Define. + (stringtab_free, emit_stringtab): Define. + (stringtab_init, add_to_stringtab): Rewrite. + (NAME(aout,write_syms)): Use new stringtab code. + (struct aout_final_link_info, NAME(aout,final_link)): Likewise. + (aout_link_write_symbols, aout_link_write_other_symbol): Likewise. + + * bfd-in.h (BFD_TRADITIONAL_FORMAT): Define new BFD flag to + request BFD to write object in the traditional format, whatever + that means for the particular backend. + * bfd-in2.h: Rebuilt. + + * hash.c (bfd_hash_allocate): If obstack_alloc fails, set + bfd_error_no_memory. + +Tue Jun 14 13:00:04 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * libaout.h (struct aoutdata): Add q_magic_format to subformat + enum. + * aout-target.h (MY_bfd_copy_private_bfd_data): Define as function + if not already defined. Copy subformat information. + (MY_text_includes_header): Define as 0 if not already defined. + (MY(backend_data)): Use MY_text_includes_header rather than 0. + (MY_final_link_callback): Rename from final_link_callback, and + define only if MY_final_link_callback is not already defined. + (MY_bfd_final_link): Rename use of final_link_callback to + MY_final_link_callback. + * aoutx.h (NAME(aout,some_aout_object_p)): Handle QMAGIC like + ZMAGIC, but set the subformat to q_magic_format. Abort if the + magic number if not recognized. + (adjust_z_magic): Use QMAGIC if q_magic_format. + * i386linux.c (MY_text_includes_header): Define as 1. + (i386linux_bfd_final_link): New static function. + (MY_bfd_final_link): Define as i386linux_bfd_final_link. + + * aoutx.h (translate_to_native_sym_flags): Check both section and + output_section against sections of abfd. + + * libecoff.h (struct ecoff_link_hash_entry): Change type of + written from boolean to char. Add new field small. + * ecoff.c (ecoff_link_hash_newfunc): Initialize written to 0 + rather than false. Initialize small to 0. + (ecoff_link_add_externals): If ECOFF type is scSUndefined, set + small. If small is set, and hash table type is common, force the + symbol into a section named SCOMMON and change the ECOFF type from + scCommon to scSCommon. + (ecoff_link_write_external): Set written to 1 rather than true. + * coff-mips.c (mips_relocate_section): Correct JMPADDR reloc + overflow check to consider section VMA of input file. + +Mon Jun 13 14:20:07 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutf1.h (aout_32_sunos4_write_object_contents): Handle a + machine type of 68000. + * aoutx.h (NAME(aout,machine_type)): Add new argument unknown. + Set *unknown to true if machine type is really unknown, as opposed + to M_UNKNOWN for the 68000. + (NAME(aout,set_arch_mach)): Change NAME(aout,machine_type) call + accordingly. + * libaout.h (NAME(aout,machine_type)): Add new argument to + prototype. + +Sun Jun 12 20:21:03 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (EXEC_AUX_ID): Define based on availablity of HPUX_AUX_ID + or HIUX_AUX_ID. + (som_begin_writing): Use EXEC_AUX_ID instead of HPUX_AUX_ID. + (som_write_armap): Use CPU_PA_RISC1_0 as the magic number. Note + som.c is careful to always define CPU_PA_RISC1_0. + +Sat Jun 11 16:32:30 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Add weak symbols as an extension to a.out. + * aoutx.h (sym_in_text_section): Don't define. + (sym_in_data_section, sym_in_bss_section): Likewise. + (sym_is_undefined, sym_is_global_defn): Likewise. + (sym_is_debugger_info, sym_is_fortrancommon): Likewise. + (sym_is_absolute, sym_is_indirect): Likewise. + (translate_from_native_sym_flags): Rewrite for clarity. Rearrange + arguments and change caller. Handle weak symbols. + (translate_to_native_sym_flags): Likewise. + (aout_link_check_ar_symbols): Don't ignore weak symbols. Pull + object in from archive if a weak defintion is found for an + existing undefined symbol. + (aout_link_add_symbols): Put all cases in switch. Set flags of an + undefined symbol to 0. Handle weak symbols. + (aout_link_write_symbols): Handle weak symbols. + (aout_link_write_other_symbol): Likewise. + (aout_link_input_section_std): Likewise. + (aout_link_input_section_ext): Likewise. + * sunos.c (sunos_write_dynamic_symbol): Likewise. + +Fri Jun 10 13:25:13 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (NAME(aout,canonicalize_reloc)): Handle .bss section. + (NAME(aout,get_reloc_upper_bound)): Likewise. + + * coff-i960.c (coff_i960_reloc_type_lookup): Add BFD_RELOC_CTOR. + * linker.c (_bfd_generic_link_write_global_symbol): Don't assume + the section of a common symbol is not NULL. + +Wed Jun 8 23:15:53 1994 Stu Grossman (grossman@cygnus.com) + + * nlmcode.h (nlm_object_p): Set EXEC_P and start address for GDB. + +Wed Jun 8 23:57:34 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (aout_get_external_symbols): Don't try to read the + strings if there are no symbols. + (aout_link_write_other_symbol): Use the output section when + working out the type. + +Tue Jun 7 13:25:08 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (assign_section_numbers): Put shstrtab, symtab and + strtab sections at end of file. Avoids bug in some versions of + SVR4 strip. From Eric Youngdale . + + * coffcode.h (styp_to_sec_flags): If COFF_PAGE_SIZE is defined, + set SEC_DEBUGGING for STYP_INFO sections. + (coff_compute_section_file_positions): If COFF_PAGE_SIZE is + defined, and D_PAGED is set, set the file position equal to the + section VMA modulo COFF_PAGE_SIZE. + * coffgen.c (coff_real_object_p): If F_EXEC is set, set D_PAGED. + * coff-i386.c: Set D_PAGED in BFD target. + (COFF_PAGE_SIZE): Define. + * coff-m68k.c, coff-sparc.c: Likewise. + +Mon Jun 6 10:57:28 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (bfd_section_from_shdr): Don't turn a reloc section + into a BFD section just because SHF_ALLOC is set; require that it + not use the normal symbol table. + (elf_section_from_bfd_section): Corresponding change. + + Better indirect and warning symbol handling inspired by Stuart + Quick . + * linker.c (enum link_action): Add REF, MIND, CWARN, REFC. + (link_action): Change UNDEF_ROW/def and UNDEFW_ROW/def from NOACT + to REF. Change UNDEF_ROW/indr and UNDEFW_ROW/indr from CYCLE to + REFC. Change DEF_ROW/indr and COMMON_ROW/indr from CYCLE to MDEF. + Change DEFW_ROW/indr from CYCLE to NOACT. Change INDR_ROW/indr + from MDEF to MIND. Change INDR_ROW/warn from WARNC to CYCLE. + Change WARN_ROW/def and WARN_ROW/indr from MWARN to CWARN. Change + WARN_ROW/com from MWARN to WARN. Change WARN_ROW/warn from NOACT + to CYCLE. Change SET_ROW/warn from WARNC to CYCLE> + (_bfd_generic_link_add_one_symbol): Handle REF, MIND, CWARN and + REFC. If a new indirect symbol has been referenced, push the + reference down to the symbol it points to. FIx handling of WARN. + * aoutx.h (translate_from_native_sym_flags): If N_WARNING, don't + clobber e_type of next symbol. + (translate_to_native_sym_flags): Likewise. + (aout_link_write_symbols): Loop on bfd_link_hash_warning as well + as bfd_link_hash_indirect. + + * libaout.h (struct aout_link_hash_entry): New field written. + * aoutx.h (NAME(aout,link_hash_newfunc)): Initialize written. + (aout_link_write_symbols): Use written, not root.written. + (aout_link_write_other_symbol): Likewise. + * sunos.c (sunos_scan_dynamic_symbol): Likewise. + * libecoff.h (struct ecoff_link_hash_entry): New field written. + * ecoff.c (ecoff_link_hash_newfunc): Initialize written. + (ecoff_link_write_external): use written, not root.written. + * genlink.h (struct generic_link_hash_entry): New field written. + * linker.c (_bfd_link_hash_newfunc): Don't initialize written. + (generic_link_hash_newfunc): Initialize written. + (_bfd_generic_link_output_symbols): Use written, not root.written. + (_bfd_generic_link_write_global_symbol): Likewise. + (_bfd_generic_reloc_link_order): Likewise. + + * libecoff.h (ecoff_data_type): Add linker field. + * ecoff.c (ecoff_write_object_contents): Check new tdata linker + field, rather than outsymbols being non-NULL, to decide whether to + output the symbols and relocs. + (ecoff_bfd_final_link): Set new tdata linker field to true. + + * ecoff.c (ecoff_bfd_copy_private_bfd_data): Don't try to copy + data to a non-ECOFF file. + + * libbfd-in.h: Add warning that libbfd.h is a generated file. + * libbfd.h: Rebuilt. + +Sun Jun 5 15:02:30 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Changes to support ELF strip and objcopy on dynamically linked + files. + * elfcode.h (elf_fake_sections): Add prototype. + (bfd_section_from_shdr): Make a BFD section from an SHT_HASH + section, and from an SHT_DYNSYM section, and from the dynamic + string table section. + (elf_object_p): Set D_PAGED if there is a program header. + (elf_make_sections): Remove. + (fix_up_strtabs): Remove. + (elf_fake_sections): Rewrite. Now sets sh_entsize. + (assign_section_numbers): Rewrite. Now sets sh_link and sh_info + for all sections. + (elf_compute_section_file_positions): Don't call obsolete + functions elf_make_sections or fix_up_strtabs. + (swap_out_syms): Set sh_addralign to FILE_ALIGN rather than 4. + (NAME(bfd_elf,write_object_contents)): Permit writing DYNAMIC + objects. + (elf_section_from_bfd_section): Treat SHT_DYNSYM like other normal + sections. If an SHT_REL or SHT_RELA section is allocated or uses + an unusual symbol table, permit a BFD section to map to it. + Permit most SHT_STRTAB sections to have a BFD section mapped to + them. + (elf_bfd_final_link): Don't set sh_link, sh_info or sh_entsize + fields of dynamic sections here; do it in assign_section_numbers. + * elf32-target.h, elf64-target.h: Add D_PAGED to permitted object + flags. + + * elf.c (_bfd_elf_make_section_from_shdr): Only set SEC_DATA if + SEC_LOAD is set, rather than checking SEC_ALLOC. + + * libbfd-in.h (bfd_realloc): Change last arg to "size_t size". + +Fri Jun 3 10:58:02 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_write_object_contents): Don't compute the file header's + checksum here. + (som_write_headers): Instead do it here. + + * libbfd.h (bfd_realloc): Change last arg to "size_t size". + +Thu Jun 2 17:39:22 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * hosts/sun3.h: Include . Don't declare free, exit or + getenv. + + Add linker support for SunOS shared libraries. + * sunos.c: Include bfdlink.h. Add many new functions and + definitions for SunOS shared library support. + * bfd-in.h (bfd_sunos_record_link_assignment): Declare. + (bfd_sunos_size_dynamic_sections): Declare. + * bfd-in2.h: Rebuilt. + * aoutx.h (struct aout_link_hash_entry): Move to libaout.h. + (struct aout_link_hash_table): Likewise. + (aout_link_hash_lookup, aout_link_hash_traverse): Likewise. + (aout_hash_table): Likewise. + (NAME(aout,link_hash_newfunc)): Rename from aout_link_hash_newfunc + and make externally visible. + (NAME(aout,link_hash_table_init)): New function. + (NAME(aout,link_hash_table_create)): Call + NAME(aout,link_hash_table_init), not _bfd_link_hash_table_init. + (aout_link_add_symbols): Don't fail if no symbols. If it exists, + call add_dynamic_symbols backend entry point for dynamic objects. + Use add_one_symbol backend entry point if it exists. + (NAME(aout,final_link)): Call finish_dynamic_link backend entry + point, if it exists. + (aout_link_input_bfd): For a dynamic object, call + link_dynamic_object backend entry point, if it exists. + (aout_link_write_other_symbol): Call write_dynamic_symbol backend + entry point, if it exists. + (aout_link_input_section): Don't read the relocs if they have + already been read. + (aout_link_input_section_std): When doing a final link, for a + reloc against an external symbol, call check_dynamic_reloc backend + entry point, if it exists. + (aout_link_input_section_ext): Likewise. + * libaout.h: Protect against multiple inclusion. Include + bfdlink.h. + (struct aout_link_hash_entry): Move in from aoutx.h. + (struct aout_link_hash_table): Likewise. + (aout_link_hash_lookup, aout_link_hash_traverse): Likewise. + (aout_hash_table): Likewise. + (struct aout_backend_data): Add fields add_dynamic_symbols, + add_one_symbol, link_dynamic_object, write_dynamic_symbol, + check_dynamic_reloc, and finish_dynamic_link. + (struct aout_section_data_struct): Define new structure. + (aout_section_data): Define new accessor macro. + (NAME(aout,link_hash_newfunc)): Declare. + (NAME(aout,link_hash_table_init)): Declare. + * aoutf1.h (sunos4_aout_backend): Initialize new aout_backend_data + fields. + * aout-target.h (MY(backend_data)): Likewise. + * i386aout.c (MY(backend_data)): Likewise. + * i386mach3.c (MY(backend_data)): Likewise. + * mipsbsd.c (MY(backend_data)): Likewise. + * sparclynx.c (sparclynx_aout_backend): Likewise. + + * aoutx.h (NAME(aout,slurp_symbol_table)): Don't zero out cached + until we know it is non-NULL. + (aout_link_write_symbols): Don't skip a warning symbol even if it + has already been written out. If skipping an indirect symbol, + skip the next symbol as well. + +Wed Jun 1 14:37:50 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * hosts/sun3.h: Don't declare qsort, malloc or realloc. + +Thu May 26 13:56:03 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * nlmcode.h (nlm_swap_auxiliary_headers_in): Cast bfd_byte pointer + to char pointer to avoid compiler warnings. + + * dep-in.sed: Remove spaces before colons. + + Merged changes back in from FSF gas release 2.3: + + * Makefile.in (stmp-bfd.h): Wrap `if' block around grep + invocation, to avoid a bug in BSD 4.4 make. + + From Ralph Campbell: + * mipsbsd.c (mips_fix_jmp_addr): If symbol is undefined, return an + error. + (mips_fix_hi16_s): Ditto. + + Fri May 13 21:21:00 1994 DJ Delorie (dj@ctron.com) + + * makefile.dos: define a default target, or archives won't work + due to multiple matches. + + Wed May 11 22:32:00 1994 DJ Delorie (dj@ctron.com) + + * configure.bat: update for latest files + * makefile.dos: update for correct targets and sources + * coff-go32.c: [new] go32's COFF format (i386coff with underscores) + * targets.c: add go32coff target + * makefile.in: add coff-go32.c support + +Thu May 26 10:10:21 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_prep_headers): Do not set the system_id here, private + bfd data has not been copied yet. + (som_write_headers): Instead do it here. + +Tue May 24 16:17:18 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Make MIPS ELF use new ELF backend linker. No shared library + support yet. + * elf32-mips.c (bfd_mips_elf32_swap_gptab_in): New function. + (bfd_mips_elf32_swap_gptab_out): New function. + (mips_elf_object_p): If last symbol is LOCAL, set elf_bad_symtab. + (mips_elf_final_write_processing): Set sh_info field for .gptab.* + sections. + (mips_elf_fake_sections): Set sh_entsize for .gptab.* sections. + (mips_elf_read_ecoff_info): Read and free external symbols last, + not first, for clarity. + (struct mips_elf_link_hash_entry): Define new structure. + (struct mips_elf_link_hash_table): Define new structure. + (mips_elf_link_hash_lookup): Define new macro. + (mips_elf_link_hash_traverse): Define new macro. + (mips_elf_hash_table): Define new macro. + (mips_elf_link_hash_newfunc): New static function. + (mips_elf_link_hash_table_create): New static function. + (mips_elf_add_symbol_hook): New static function. + (struct extsym_info): Define new structure. + (mips_elf_get_extr, mips_elf_set_index): Remove. + (mips_elf_output_extsym): New static function. + (gptab_compare): New static function. + (mips_elf_final_link): Rewrite to use ELF backend linker, and to + merge gptab information in input files. + (mips_elf_relocate_hi16): New static function. + (mips_elf_relocate_section): New static function. + (bfd_elf32_bfd_link_hash_table_create): Define as macro before + including elf32-target.h. + (elf_backend_relocate_section): Likewise. + (elf_backend_add_symbol_hook): Likewise. + * elf.c (_bfd_elf_link_hash_newfunc): Rename from + elf_link_hash_newfunc and make globally visible. Change caller. + (_bfd_elf_link_hash_table_init): New function, broken out of + _bfd_elf_link_hash_table_create. + (_bfd_elf_link_hash_table_create): Use + _bfd_elf_link_hash_table_init. + * libelf.h (struct elf_obj_tdata): Add new field bad_symtab. + (elf_bad_symtab): Define new accessor macro. + (_bfd_elf_link_hash_newfunc): Declare. + (_bew_elf_link_hash_table_init): Declare. + * elfcode.h (elf_object_p): Call backend object_p hook after + swapping in all the section headers. + (map_program_segments): Correct typo: Internal for External. + (elf_link_add_object_symbols): If elf_bad_symtab is set, read all + the symbols. Skip STB_LOCAL symbols rather than giving an error. + (elf_bfd_final_link): If elf_bad_symtab is set, allocate space for + all symbols, not just locals. + (elf_link_output_extsym): Only skip a symbol not mentioned by a + regular file if it is mentioned by a dynamic object. + (elf_link_input_bfd): If elf_bad_symtab is set, read all the + symbols. + +Fri May 20 13:38:23 1994 Jeff Law (law@snake.cs.utah.edu) + + * som.c (som_set_reloc_info): Do not set any relocation info + for SOM fixups which are never passed to BFD. + +Fri May 20 11:57:05 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-mips.c (mips_relocate_section): Add MIPS_R_JMPADDR overflow + checking. + + * elf32-i386.c (elf_i386_size_dynamic_sections): Add DT_DEBUG to + the dynamic linking information for the benefit of the debugger. + From Peter Schauer. + * elf32-sparc.c (elf32_sparc_size_dynamic_sections): Likewise. + + * elf.c (_bfd_elf_make_section_from_shdr): New function, based on + code repeated three times in bfd_section_from_shdr in elfcode.h. + * libelf.h (_bfd_elf_make_section_from_shdr): Declare. + * elfcode.h (bfd_section_from_shdr): Use new function + _bfd_elf_make_section_from_shdr to create BFD sections. If a + reloc section does not use the main symbol table, or it is part of + the process image, treat it as a normal section, not relocs. + * elf32-mips.c (mips_elf_section_from_shdr): Use new function + _bfd_elf_make_section_from_shdr. + +Thu May 19 11:37:11 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elf32-target.h, elf64-target.h: Change ar_max_namelen value from + 15 to 14 to match SVR4 ar. + + Add support for ELF shared libraries. Loosely based on work by + Eric Youngdale . + * libelf.h (struct elf_backend_data): Add new fields for dynamic + linking: elf_backend_create_dynamic_sections, + elf_backend_adjust_dynamic_symbol, + elf_backend_size_dynamic_sections, + elf_backend_finish_dynamic_symbol, + elf_backend_finish_dynamic_sections. + (struct elf_link_hash_entry): Change type of align field to + bfd_size_type. Add fields dynindx, dynstr_index, weakdef, + elf_link_hash_flags. + (struct elf_link_hash_table): Add fields dynobj, dynsymcount, + dynstr, bucketcount. + (bfd_elf32_swap_reloc_in, bfd_elf32_swap_reloc_out): Declare. + (bfd_elf32_swap_reloca_in, bfd_elf32_swap_reloca_out): Declare. + (bfd_elf32_swap_dyn_in, bfd_elf32_swap_dyn_out): Declare. + (bfd_elf32_add_dynamic_entry): Declare. + (bfd_elf64_swap_reloc_in, bfd_elf64_swap_reloc_out): Declare. + (bfd_elf64_swap_reloca_in, bfd_elf64_swap_reloca_out): Declare. + (bfd_elf64_swap_dyn_in, bfd_elf64_swap_dyn_out): Declare. + (bfd_elf64_add_dynamic_entry): Declare. + * elfcode.h (Elf_External_Dyn): Define. + (elf_swap_reloc_in): Define as macro using NAME. Make externally + visible. + (elf_swap_reloc_out): Likewise. + (elf_swap_reloca_in, elf_swap_reloca_out): Likewise. + (elf_swap_dyn_in, elf_swap_dyn_out): Define as macro using NAME + and as new externally visible function. + (elf_fake_sections): Set section type of dynamic sections based on + section names. + (elf_write_phdrs): Remove. + (assign_file_position_for_section): Add new align argument. + Change all callers. + (get_program_header_size): New static function. + (struct seg_info): Remove. + (map_program_segments): Completely rewrite. + (assign_file_positions_except_relocs): Completely rewrite. + (assign_file_positions_for_relocs): Don't set a file position for + sections which already have one. Don't bother to align the file + position here. + (section_from_elf_index): Handle SHT_HASH and SHT_DYNAMIC + section types. + (elf_section_from_bfd_section): Likewise. + (elf_slurp_symbol_table): If section_from_elf_index fails, just + use bfd_abs_section rather than returning an error. + (elf_sizeof_headers): Make useful. + (elf_link_record_dynamic_symbol): New static function. + (elf_link_add_object_symbols): Handle dynamic objects. + (elf_link_create_dynamic_sections): New static function. + (elf_add_dynamic_entry): Define as macro using NAME and as new + externally visible function. + (NAME(bfd_elf,record_link_assignment)): New function. + (elf_buckets): New static variable. + (NAME(bfd_elf,size_dynamic_sections)): New function. + (struct elf_final_link_info): Add dynsym_sec and hash_sec fields. + (elf_bfd_final_link): Handle dynamic linking. Create a section + symbol for all ELF sections, not all BFD sections. Store section + symbol index in target_index field, not index field. Traverse + over global symbols even if stripping. + (elf_link_output_extsym): Output dynamic symbols. Mark symbols + defined by dynamic objects as undefined. + (elf_link_input_bfd): Ignore dynamic objects. Use target_index + field for section relocs, and make sure it is set. + (elf_reloc_link_order): Use target_index field for section relocs, + and make sure it is set. + * elf.c (elf_link_hash_newfunc): Initialize dynindx, dynstr_index, + weakdef and elf_link_hash_flags fields. + (_bfd_elf_link_hash_table_create): Initialize dynobj, dynsymcount, + dynstr and bucketcount fields. + * elf32-target.h: Initialize new dynamic linking fields. + * elf64-target.h: Likewise. + * elf32-i386.c: New functions for dynamic linking support. + * elf32-sparc.c: Likewise. + * bfd-in.h (bfd_elf32_record_link_assignment): Declare. + (bfd_elf64_record_link_assignment): Declare. + (bfd_elf32_size_dynamic_sections): Declare. + (bfd_elf64_size_dynamic_sections): Declare. + * bfd-in2.h: Rebuilt. + +Wed May 18 08:29:04 1994 Ian Lance Taylor (ian@cygnus.com) + + * som.c: Don't include or . + (som_reloc_queue_find): Call memcmp instead of bcmp. + (som_bfd_reloc_type_lookup): Change first argument to bfd *. + (compare_syms): Change types of arguments to const void *. + (bfd_section_from_som_symbol): Removed unused local found. + (som_write_armap): Add elength, map, orl_count and int arguments. + (som_write_armap): Use %ld and cast to long for getuid result. + +Wed May 18 09:09:32 1994 Jeff Law (law@snake.cs.utah.edu) + + * elf32-hppa.h (R_HPPA_ABS_CALL): Define. + * elf32-hppa.c (hppa_elf_gen_reloc_type): Handle absolute calls. + + * som.h (R_HPPA_ABS_CALL): Define. + * som.c (hppa_som_gen_reloc_type): Delete complex relocation types. + +Tue May 17 19:33:12 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * coff-i960.c (icoff_little_vec, icoff_big_vec): Indicate leading + underscore, for compatibility with Intel tool chain (gnu960v2). + +Mon May 16 10:09:22 1994 Jeff Law (law@snake.cs.utah.edu) + + * bfd-in2.h: Rebuilt. + + * elf32-hppa.c: Change .hppa_linker_stubs to .PARISC.stubs, + likewise for other PA specific sections. + (hppa_elf_relocate_unwind_table): Delete unused + function. + (elf_hppa_howto_table): Completely new table based on 94-02-02 + draft PA ELF spec. Change relocation tags appropriately + throughout elf32-hppa.c + (hppa_elf_gen_reloc_type): Rewrite and simplify based on 94-02-02 + spec. + (hppa_elf_reloc): Likewise. + (hppa_look_for_stubs_in_section): Likewise + (ELF_MACHINE_CODE): Change to EM_PARISC. + * elf32-hppa.h: Include "elf/hppa.h". Change relocation tags + appropriately throughout elf32-hppa.h. + (elf32_hppa_reloc_type): New table based on 94-02-02 draft PA ELF + spec. + (R_HPPA_ABS_CALL, R_HPPA_COMPLEX*, R_HPPA_UNWIND): Delete definitions. + * elfcode.h (prep_headers): Use EM_PARISC instead of EM_HPPA. + * reloc.c (bfd_reloc_code_real): Delete unused HPPA relocations. + * som.h (R_HPPA_ABS_CALL, R_HPPA_COMPLEX): Delete definitions. + + * libhppa.h (hppa_field_adjust): Avoid adding constant_value into + the final value twice for LR and RR field selectors. + +Sat May 14 09:09:19 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * aoutx.h (add_to_stringtab): Use BFD_ASSERT not assert. This + avoids __eprintf troubles. + +Fri May 13 10:51:21 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * bout.c (b_out_bfd_reloc_type_lookup): Handle BFD_RELOC_CTOR. + + * config/mipsbelf.mt (SELECT_VECS): Add ecoff_big_vec and + ecoff_little_vec since Irix 5 supports ECOFF executables. + +Wed May 11 00:31:57 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_find_nearest_line): Handle fdr.adr != pdr.adr + correctly. + + * Makefile.in (stmp-bfd.h): Use || instead of ; to force SunOS + make to invoke the shell. + +Tue May 10 14:23:43 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * section.c (SEC_COFF_SHARED_LIBRARY): Renamed from + SEC_SHARED_LIBRARY for clarity. Changed all uses. + * bfd-in2.h: Rebuilt. + * coffcode.h (sec_to_styp_flags): If SEC_COFF_SHARED_LIBRARY is + set, set STYP_NOLOAD. + * coffgen.c (coff_section_from_bfd_index): Don't get an assertion + failure because of a bad shared library. + +Mon May 9 18:53:40 1994 Bill Cox (bill@rtl.cygnus.com) + + * linker.c: Add missing comment terminator. + +Mon May 9 11:53:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * linker.c (_bfd_generic_link_add_one_symbol): If hashp and *hashp + are not NULL, assume the caller has already looked up the symbol + in the hash table and has stored the entry in *hashp. + (generic_link_add_symbol_list): Set h to NULL before calling + _bfd_generic_link_add_one_symbol. + * ecoff.c (ecoff_link_add_externals): Likewise. + + * elfcode.h (assign_file_positions_except_relocs): Don't require + page shared between .data and .bss segments to contain zeroes. + + * elfcode.h: Include bfdlink.h. Added several new functions to do + linking. + (ELF_R_TYPE): Define. + (bfd_add_to_strtab): Return unsigned long. Change check for + realloc failure. + (elf_fake_sections): Check return value of bfd_add_to_strtab. + (elf_compute_section_file_positions): Add link_info argument. + Call elf_backend_begin_write_processing hook and prep_headers + here. Only call swap_out_syms if link_info is NULL. Set up + .shstrtab section here. Pass dosyms argument to + assign_file_positions_except_relocs. Set output_has_begun flag. + (assign_file_positions_for_symtab_and_strtabs): Add dosyms + argument, and use it to control setting .symtab and .strtab file + positions. + (assign_file_positions_except_relocs): Add dosyms argument, and + pass it on. + (prep_headers): Check return value of bfd_add_to_strtab. + (swap_out_syms): Likewise. Also, don't set up .shstrtab here. + (NAME(bfd_elf,write_object_contents)): Some calls moved into + elf_compute_section_file_positions. + (elf_set_section_contents): Likewise. + (elf_slurp_symbol_table): SHN_LORESERV corrected to SHN_LORESERVE. + * libelf.h: Include bfdlink.h. + (struct elf_backend_data): Add fields collect, + elf_add_symbol_hook, elf_backend_relocate_section. + (struct bfd_elf_section_data): Add field rel_hashes. + (struct elf_obj_tdata): Remove fields internal_syms and symbols. + Add field sym_hashes. + (obj_symbols, obj_internal_syms): Remove definitions. + (elf_sym_hashes): Define. + (struct elf_link_hash_entry): Define. + (struct elf_link_hash_table): Define. + (elf_link_hash_lookup): Define. + (elf_link_hash_traverse): Define. + (elf_hash_table): Define. + (_bfd_elf_link_hash_table_create): Declare. + (bfd_elf32_bfd_link_add_symbols): Declare. + (bfd_elf32_bfd_final_link): Declare. + (bfd_elf64_bfd_link_add_symbols): Declare. + (bfd_elf64_bfd_final_link): Declare. + * elf.c: Include bfdlink.h. + (elf_link_hash_newfunc): New function. + (_bfd_elf_link_hash_table_create): New function. + * elf32-target.h (elf_backend_relocate_section): If not defined, + define as 0 and use generic linker. Otherwise, use ELF backend + linker. + (elf_backend_collect): If not defined, define as false. + (elf_backend_add_symbol_hook): If not defined, define as 0. + (elf32_bed): Initialize new fields. + * elf64-target.h: Same changes as elf32-target.h. + * elf32-i386.c: Include bfdlink.h. + (elf_i386_relocate_section): New function. + (elf_backend_relocate_section): Define. + * elf32-sparc.c: Include bfdlink.h. + (elf_info_to_howto): Change type of dst from Elf32_Internal_Rela + to Elf_Internal_Rela (they're the same type anyhow). + (elf_sparc_relocate_section): New function. + (elf_backend_relocate_section): Define. + * elf32-mips.c (elf_backend_collect): Define. + + * Makefile.in (stmp-bfd.h): Avoid useless make error message in a + different way; touch takes a numeric argument on some systems. + +Fri May 6 13:34:14 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmcode.h (nlm_swap_auxiliary_headers_in): Rework custom header + handling for latest suggested format. + (nlm_swap_auxiliary_headers_out): Likewise. + (nlm_compute_section_file_positions): Likewise. + +Fri May 6 11:11:50 1994 D. V. Henkel-Wallace (gumby@rtl.cygnus.com) + + * config.bfd: handle erricsson config (for OSE). + +Thu May 5 15:40:47 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + Patches from Ralph Campbell: + * mipsbsd.c (mips_fix_jmp_addr): New function. + (mips_fix_hi16_s): Use bfd_is_com_section. + (mips_howto_table_ext): Call mips_fix_jmp_addr for MIPS_RELOC_JMP. + +Fri May 6 11:48:55 1994 Steve Chamberlain (sac@cygnus.com) + + * config/go32.mh: XX support. + + From bill + * Makefile.in: Build sysdep.h without causing worrying but + harmless error message. + +Wed May 4 11:09:53 1994 Ian Lance Taylor (ian@cygnus.com) + + Changed m68k-aout to set flags to 0; m68k-sunos still uses 1. + * aout0.c: New file. + * targets.c (aout0_big_vec): Declare. + (bfd_target_vector): Add aout0_big_vec. + * config.bfd (m68*-*-aout*): Use m68k-0aout, not m68k-aout. + * config/m68k-aout.mt (SELECT_VECS): Removed. + * config/m68k-0aout.mt: New file. + * configure.in (aout0_big_vec): New target vector: use aout0.o, + aout32.o and stab-syms.o. + * Makefile.in: Rebuilt dependencies. + (BFD32_BACKENDS): Add aout0.o. + (CFILES): Add aout0.c. + + * libaout.h (struct aout_backend_data): Add field exec_hdr_flags. + * aout-target.h (MY_exec_hdr_flags): If not defined, define as 0. + MY(backend_data): Initialize exec_hdr_flags field. + * aoutf1.h (sunos_32_set_arch_mach): Make static. + (aout32_sunos4_write_object_contents): Set flags from backend + info. + (MY_exec_hdr_flags): If not defined, define as 1. + (sunos4_aout_backend): Initialize exec_hdr_flags field. + * aout-encap.c (encap_write_object_contents): Set flags from + backend info. + (MY_exec_hdr_flags): Define as N_FLAGS_COFF_ENCAPSULATE. + * hp300hpux.c (MY_exec_hdr_flags): Define as 0x2. + (MY(write_object_contents)): Set flags from backend info. + * i386aout.c (MY(backend_data)): Initialize exec_hdr_flags field. + * i386mach3.c (MY(backend_data)): Likewise. + * mipsbsd.c (MY(backend_data)): Likewise. + * sparclynx.c (NAME(aout,sparclynx_write_object_contents)): Set + flags from backend info. + (sparclynx_aout_backend): Initialize exec_hdr_flags field. + +Wed May 4 02:56:00 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * config.bfd (i386-*-gnu*): Treat like i386-*-mach*. + (m68*-apollo-*): Treat all Apollo configs the same, don't handle + BSD specially. + +Tue May 3 19:43:21 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * cache.c: Rewrote to work correctly. + * libbfd.h: Rebuilt. + * opncls.c (bfd_cache_init, bfd_open_file): Don't declare. + (bfd_fdopenr): Check return value of bfd_cache_init. + +Fri Apr 29 15:08:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * cf-m68klynx.c (CALC_ADDEND): Check for PC relative relocs by + enumerating them, since the reloc type can not serve as an index + into the m68k COFF howto_table. + +Fri Apr 29 09:42:39 1994 Steve Chamberlain (sac@cygnus.com) + + * config.bfd (*-go32): Changed to coff. + * coff-h8300.c (JMPL1): Get HOWTO right for 24bit branches. + * srec.c (srec_write_symbols): Write out the correct number of + symbols and don't stick in extra nulls. + +Tue Apr 26 15:07:24 1994 Stan Shebs (shebs@andros.cygnus.com) + + * cf-sparclynx.c (LYNXOS, COFF_LONG_FILENAMES): Define. + * coff-sparc.c (BADMAG): Recognize LYNXCOFFMAGIC. + (COFF_SPARC): Define. + * coffcode.h (coff_new_section_hook): If COFF_SPARC, set alignment + power of data and bss sections to 3. + * hosts/lynx.h (__LYNXOS): Define. + +Tue Apr 26 15:04:26 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (hppa_elf_reloc): Adjust the addend of relocations + against section symbols to avoid losing during ld -r. + +Tue Apr 26 12:16:41 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (shstrtab_length_fixed): Remove useless static + variable. + (struct elf_sect_data): Remove unused structure. + (elf_object_p): Free memory if error occurs. Check return value + of bfd_default_set_arch_mach. If elf_get_str_section fails, + preserve error code rather than setting wrong_format. + (null_shdr): Remove static variable. + (assign_section_numbers): Remove shstrtab_length_fixed assignment. + Allocate first section header on BFD obstack rather than using + null_shdr. + (bfd_prpsinfo): Remove unused local variable newsect. + +Mon Apr 25 15:31:04 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (write_relocs): Undo patch of Apr 10; breaks Solaris. + + * elfcode.h (bfd_section_from_shdr): Use bfd_make_section_anyway + to create sections. Check return value of recursive calls. + (bfd_section_from_phdr): Check return value of bfd_make_section. + (elf_symbol_from_bfd_symbol): Likewise. + (elf_object_p): Check return value of bfd_section_from_shdr. + (section_from_elf_index): Likewise. + (elf_slurp_symbol_table): Check return value of + section_from_elf_index. + (bfd_prstatus): Return boolean value. Check return value of + bfd_make_section. + (bfd_fpregset): Likewise. + (bfd_prpsinfo): Return boolean value. + (elf_corefile_note): Check return values of bfd_prstatus, + bfd_fpregset, and bfd_prpsinfo. + (elf_core_file_p): Check return value of elf_corefile_note. + +Fri Apr 22 11:08:38 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Get rid of the ECOFF .reginfo section hack. + * ecoff.c (ecoff_mkobject_hook): Don't create a .reginfo section. + (ecoff_new_section_hook): Don't handle the .reginfo section. + (ecoff_sizeof_headers): Likewise. + (ecoff_get_section_contents): Likewise. + (ecoff_compute_section_file_positions): Likewise. + (ecoff_compute_reloc_file_positions): Likewise. + (ecoff_set_section_contents): Likewise. + (ecoff_write_object_contents): Likewise. + (ecoff_bfd_final_link): Likewise. + (ecoff_bfd_copy_private_bfd_data): Copy the GP value and the + register masks. + (bfd_ecoff_get_gp_value): New function. + (bfd_ecoff_set_gp_value): New function. + (bfd_ecoff_set_regmasks): New function. + * bfd-in.h (bfd_ecoff_get_gp_value): Declare. + (bfd_ecoff_set_gp_value): Declare. + (bfd_ecoff_set_regmasks): Declare. + * bfd-in2.h: Rebuilt. + + Fix ECOFF objcopy to actually copy debugging information. + * ecoff.c (ecoff_bfd_copy_private_bfd_data): New function. + (ecoff_get_extr): Assume that any ECOFF symbol with local clear is + an external symbol, rather than checking the symbol flags. Only + check the flags for non-ECOFF symbols. + * ecofflink.c (bfd_ecoff_debug_externals): Don't crash if the + output_section field of the symbol section is NULL. + * libecoff.h (ecoff_bfd_copy_private_bfd_data): Declare as + function rather than defining as macro. + + * ieee.c (ieee_object_p): Set bfd_error_got_wrong_format if + appropriate. + + * targets.c (bfd_target_vector): Add bfd_elf32_powerpc_vec. + + * aout-adobe.c (aout_adobe_set_arch_mach): Check return value of + bfd_default_set_arch_mach. Accept bfd_arch_m68k as well as + bfd_arch_unknown. + * coffcode.h (coff_set_arch_mach): Check return value of + bfd_default_set_arch_mach. + * elfcode.h (elf_set_arch_mach): Don't check a list of ELF + architectures, just see if the desired architecture matches what + the ELF backend permits. + + * coffcode.h (coff_set_arch_mach_hook): Rename SHMAGIC to + SH_ARCH_MAGIC to match change in coff/sh.h. + (coff_set_flags): Likewise. + + Follow convention in which each NLM header has an 8 byte stamp + followed by a four byte length. + * libnlm.h (struct nlm_obj_tdata): Rename nlm_cygnus_section_hdr + to nlm_cygnus_ext_header, and change type to + Nlm_Internal_Cygnus_Ext_Header. + (nlm_cygnus_ext_header): Rename from nlm_cygnus_section_header. + * nlmcode.h (nlm_swap_auxiliary_headers_in): Use CyGnUsEx instead + of CyGnUsSeCs. Rename from cygnus_section to cygnus_ext. Require + length word to be 8. + (nlm_swap_auxiliary_headers_out): Rename from cygnus_section to + cygnus_ext. Set length word to 8. + (nlm_compute_section_file_positions): Rename from cygnus_section + to cygnus_ext. + +Thu Apr 21 22:54:22 1994 Stu Grossman (grossman at cygnus.com) + + * nlmcode.h (nlm_swap_auxiliary_headers_in): Keep section table + (from CyGnUsSeCs) in more permanent memory to keep section names + from getting trashed. + +Thu Apr 21 09:29:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * libelf.h (elf_obj_tdata): Add members for dynamic symbol table + handling. + * elfcode.h (bfd_section_from_shdr): Handle dynamic symbol table. + * elfcode.h (elf_slurp_symbol_table): Take additional parameter + to select static or dynamic symbol table and return number of + symbols slurped or -1 on error. + * elfcode.h (elf_get_symtab): Set bfd symcount from + elf_slurp_symbol_table result. + * elfcode.h (elf_get_dynamic_symtab_upper_bound, + elf_canonicalize_dynamic_symtab): New functions to handle dynamic + symbol table. + * elf32-target.h, elf64-target.h (BFD_JUMP_TABLE_DYNAMIC): + Change to handle dynamic symbol table, provide default definitions + for dynamic relocs. + * aoutx.h (howto_table_std, NAME(aout,swap_std_reloc_out), + NAME(aout,swap_std_reloc_in), aout_link_input_section_std, + aout_link_reloc_link_order): Handle r_jmptable and r_relative + relocations. + +Thu Apr 21 11:58:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Clean up uses of _bfd_dummy_target (from Peter Schauer). + * libbfd.c (_bfd_dummy_target): Set bfd_error_wrong_format. + * nlm-target.h (nlm_core_file_p): Define as _bfd_dummy_target, not + NULL. + * srec.c (srec_vec): Use _bfd_dummy_target, not NULL, in + _bfd_check_format. + (symbolsrec_vec): Likewise. + * tekhex.c (tekhex_vec): Likewise. + + * libnlm.h (struct nlm_obj_tdata): Add nlm_cygnus_section_hdr + field. + (nlm_cygnus_section_header): New accessor macro. + * nlmcode.h (nlm_object_p): Free new tdata structure if failure. + Add fixed sections before swapping in auxiliary headers. After + adding sections, treat errors as real, not as wrong format. + (nlm_swap_auxiliary_headers_in): Swap in the sections header; add + sections to the BFD for each section it describes. + (nlm_swap_auxiliary_headers_out): Swap out the sections header. + (nlm_compute_section_file_positions): Account for the size of the + sections header. + +Wed Apr 20 16:45:51 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * coff-sparc.c (sparccoff_vec): Change minimum alignment power to + 2, so that stab sections can be multiples of 4 bytes only. + + * hosts/i386aix.h: Changes to avoid prototypes conflicts with the + ones defined in stdlib.h. (From Minh Tran-Le.) + +Wed Apr 20 14:15:21 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlm32-ppc.c: Complete rewrite for new version of PowerPC + NetWare. Old code still present, but ifdeffed out. + + * nlmcode.h (nlm_swap_auxiliary_headers_in): Don't assume a + particular format for the customer header. Allocate a block of + memory and read it into that. + (nlm_swap_auxiliary_headers_out): Write out the block of memory. + (nlm_compute_section_file_positions): Include length of customer + header when computing its size. + +Mon Apr 18 14:27:17 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_prep_headers): Get the space's number from the + backend private section data rather than target_index. + (bfd_som_set_section_attributes): Store the space's number + in the backend private section data rather than target_index. + + * som.h (som_copyable_section_data_struct): Add space_number. + +Fri Apr 15 12:22:07 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-a29k.c (reloc_processing): Always set the address of a + R_IHCONST reloc to that of the immediately preceding R_IHIHALF. + gas does this anyhow, but some other assemblers seem to leave + garbage in the R_IHCONST address field. + + * bfd/archive.c: Consistently use ARFMAG; from + schwab@issan.informatik.uni-dortmund.de (Andreas Schwab). + (_bfd_write_archive_contents): Use ARFMAG rather than '`' and + '\012'. + (bsd_write_armap): Likewise. + (coff_write_armap): Likewise. + + * coff-mips.c (mips_relocate_section): When relaxing, adjust local + relocs against the .text section as required. + * ecofflink.c (bfd_ecoff_debug_accumulate): When relaxing, adjust + PDR addresses as required. + + * ecoff.c (ecoff_emit_aggregate): Take fdr argument. Map fdr + index through rfd map if it exists. Check for a couple of cases + which gdb handles specially. Change all callers. + (ecoff_type_to_string): Take fdr argument rather than aux_ptr and + bigendian argument. Change all callers. + (ecoff_print_symbol): Handle stStruct, stUnion and stEnum. + +Thu Apr 14 13:05:10 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-mips.c (mips_howto_table): Add dummy entries to account for + numbering changes in include/coff/mips.h. Add entries for + MIPS_R_RELHI and MIPS_R_RELLO. + (mips_ecoff_swap_reloc_in): Handle an extra bit for the reloc type + when little endian. Treat internal MIPS_R_RELLO or MIPS_R_RELHI + relocs like MIPS_R_SWITCH, and convert r_offset from 24 to 32 + bits. + (mips_ecoff_swap_reloc_out): Likewise. + (mips_adjust_reloc_in): Handle internal MIPS_R_RELLO or + MIPS_R_RELHI relocs like MIPS_R_SWITCH. + (mips_adjust_reloc_out): Likewise. + (mips_relhi_addr, mips_relhi_addend): New static variables. + (mips_relhi_reloc, mips_rello_reloc): New functions. + (mips_bfd_reloc_type_lookup): Turn BFD_RELOC_PCREL_HI16_S into + MIPS_R_RELHI and turn BFD_RELOC_PCREL_LO16 into MIPS_R_RELLO. + (mips_relocate_hi): Rename from mips_relocate_refhi, and add pcrel + argument. Changed all callers. + (mips_relocate_section): Rename got_reflo to got_lo and + reflo_int_rel to lo_int_rel. Handle MIPS_R_RELLO and MIPS_R_RELHI + relocs. + (mips_relax_section): Adjust MIPS_R_RELHI/MIPS_R_RELLO pairs when + expanding a PC relative call. + + * reloc.c (bfd_reloc_code_real_type): Add BFD_RELOC_PCREL_HI16_S + and BFD_RELOC_PCREL_LO16. + * bfd-in2.h: Rebuilt. + +Wed Apr 13 11:50:07 1994 Stan Shebs (shebs@andros.cygnus.com) + + * coff-sparc.c (sparccoff_vec): Set minimum alignment power to 3. + +Tue Apr 12 13:36:20 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_write_fixups): Always emit at least + one relocation for any non-bss section. + +Mon Apr 11 14:41:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (assign_file_positions_except_relocs): Don't require + the file alignment to correspond to the page size when linking + with -N. + +Sun Apr 10 01:02:24 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * elfcode.h (write_relocs): For rela relocations, adjust the + addend for relocations involving section symbols to account + for the lossage of 1:1 mapping from input section symbols to + output section symbols. + +Fri Apr 8 12:22:02 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (NAME(aout,make_sections)): New function. + (NAME(aout,some_aout_object_p)): Call NAME(aout,make_sections) + rather than making sections inline. + (NAME(aout,mkobject)): Don't make any sections. + (NAME(aout,adjust_sizes_and_vmas)): Call NAME(aout,make_sections). + (NAME(aout,final_link)): Don't dereference obj_textsec (abfd) or + obj_datasec (abfd) if they are NULL. + * libaout.h (NAME(aout,make_sections)): Declare. + * bout.c (b_out_mkobject): Don't make any sections. + (b_out_write_object_contents): Call aout_32_make_sections. + (b_out_set_section_contents): Likewise. + * i386os9k.c (os9k_mkobject): Don't make any sections. + (os9k_write_object_contents): Call aout_32_make_sections. + (os9k_set_section_contents): Likewise. + + * aoutx.h (NAME(aout,new_section_hook)): Don't set N_EXT in target + index. + +Wed Apr 6 20:44:56 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * config.bfd, configure.host: Add mips-*-sysv4* support. + +Thu Apr 7 14:23:05 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-mips.c (mips_howto_table): Add entry for MIPS_R_SWITCH. + (mips_ecoff_swap_reloc_in): For MIPS_R_SWTICH, copy r_symndx into + r_offset and set r_symndx to RELOC_SECTION_TEXT. + (mips_ecoff_swap_reloc_out): For MIPS_R_SWITCH, get the r_symndx + value from the r_offset field. + (mips_adjust_reloc_in): Maximum r_type value is now MIPS_R_SWITCH. + For MIPS_R_SWITCH, copy the r_offset field into the addend field. + (mips_adjust_reloc_out): For MIPS_R_SWITCH, copy the addend field + into the r_offset field. + (mips_switch_reloc): New function. + (mips_bfd_reloc_type_lookup): Translate BFD_RELOC_GPREL32 into + MIPS_R_SWITCH. + (mips_relocate_section): Handle MIPS_R_SWITCH. + (mips_relax_section): Adjust MIPS_R_SWITCH offset if necessary. + +Thu Apr 7 11:10:51 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * elfcode.h (elf_set_section_contents): Support calling the backend + function elf_backend_begin_write_processing when just beginning to + write an object file. + + * libelf.h (elf_backend_begin_write_processing): Declare. + + * elf{32,64}-target.h (elf_backend_begin_write_processing): Provide + a default definition. + (elf{32,64}_bed): Add elf_backend_begin_write_processing. + + * elf32-hppa.h (elf_hppa_tc_symbol): Delete extern declaration. + (elf_hppa_tc_make_sections): Likewise. + + * elf32-hppa.c (symext_chain_built): Delete. + (symext_chain_size): Renamed from symextn_contents_real_size. + (elf32_hppa_backend_{begin,final}_write_processing): New functions. + (add_entry_to_symext_chain): New function. + (hppa_elf_set_section_contents): Ignore writes to the symbol extension + section until it's been rebuilt internally. + (hppa_elf_get_section_contents): Symbol extension section is no + longer special. + (elf_backend_{begin,final}_write_processing): Define. + (elf_hppa_tc_make_sections): Simplify now that much code has + migrated into elf32_hppa_backend_{being,final}_write_processing. + +Wed Apr 6 17:24:14 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Add new target vectors to read the dynamic symbols and dynamic + relocs. Change a.out to use these rather than reading the dynamic + symbols and relocs along with the normal symbols and relocs. + * targets.c (bfd_target): Add fields + _bfd_get_dynamic_symtab_upper_bound, + _bfd_canonicalize_dynamic_symtab, + _bfd_get_dynamic_reloc_upper_bound, + _bfd_canonicalize_dynamic_reloc. + (BFD_JUMP_TABLE_DYNAMIC): Define. + * libbfd-in.h (_bfd_nodynamic_get_dynamic_symtab_upper_bound): + Define. + (_bfd_nodynamic_canonicalize_dynamic_symtab): Define. + (_bfd_nodynamic_get_dynamic_reloc_upper_bound): Define. + (_bfd_nodynamic_canonicalize_dynamic_reloc): Define. + * bfd.c (bfd_get_dynamic_symtab_upper_bound): Define. + (bfd_canonicalize_dynamic_symtab): Define. + (bfd_get_dynamic_reloc_upper_bound): Define. + (bfd_canonicalize_dynamic_reloc): Define. + * sunos.c (MY_read_dynamic_symbols): Don't define. + (MY_read_dynamic_relocs): Don't define. + (MY_get_dynamic_symtab_upper_bound): Define. + (MY_canonicalize_dynamic_symtab): Define. + (MY_get_dynamic_reloc_upper_bound): Define. + (MY_canonicalize_dynamic_reloc): Define. + (struct sunos_dynamic_info): Change type of dynsym_count and + dynrel_count to long. Add fields canonical_dynsym and + canonical_dynrel. + (sunos_read_dynamic_info): Check that BFD had DYNAMIC flag set. + Clear info->canonical_dynsym and info->canonical_dynrel. + (MY(read_dynamic_symbols)): Removed. + (MY(read_dynamic_relocs)): Removed. + (sunos_get_dynamic_symtab_upper_bound): New function. + (sunos_canonicalize_dynamic_symtab): New function. + (sunos_get_dynamic_reloc_upper_bound): New function. + (sunos_canonicalize_dynamic_reloc): New function. + * libaout.h: Declare struct reloc_ext_external and + reloc_std_external to avoid prototype problems. + (struct aout_backend_data): Remove fields read_dynamic_symbols and + read_dynamic_relocs. + (NAME(aout,translate_symbol_table)): Declare. + (NAME(aout,swap_ext_reloc_in)): Declare. + (NAME(aout,swap_std_reloc_in)): Declare. + * aoutx.h (NAME(aout,translate_symbol_table)): Renamed from + translate_symbol_table and made non-static. Changed all callers. + (NAME(aout,slurp_symbol_table)): Don't read dynamic symbols. + (NAME(aout,slurp_reloc_table)): Don't read dynamic relocs. + (NAME(aout,get_reloc_upper_bound)): Don't count dynamic relocs. + * aoutf1.h (aout_32_sunos4_write_object_contents): Don't bother to + remove dynamic symbols and relocs. They will no longer be + present. + (MY_read_dynamic_symbols): Don't define. + (MY_read_dynamic_relocs): Don't define. + (sunos4_aout_backend): Don't initialize dynamic entry points. + * aout-target.h (MY_read_dynamic_symbols): Don't define. + (MY_read_dynamic_relocs): Don't define. + (MY(backend_data)): Don't initialize dynamic entry points. + (MY_get_dynamic_symtab_upper_bound): If not defined, define to + _bfd_nodynamic version. + (MY_canonicalize_dynamic_symtab): Likewise. + (MY_get_dynamic_reloc_upper_bound): Likewise. + (MY_canonicalize_dynamic_reloc): Likewise. + * All backends: Added BFD_JUMP_TABLE_DYNAMIC to target vector. + * bfd-in2.h: Rebuilt. + * libbfd.h: Rebuilt. + + * cf-m68klynx.c: Include sysdep.h. + + * hp300hpux.c: Removed some spaces in uses of NAME to avoid + problems with traditional C compilers. + + * targets.c (bfd_target): Rearranged fields in target vector. + Removed _bfd_debug_info_start, _bfd_debug_info_end and + _bfd_debug_info_accumulate, which were never used. + (BFD_JUMP_TABLE_GENERIC, BFD_JUMP_TABLE_COPY): Defined. + (BFD_JUMP_TABLE_CORE, BFD_JUMP_TABLE_ARCHIVE): Defined. + (BFD_JUMP_TABLE_SYMBOLS, BFD_JUMP_TABLE_RELOCS): Defined. + (BFD_JUMP_TABLE_WRITE, BFD_JUMP_TABLE_LINK): Defined. + * All backends: Changed to use the new BFD_JUMP_TABLE_* macros + rather than the single JUMP_TABLE macro. Removed many of the + weird macro definitions needed to support the monolithic + JUMP_TABLE. + * bfd-in.h (JUMP_TABLE): Removed. + * libbfd-in.h: Define a bunch of macros, and declare a few + functions, for use with the new BFD_JUMP_TABLE_* macros. + * libbfd.c (_bfd_dummy_new_section_hook): Removed. + (bfd_false): Set bfd_error_invalid_operation. + (bfd_nullvoidptr): Likewise. + (bfd_n1): New function. + (_bfd_nocore_core_file_matches_executable_p): Renamed from + _bfd_dummy_core_file_matches_executable_p. + (_bfd_nocore_core_file_failing_command): Similar rename. Set + bfd_error_invalid_operation. + (_bfd_nocore_core_file_failing_signal): Likewise. + (_bfd_generic_get_section_contents): Renamed from + bfd_generic_get_section_contents. Changed all callers. + (_bfd_generic_set_section_contents): Similar rename. + * ieee.c: #if 0 out ieee_bfd_debug_info_start, + ieee_bfd_debug_info_end, ieee_bfd_debug_info_accumulate. They + were never called. + * bfd-in2.h: Rebuilt. + * libbfd.h: Rebuilt. + +Tue Apr 5 22:10:04 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Crude support for examining dynamic libraries. + * som.c (som_object_setup): Set DYNAMIC flag for SHL_MAGIC and + DL_MAGIC objects. + (som_prep_headers): Preserve the system_id for DYNAMIC objects. + Use SHL_MAGIC as the magic number of the DYNAMIC flag is set. + Write exec headers for DYNAMIC objects. + (som_begin_writing): DYNAMIC objects have the same alignment + restrictions as D_PAGED objects. + (bfd_section_from_som_symbol): Treat DYNAMIC objects like EXEC_P + objects. + (object_flags): Add DYNAMIC. + +Tue Apr 5 17:48:52 1994 Stan Shebs (shebs@andros.cygnus.com) + + * i386lynx.c, sparclynx.c (NAME): Remove embedded whitespace in + macro uses, confuses some non-ANSI compilers. + +Tue Apr 5 15:50:01 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_free_cached_info): Add missing PARAMS decl. + Don't free anything if we don't have a bfd_object. + (som_close_and_cleanup): Call som_bfd_free_cached_info. + +Tue Apr 5 11:22:38 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elf32-mips.c (mips_elf_final_link): Don't remove empty sections. + It turns out not to be required on Irix 5, and it causes problems + if the sections happen to contain symbols. + + * elfcode.h (write_shdrs_and_ehdr): Correct bfd_write check. + + * aoutx.h (NAME(aout,canonicalize_reloc)): Don't error out if + section->relocation is NULL; malloc might have returned NULL when + given a zero size if there were no relocations. + * bout.c (b_out_canonicalize_reloc): Likewise. + * coffcode.h (coff_canonicalize_reloc): Likewise. + * ecoff.c (ecoff_canonicalize_reloc): Likewise. + * elfcode.h (elf_canonicalize_reloc): Likewise. + * mipsbsd.c (MY(canonicalize_reloc)): Likewise. + * i386lynx.c (NAME(lynx,canonicalize_reloc)): Likewise. + * nlmcode.h (nlm_canonicalize_reloc): Likewise. + * som.c (som_canonicalize_reloc): Likewise. + * hp300hpux.c (MY(slurp_reloc_table)): Likewise. Also, if malloc + returns NULL, don't report an error if we asked for zero bytes. + * i386lynx.c (NAME(lynx,slurp_reloc_table)): If malloc returns + NULL, don't report an error if we asked for zero bytes. + * nlmcode.h (nlm_slurp_reloc_fixups): Likewise. + +Mon Apr 4 15:30:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (NAME(aout,bfd_free_cached_info)): Don't free anything + if we don't have a bfd_object. + + Made sure that every call to bfd_read, bfd_write, and bfd_seek + checks the return value and handled bfd_error correctly. These + changes are not itemised. Also: + * aoutx.h (emit_strtab): Change return type to boolean, and return + errors. + (NAME(aout,write_syms)): Check emit_strtab return value. + (NAME(aout,final_link)): Likewise. + * coffcode.h (coff_write_relocs): Change return type to boolean, + and return errors. + (coff_write_object_contents): Check coff_write_relocs return + value. + * i386os9k.c (os9k_swap_exec_header_in): Change return type to + boolean. + (os9k_object_p): Check os9k_swap_exec_header_in return value. + * oasys.c (oasys_read_record): Change return type to boolean. + (oasys_slurp_symbol_table: Check oasys_read_record return value. + (oasys_object_p, oasys_slurp_section_data): Likewise. + (oasys_write_record): Change return type to boolean. + (oasys_write_syms): Likewise. Also, check oasys_write_record + return value. + (oasys_write_sections): Check oasys_write_record return value. + (oasys_write_header): Change return type to boolean. Check + oasys_write_record return value. + (oasys_write_end, oasys_write_data): Likewise. + (oasys_write_object_contents): Check return values of + oasys_write_header, oasys_write_syms, oasys_write_data, and + oasys_write_end. + * srec.c (srec_write_record): Change return type to boolean. + (srec_write_header): Likewise. Also, check srec_write_record + return value. + (srec_write_section, srec_write_terminator): Likewise. + (srec_write_symbols): Change return type to boolean. + (internal_srec_write_object_contents): Check return value of + srec_write_symbols, srec_write_header, srec_write_section, and + srec_write_terminator. + + * Makefile.in: Rebuilt dependencies. + +Mon Apr 4 10:56:45 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * aix386-core.c (aix386_bfd_is_local_label): Correct cast from + asection to asymbol. + * ptrace-core.c (ptrace_unix_bfd_is_local_label): Correct cast from + bfd to asymbol. + * trad-core.c (trad_unix_bfd_is_local_label): Correct cast from + asection to asymbol. + +Sun Apr 3 18:27:29 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_slurp_string_table): Use malloc to allocate space + for the cached copy of the native string table. + (som_slurp_symbol_table): Likewise for the native symbol table. + (som_slurp_reloc_table): Likewise for the native and generic + relocation tables. + (som_bfd_free_cached_info): Free the cached native strings, + symbols, and relocations. Also free the canonical cached + relocations. + +Fri Apr 1 12:40:58 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (aout_link_write_symbols): If keep_memory is false, make + sure the symbol name is stored in permanent memory before adding + it to the string table. + + * archive.c (_bfd_write_archive_contents): Once we've found an + object, don't bother to look for more when deciding whether to + build a map. + (compute_and_write_armap): After adding the symbols for a BFD, + call bfd_free_cached_info on it. + + Add bfd_free_cached_info support to a.out backends. + * aoutx.h (aout_get_external_symbols): Renamed from + aout_link_get_symbols. Read strings even if symbols have been + read. Store string size in obj_aout_string_size. + (NAME(aout,slurp_symbol_table)): Call aout_get_external_symbols to + read the symbols. Allocate the cached symbols with malloc, not + bfd_alloc. + (NAME(aout,slurp_reloc_table)): Allocate the cached relocs with + malloc, not bfd_alloc. + (NAME(aout,bfd_free_cached_info)): New function; free cached + symbols and relocs. + * libaout.h (struct aoutdata): Add external_string_size field. + (obj_aout_external_string_size): New accessor macro. + (NAME(aout,close_and_cleanup)): Don't declare. + (NAME(aout,bfd_free_cached_info)): Declare. + (aout_32_close_and_cleanup): Don't define. + (aout_64_close_and_cleanup): Don't define. + * aout-target.h (MY_bfd_free_cached_info): If not already defined, + define as NAME(aout,free_cached_info). + (MY_close_and_cleanup): If not already defined, define as + MY_bfd_free_cached_info. + * aout-adobe.c (aout_32_close_and_cleanup): Define. + (aout_32_bfd_free_cached_info): Don't define. + * bout.c (aout_32_close_and_cleanup): Define. + (aout_32_bfd_free_cached_info): Don't define. + * hp300hpux.c (MY_bfd_free_cached_info): Define as bfd_true. + (MY_close_and_cleanup): Don't define. + * i386lynx.c (NAME(lynx,slurp_reloc_table)): Allocate the cached + relocs with malloc, not bfd_alloc. + * i386os9k.c (aout_32_close_and_cleanup): Define. + (aout_32_bfd_free_cached_info): Don't define. + + Add a new entry point to free memory cached by a BFD. + * targets.c (bfd_target): Add _bfd_free_cached_info field. + * bfd.c (bfd_free_cached_info): Define. + * bfd-in.h (JUMP_TABLE): Add _bfd_free_cached_info. + * bfd-in2.h: Rebuilt. + * All backends: Initialize bfd_free_cached_info entry point to + bfd_true. + + * elf32-hppa.c (elf_hppa_reloc_type_lookup): Correct type of + first, unused, argument. + (hppa_elf_is_local_label): Declare instead of + som_bfd_is_local_label. + + * coff-a29k.c (a29k_reloc): Add reloc_entry->address to value of + absolute R_IREL reloc. + +Thu Mar 31 11:52:15 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Added some support for Irix 4 shared libraries. + * ecoff.c (ecoff_new_section_hook): Set SEC_SHARED_LIBRARY for a + .lib section. + (ecoff_sec_to_styp_flags): Set SEC_SHARED_LIBRARY if + STYP_ECOFF_LIB bit is set. + (ecoff_compute_section_file_positions): Round the contents of a + .lib section up to the next page boundary. + (ecoff_set_section_contents): If we see a .lib section, increment + the vma by one to count the number of shared libraries we have. + (ecoff_write_object_contents): Don't crash if we see a + STYP_ECOFF_LIB section, and don't adjust text_start or data_start + or bss_size either. + + * coffcode.h (CALC_ADDEND): Change to fetch original symbol value + from original BFD, rather than using value of current BFD symbol. + Needed for new linker. + * coff-sparc.c (CALC_ADDEND): Likewise. + + * ecoff.c (ecoff_write_object_contents): Set the text_start and + data_start entries in the optional header correctly even if a text + or data section starts at location zero. + + * reloc.c (bfd_reloc_code_real_type): Added BFD_RELOC_26 (from sef + and raeburn). + * bfd-in2.h: Rebuilt. + + * nlm32-i386.c (nlm_i386_read_import): Null terminate the symbol + name. + * nlm32-alpha.c (nlm_alpha_read_import): Likewise. + * nlm32-sparc.c (nlm_sparc_read_import): Likewise. + + * coffgen.c (coff_write_symbol): Reindented. Changed to return + boolean, and changed written to unsigned int *. Check error + returns from called functions. + (coff_write_alien_symbol): Likewise. + (coff_write_native_symbol): Likewise. + (coff_write_symbols): Likewise. Reworked checks on whether to + write symbol name to string table for clarity and to avoid core + dumping when given a non COFF symbol. + * libcoff-in.h (coff_write_symbols): Declare as returning boolean. + * libcoff.h: Rebuilt. + * coffcode.h (coff_write_object_contents): Check return value of + coff_write_symbols. + +Wed Mar 30 16:25:41 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Changes to let BFD return an error indication from + get_symtab_upper_bound, bfd_canonicalize_symtab, + bfd_get_reloc_upper_bound, and bfd_canonicalize_reloc. They now + return long instead of unsigned int, and use -1 to indicate an + error. Along the way, rename get_symtab_upper_bound to + bfd_get_symtab_upper_bound. + * bfd.c (bfd_get_reloc_upper_bound): Return long, and -1 on + errors. + (bfd_canonicalize_reloc): Likewise. + * syms.c (bfd_get_symtab_upper_bound): Renamed from + get_symtab_upper_bound. + * targets.c (bfd_target): Renamed _get_symtab_upper_bound to + _bfd_get_symtab_upper_bound, and changed it and + _bfd_canonicalize_symtab and _get_reloc_upper_bound and + _bfd_canonicalize_reloc to all return long. + * aoutx.h (NAME(aout,get_symtab)): Return long, and -1 on errors. + (NAME(aout,canonicalize_reloc)): Likewise. + (NAME(aout,get_reloc_upper_bound)): Likewise. + (NAME(aout,get_symtab_upper_bound)): Likewise. + * bout.c (b_out_canonicalize_reloc): Likewise. + (b_out_get_reloc_upper_bound): Likewise. + * coffcode.h (coff_canonicalize_reloc): Likewise. + * coffgen.c (coff_get_symtab_upper_bound): Likewise. + (coff_get_symtab): Likewise. + (coff_get_reloc_upper_bound): Likewise. + * ecoff.c (ecoff_get_symtab_upper_bound): Likewise. + (ecoff_get_symtab): Likewise. + (ecoff_canonicalize_reloc): Likewise. + * elfcode.h (elf_get_symtab_upper_bound): Likewise. + (elf_get_reloc_upper_bound): Likewise. + (elf_canonicalize_reloc): Likewise. + (elf_get_symtab): Likewise. + * hp300hpux.c (MY(get_symtab)): Likewise. + (MY(get_symtab_upper_bound)): Likewise. + (MY(canonicalize_reloc)): Likewise. + * i386lynx.c (NAME(lynx,canonicalize_reloc)): Likewise. + * ieee.c (ieee_slurp_external_symbols): Change return type to + boolean. Check for errors from get_symbol. + (ieee_slurp_symbol_table): Change return type to boolean. Check + for errors from ieee_slurp_external_symbols. + (ieee_get_symtab_upper_bound): Return long, and -1 on errors. + (ieee_get_symtab): Likewise. + (ieee_get_reloc_upper_bound): Likewise. + (ieee_canonicalize_reloc): Likewise. + * mipsbsd.c (MY(canonicalize_reloc)): Likewise. + * nlmcode.h (nlm_get_symtab_upper_bound): Likewise. + (nlm_get_symtab): Likewise. + (nlm_get_reloc_upper_bound): Likewise. + (nlm_canonicalize_reloc): Likewise. + * oasys.c (oasys_get_symtab_upper_bound): Likewise. + (oasys_get_symtab): Likewise. + (oasys_get_reloc_upper_bound): Likewise. + (oasys_canonicalize_reloc): Likewise. + * som.c (som_get_symtab_upper_bound): Likewise. + (som_get_symtab): Likewise. + (som_get_reloc_upper_bound): Likewise. + (som_canonicalize_reloc): Likewise. + * srec.c (srec_get_symtab_upper_bound): Likewise. + (srec_get_symtab): Likewise. + (srec_get_reloc_upper_bound): Define as bfd_0l. + (srec_canonicalize_reloc): Likewise. + * tekhex.c (tekhex_get_symtab): Return long, and -1 on errors. + (tekhex_get_symtab_upper_bound): Likewise. + (tekhex_get_reloc_upper_bound): Define as bfd_0l. + (tekhex_canonicalize_reloc): Likewise. + * libaout.h (NAME(aout,get_symtab_upper_bound)): Change + declaration to return long. + (NAME(aout,get_symtab)): Likewise. + (NAME(aout,canonicalize_reloc)): Likewise. + (NAME(aout,get_reloc_upper_bound)): Likewise. + * libcoff-in.h (coff_get_symtab_upper_bound): Likewise. + (coff_get_symtab): Likewise. + (coff_get_reloc_upper_bound): Likewise. + * libecoff.h (ecoff_get_symtab_upper_bound): Likewise. + (ecoff_get_symtab): Likewise. + (ecoff_canonicalize_reloc): Likewise. + * libelf.h (bfd_elf32_get_symtab_upper_bound): Likewise. + (bfd_elf32_get_symtab): Likewise. + (bfd_elf32_get_reloc_upper_bound): Likewise. + (bfd_elf32_canonicalize_reloc): Likewise. + (bfd_elf64_get_symtab_upper_bound): Likewise. + (bfd_elf64_get_symtab): Likewise. + (bfd_elf64_get_reloc_upper_bound): Likewise. + (bfd_elf64_canonicalize_reloc): Likewise. + * libnlm.h (nlmNAME(get_symtab_upper_bound)): Likewise. + (nlmNAME(get_symtab)): Likewise. + (nlmNAME(get_reloc_upper_bound)): Likewise. + (nlmNAME(canonicalize_reloc)): Likewise. + * archive.c (compute_and_write_armap): Use error_return and + no_memory_return labels rather than freeing information in various + places. Change storage, symcount and src_count to long. Check + errors from bfd_get_symtab_upper_bound and + bfd_canonicalize_symtab. + * bout.c (b_out_relax_section): Change reloc_size to long. Check + for errors from bfd_get_reloc_upper_bound and + bfd_canonicalize_reloc. + (b_out_get_relocated_section_contents): Likewise. + * coff-alpha.c (alpha_ecoff_get_relocated_section_contents): + Likewise. + * elf32-mips.c: Likewise. + * elf32-hppa.c (hppa_elf_stub_finish): Likewise. + (hppa_look_for_stubs_in_section): Check for errors from + bfd_get_symtab_upper_bound, bfd_canonicalize_symtab, and + bfd_canonicalize_reloc. + * ecofflink.c (bfd_ecoff_debug_accumulate_other): Check for errors + from bfd_get_symtab_upper_bound and bfd_canonicalize_symtab. + * linker.c (generic_link_read_symbols): Likewise. + (_bfd_generic_final_link): Check for errors from + bfd_get_reloc_upper_bound and bfd_canonicalize_reloc. + * reloc.c (bfd_generic_get_relocated_section_contents): Likewise. + * reloc16.c (bfd_coff_reloc16_relax_section): Likewise. + (bfd_coff_reloc16_get_relocated_section_contents): Likewise. + * libbfd.c (bfd_0l): New function. + * libbfd-in.h (bfd_0l): Declare. + * aix386-core.c: Change get_symtab_upper_bound, get_symtab, + get_reloc_upper_bound, and canonicalize_reloc to use bfd_0l rather + than bfd_0u. + * cisco-core.c, hppabsd-core.c, hpux-core.c: Likewise. + * irix-core.c, osf-core.c, ptrace-core.c, trad-core.c: Likewise. + * bfd-in2.h: Rebuilt. + * libbfd.h: Rebuilt. + * libcoff.h: Rebuilt. + + * nlm32-sparc.c (nlm_sparc_read_reloc): Remove unused variables + temp and name. + +Wed Mar 30 08:33:04 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hosts/dpx2.h: Define POSIX_UTIME. + +Wed Mar 30 00:31:49 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * i386dynix.c, config/i386-dynix.mt: New files, handling Dynix + variant of a.out. + * configure.in, config.bfd: Use them for Dynix. + * Makefile.in: Add dependencies for i386dynix.o. + * targets.c: Add definition for i386dynix_vec. + * hosts/symmetry.h: Do not define TRAD_CORE_USER_OFFSET for Dynix. + Define HOST_DATA_START_ADDR and TRAD_UNIX_CORE_FILE_FAILING_SIGNAL + for Dynix. Remove inclusion of dynix3.h, Dynix bfd is now handled by + i386dynix.c + +Mon Mar 28 12:53:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (BFD32_BACKENDS): Add coff-sparc.o. + + * coffcode.h (coff_set_flags): Handle bfd_arch_powerpc like + bfd_arch_rs6000. + + * config.bfd (powerpc-*-aix*): New target; use rs6000.mt. + * config/rs6000.mt (SELECT_ARCHITECTURES): Add bfd_powerpc_arch. + + * aoutx.h (translate_from_native_sym_flags): Set SEC_RELOC flag + for generated constructor section. + +Sun Mar 27 16:25:22 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_begin_writing): New approach at dealing with holes + in executables left by the HP linker. Does not rely on subspace + alignments as subspaces are *NOT* guaranteed to be properly + aligned in an executable (can you believe that!). + +Sat Mar 26 10:25:43 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_get_section_contents): New function. Do not try + to actually read data from a section that doesn't have either + SEC_LOAD or SEC_DEBUGGING set (eg $BSS$) just return true. + + * libbfd.c (bfd_read): Set bfd_error as appropriate for a short + read. (bfd_error_system_call or bfd_error_file_truncated). + + * som.c: Do not blindly set bfd_error_system_call after a + failing bfd_read, bfd_write, or bfd_seek. In a few places + (like som_object_p) override the error status set by bfd_read. + + * aix386-core.c, aout-encap,c archive.c, bout.c: Likewise. + * coff-rs6000.c, coffgen.c ecoff.c, elf.c: Likewise. + * elf32-hppa.c, elfcode.h, hp300hpux.c, i386lynx.c: Likewise. + * nlm32-alpha.c, nlm32-i386.c, nlm32-sparc.c: Likewise. + + * som.c: Check return values from several bfd_{seek,read,write} + calls that we just assumed were not failing. + +Fri Mar 25 11:44:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * hosts/sysv4.h (HAVE_PROCFS): Add comments about ptx4. + * config/sysv4.mh: Add comment. + * config/symmetry.mh: Change comment. + * configure.host: Use sysv4, not symmetry, for i[34]86-sequent-sysv4*. + +Fri Mar 25 17:10:45 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Changes to support linker relaxing of embedded MIPS PIC code to + use a five instruction sequence for function calls which are out of + range of the bal instruction. + * libecoff.h (struct ecoff_section_tdata): Define. + (ecoff_section_data): Define. + (ecoff_bfd_relax_section): Don't define. + * ecoff.c (ecoff_final_link_debug_accumulate): Don't read or free + the debugging information if it has already been read. + (ecoff_indirect_link_order): Handle _cooked_size being different + from _raw_size. Don't reread the contents or the relocs if they + have already been read in. + * coff-mips.c (mips_howto_table): Change bitsize of PCREL16 from + 18 to 16. + (PCREL16_EXPANSION_ADJUSTMENT): Define. + (mips_relocate_refhi): Take adjust argument. + (mips_relocate_section): Handle reloc offsets stored in section + used_by_bfd field. Call mips_relax_pcrel16 to handle details of + expanding an out of range PCREL16. Keep trace of adjustments + required by expansions. Set s and unset h when converting a reloc + from undefined to section. Change handling of PC relative relocs: + if against a section, they are correct in the object file, if + against an external symbol they are pcrel_offset. + (mips_relax_section): New function. + (mips_relax_pcrel16): New function. + (ecoff_bfd_relax_section): Define. + * coff-alpha.c (ecoff_bfd_relax_section): Define. + * ecofflink.c (bfd_ecoff_debug_accumulate): Handle adjustments + built by mips_relax_section when writing out addresses. + * elf32-mips.c (mips_elf_read_ecoff_info): Clear adjust field. + + * aoutx.h (NAME(aout,find_nearest_line)): The caller expects + functionname_ptr to be set to a symbol name, so prepend + symbol_leading_char. + +Thu Mar 24 11:33:46 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coff-h8300.c (h8300_reloc16_extra_cases): Add relaxing info + for 16bit relative branches. + * coff-h8500.c (r_high8, r_low16, r_high16): Don't complain on + overflow. + +Thu Mar 24 09:21:13 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_prep_for_ar_write): Ignore non-SOM objects. + (som_bfd_ar_write_symbol_stuff, som_write_armap): Likewise. + +Wed Mar 23 14:29:31 1994 David J. Mackenzie (djm@rtl.cygnus.com) + + * netbsd386.c (N_SET_FLAGS): Delete the old definition. + +Wed Mar 23 14:58:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Clean up the relaxing code for the new linker. + * targets.c (_bfd_relax_section): Take boolean *again argument + rather than asymbol list. + * bfd.c (bfd_relax_section): Change name of fourth argument from + symbols to again. + * reloc.c (bfd_generic_relax_section): Take boolean *again + argument rather than asymbol list. Always return true. + * bout.c: Include genlink.h. + (aligncode, perform_slip): Declare. + (perform_slip): Take BFD argument rather than asymbol list. + Changed all callers. Get the symbols from the BFD. Change the + hash table entry value as well as the symbol value. + (abs32code): Take BFD argument rather than asymbol list. Changed + all callers. + (aligncode): Likewise. + (b_out_relax_section): Take boolean *again argument rather than + asymbol list. Only return false if an error occurred. Set *again + to false. Get symbols from BFD. + * reloc16.c: Include genlink.h. + (bfd_perform_slip): Take BFD argument rather than asymbol list. + Get the symbols from the BFD. Change the hash table entry value + as well as the symbol value. + (bfd_coff_reloc16_relax_section): Take boolean *again argument + rather than asymbol list. Only return false if an error occurred. + Set *again to false. Get symbols from BFD. + * coffcode.h (bfd_coff_backend_data): Change + _bfd_coff_reloc16_estimate to take BFD argument rather than + asymbol list. + (bfd_coff_reloc16_estimate): Corresponding change. + (dummy_reloc16_estimate): Corresponding change. + * libcoff-in.h (bfd_coff_reloc16_relax_section): Change + declaration to take boolean * rather than asymbol list. + (bfd_perform_slip): Change declaration to take BFD rather than + asymbol list. + * coff-h8300.c (h300_reloc16_estimate): Take BFD argument rather + than asymbol list. Changed calls to bfd_perform_slip. + * bfd-in2.h: Rebuilt. + * libbfd.h: Rebuilt. + * libcoff.h: Rebuilt. + * Makefile.in: Rebuilt dependencies. + + * genlink.h (_bfd_generic_link_get_symbols): Define. + (_bfd_generic_link_get_symcount): Define. + * linker.c (generic_link_read_symbols): New function. + (generic_link_add_object_symbols): Use it. Use + _bfd_generic_link_get_symbols and _bfd_generic_link_get_symcount + to get the symbols from the BFD. + (generic_link_check_archive_element): Likewise. + (_bfd_generic_final_link): Likewise. + (_bfd_generic_link_output_symbols): Likewise. + (default_indirect_link_order): Likewise. + (generic_link_add_symbol_list): Store pointer to hash table entry + in asymbol udata field. + +Tue Mar 22 13:09:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-mips.c (mips_howto_table): Add entry for new MIPS_R_PCREL16 + reloc, used in embedded PIC code. + (mips_adjust_reloc_in): Change sanity check to permit new reloc. + (mips_bfd_reloc_type_lookup): Turn BFD_RELOC_16_PCREL_S2 into + MIPS_R_PCREL16. + + * elf32-mips.c (mips_elf_final_link): Account for link_order + relocs when allocating space for relocations. Set SEC_RELOC flag + for any section which has relocs. Handle link_order relocs in + link_order loop. Use _bfd_generic_link_add_symbols_collect for + add_symbls entry point. + + * linker.c (_bfd_generic_final_link): Set reloc_count to 0 before + counting relocs. Set SEC_RELOC flag for any section which has + relocs. + + * linker.c (_bfd_default_link_order): Handle bfd_data_link_order. + + * linker.c (_bfd_generic_link_add_symbols): Just call + generic_link_add_symbols. + (_bfd_generic_link_add_symbols_collect): New function, like + _bfd_generic_link_add_symbols but also collect constructors and + destructors by name as collect2 does. + (generic_link_add_symbols): New function, like old + _bfd_generic_link_add_symbols but with collect argument. + (generic_link_add_object_symbols): Take collect argument. + (generic_link_check_archive_element_no_collect): New function. + (generic_link_check_archive_element_collect): New function. + (generic_link_check_archive_element): Take collect argument. + (generic_link_add_symbol_list): Take collect argument. + (_bfd_generic_link_add_one_symbol): Rename constructor argument to + collect. + * libbfd-in.h (_bfd_generic_link_add_symbols_collect): Declare. + * libbfd.h: Rebuilt. + +Tue Mar 22 10:04:00 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * archive.c (bfd_construct_extended_name_table): Use ar_padchar + for first character in an extended name. + (_bfd_write_archive_contents): If ar_padchar == '/', then use + "//" as the name of the special archive member holding the + extended name table. + +Mon Mar 21 12:28:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Support for link_order types which generate relocs in order to + support -Ur in the linker. + * linker.c (generic_link_add_symbol_list): Remove bitsize argument + from call to _bfd_generic_link_add_one_symbol. + (_bfd_generic_link_add_one_symbol): Remove bitsize argument. + Don't pass bitsize to constructor call back. Pass BFD_RELOC_CTOR + instead of bitsize to add_to_set call back. + (_bfd_generic_final_link): Account for link_order relocs when + allocating space for relocations. Handle them in link_order loop. + (_bfd_generic_reloc_link_order): New function. + (_bfd_default_link_order): If a reloc_link_order is seen here, + abort. + (_bfd_count_link_order_relocs): New function. + * libbfd-in.h (_bfd_generic_link_add_one_symbol): Remove bitsize + argument from declaration. + (_bfd_generic_reloc_link_order): Declare. + (_bfd_count_link_order_relocs): Declare. + * libbfd.h: Rebuilt. + * aoutx.h (aout_link_add_symbols): Remove bitsize argument from + call to _bfd_generic_link_add_one_symbol. + (NAME(aout,final_link)): Account for link_order relocs when + allocating space for relocations. Handle them after handling all + input BFDs. + (aout_link_reloc_link_order): New function. + * ecoff.c (ecoff_link_add_externals): Remove bitsize argument from + call to _bfd_generic_link_add_one_symbol. + (ecoff_bfd_final_link): Account for link_order relocs when + allocating space for relocations. Handle them in link_order loop. + (ecoff_link_write_external): Set the storage class of a defined + linker created symbol based on the section it is in. Correct + bfd_link_hash_weak case to use .sc rather than .st. + (ecoff_reloc_link_order): New function. + * coff-alpha.c (alpha_bfd_reloc_type_lookup): Handle + BFD_RELOC_CTOR. + * coff-mips.c (mips_bfd_reloc_type_lookup): Likewise. + + * sunos.c (sunos_read_dynamic_info): Remove unused locals dynsym + and buf. + + * cisco-core.c (cisco_core_file_p): Only pass one argument to + bfd_zmalloc. Free a pointer, not a union. + (cisco_bfd_is_local_label): Correct cast from asection to asymbol. + +Sun Mar 20 09:24:36 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * bfd/som.c (som_begin_writing): Fix thinko (off by one error). + + * som.c (bfd_section_from_som_symbol): Only to do the value + comparison for function symbols within executables. + + * som.c (bfd_section_from_som_symbol): Renamed from + som_section_from_subspace_index. Pass in a native SOM symbol. + For executables, iterate through the sections to find out + which contains the symbol's address rather than using the + symbol_info field. (symbol_info has a different meaning for + dynamicly linked executables.) + + * trad-core.c (trad_unix_core_file_p): Don't pass abfd to + bfd_zmalloc. + + * som.c (som_begin_writing): Fix braino (one call to align + space/subspace data was done unconditionally rather than + just for executables.) + + * som.c (som_begin_writing): Align text in all executables to + make HPUX kernel happy. Fixes strip/objcopy for shared + executables. + +Sat Mar 19 07:06:59 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_begin_writing): Account for alignment needs of + subspaces too when writing executables. Never request a negative + bss size. Fixes some problems with demand paged executables, + still having problems with pure executables and shared executables. + +Fri Mar 18 19:12:47 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * trad-core.c (trad_unix_core_file_p): Call bfd_zmalloc not + bfd_zalloc for rawptr, because later on we may call free, not + bfd_release, on it. + + * bfd.c (struct _bfd): Add cisco_core_struct to tdata union. + * libbfd.c (bfd_read, bfd_seek): Add comments regarding errors. + * cisco-core.c: New file. + * Makefile.in: Change accordingly. + * configure.in: Recognize cisco_core_vec. + * config/m68k-aout.mt (SELECT_VECS): Add cisco_core_vec. + * targets.c: Add cisco_core_vec. + * bfd-in2.h: Rebuilt. + +Fri Mar 18 18:13:49 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.h (som_copyable_section_data_struct): New structure + containing all the private section information which needs + to be copied from input section to output section during + objcopy or strip. + (som_section_data_struct): Remove several fields now in + som_copyable_section_data_struct. Make the space and + subspace dictionaries be pointers (to save space when + only reading objects). + + * som.c (bfd_som_set_section_attributes): Now returns a boolean; + some references changed. Allocate a copyable data stucture if + none exists. Store info into the copyable data structure. + (bfd_som_set_subsection_attributes): Likewise. + (som_is_space, som_is_subspace, som_is_container): New functions. + Use these instead of directly accessing private data. + (som_prep_headers): Allocate space and subspace headers here. + Fill in some fields in the space/subspace headers from the + copyable data. + (som_bfd_copy_private_section_data): Only copy the stuff + that we really need to make objcopy and strip work. Allocate + the copy_data structure for the output bfd before copying. + + * som.h (struct som_exec_data): New structure to hold exec + info that must be preserved when running objcopy/strip. + (struct somdata): Add new "exec_data" field and accessor + macro. Add some comments on how the various fields are used. + (som_section_data_struct): Make is_space and is_subspace bitfields. + Delete unused subspace_index. All references now use the + target_index field within the section structure itself. + + * som.c (make_unique_section): Delete unused declaration. + (som_bfd_copy_private_bfd_data): New function. + (som_object_setup): Allocate space for and save exec information + that needs to be copied during objcopy/strip. + (som_mkobject): Do not allocate space for a file header here. + It is not used when only reading SOM objects. + (som_prep_headers): Allocate space for and attach a file header + to the output bfd. For executables, use the saved system_id + value rather than trying to guess the right value. Do not abort + wwhen setting file_hdr->entry* for executables. + (som_begin_writing): For executables, set the exec_entry and + exec_flags fields. + (som_copy_private_backend_section_data): Always return a value. + + * libhppa.h (PA_PAGESIZE): Define. + + * som.c (SOM_ALIGN): Define. + (som_begin_writing): If writing an executable, initialize all + fields in the exec header to zero. Update fields in the exec + header as sizes of loadable subspaces are computed. Carefully + preserve alignments when building executables. Actually write the + exec after all the fields are filled in. + + * Better long-filename handling. Reads SOM ABI compliant extended + names, but doesn't quite write compliant extended names yet. + * som.c (som_slurp_extended_name_table): Delete function. The + generic code will handle things correctly. + (som_slurp_armap): Seek to the beginning of the next member. + (normalize): New function. + (som_bfd_ar_write_symbol_stuff): Take the size of the extended + name table into account when computing the file offsets in the + SOM dictionary. Make sure to align to an even boundary. + (som_write_armap): Initialize the checksum to zero. + (ar_maxchars): Fix. Opps. + +Fri Mar 18 20:35:24 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * aoutx.h (reloc_type_lookup): Handle BFD_RELOC_CTOR on a 64-bit + machine. Handle BFD_RELOC_SPARC13 and BFD_RELOC_SPARC_BASE13. + +Thu Mar 17 18:26:46 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * bfd-in.h (BFD_VERSION): Use @VERSION@. + * Makefile.in (bfd.h): Replace it with contents of VERSION file. + * bfd-in2.h: Regenerated. + + * trad-core.c (trad_unix_bfd_is_local_label): Fixed typo where + this was also named trad_unix_bfd_copy_private_bfd_data. + +Thu Mar 17 10:37:07 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * aoutx.h, elfcode.h, coff-alpha.c, bout.c, ecoff.c, ecofflink.c, + elf32-hppa.c, elf32-mips.c, linker.c, som.c, sunos.c: If malloc(0) + returns NULL, it is not an error. It's possible that some of + these checks are not necessary (because the size can never be + zero), but putting in the checks is the conservative thing to do + in light of the fact that some of these malloc calls replaced + unchecked alloca calls, in which a zero argument would work fine. + +Thu Mar 17 11:44:45 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * osf-core.c (osf_core_bfd_copy_private_bfd_data): Remove + duplicate definition. + (osf_core_bfd_is_local_label): Define. + + * reloc.c (bfd_generic_get_relocated_section_contents): Don't fail + if malloc (0) fails. bfd_canonicalize_reloc returning 0 is not a + failure indication, it merely means there are no relocs. + + * elfcode.h (NAME(bfd_elf,write_object_contents)): Don't use space + after NAME, since SunOS /bin/cc can't handle it. + +Wed Mar 16 16:43:33 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * netbsd386.c (N_SET_FLAGS): Don't nuke the machine id field. + From sukes@glue.umd.edu (Tasuki Hirata). + +Wed Mar 16 07:55:54 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * aoutf1.h (4 places): Use a simple #if on ARCH_SIZE, rather than + all that convoluted stuff with NAME, CAT3, etc. The convoluted + stuff broke for SunOS4 /bin/cc (due to DEFUN elimination, I guess). + +Wed Mar 16 00:02:05 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_prep_for_fixups): Detect section symbols based + on either the lack of private data or the symbol flags. Do not + munge section symbol names anymore -- they no longer confuse GDB. + (som_begin_writing): Leave space for an exec header if writing + an executable. + (som_slurp_symbol_table): Recognize both forms of section symbol + names "L$0\002" and "$$". Change the name of "L$0\002" + section symbols to be the name of the section they represent. + Debugging symbols begin with "L$0\001", not just "L$". + +Tue Mar 15 22:58:28 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * bfd-in2.h, libbfd.h, libcoff.h: Rebuilt. + + * bfd-in.h (JUMP_TABLE): Add new entries to the jump table + for bfd_copy_private_section_data, bfd_copy_private_bfd_data, + and bfd_is_local_label. + + * targets.c: Add new entries to the bfd_target structure. + + * bfd.c (bfd_copy_private_bfd_data): New definition. + + * section.c (bfd_copy_private_section_data): New definition. + + * syms.c (bfd_is_local_label): New definition. + + * libbfd-in.h (bfd_generic_is_local_label): Declare. + + * libbfd.c (bfd_generic_is_local_label): New function. + + * *-core.c: Provide default definitions for new functions in + the target vector which all point to bfd_false. + + * aout-target.h, coffcode.h, elf32-target.h elf64-target.h, ieee.c + libaout.h, libecoff.h, nlm-target.h, oasys.c, srec.c, tekhex.c + Default new vectors for copying private backend data to bfd_true. + Default new vector for determining if a symbol is a local label + to bfd_generic_is_local_label. + + * som.c (som_bfd_copy_private_section_data): New function. + (som_bfd_is_local_label): New function. + (som_bfd_copy_private_bfd_data): For now default to bfd_true. + + * elf32-hppa.c (hppa_elf_is_local_label): New function. + +Tue Mar 15 23:55:47 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * cf-m68klynx.c (CALC_ADDEND): Use _bfd_m68klynx_howto_table. + +Tue Mar 15 04:41:13 1994 David J. Mackenzie (djm@rtl.cygnus.com) + + * Most files: + Replace DEFUN and DEFUN_VOID with K&R-style function definition. + Indent some of them to GNU standards. + + * aout32.c, archures.c, core.c, cpu-h8300.c, cpu-i960.c, + cpu-m68k.c, cpu-m88k.c, cpu-mips.c, cpu-vax.c, ctor.c, demo64.c, + elf32-hppa.h, gen-aout.c, host-aout.c, init.c, libhppa.h, + libieee.h, liboasys.h, newsos3.c, som.h, stab-syms.c, sunos.c: + Update copyright years. + +Mon Mar 14 11:41:23 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_prep_for_fixups): A relocation involving the section + symbol for the *ABS* section is really a relocation involving + no symbol. + (som_slurp_symbol_table): Do not set BSF_GLOBAL or BSF_EXPORT for + undefined symbols. Correctly distinguish between debugger symbols + and section symbols. + + * som (setup_sections): Set SEC_DEBUGGING and the section attributes + for spaces and subspaces. + + * som.c (som_bfd_count_ar_symbols): Fix typo. + + * som.c (som_object_setup): Set EXEC_P, D_PAGED, WP_TEXT, and + HAS_RELOC based on the object's magic number. + (make_unique_section): Delete function. BFD and its users are + prepared to handle multiple sections with the same name. + (setup_sections): Allocate space on the BFD's obstack to hold + section names. Use bfd_make_setion_anyway rather than the + obsolete make_unique_section. + (som_prep_headers): Choose the correct SOM magic number based + on the BFD's flags. + (som_bfd_fill_in_ar_symbols): Return false, not NULL on error. + +Sat Mar 12 09:46:09 1994 Ian Lance Taylor (ian@cygnus.com) + + * elf32-ppc.c: Renamed from elf32-powerpc.c. + * nlm32-ppc.c: Renamed from nlm32-powerpc.c. + * Makefile.in, configure.in: Corresponding changes. + +Fri Mar 11 22:27:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elf32-powerpc.c: Extensive changes to update to preliminary ABI. + +Fri Mar 11 00:34:59 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * sunos.c (sunos_read_dynamic_info): Assume that dynamic info + is always located at the start of the data section to allow + recovery of the dynamic info from a stripped executable. + * ecoff.c (ecoff_styp_to_sec_flags): Handle STYP_PDATA, STYP_XDATA + and STYP_COMMENT. + +Wed Mar 9 17:17:53 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * libbfd-in.h: Remove alloca cruft. It was missing some necessary + cruft (like the #pragma alloca for AIX). + In addition to that problem, the C alloca calls xmalloc, which + means checking for being out of memory can't work right. The + following changes remove all uses of alloca from BFD. + * hosts/solaris2.h: Remove alloca cruft. + * som.c: Replace alloca with a fixed size auto array. + * aoutx.h, elfcode.h, nlmcode.h, bout.c, coff-alpha.c, ecoff.c, + ecofflink.c, elf32-hppa.c, elf32-mips.c, linker.c, reloc.c, som.c, + sunos.c: Replace alloca with malloc and appropriate error checking and + freeing. + * linker.c: Replace alloca with obstack_alloc. + * libbfd.h: Rebuilt. + +Tue Mar 8 12:10:38 1994 Ian Lance Taylor (ian@cygnus.com) + + * coff-mips.c (mips_relocate_section): Handle MIPS_R_LITERAL like + MIPS_R_GPREL. + +Sat Mar 5 14:08:54 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * elf32-hppa.h, elfcode.h: Replace uses of Elf*_Half, Elf*_Word, + Elf*_Off typedefs by their expansion, the typedefs have been + removed from include/elf/internal.h. + * elfcode.h (bfd_section_from_shdr): Handle SHT_DYNAMIC section like + SHT_PROGBITS section. + +Thu Mar 3 20:03:39 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.h (_PA_RISC_ID): Treat HOST_HPPAOSF just like HOST_HPPABSD. + +Wed Mar 2 13:28:06 1994 Jim Kingdon (kingdon@deneb.cygnus.com) + + * configure.host: Recognize i[34]86-sequent-*. + + * trad-core.c (trad_unix_core_file_p): A non-zero, not zero, + return from bfd_seek indicates an error. + New macro TRAD_CORE_DSIZE_INCLUDES_TSIZE to replace + TRAD_CORE_STACK_OFFSET. + * hosts/symmetry.h: Define TRAD_CORE_DSIZE_INCLUDES_TSIZE and + TRAD_CORE_USER_OFFSET but not HOST_STACK_OFFSET. + +Wed Mar 2 11:57:03 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.[ch]: Do not include libhppa.h in som.c, instead include + it in som.h. + + * elf32-hppa.[ch]: Do not include libhppa.h in elf32-hppa.c, instead + include it in elf32-hppa.h. + + * som.c (log2): Return -1 on error rather than aborting. + (setup_sections): Bubble up an error from log2. + + * Changes to make HP C compiler happy in both traditional + and ANSI mode. + * som.c (hppa_som_gen_reloc_type): Use correct enum type for + field parameter. + (bfd_som_set_section_attributes): Use unsigned int rather than + unsigned char to avoid GNU-C extensions. + (bfd_som_attach_aux_hdr): Return a boolean to indicate success + or failure rather than aborting on failure. + + * som.h (bfd_som_set_section_attributes): Fix prototype to match + som.c changes. + (bfd_som_attach_aux_hdr): Add prototype. + (hppa_som-gen_reloc_type): Likewise. + + * elf32-hppa.c: Add a couple casts to make HP compiler happy. + (hppa_look_for_stubs_in_section): Do not return false on failure + until rest of code is ready to handle it. Abort for now. + +Tue Mar 1 18:33:59 1994 Jim Kingdon (kingdon@deneb.cygnus.com) + + * bfd-in2.h: Rebuilt. + +Tue Mar 1 13:06:53 1994 Kung Hsu (kung@mexican.cygnus.com) + + * i386os9k.c: use new functions bfd_set_error and bfd_get_error. + * Makefile.in: delete an extra blank. + * configure.in : Add i396os9k_vec. + +Mon Feb 28 15:41:01 1994 Kung Hsu (kung@mexican.cygnus.com) + + * config.bfd : Add i386-os9k. + * config/i386-os9k.mt : Newly add os9k target makefile. + + * i386os9k.c : new file to handle os9k format bfd. + * Makefile.in : Handle new file i386os9k.c + * targets.c : Add bfd_target_os9k_flavour and i386os9k_vec. + * cache.c : Initialize cache_sentinel to 0. + +Sun Feb 27 16:30:55 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (mismatches, retval_mismatches): Fix mismatch + action in case where caller specified no argument relocation. + (hppa_elf_build_linker_stub): Try again to get the sym_ptr_ptr + right in the original relocation and the stub's relocation. + + * elf32-hppa.h (hppa_look_for_stub_in_section): Fix typo. Delete + unused symbols argument. + + * elf32-hppa.c (hppa_elf_stub_reloc): Accept asymbol ** rather + than asymbol * for original target symbol. All callers changed. + Set reloc->sym_ptr_ptr appropriately. + (hppa_elf_build_linker_stub): Set reloc->sym_ptr_ptr correctly. + (hppa_elf_look_for_stubs_in_section): No longer need symbols + argument. Use the output symbols when canonicalizing the relocs, + creating them if necessary. + + * linker.c (_bfd_generic_link_output_symbols): Do not + rebuild/clobber the output symbols if they already exist. + +Sun Feb 27 15:22:36 1994 Stan Shebs (shebs@andros.cygnus.com) + + * targets.c (BFD_SEND, BFD_SEND_FMT): Add debugging versions that + check all the pointer dereferences. Enabled via DEBUG_BFD_SEND. + * bfd-in2.h: Rebuilt. + + * srec.c (hex_value): Always set to a size of 256 bytes. + (srec_init): Cosmetic changes. + +Sun Feb 27 11:18:47 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * elf32-hppa.c: Second half of major cleanup. More comments, + PARAMize and staticize rest of functions. Delete unused + functions. Delete unused/unnecessary arguments to some functions. + Group static vars together. Abort for bad errors until we have + error code propogation working. Work on spacing and indention. + Add FIXMEs for unresolved problems. Use enums rather than + #defines for lots of things. Merge two functions which build + linker stubs into a single function (so they can easily share a + ton of common code). + +Sat Feb 26 10:00:45 1994 Ian Lance Taylor (ian@cygnus.com) + + * reloc.c (_bfd_relocate_contents): Adjust handling of overflow to + avoid depending upon right shifts of signed numbers, and to + correct handling of src_mask with lower bits zero. + + * aoutx.h, archive.c: Add casts to avoid warnings from SVR4 cc. + * ecoff.c, ecofflink.c, ecoffswap.h, srec.c: Likewise. + * elf32-i386.c: Likewise. + * elfcode.h (bfd_section_from_shdr): Make i unsigned; remove old + #if 0 code. + (elf_write_phdrs): Make i unsigned. + (map_program_segments): Make i and n_left unsigned. + (assign_file_positions_except_relocs): Make i unsigned. + (write_shdrs_and_ehdr): Make count unsigned. + (assign_file_positions_for_relocs): Make i unsigned. + (NAME(bfd,elf_write_object_contents)): Make count unsigned. + (section_from_elf_index): Make index argument unsigned. + +Fri Feb 25 21:34:58 1994 Ian Lance Taylor (ian@cygnus.com) + + * elfcode.h: Don't include assert.h. + (swap_out_syms): Use BFD_ASSERT rather than assert. + + * linker.c (_bfd_generic_link_write_global_symbol): Add missing + break in switch. + + * hosts/i386v4.h (qsort, strtol): Remove incorrect and useless + declarations. + +Fri Feb 25 16:35:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * libhppa.h (hppa_rebuild_insn): Moved here from elf32-hppa.c. + + * elf32-hppa.h (elf_hppa_tc_symbol): Add new arguments. + (elf_hppa_tc_make_sections): Likewise. + (elf_hppa_final_processing): Add extern decl. + + * elf32-hppa.c: First half of major cleanup. Add/cleanup lots of + comments. PARAMize some static functions. Delete unused functions. + Delete unused/unnecessary arguments to many functions. Group + static vars together. Collapse common case statements together + in many places. Use default case when possible instead of listing + each case separately. Abort for bad errors until we get error + code propogation working. Work on spacing and indention problems. + Add FIXMEs for some unresolved problems. Delete hopelessly broken + COMPLEX relocation support (it's never used anyway). + (hppa_elf_rebuild_insn): Delete. Moved into libhppa.h. + (elf_hppa_tc_symbol): Accept and use new arguments (symext chains). + (elf_hppa_tc_make_sections): Likewise. + + * format.c (bfd_check_format_matches): Initialize matching_vector + to keep gcc -Wall quiet. + + * elfcode.h (elf_slurp_reloca_table): Fix typo. + + * som.c (som_get_symtab_upper_bound): Use "sizeof (asymbol *)" + not "sizeof (som_symbol_type *)". + + * elfcode.h (elf_get_symtab_upper_bound): Use "sizeof (asymbol *)" + not "sizeof (asymbol"). Opps. + +Fri Feb 25 13:19:04 1994 Ted Lemon (mellon@pepper.ncd.com) + + * bfd.c (bfd_get_gp_size): Can't return gp value on an archive. + (bfd_set_gp_size): Can't set gp value on an archive. + +Fri Feb 25 12:57:00 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * srec.c (pass_over): Don't skip too many characters when + end of line seen. + +Fri Feb 25 11:41:57 1994 Ian Lance Taylor (ian@cygnus.com) + + * ecoff.c (ecoff_sizeof_headers): Align result to 16 byte + boundary. + +Thu Feb 24 07:13:22 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_derive_misc_symbol_info): Derive symbol_info + field for absolute symbols in the same manner as undefined + and common symbols. + +Thu Feb 24 04:29:19 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * elfcode.h (elf_core_file_p): Check for core file e_machine match + like in elf_object_p. + +Wed Feb 23 18:28:37 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * elfcode.h (alloca): Delete declaration. + + * som.c (som_prep_headers): Use CPU_PA_RISC1_0 for magic + number rather than HP9000S800_ID. Note som.c is careful + to make sure CPU_PA_RISC1_0 is always defined. + +Mon Feb 21 10:12:02 1994 Stan Shebs (shebs@andros.cygnus.com) + + * Makefile.in (targets.o, archures.o): Use ALL_CFLAGS to supply + flags to explicit compile actions. + +Mon Feb 21 09:50:06 1994 Ian Lance Taylor (ian@lisa.cygnus.com) + + * ecofflink.c (ecoff_write_symhdr): Set symhdr->magic here. + * ecoff.c (ecoff_write_object_contents): Make sure .bss section + ends on a page boundary if there is no symbol table. + (ecoff_bfd_final_link): Don't set symhdr->magic here. + + * hosts/hp300.h: Include ; don't declare free. + + * som.c (som_bfd_count_ar_symbols): Use a pointer and alloca + rather than an array of variable size. + (som_bfd_fill_in_ar_symbols): Likewise. + (som_bfd_ar_write_symbol_stuff): Likewise. + + * coff-alpha.c (alpha_relocate_section): Rewrite mask and shift + operation to avoid OSF 1.3 cc bug. + * ecoff.c (ecoff_write_object_contents): Make text_size, data_size + and bss_size bfd_size_type instead of unsigned long. Make + text_start and data_start bfd_vma instead of unsigned long. + * ecofflink.c (ecoff_add_string): Remove incorrect cast of return + value. + +Sun Feb 20 16:06:54 1994 Ian Lance Taylor (ian@lisa.cygnus.com) + + * linker.c (_bfd_generic_link_add_archive_symbols): Consider + symbols in the order they appear in the archive map. + +Sat Feb 19 03:17:32 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * coff-alpha.c (reloc_nil): Add forward declaration, add missing + error_message argument. + * coff-sparc.c (bfd_coff_generic_reloc): Add forward declaration, + add missing error_message argument. + * mipsbsd.c (mips_fix_hi16_s): Add forward declaration, add missing + error_message argument. + +Fri Feb 18 11:41:58 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Support for PowerPC NetWare. + * nlm32-powerpc.c: New file. + * config.bfd (powerpc-*-netware*): New target; use ppc-nlm. + * config/ppc-nlm.mt: New file. + * configure.in (nlm32_powerpc_vec): New target vector; use + nlm32-powerpc.o, nlm32.o, nlm.o. + * targets.c (nlm32_powerpc_vec): Declare. + * Makefile.in (BFD32_BACKENDS): Add nlm32-powerpc.o. + (CFILES): Add nlm32-powerpc.c. + + Initial support for PowerPC ELF. Done without an ABI, and + probably to be changed when I get an ABI. + * config.bfd (powerpc-*-sysv4*): New target; use ppc-elf. + * config/ppc-elf.mt: New file. + * configure.in (bfd_elf32_powerpc_vec): New target vector; use + elf32-powerpc.o, elf32.o, elf.o. + * elf32-powerpc.c: New file. + * elfcode.h (prep_headers): Add bfd_arch_powerpc case. + (elf_set_arch_mach): Likewise. + * targets.c (bfd_elf32_powerpc_vec): Declare. + * Makefile.in (BFD32_BACKENDS): Add elf32-powerpc.o. + (CFILES): Add elf32-powerpc.c. + Rebuilt dependencies. + +Thu Feb 17 15:29:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coffgen.c (coff_write_linenumbers): Always return a value. + + * elfcode.h (elf_slurp_symbol_table): Handle zero symbols + reasonably. Allocate x_symp using alloca. + + * elfcode.h (map_program_segments): ELF program header entries + must be sorted by load address. This used to generate the entries + in reverse order. + + * section.c (SEC_IN_MEMORY): Define. + (asection): Rename unused field otheruserdata to contents, and + make it char *. + (bfd_make_section_anyway): Initialize contents field to NULL. + (bfd_get_section_contents): If SEC_IN_MEMORY is set, get section + contents from contents field rather than from file. + * bfd-in2.h: Rebuilt. + +Thu Feb 17 08:30:53 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * bfd.c (bfd_get_error, bfd_set_error): New functions. + (bfd_error): Make static. + (bfd_error_type): Renamed from bfd_ec. Prepend "bfd_error_" to + all values. + * bfd-in2.h: Regenerated. + * aix386-core.c, aout-adobe.c, aout-encap.c, aout-target.h, + aoutf1.h, aoutx.h, archive.c, archures.c, + bfd.c, bout.c, cache.c, coff-alpha.c, coff-mips.c, + coff-rs6000.c, coffcode.h, coffgen.c, core.c, ctor.c, + ecoff.c, ecofflink.c, elf.c, elf32-hppa.c, elf32-mips.c, + elfcode.h, format.c, hash.c, hp300hpux.c, hppabsd-core.c, + i386lynx.c, ieee.c, libbfd.c, libelf.h, linker.c, + lynx-core.c, nlm.c, nlm32-alpha.c, nlm32-i386.c, + nlm32-sparc.c, nlmcode.h, oasys.c, opncls.c, osf-core.c, + ptrace-core.c, reloc16.c, rs6000-core.c, section.c, som.c, + srec.c, sunos.c, syms.c, targets.c, tekhex.c, + trad-core.c: Change callers. + +Tue Feb 15 22:27:27 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c: Remove FIXMEs for things which have been dealt with. + +Tue Feb 15 19:39:24 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * section.c (bfd_get_section_contents): Since this function reads + unrelocated contents, the section's raw size is always the one to + use for bounds checking. + + * linker.c (default_indirect_link_order): In assertion, compare + link_order size field against cooked size, not raw size, of input + section. + + * bout.c (b_out_get_reloc_upper_bound): For BSS section, just + return 0. + (aligncode): When shrinking, the addend should be set to the + current offset in the section plus the number of bytes of padding + that will actually be retained. + (b_out_relax_section): If a section contains no relocations, don't + bother processing them. + (b_out_get_relocated_section_contents): Set reloc_done. Assert + that bfd_get_section_contents returns true. Check that relocs are + properly ordered. + (b_out_get_relocated_section_contents, case ALIGNDONE): Assert + that reloc->addend falls between the current source offset and the + raw size of the input section. + + * config.bfd: Support i960 vxworks versions > 5.0 with coff, not + bout. Default with no version number is still bout. Support + explicit i960-coff target too. + + * bout.c: Changed some indentation, deleted trailing whitespace, + fixed some comments, removed some "#if 1" lines. + (output_addr): New macro. + (calljx_callback, callj_callback, get_value, abs32code, aligncode, + b_out_get_relocated_section_contents): Use it for readability. + +Tue Feb 15 09:00:16 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_prep_for_ar_write): Iterate through the SOM + symbols, not the BFD symbols. + (som_bfd_ar_write_symbol_stuff): Likewise. + +Mon Feb 14 22:55:20 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_slurp_symbol_table): Do not die if a BFD doesn't + have any symbols. + + * Finish basic read-write support for SOM archive libraries. Bugs + surely remain as this hasn't been tested all that much. + * som.c (SOM_LST_HASH_SIZE, SOM_LST_MODULE_LIMIT): Define. + (struct som_misc_symbol_info): New structure to hold info necessary + to build both normal and library symbol tables. + (som_derive_misc_symbol_info): New function to derive info necessary + to build both normal and library symbol tables. + (som_build_and_write_symbol_table): Use new function to derive misc + symbol information. + (som_slurp_symbol_table): Update backend private data for symbols + appropriately. + (som_bfd_prep_for_ar_write): New function. + (som_bfd_ar_symbol_hash): New function. + (som_bfd_ar_write_symbol_stuff): New function. + (som_write_armap): Flesh out. + (som_vec): Fix ar padding character. + + * som.c: Consistently use memset rather than bzero. + +Mon Feb 14 17:02:28 1994 Stu Grossman (grossman at cygnus.com) + + * coff-rs6000.c: Add Lynx core file support, use HOST_AIX, where + appropriate. + * rs6000-core.c: Use HOST_AIX instead of COREFILES_PLEASE. + * config/rs6000.mh: Remove defs of ARCHIVES_PLEASE and + COREFILES_PLEASE. + * config/rs6000lynx.mh: Turn on Lynx core file support. + * hosts/rs6000.h: #define HOST_AIX. + * hosts/rs6000lynx.h: Create this to enable Lynx host support. + +Sun Feb 13 14:30:00 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.h (som_symbol_data): Safely access backend private data + for BFD symbols. All callers changed. + + * Read-only SOM archive support. + * som.c (som_bfd_count_ar_symbols): New helper function. + (som_bfd_fill_in_ar_symbols): New helper function. + (som_slurp_armap): New function to read a SOM LST. + + * som.h: Include and . + +Sat Feb 12 22:34:14 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * elfcode.h (elf_map_symbols): Fix typo. + (write_object_contents): Check return values from prep_headers and + elf_compute_section_file_positions. + (set_section_contents): Likewise. + +Fri Feb 11 16:56:50 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * archive.c (normalize) [VMS]: Call malloc, not bfd_xmalloc. + (bfd_construct_extended_name_table): Check result of normalize. + +Tue Feb 8 08:57:31 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + Make all callers of malloc or realloc (including via obstacks) + check the result for NULL. Most set bfd_error to no_memory and + return in that case; a few are harder to fix, and are marked + with "FIXME ". + + * elf32-hppa.c (hppa_elf_build_arg_reloc_stub + hppa_elf_build_long_branch_stub): Check bfd_make_empty_symbol return. + * linker.c (_bfd_generic_link_output_symbols + _bfd_generic_link_write_global_symbol): Ditto + * section.c (bfd_make_section_anyway): Ditto. + + * tekhex.c (find_chunk tekhex_mkobject): Check bfd_alloc. + (first_phase): Ditto. FIXME void + (tekhex_make_empty_symbol): Check bfd_zalloc. + + * sunos.c (sunos_read_dynamic_info): Check bfd_zalloc. + (MY(read_dynamic_symbols) MY(read_dynamic_relocs)): Check bfd_alloc. + + * stringhash.c (_bfd_stringtab_hash_newfunc): Check bfd_hash_allocate. + + * srec.c: Indent. + (fillup_symbols): Check bfd_alloc. FIXME void + (srec_mkobject srec_get_section_contents + srec_set_section_contents): Check bfd_alloc. + (srec_make_empty_symbol): Check bfd_zalloc. + + * som.c (hppa_som_gen_reloc_type): Check bfd_alloc_by_size_t. + (make_unique_section): Check bfd_alloc. + (som_new_section_hook): Check bfd_zalloc. + (bfd_som_attach_aux_hdr): Ditto. FIXME void + + * rs6000-core.c (rs6000coff_core_p): Check bfd_zalloc. + + * osf-core.c (osf_core_make_empty_symbol): Check bfd_zalloc. + (osf_core_core_file_p): Check bfd_alloc. + + * oasys.c (oasys_slurp_symbol_table oasys_archive_p + oasys_mkobject oasys_object_p oasys_new_section_hook + oasys_set_section_contents): Check bfd_alloc. + (oasys_slurp_section_data): Check bfd_zalloc and bfd_alloc. + (oasys_make_empty_symbol): Check bfd_zalloc. + + * nlmcode.h (nlm_make_empty_symbol): Check bfd_zalloc. + (nlm_slurp_symbol_table): Check bfd_zalloc and bfd_alloc. + + * nlm32-sparc.c (nlm_sparc_read_import): Check bfd_alloc. + + * nlm32-i386.c (nlm_i386_read_import): Check bfd_alloc. + + * nlm32-alpha.c (nlm_alpha_read_import): Check bfd_alloc. + + * linker.c (_bfd_link_hash_newfunc + (generic_link_hash_newfunc + (archive_hash_newfunc + (_bfd_generic_link_add_one_symbol): Check bfd_hash_allocate. + (_bfd_generic_final_link + (_bfd_generic_link_output_symbols + (default_indirect_link_order): Check bfd_alloc. + (bfd_new_link_order): Check bfd_alloc_by_size_t. + + * irix-core.c (irix_core_make_empty_symbol): Check bfd_zalloc. + + * ieee.c: Indent. + (read_id get_symbol get_section_entry ieee_archive_p ieee_object_p + ieee_slurp_section_data ieee_new_section_hook): Check bfd_alloc. + (do_one): Check bfd_alloc. Return a boolean. + (ieee_slurp_section_data): Check it. + (init_for_output): Check bfd_alloc. Return a boolean. + (ieee_set_section_contents): Check it. + (do_with_relocs): Check bfd_alloc. Return a boolean. + (ieee_bfd_debug_info_accumulate): Ditto. FIXME void. + (ieee_mkobject): Check bfd_zalloc. + (ieee_make_empty_symbol): Check bfd_zmalloc. + + * hpux-core.c (hpux_core_make_empty_symbol): Check + bfd_zalloc. + + * hppabsd-core.c (hppabsd_core_make_empty_symbol): Check + bfd_zalloc. + (hppabsd_core_core_file_p): Check bfd_zalloc. + + * hp300hpux.c (MY(slurp_symbol_table)): Check bfd_alloc. + + * elfcode.h (elf_new_section_hook): Check bfd_alloc. + (bfd_section_from_phdr): Ditto. + (write_relocs): Ditto. FIXME void + (elf_map_symbols assign_section_numbers map_program_segments): + Ditto. Return a boolean. + (swap_out_syms): Ditto. Check elf_map_symbols. + (elf_slurp_symbol_table): Check bfd_zalloc. + (elf_slurp_reloca_table): Check bfd_alloc. + (elf_slurp_reloc_table): Ditto. + (elf_compute_section_file_positions): Check assign_section_numbers. + (assign_file_positions_except_relocs): Return a boolean. + Check map_program_segments. + (elf_compute_section_file_positions): Check it. + + * elf32-mips.c (mips_elf_final_link): Check bfd_alloc. + + * elf32-hppa.c (hppa_elf_stub_branch_reloc): Check bfd_zmalloc and + realloc. + (hppa_elf_stub_reloc): Ditto. + (hppa_elf_build_arg_reloc_stub): Check bfd_zalloc. + (hppa_elf_build_long_branch_stub): Ditto. + (elf32_hppa_backend_symbol_table_processing): Ditto. + + * ecoff.c (ecoff_set_symbol_info): Check bfd_alloc. Return a boolean. + (ecoff_slurp_symbol_table): Check it. + (ecoff_slurp_armap): Check bfd_alloc. + (ecoff_write_armap): Check bfd_zalloc. + (ecoff_link_hash_newfunc): Check bfd_hash_allocate and + _bfd_link_hash_newfunc. + (ecoff_link_add_externals): Check bfd_alloc. + + * ctor.c (bfd_constructor_entry): Check bfd_alloc. + + * coffgen.c (coff_real_object_p): Check bfd_alloc. + (coff_renumber_symbols): Check bfd_alloc_by_size_t. Return a boolean. + (coff_write_symbol): Check bfd_alloc. FIXME int + (coff_write_linenumbers): Check bfd_alloc. Return a boolean. + (coff_section_symbol): Check bfd_alloc_by_size_t. + (coff_get_normalized_symtab): Check bfd_alloc. + (coff_bfd_make_debug_symbol): Check bfd_zalloc. + * libcoff-in.h: Change decls of coff_renumber_symbols, + coff_write_linenumbers. + * libcoff.h: Rebuilt. + * coffcode.h (coff_write_object_contents): Check + coff_renumber_symbols, coff_write_linenumbers. + + * coffcode.h: Indent. + (coff_add_missing_symbols): Check bfd_alloc_by_size_t. Return a + boolean. + (coff_write_object_contents): Check it. + + * coff-alpha.c (alpha_relocate_section): Check bfd_alloc. + * coff-mips.c (mips_relocate_section): Ditto. + + * archive.c (bfd_slurp_bsd_armap_f2): Check bfd_alloc value. + (do_slurp_bsd_armap): Ditto. + (compute_and_write_armap): Check bfd_realloc value. + + * aoutx.h (translate_from_native_sym_flags): Check bfd_alloc + return value. Return boolean value. + (NAME(aout,make_empty_symbol)): Check bfd_zalloc return value. + (NAME(aout,slurp_symbol_table)): Check bf_alloc and bfd_zalloc + return value. + (add_to_stringtab): Ditto. FIXME void + (aout_link_hash_newfunc): Check bfd_hash_allocate return value. + (aout_link_add_symbols): Check bfd_alloc value. + (translate_symbol_table): Check translate_from_native_sym_flags. + * hp300hpux.c (MY(slurp_symbol_table)): Ditto. + * aoutx.h (aout_link_hash_newfunc): Check _bfd_link_hash_newfunc. + + * opncls.c (bfd_zalloc bfd_realloc): Check result of bfd_alloc. + + * opncls.c (obstack_chunk_alloc): Define as malloc, not + bfd_xmalloc_by_size_t. + (_bfd_new_bfd): Check obstack_begin for 0 return. + + * ieee.c (obstack_chunk_alloc): Define as malloc, not + bfd_xmalloc_by_size_t. + (ieee_archive_p): Check obstack_begin for 0 return and + obstack_finish for NULL return. + + * hash.c (obstack_chunk_alloc): Define as malloc, not + bfd_xmalloc_by_size_t. + (bfd_hash_table_init_n): Check obstack_begin for 0 return and + obstack_finish for NULL return. + (bfd_hash_lookup): Check obstack_alloc for NULL return. + + * ecofflink.c (obstack_chunk_alloc): Define as malloc, not + bfd_xmalloc_by_size_t. + bfd_ecoff_debug_accumulate + bfd_ecoff_debug_accumulate_other): Check obstack_alloc. + (add_file_shuffle add_memory_shuffle): Check obstack_alloc for + NULL return. Return boolean, not void. + (bfd_ecoff_debug_init): Check obstack_begin for 0 return. + (bfd_ecoff_debug_accumulate): Check add_file_shuffle + and add_memory_shuffle return. + (string_hash_newfunc): Check bfd_hash_allocate and bfd_hash_newfunc. + (bfd_ecoff_debug_accumulate): Check bfd_alloc. + (ecoff_add_string): Check add_memory_shuffle return. + + * libbfd-in.h (xmalloc, bfd_xmalloc, bfd_xmalloc_by_size_t): + Remove decls. + * libbfd.h: Rebuilt. + +Fri Feb 11 15:35:32 1994 Stu Grossman (grossman at cygnus.com) + + * configure.host: Add Lynx/rs6000 support. + * config/i386-nlm.mt: Enable a.out file support. + * config/rs6000lynx.mh: Lynx/rs6000 host support. + +Fri Feb 11 17:25:58 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * archive.c (compute_and_write_armap): Rewrite somewhat to improve + memory usage. + +Fri Feb 11 13:10:42 1994 Stan Shebs (shebs@andros.cygnus.com) + + * archive.c: Change all references to '\n' in archive magic + to '\012', for greater portability. + * ecoff.c (ecoff_write_armap): Ditto. + +Thu Feb 10 12:58:48 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (aout_link_write_other_symbol): Check strip settings to + see whether symbol should be output. + * genlink.h (struct generic_write_global_symbol_info): Added info + field. + * linker.c (_bfd_generic_final_link): Initialize wginfo.info. + (_bfd_generic_link_write_global_symbol): Check strip settings to + see whether symbol should be output. + * elf32-mips.c (mips_elf_final_link): Initialize wginfo.info. + +Wed Feb 9 21:34:58 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_reloc_queue_find): Do not examine a NULL queue entry. + + * som.c: Cast return values from BFD memory allocation routines to + avoid warnings from the HP compiler. + +Wed Feb 9 12:55:02 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-alpha.c (alpha_relocate_section): Accept a LITERAL + reloc on an "ldl" instruction too. + + * archive.c (bfd_ar_hdr_from_filesystem): Cast status elements + when passing them to sprintf. Use %ld instead of %d. + + * coff-rs6000.c (rs6000coff_mkarchive): Return false. + (rs6000_coff_snarf_ar_hdr): Don't declare errno; it's not used. + Also removed unused variable namelen. + (rs6000coff_write_armap): Declare orl_count and stridx parameters. + +Tue Feb 8 18:00:34 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * libbfd-in.h (xmalloc): Don't declare parameter type, to avoid + conflicts. + * libbfd.h: Rebuilt. + +Tue Feb 8 15:55:50 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * coff-alpha.c (reloc_nil): New function. + (alpha_howto_table): Use it as special_function to prevent certain + relocs from being adjusted by bfd_perform_relocation. IGNORE + reloc should be partial_inplace. + (alpha_ecoff_get_relocated_section_contents): Accept a LITERAL + reloc on an "ldl" instruction too. + +Tue Feb 8 00:32:28 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * elf32-hppa.c (CURRENT_STUB_OFFSET, hppa_elf_build_arg_reloc_stub, + hppa_elf_build_long_branch_stub): Cast to char * instead of int + before performing pointer arithmetic. + +Mon Feb 7 20:56:27 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config.bfd (hppa*-*-osf*): Use bfd_name hppaosf for this + configuration. + (hppa*-*-*elf*): This configuration used hppa-elf now. + + * som.c: This file is also used for HOST_HPPAOSF. + + * targets.c (bfd_target_vector): Enable som_vec for HOST_HPPAOSF. + + * hosts/hppaosf.h: New host configuration file. + + * config/hppabsd.mt (SELECT_VECS): Add bfd_elf32_hppa_vec as + BSD handles both SOM and ELF object files. + + * config/hppaosf.mh (HDEFINES): Delete. No longer needed. + (RANLIB): Doesn't do anything, define it to be "echo". + + * config/hppaosf.mt: New target makefile fragment for a PA running + OSF1. + +Mon Feb 7 15:02:06 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * archures.c (enum bfd_architecture): Added bfd_arch_powerpc. + (archures_init_table): If SELECT_ARCHITECTURES is not defined, + added bfd_powerpc_arch. + * bfd-in2.h: Rebuilt. + * cpu-powerpc.c: New file. + * Makefile.in (ALL_MACHINES, CFILES): Added cpu-powerpc.c. + Rebuilt dependencies. + + * elfcode.h (bfd_section_from_shdr): Get vma and alignment_power + of an SHT_STRTAB section from sh_addr and sh_addralign, rather + than just setting them to zero. + +Sun Feb 6 20:04:10 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * elfcode.h (prep_headers, swap_out_syms): Check for NULL return + from bfd_new_strtab. + (elf_compute_section_file_positions): Check for false return from + swap_out_syms. + + * linker.c (default_indirect_link_order): Check for NULL return + from bfd_get_relocated_section_contents. + + * syms.c: Make example application in doc call xmalloc, not + bfd_xmalloc. + + * aoutx.h (NAME(aout,slurp_symbol_table), + aout_link_get_symbols, NAME(aout,link_hash_table_create)): + * bout.c (b_out_slurp_reloc_table, b_out_squirt_out_relocs): + * ecoff.c (ecoff_bfd_link_hash_table_create): + * ecofflink.c (bfd_ecoff_debug_init): + * format.c (bfd_check_format_matches): + * linker.c (_bfd_generic_link_hash_table_create): + (_bfd_generic_final_link): + * reloc16.c (bfd_coff_reloc16_relax_section): + (bfd_coff_reloc16_get_relocated_section_contents): + * elf32-hppa.c (hppa_elf_build_arg_reloc_stub): + * elf32-mips.c (mips_elf_final_link): + * elfcode.h (bfd_new_strtab): + (bfd_add_2_to_strtab): + (elf_slurp_symbol_table): + (elf_corefile_note): + * libbfd.c (bfd_zmalloc): + Use malloc and check the result, instead of bfd_xmalloc. + +Sat Feb 5 12:39:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config.bfd: Put m68*-*-sysv* line after m68*-*-sysv4*. + +Sat Feb 5 05:32:44 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * srec.c (srec_write_record): Put CONST keyword for "src" before + "unsigned", some compilers don't like it after "unsigned". + * libcoff.h, libcoff-in.h (bfd_perform_slip): Rename "value" to + "val" in prototype declaration because some compilers don't like + arguments whose names are the same as types. + +Sat Feb 5 01:14:38 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (aout_link_check_ar_symbols): Correct test for whether + object file defines symbol. Also, if skipping a symbol, skip the + second symbol of a N_WARNING or N_INDR symbol as well. + +Fri Feb 4 23:55:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Add basic support for writing RS/6000 XCOFF files. + * coff-rs6000.c (dummy_reloc): Removed. + (rs6000coff_howto_table): Defined XCOFF relocs. + (RTYPE2HOWTO): Defined to use rs6000coff_rtype2howto. + (rs6000coff_rtype2howto): New function. + (coff_bfd_reloc_type_lookup): Defined to use + rs6000coff_reloc_type_lookup. + (rs6000coff_reloc_type_lookup): New function. + (SELECT_RELOC): Defined to set r_type and r_size fields. + (COFF_LONG_FILENAMES): Defined. + * coffcode.h (combined_entry_type): Changed fix_tag and fix_end + fields to bitfields. Added fields fix_value and fix_scnlen. + (sec_to_styp_flags): If STYP_DEBUG is defined, use it rather than + STYP_INFO for the type of a section named .debug. + (coff_add_missing_symbols): Don't define if RS6000COFF_C. + (coff_write_object_contents): If RS6000COFF_C, don't call + coff_add_missing_symbols. + (coff_slurp_symbol_table): If RS6000COFF_C, then if the last aux + entry has type STY_LD change the x_scnlen into a pointer to a + symbol and set fix_scnlen. Also, for a C_BSTAT symbol, change the + value into a pointer to a symbol and set fix_value. + * libcoff.h: Rebuilt. + * coffgen.c (coff_mangle_symbols): Reindent. If fix_value is set, + get the symbol offset. Likewise for fix_scnlen. + (string_size): Change type to bfd_size_type. + (debug_string_size, debug_string_section): New static variables. + (coff_fix_symbol_name): If bfd_coff_symname_in_debug returns true, + write the symbol name into the .debug section; assume that the + section has already been created with the right size. + (coff_write_symbols): Initialize debug_string_size to 0. If + bfd_coff_symname_in_debug returns true, don't put symbol name in + usual string table. After writing out all symbols, if + debug_string_size is not 0, check that it matches the size of the + .debug section. + (coff_get_normalized_symtab): Clear new fix_value and fix_scnlen + fields. If the string offset is 0, always use an empty string as + the name. + (coff_make_empty_symbol): Zero out the symbol structure. + * reloc.c (bfd_perform_relocation): Work around one gross hack + with another: actually look at the target name to avoid the broken + COFF check. + (bfd_reloc_code_real_type): Add BFD_RELOC_PPC_B26, + BFD_RELOC_PPC_BA26 and BFD_RELOC_PPC_TOC16. + * bfd-in2.h: Rebuilt. + +Fri Feb 4 17:28:32 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * libbfd.c (bfd_zmalloc): Call bfd_xmalloc instead of malloc. + (bfd_xmalloc, bfd_xmalloc_by_size_t): Functions deleted. + * libbfd-in.h: Define them as macros calling xmalloc and declare + xmalloc. + * libbfd.h: Rebuilt. + +Thu Feb 3 16:49:35 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecofflink.c (bfd_ecoff_debug_externals): If a small undefined + symbol has a value in the ECOFF symbol but not in the BFD symbol, + keep the value in the ECOFF symbol. This helps gas. + + * linker.c (_bfd_generic_link_output_symbols, + _bfd_generic_link_write_global_symbol): Don't require that all + references to a common symbol be themselves common symbols. + + * aoutx.h (aout_reloc_index_to_section): Handle N_UNDF. + +Wed Feb 2 20:37:19 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * libbfd.c, bfd-in.h, hosts/alphaosf.h, hosts/sparc-ll.h, aoutf1.h, + sparclynx.c, Makefile.in: Change HOST_64_BIT to BFD_HOST_64_BIT. + * bfd-in2.h: Rebuilt. + +Wed Feb 2 12:30:13 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coffswap.h (coff_swap_reloc_out): If RS6000COFF_C, handle type + and size correctly. + (coff_swap_aux_in): If RS6000COFF_C, change x_csect.x_scnlen to + x_csect.x_scnlen.l to match change in coff/internal.h. + (coff_swap_aux_out): Likewise. + + * coff-mips.c (mips_ecoff_backend_data), coff-alpha.c + (alpha_ecoff_backend_data): Change casts of aux_in and aux_out + fields to match yesterday's changes. + + * coffcode.h (coff_write_relocs): If SELECT_RELOC is defined, pass + in the internal_reloc itself, not the type. + * coff-apollo.c, coff-h8300.c, coff-h8500.c, coff-i386.c, + coff-m68k.c, coff-sh.c, coff-we32k.c, coff-z8k.c: Changed + definition of SELECT_RELOC accordingly. + +Tue Feb 1 12:05:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coffcode.h (bfd_coff_backend_data): Added new arguments to + _bfd_coff_swap_aux_in and _bfd_coff_swap_aux_out: aux index number + and number of aux entries. + (bfd_coff_swap_aux_in, bfd_coff_swap_aux_out): Changed + accordingly. + * libcoff.h: Rebuilt. + * coffswap.h (coff_swap_aux_in, coff_swap_aux_out): Accept new + arguments. If RS6000COFF_C, only treat C_EXT and C_HIDEXT + specially if this is the last aux entry. + * coffgen.c (coff_write_symbol, coff_get_normalized_symtab): Pass + new arguments to swap_aux functions. + +Sun Jan 30 15:14:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * gen-aout.c (main): Set DEFAULT_ARCH based on preprocessor macros + (only testing for m68k and vax at the moment); do verify that the + preprocessor didn't trash the arch name inside the string version. + Don't print out "pagesize =" line that prevents output from + compiling. Derive BYTES_IN_WORD and ARCH values from sizeof + results. + * Makefile.in (aout-params.h): Pass gen-aout a dummy target name. + (check, installcheck): Identify directory in "no testsuites" + message. + +Sun Jan 30 13:25:28 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (aout_link_write_symbols): Write out correct value for + object file symbol. + +Fri Jan 28 18:34:05 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * hosts/vaxbsd.h (HOST_STACK_END_ADDR): Vax BSD doesn't define + KERNBASE, so hard-code 0x80000000 instead. + +Thu Jan 27 13:54:08 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * linker.c (generic_link_add_symbol_list): If symbol is common, + set the BSF_OLD_COMMON flag. + +Wed Jan 26 13:47:15 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * format.c (bfd_check_format_matches): Put the new entry in the + correct element of matching_vector. + +Tue Jan 25 11:43:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * som.c, som.h (bfd_som_set_section_attributes, + bfd_som_set_subsection_attributes): Change parameters from char + to int. Following a prototype with an old-style function definition + in the presence of widened parameters is a GCC-ism not supported + by the HP compiler in ANSI mode. + +Tue Jan 25 11:46:46 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * reloc.c (bfd_get_reloc_size): Size of type -2 is 4 bytes, not 2. + + * hp300hpux.c (MY(write_object_contents)): Write out the symbols + before writing out the relocs, so that the right symbol indices + are used. + + * archive.c (do_slurp_bsd_armap, bfd_slurp_bsd_armap_f2): Do not + try to overlay the internal carsyms on the external symdefs. That + can not work if the size of a host pointer is larger than 4 bytes. + + * format.c (bfd_check_format_matches): Cast result of + bfd_xmalloc_by_size_t. + * opncls.c (_bfd_new_bfd): Avoid ANSI C prototype. + + * archive.c: Reindented to GNU standards. + +Mon Jan 24 14:41:23 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * opncls.c (_bfd_new_bfd, _bfd_new_bfd_contained_in): Add + "_bfd_" to function names. + * archive.c (_bfd_create_empty_archive_element_shell), + libbfd-in.h: Change callers. + + * libbfd.c (bfd_zmalloc): Renamed from zalloc. + * libbfd.c (bfd_add_to_string_table), + trad-core.c (trad_unix_core_file_p), + targets.c (bfd_target_list), + ptrace-core.c (ptrace_unix_core_file_p), + opncls.c (new_bfd), libbfd-in.h, + ieee.c (ieee_make_empty_symbol), + elf32-hppa.c (hppa_elf_stub_branch_reloc), + (hppa_elf_stub_reloc): Change callers. + * libbfd.h: Regenerated. + + * archive.c (_bfd_look_for_bfd_in_cache): Add "_bfd_" to name. + (_bfd_get_elt_at_filepos), + coff-rs6000.c (rs6000coff_get_elt_at_filepos), libbfd-in.h: + Change callers. + + * format.c (bfd_check_format_matches), libbfd-in.h, targets.c, + elfcode.h (elf_object_p): Rename target_vector to bfd_target_vector + and default_vector to bfd_default_vector. + * libbfd.h: Regenerated. + + * format.c (bfd_check_format_matches): New function. + (bfd_check_format): Call it. + (bfd_matching_formats): Function removed. + * targets.c: Replace the vector added on Jan 21 with a count of + entries in default_vector. + * bfd-in2.h: Regenerated. + +Mon Jan 24 12:38:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-alpha.c (alpha_ecoff_object_p): New function. Set size of + .pdata section based on lnnoptr field, not section header. + (alpha_relocate_section): Don't bother to check if r_symndx >= 0, + since it is unsigned. + (ecoffalpha_little_vec): Use alpha_ecoff_object_p rather than + coff_object_p. + * ecoff.c (ecoff_new_section_hook): Set alignment_power field of + .pdata section to 3. + (ecoff_compute_section_file_positions): Save the size of the + .pdata section in the line_filepos field, and actually align the + .pdata section to an alignment power of 4. + (ecoff_compute_reloc_file_positions): Set output_has_begun after + calling ecoff_compute_section_file_positions. + (ecoff_write_object_contents): Set s_lnnoptr for the .pdata + section from the line_filepos field. Set vstamp for the optional + header from the vstamp of the symbolic header. + (ecoff_bfd_final_link): Set vstamp of the symbolic header to the + vstamp used by the first object file in the link. + + * ecofflink.c (ecoff_align_debug): Align RFDs to debug_align. + + * linker.c (generic_link_check_achive_element): Set SEC_ALLOC flag + for a created common section. + (_bfd_generic_link_add_one_symbol): Likewise. + + * elfcode.h (swap_out_syms): Use elf_section_from_bfd_section to + get the index of a common section, rather than always using + SHN_COMMON (MIPS has multiple common sections). + + * elf32-hppa.c (hppa_elf_gen_reloc_type): Typo (== for =). + + * bfd/aoutx.h (aout_link_input_section_std, + aout_link_input_section_ext): Pass additional arguments to + reloc_overflow callback. + * coff-alpha.c (alpha_ecoff_get_relocated_section_contents, + alpha_relocat_section): Likewise. + * coff-h8300.c (h8300_reloc16_extra_cases): Likewise. + * coff-h8500.c (extra_case): Likewise. + * coff-mips.c (mips_relocate_section): Likewise. + * coff-z8k.c (extra_case): Likewise. + * elf32-hppa.c (hppa_elf_stub_finish): Likewise. + * reloc.c (bfd_generic_get_relocated_section_contents): Likewise. + + * bout.c (calljx_callback, callj_callback): Use get_value to get + the symbol value and check for undefined symbols. + (get_value): If the symbol is undefined, look it up in the linker + hash table. + (b_out_get_relocated_section_contents): For PCREL24 and PCREL13 + use get_value to get the symbol value and check for undefined + symbols. + * reloc16.c (bfd_coff_reloc16_get_value): If the symbol is + undefined, look it up in the linker hash table. + + * aoutx.h (translate_symbol_table): The string index 0 has a + special meaning for normal symbols, but not for dynamic symbols. + +Sat Jan 22 12:26:01 1994 Stu Grossman (grossman at cygnus.com) + + * sparclynx.c: Setup appropriate macros to enable core file + support. + +Fri Jan 21 16:25:35 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * targets.c: Add a vector of matching format names. + * format.c (bfd_matching_formats): New function to return it. + (bfd_check_format): Set it. + * bfd-in2.h: Regenerated. + + * bfd-in.h: Remove decls of bfd_ec type and error printing functions. + Remove decl of type symclass; wasn't used. + * bfd.c: Document error handling, including code fragments + containing the error decls that were in bfd-in.h. + Remove DEFUNs. + * bfd-in2.h: Regenerated. + +Fri Jan 21 14:11:16 1994 Sean Fagan (sef@cygnus.com) + + * nlmcode.h, liblnm.h, nlm32-alpha.c nlm32-i386.c nlm32-sparc.c: + The sparc (and possibly other?) NLM format requires a different + way to write exports, so add a write_export field to the backend + data (and set it to NULL for everything but the sparc). + +Fri Jan 21 14:11:16 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * sunos.c (MY(read_dynamic_relocs)): Compare info->dynrel with NULL, + not (struct external_nlist *) NULL. info->dynrel is a PTR, not + a struct external_nlist *. + +Fri Jan 21 09:29:01 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * bfd.c: Remove error strings for errors removed below. + * aoutx.h (translate_to_native_sym_flags), bfd-in.h (bfd_ec), + oasys.c (oasys_write_sections): Rename + bfd_error_nonrepresentable_section to nonrepresentable_section. + None of the other bfd error names start with "bfd_error". + Remove errors symbol_not_found and no_relocation_info, which seem + to be unused. + * bfd-in2.h: Regenerated. + +Fri Jan 21 01:11:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * bfd.c (bfd_get_gp_size): Added support for ELF. + + * syms.c (BSF_DYNAMIC): New symbol flag. + (bfd_print_symbol_vandf): Print it. + * bfd-in2.h: Rebuilt. + * libaout.h (struct aout_backend_data): New read_dynamic_symbols + and read_dynamic_relocs fields. + (struct aoutdata): New dynamic_info field. + (obj_aout_dynamic_info): New accessor macro. + * sunos.c (struct sunos_dynamic_info): New structure. + (sunos_read_dynamic_info, MY(read_dynamic_symbols), + MY(read_dynamic_relocs)): New functions to read dynamic symbols + and relocs. + * aoutx.h (NAME(aout,some_aout_object_p)): If the object is + dynamically linked, set SEC_RELOC for both the .text and .data + sections. + (translate_from_native_sym_flags): Don't set BSF_LOCAL for an + undefined symbol. + (translate_symbol_table): New function, split out of + slurp_symbol_table; set the BSF_DYNAMIC flag appropriately. + (NAME(aout,slurp_symbol_table)): Read dynamic symbols, if any. + (NAME(aout,slurp_reloc_table)): Read dynamic relocs, if any. + (NAME(aout,get_reloc_upper_bound)): Include dynamic reloc count in + return value. + * aoutf1.h (NAME(aout,sunos4_write_object_contents)): Don't write + out dynamic symbols or relocs against reloc symbols, since they + are already in the .text section and we wouldn't know where to + write them anyhow. + (sunos4_aout_backend): Initialize read_dynamic_symbols and + read_dynamic_relocs fields. + * aout-target.h (MY(backend_data)): Initialize + read_dynamic_symbols and read_dynamic_relocs fields. + +Thu Jan 20 20:57:27 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * hosts/alphaosf.h (uint64e_type, uint64_type, int64_type): Delete + typedefs, since HOST_64_BIT will take care of defining them in + bfd.h. + +Wed Jan 19 17:28:59 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/alphaosf.mh (HDEFINES): Don't define HOST_64_BIT here; + that's dealt with elsewhere. + * hosts/alphaosf.h (sprintf_vma, fprintf_vma): New macros. + (uint64_typeHIGH, uint64_typeLOW): Comment with HOST_64_BIT so + they get copied to bfd.h. + + * reloc.c (enum bfd_reloc_code_real): Add some Alpha relocation + types. Reorganized some of the existing ones. + * coff-alpha.c (alpha_howto_table): Construct 64-bit negative one + values in case of compilation on a 32-bit machine. Fix pcrel + fields of some reloc types. + (alpha_bfd_reloc_type_lookup): Handle more relocation types. + + * bfd-in.h (uint64_typeHIGH, uint64_typeLOW): Supply default + definitions when not defined, regardless of whether uint64_type is + a defined macro or not. + (fprintf_vma, sprintf_vma): Define only if fprintf_vma is not + already defined. + +Wed Jan 19 00:02:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (translate_to_native_sym_flags): Set the type of a + BSF_WARNING symbol to N_WARNING. + +Tue Jan 18 16:43:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (aout_link_add_symbols): Increment sym_hash as well as p + for an indirect or warning symbol. + (aout_link_write_symbols): Update sym_hash with the target of an + indirect or warning symbol. If an indirect symbol is defined, + output the calculated value and don't output the target symbol. + +Tue Jan 18 03:54:59 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * aoutx.h (translate_from_native_sym_flags): Give warning symbols + an (unused) nonzero section value, needed for check below. + +Mon Jan 17 15:12:07 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * aoutx.h (translate_from_native_sym_flags, + aout_link_add_symbols): Treat N_SET[ABDT] | N_EXT like + N_SET[ABDT]. + +Fri Jan 14 16:45:43 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (elf_object_p): If there is a SHT_DYNAMIC section, set + the DYNAMIC flag for the BFD. + (NAME(bfd_elf,write_object_contents)): Don't try to write out a + BFD with the DYNAMIC flag set, since we don't generate the program + header table correctly. + +Fri Jan 14 01:04:36 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * elfcode.h (elf_slurp_symbol_table): Free x_symp at the end + of the function to avoid storage leak. + +Thu Jan 13 23:07:32 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_link_write_external): An ifd can be -1. + +Thu Jan 13 12:33:27 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_set_reloc_info): Provide a default symbol for + relocations which don't actually have an associated symbol. + + * som.c (hppa_som_reloc): Add new "error message" argument. + +Wed Jan 12 13:36:43 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + Enable gdb to write to core files on more core file readers. + * libbfd.c (bfd_generic_set_section_contents): Remove range check + for section size, it is already done in bfd_set_section_contents + with bfd_get_section_size_now. + * aix386-core.c, hppabsd-core.c, hpux-core.c, irix-core.c, + osf-core.c, ptrace-core.c, trad-core.c (*_set_section_contents): + Use bfd_generic_set_section_contents instead of bfd_false. + +Wed Jan 12 15:31:57 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * linker.c: Added initial documentation. + + * linker.c (default_indirect_link_order): Don't expect space for + output relocations if there aren't any input relocations. + +Tue Jan 11 14:37:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * aoutx.h (NAME(aout,final_link)): Set a_entry before computing + file offsets. + + * elfcode.h (swap_out_syms): A common symbol is STT_OBJECT, not + STT_NOTYPE. + +Tue Jan 11 09:10:56 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config.bfd: Use ELF, not COFF for m88*-*-dgux*. + Combine m88k-*-* and m88110-*-* cases into m88*-*-*. + +Tue Jan 11 00:07:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecofflink.c: Extensive changes to compress and merge debugging + information, and to write some of out directly rather than saving + it in memory. Several new functions and structures, and new + arguments to existing functions. + * ecoff.c (ecoff_compute_reloc_file_positions): Compute + sym_filepos as well. + (ecoff_get_extr): Use ifdmap instead of ifdbase. + (ecoff_write_object_contents): Don't compute sym_filepos here. + Only output symbols if outsymbols is not NULL. + (ecoff_bfd_final_link): Adjust for changes in ecoff_debug_info and + bfd_ecoff_debug functions. Write out debugging information here. + (ecoff_final_link_debug_accumulate): Adjust for changes in + bfd_ecoff_debug functions. + (ecoff_link_write_external): Use ifdmap rather than ifdbase. + * elf32-mips.c (mips_elf_read_ecoff_info): Read external symbols + first, to put them in the first memory buffer. Clear fdr field. + (mips_elf_get_extr): Use pointer to unswapped external symbol. + (mips_elf_final_link): Adjust for changes in bfd_ecoff functions. + Preserve .text, .data and .bss even if they are empty. Save + pointer to unswapped external symbol rather than copying it. + Don't free up the external symbols. + * libelf.h (elf_symbol_type): Change mips_extr to PTR. + * bfd-in.h (bfd_ecoff_debug_init, bfd_ecoff_debug_free): Declare. + (bfd_ecoff_debug_accumulate): Update declaration. + (bfd_ecoff_debug_accumulate_other): Rename declaration from + bfd_ecoff_debug_link_other and update. + (bfd_ecoff_write_accumulated_debug): Declare. + * bfd-in2.h: Rebuilt. + * Makefile.in: Rebuilt dependencies. + +Mon Jan 10 20:46:53 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * Makefile.in (install): Remove "@" which follows a backslash. In + this position it just causes errors, not suppresses echoes. + +Mon Jan 10 09:06:21 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (hppa_som_gen_reloc_type): Fix handling of LT and RT + field selectors. + +Sun Jan 9 04:32:25 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * config/i386-netbsd.mt (SELECT_VECS): Include i386bsd_vec. + +Fri Jan 7 10:27:27 1994 David J. Mackenzie (djm@rtl.cygnus.com) + + * aoutx.h (adjust_z_magic): Don't merge the start of bss with the + end of data if they are not contiguous. + + * aoutf1.h (sunos4_aout_backend): Comment the fields' meanings. + +Fri Jan 7 15:40:16 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_mkobject_hook): Don't set SEC_SHARED_LIBRARY flag + for .reginfo section here. + (ecoff_new_section_hook): Set it here instead. + +Fri Jan 7 10:29:27 1994 Stan Shebs (shebs@andros.cygnus.com) + + * bfd-in.h: (bfd_boolean): Add workaround for systems that also + define true and false as enums. + (ALMOST_STDC): Add as alternative to __STDC__. + * bfd-in2.h: Rebuilt. + * syms.c (bfd_print_symbol_vandf): Convert a PTR to FILE*. + +Thu Jan 6 14:24:44 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * aoutx.h (translate_to_native_sym_flags): Catch the case where + there is no output section. + +Thu Jan 6 14:37:42 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmcode.h (nlm_object_p): If we can't read the fixed header, + count it as a wrong format error, not a system call error, since + the object file might simply be too small. + + * targets.c (target_vector): Added nlm32_alpha_vec inside #ifdef + BFD64. + * Makefile.in (BFD32_BACKENDS): Remove nlm32-alpha.o. + (BFD64_BACKENDS): Add nlm32-alpha.o. It depends on 64 bit + support, even though it is for an Alpha in 32 bit mode. + * configure.in (nlm32_alpha_vec): Set target64 to true. + + * nlm32-gen.c, nlm64-gen.c: Removed. All nlm targets are + different, so there is no point to providing a generic one. + * libnlm.h: Don't bother to check for nlm_backend(bfd) being NULL + in the backend accessor macros; that should no longer be possible. + * targets.c (target_vector): Removed nlm32_big_generic_vec, + nlm64_big_generic_vec, nlm64_little_generic_vec. + * configure.in (nlm32_big_generic_vec, nlm32_little_generic_vec, + nlm64_big_generic_vec, nlm64_little_generic_vec): Removed. + * Makefile.in: Rebuilt dependencies, and + (BFD32_BACKENDS): Removed nlm32-gen.o. + (BFD64_BACKENDS): Removed nlm64-gen.o. + (CFILES): Removed nlm32-gen.c and nlm64-gen.c. + + * hp300hpux.c (ARCH_SIZE): Define before including aoutx.h. + + * linker.c (_bfd_generic_link_add_one_symbol): Add constructor and + bitsize arguments. Changed all callers (aoutx.h). + * libbfd-in.h (_bfd_generic_link_add_one_symbol): Add constructor + and bitsize arguments to declaration. + * libbfd.h: Rebuilt. + + * ecoff.c: First cut at new style of linker backend for + ECOFF--added a bunch of functions. Also: + (ecoff_sec_to_styp_flags): Set flags for .pdata and .xdata. + (ecoff_slurp_symbolic_header): New function. + (ecoff_slurp_symbolic_info): Call ecoff_slurp_symbolic_header. + (ecoff_compute_reloc_file_positions): New function. + (ecoff_set_section_contents): Get out quickly if count is zero. + Check errors better. + (ecoff_write_object_contents): Put .xdata section in data segment. + Call ecoff_compute_reloc_file_positions. Don't output relocs or + external symbols if outsymbols is NULL. + (ecoff_bfd_final_link): Completely rewritten. + * libecoff.h: Include bfdlink.h. + (struct ecoff_backend_data): Add relocate_section field. + (ecoff_data_type): Add sym_hashes and symndx_to_section fields. + (struct ecoff_link_hash_entry): Define. + (struct ecoff_link_hash_table): Define. + (ecoff_bfd_link_add_symbols): Declare as function, not macro. + (ecoff_bfd_link_hash_table_create): Likewise. + * ecofflink.c (bfd_ecoff_debug_one_external): New function. + (bfd_ecoff_debug_externals): Call bfd_ecoff_debug_one_external. + * bfd-in.h (bfd_ecoff_debug_one_external): Declare. + * bfd-in2.h: Rebuilt. + * coff-alpha.c (alpha_howto_table): Mark BRADDR as + partial_inplace, and set the src_mask to 0x1fffff. + (alpha_ecoff_get_relocated_section_contents): Remove unused + variable gp_warned. + (alpha_convert_external_reloc): New static function. + (alpha_relocate_section): New static function. + (alpha_ecoff_backend_data): Initialize relocate_section field. + * coff-mips.c (mips_relocate_refhi): New static function. + (mips_relocate_section): New static function. + (mips_ecoff_backend_data): Initialize relocate_section field. + + * reloc.c (_bfd_relocate_contents): Corrected signed overflow + checking when there is an addend. + + * aoutx.h (NAME(aout,final_link)): Don't abort when trying to link + a non a.out file, just pass it to _bfd_default_link_order. + (aout_link_input_section_std): When doing a final PC relative link + against a section symbol, subtract the VMA of the input section. + (aout_link_input_section_ext): Likewise. + + * linker.c (default_indirect_link_order): Renamed from + _bfd_generic_indirect_link_order and made static. + (_bfd_generic_final_link): Don't switch on link_order type, just + call _bfd_default_link_order. + (_bfd_default_link_order): Handle bfd_indirect_link_order type. + * genlink.h: Removed declaration of + _bfd_generic_indirect_link_order. + * elf32-mips.c (mips_elf_final_link): Don't switch on link_order + type, just call _bfd_default_link_order. + +Tue Jan 4 21:23:37 1994 Ian Lance Taylor (ian@cygnus.com) + + * linker.c (generic_link_check_archive_element): Base the name of + the created common section on the name of the section the symbol + came from. + (_bfd_generic_link_add_one_symbol): (case BIG): A common symbol + must have a section, so don't bother to create one. + +Mon Jan 3 15:32:16 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * aout-target.h (MY(vec)): Add DYNAMIC to mask of object flags. + * aoutf1.h (NAME(aout,sunos4_write_object_contents)): + If the DYNAMIC flag is set, set it in the exec header. + * aoutx.h (NAME(aout,some_aout_object_p)): If the object is + dynamically linked, set the DYNAMIC flag in the BFD. + * libaout.h (N_SET_DYNAMIC): New macro. + (N_DYNAMIC): Add missing 0 in mask. + +Mon Jan 3 11:41:45 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_get_extr): Don't output section symbols as + external symbols. + + * bfd-in.h, hash.c: Change bfd_hash_allocate argument from size_t + to unsigned int, because size_t may not be defined in bfd.h. + * bfd-in2.h: Rebuilt. + + * bfd-in.h (bfd_get{b,l}[_signed_]{16,32,64}): Declare argument to + be a const pointer. + * bfd-in2.h: Rebuilt. + * libbfd.c (bfd_get{b,l}[_signed_]{16,32,64}): Declare argument to + be a const pointer. + * targets.c (bfd_target): Change swap function pointers + accordingly. + * archive.c (do_slurp_coff_armap): Change swap accordingly. + * aix386-core.c: Change NO_GET and NO_GETS accordingly. + * hppabsd-core.c, hpux-core.c, irix-core.c, osf-core.c, + ptrace-core.c, trad-core.c: Change NO_GET and NO_SIGNED_GET + accordingly. + + * libbfd-in.h (struct artdata): Added tdata field. + (_bfd_add_bfd_to_archive_cache): Declare. + (_bfd_get_elt_at_filepos): Declare. + (_bfd_snarf_ar_hdr): Renamed from snarf_ar_hdr. + * libbfd.h: Rebuilt. + * archive.c: Cleaned up some more. + (_bfd_generic_mkarchive, bfd_generic_archive_p): Initialize + pointer elements of artdata. + (_bfd_add_bfd_to_archive_cache): Renamed from add_bfd_to_cache. + (_bfd_snarf_ar_hdr): Renamed from snarf_ar_hdr. + (_bfd_get_elt_at_filepos): Renamed from get_elt_at_filepos. + (get_extended_arelt_filename, bfd_construct_extended_name_table, + bfd_ar_hdr_from_filesystem, compute_and_write_armap): Made static. + * ecoff.c: Some comment changes. + (ecoff_slurp_armap): Handle rename of snarf_ar_hdr. Set + ardata->tdata to raw_armap. + (ecoff_archive_p): Initialize pointer elements of artdata. + * coff-rs6000.c (rs6000coff_get_elt_at_filepos): Handle rename of + add_bfd_to_cache. + + * hash.c: Added some documentation. + +Mon Jan 3 11:09:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * aout-target.h, netbsd386.c: Replace NO_SWAP_MAGIC with SWAP_MAGIC, + and do the swapping here rather than calling ntohl from the N_* + macros. This cleans up assumptions about the size of a host long, + the existence to ntohl, etc. + +Sat Jan 1 13:50:05 1994 Rob Savoye (rob@darkstar.cygnus.com) + + * config.bfd: Add support for VSTa micro-kernel. It currently uses + i386-aout. + +Sat Jan 1 10:18:54 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * hosts/i386mach3.h (HOST_SEGMENT_SIZE): Fix value. + * i386mach3.c (SEGMENT_SIZE): Fix value. + +Fri Dec 31 16:23:43 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Minor cleanups suggested by CodeCenter. + * aoutx.h, coffgen.c, ecoff.c, ecofflink.c, elf.c, libbfd.c, + linker.c, reloc.c, section.c, srec.c: Added /*ARGSUSED*/ as + appropriate. + * aoutx.h (struct external_exec): Removed unnecessary declaration. + (NAME(aout,some_aout_object_p)): Set some tdata pointers to NULL. + (adjust_z_magic): Removed useless variable data_vma. + (stringtab_init): Initialize hash_zero. + (add_to_stringtab): Removed unused fourth argument. + (NAME(aout,swap_std_reloc_out)): Removed useless variable + r_addend. + (aout_link_input_section): Added some casts. + * archive.c (get_extended_arelt_filename, do_slurp_coff_armap, + bfd_ar_hdr_from_filesystem, bsd_write_armap, coff_write_armap): + Minor code rewriting to make it more C like. + (do_slurp_bsd_armap): Added some casts. + * ecoff.c (ecoff_write_object_contents): Removed useless variable + scn_base. + (ecoff_write_armap): Added some casts. Use "" rather than "\0". + * ecofflink.c (bfd_ecoff_write_debug): Added a cast. + * libaout.h (struct internal_exec): Removed unnecessary + declaration. + * linker.c (_bfd_generic_indirect_link_order): Added a cast. + * opncls.c (new_bfd): Removed a cast. + * reloc.c (bfd_generic_get_relocated_section_contents): Added + some casts. + * srec.c (internal_srec_write_object_contents): Removed useless + variable bytes_written. + +Fri Dec 31 11:46:13 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * i386mach3.c (N_TXTADDR): Don't define after all. + (TEXT_START_ADDR): Don't include exec header size in value. + +Thu Dec 30 15:47:54 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * i386mach3.c (N_TXTADDR): Define. + +Thu Dec 30 13:37:24 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Extensive changes to move the bulk of the linker into BFD so that + more efficient backend code can be written for specific object + files. Only existing efficient backend is a.out. + * seclet.c, seclet.h: Removed. + * hash.c, linker.c, genlink.h: New files. + * bfd-in.h: Removed bfd_error_vector. Declared hash table + structures and functions. + (JUMP_TABLE): Removed bfd_seclet_link, added + bfd_link_hash_table_create, bfd_link_add_symbols and + bfd_final_link. + * All backends: Changed accordingly. + * bfd-in2.h: Rebuilt. + * bfd.c (struct _bfd): Added link_next and archive_pass fields. + Removed ld_symbols field. + (bfd_nonrepresentable_section, bfd_undefined_symbol, + bfd_reloc_value_truncated, bfd_reloc_is_dangerous, + bfd_error_vector): Removed. + (bfd_default_error_trap, bfd_error_trap, + bfd_error_nonrepresentabltrap): Removed. + (bfd_get_relocated_section_contents): Pass link_info. Pass + link_order instead of seclet. Pass symbols. + (bfd_relax_section): Pass link_info. + (bfd_seclet_link): Removed. + (bfd_link_hash_table_create, bfd_link_add_symbols, + bfd_final_link): New macros. + * libbfd-in.h: If __GNUC__ is defined and alloca is not, define + alloca as __builtin_alloca. Declare internal linking functions. + * libbfd.h: Rebuilt. + * libbfd.c (bfd_seek): Comment out fseek assertion. It's worked + for months. + * reloc.c (reloc_howto_type): Added error_message argument to + special_function field. Changed all callers and all definitions. + (bfd_get_reloc_size): Make argument a const pointer. + (bfd_perform_relocation): Add error_message argument to hold + string set if return value if bfd_reloc_dangerous. Changed all + callers. + (_bfd_final_link_relocate, _bfd_relocate_contents): New functions. + * section.c (asection): Renamed seclets_head and seclets_tail to + link_order_head and link_order_tail. + * targets.c (bfd_target): Replaced seclet argument with link_info + and link_order and symbols arguments in + bfd_get_relocated_section_contents. Added symbols argument to + bfd_relax_section. Removed bfd_seclet_link. Added + bfd_link_hash_table_create, bfd_link_add_symbols and + bfd_final_link. + * libaout.h (struct aoutdata): Added external_syms, + external_sym_count, external_strings, sym_hashes fields. + (obj_aout_external_syms, obj_aout_external_sym_count, + obj_aout_external_strings, obj_aout_sym_hashes): New accessor + macros. + (WRITE_HEADERS): Only output symbols if outsymbols is not NULL. + * aoutx.h: Wrote new back end linker routines. + (translate_to_native_sym_flags): Return boolean value. Don't use + bfd_error_vector. + (NAME(aout,write_syms)): Return boolean value. Check return value + of translate_to_native_sym_flags and bfd_write. + * aout-target.h (final_link_callback): New function. + (MY_bfd_final_link): New function. + * aout-adobe.c (aout_adobe_write_object_contents): Check return + value of aout_32_write_syms. + * hp300hpux.c (MY(write_object_contents)): Likewise. + * i386lynx.c (WRITE_HEADERS): Likewise. + * libaout.h (WRITE_HEADERS): Likewise. + * bout.c: Changed functions to use link_info->callbacks rather + than bfd_error_vector, and link_orders rather than seclets. + * coff-alpha.c: Likewise. + * coff-h8300.c: Likewise. + * coff-h8500.c: Likewise. + * coff-sh.c: Likewise. + * coff-z8k.c: Likewise. + * elf32-hppa.c: Likewise. + * reloc16.c: Likewise. + * coff-alpha.c (alpha_ecoff_get_relocated_section_contents): Look + up _gp in the hash table rather than in outsymbols. + * coff-a29k.c (a29k_reloc): Pass errors back in new error_message + argument rather than printing them. + * coffcode.h (bfd_coff_reloc16_extra_cases): Take link_info and + link_order arguments rather than seclet. Changed all uses and + definitions. + (bfd_coff_reloc16_estimate): Pass link_info arguments. Changed + all uses and definitions. + * libcoff.h: Rebuilt. + * ecoff.c (ecoff_get_extr): If symbol is defined by linker, but + not by ECOFF, make it scAbs. + (ecoff_bfd_final_link): Renamed from ecoff_bfd_seclet_link and + rewritten. + * elf32-mips.c (mips_elf_final_link): Renamed from + mips_elf_seclet_link and rewritten. + * elf32-hppa.c (elf32_hppa_stub_description): Added link_info + field. + (new_stub, add_stub_by_name, hppa_elf_build_arg_reloc_stub, + hppa_elf_build_long_branch_stub, hppa_look_for_stubs_in_section): + Added link_info arguments. Changed all callers. + * elfcode.h (elf_slurp_symbol_table): Don't quit if outsymbols is + not NULL. + * oasys.c (oasys_write_sections): Return boolean value rather than + using bfd_error_vector. + (oasys_write_object_contents): Check return value of + oasys_write_sections. + * hosts/std-host.h: Don't declare qsort or strtol. + * Makefile.in: Rebuild dependencies. + (BFD_LIBS): Removed seclet.o. Added hash.o and linker.o. + (CFILES): Removed seclet.c. Added hash.c and linker.c. + (HFILES): Removed seclet.h. Added genlink.h. + +Thu Dec 30 07:41:36 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * section.c (bfd_get_section_contents): Return zero filled buffer + if section has no contents. + +Tue Dec 28 12:43:54 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elf.c (bfd_elf_generic_reloc): If this is not an inplace reloc, + then skip bfd_perform_relocation even if the addend is non-zero. + +Tue Dec 21 09:22:19 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * coffcode.h (coff_write_relocs) [SWAP_OUT_RELOC_OFFSET]: Copy + addend to r_offset field. + + * Makefile.in (CFILES): Added coff-sparc.c. Rebuild dependencies. + + * coff-sparc.c (SWAP_IN_RELOC_OFFSET, SWAP_OUT_RELOC_OFFSET, + CALC_ADDEND): Define. + + * aix386-core.c (aix386_core_file_p): Use cd_regs[0] for computing + the offsetof because AIX /bin/cc does not like to take the address + of an array. (From Minh Tran-Le.) + +Thu Dec 16 13:06:32 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Thu Dec 16 15:41:06 1993 Peter Hoogenboom (hoogen@cs.utah.edu) + + * elf32-hppa.c (hppa_elf_build_arg_reloc_stub): Make sure to copy + the return pointer into %r2 if no jump-in-call-delay-slot + optimization was done. + + * hosts/hp300bsd.h: Correctly identify 4.3BSD vs 4.4BSD. + +Wed Dec 15 08:04:16 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * hosts/std-host.h: (time): Don't declare; conflicts on Mach3. + + * hosts/i386mach3.h (HOST_PAGE_SIZE): Set to 1 to avoid padding. + (HOST_SEGMENT_SIZE): Set to 0 for same reason. + + * i386mach3.c (PAGE_SIZE, SEGMENT_SIZE): Same changes as above. + (TEXT_START_ADDR): Correct. + (MY_backend_data): Define. + + * aoutx.h (adjust_o_magic, adjust_z_magic, adjust_n_magic): + New functions; code moved from aout__adjust_sizes_and_vmas. + +Tue Dec 14 21:48:33 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_begin_writing): Fix thinkos in auxiliary header + support. + (bfd_som_attach_aux_hdr): Likewise. + +Mon Dec 13 23:34:48 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (hppa_elf_gen_reloc_type): Handle 'T' field + selectors for PIC code. + + * som.c (hppa_som_gen_reloc_type): Handle 'T' field selectors. + (som_write_fixups): Handle R_DLT_REL, R_FSEL, R_RSEL, R_LSEL + relocations needed by PIC. + +Tue Dec 7 15:47:51 1993 Stu Grossman (grossman at cygnus.com) + + * nlmcode.h: Fixes to avoid compiler warnings... + +Tue Dec 7 15:10:54 1993 Ian Lance Taylor (ian@cygnus.com) + + * libnlm.h (nlm_backend_data): Removed macro definition. + (nlm_alpha_backend_data): Adjusted accordingly. + +Sun Dec 5 19:32:08 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_begin_writing): Flesh out code for handling simple + auxiliary headers. + (bfd_som_attach_aux_hdr): New function. + + * som.h (struct somdata): Add fields for attaching version and + copyright headers. Add accessor macros. + + * som.c (R_DLT_REL, R_AUX_UNWIND, R_SEC_STMT): Add protected + definitions for old versions of HPUX which fail to define them. + (som_hppa_howto_talbe): Add R_DLT_REL, R_AUX_UNWIND, and R_SEC_STMT + now that they're safe. Delete bogus R_STATEMENT relocations. + + * som.c (som_hppa_howto_table): Add missing R_END_TRY. Delete + extra R_DATA_OVERRIDE. + (hppa_som_gen_reloc_type): Generate a relocation for the rounding + mode selector if needed. + (som_write_fixups): Handle requests for a change in the default + rounding mode. Rounding modes do not consume input bytes, but + are just markers much like R_ENTRY and R_EXIT. + +Sat Dec 4 19:40:32 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + Fri Dec 3 09:55:17 1993 Pete Hoogenboom (hoogen@cs.utah.edu) + + * elf32-hppa.c: (hppa_elf_reloc): Do not do code reordering when + the branch instruction as originally been nullified. + hppa_elf_reloc): Avoid useless call to bfd_put_32 () in the + case of no code reordering due to an LDO instruction in the + delay slot of the branch. Make sure to relocate the correct + instruction. Do not perform instruction reordering for millicode + calls. + (hppa_elf_build_arg_reloc_stub): Change the relocation type + to R_HPPA_STUB_CALL_17 when special processing might be needed. + (hppa_elf_build_long_branch_stub): Prevent code reordering on + a call from a linker stub to another linker stub and for millicode + calls. Do not trash the return register for calls from one linker + stub to a second linker stub. + + * elf32-hppa.c: (elf_hppa_howto_table): PLABEL and DLT + relocations are not pc-relative. + + * hppa_stubs.h: (BLE_N_XXX_0_31): New instruction used in + linker stub code. + (COPY_2_31): Likewise. + +Fri Dec 3 18:40:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/solaris2.mh (HDEFINES): Remove -Dconst= + * hosts/solaris.h: If not __GNUC__, define const as empty. + +Thu Dec 2 15:43:32 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c: Added various casts for 32/64 bit cross targeting. + (ecoff_mkobject_hook): Set SEC_SHARED_LIBRARY for the .reginfo + section so that the linker ignores it. + * ecofflink.c: Added various casts for 32/64 bit cross targeting. + (ecoff_add_bytes): Changed need argument to size_t. + (bfd_ecoff_debug_link_other): Check return value of + ecoff_add_string. + + * libbfd-in.h (new_bfd): Use void rather than an empty parameter + list. + * libbfd.h: Rebuilt. + + * libnlm.h (struct nlm_obj_tdata): New field backend_data. + (nlm_backend_data, nlm_alpha_backend_data): New accessor macros. + (struct nlm_backend_data): New field no_uninitialized_data. + (nlm_no_uninitialized_data): New accessor macro. + * nlmcode.h (nlm_compute_section_file_positions): Handle + no_uninitialized_data. + (nlm_external_reloc_compare): Sort relocs by address for a + particular symbol, to make the sort more stable. + (nlm_write_object_contents): Cast the arguments to qsort. Get the + value of a debugging symbol the same way we get the value of a + normal symbol. + * nlm32-alpha.c: Various changes. Write out GP and .lita relocs. + Set no_uninitialized_data to true. + * nlm32-i386.c (nlm32_i386_backend), nlm32-sparc.c + (nlm32_sparc_backend): Set no_uninitialized_data field false. + * nlmswap.h (nlm_swap_fixed_header_out): Zero out destination + before filling it in. + +Wed Dec 1 21:47:58 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_section_type, som_decode_symcalss): New functions. + (som_get_symbol_info): Use them. + (som_slurp_symbol_table): Set the section of common and undefined + symbols correctly. + +Wed Dec 1 14:15:10 1993 Ken Raeburn (raeburn@cygnus.com) + + * elfcode.h (write_relocs): Initialize local var LAST_SYM_IDX, to + make gcc happy. + + * mipsbsd.c: Changes from Ralph Campbell: + (mips_howto_table_ext): MIPS_RELOC_LO16 should use + complain_overflow_dont. + (aout_mips_*_vec): Make name use "a.out" instead of "aout", to + make gdb happy. + + * bfd.c (bfd_errmsgs): Reword invalid-target message. + + * config.bfd: For sparc*-*-coff, use sparc-coff. + * configure.in: Handle sparccoff_vec. + * targets.c (sparccoff_vec): Declare. + + * reloc.c (bfd_get_reloc_size): New function. + (struct reloc_howto_type): Update documentation of size field. + +Wed Dec 1 14:39:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlm32-alpha.c: New file; preliminary Alpha NetWare support. + * config.bfd (alpha-*-netware*): New target; use alpha-nlm. + * config/alpha-nlm.mt: New file. + * configure.in (nlm32_alpha_vec): New vector; use nlm32-alpha.o, + nlm32.o, and nlm.o. + * Makefile.in (BFD32_BACKENDS): Added nlm32-alpha.o. + (CFILES): Added nlm32-alpha.c. + Rebuilt dependencies. + * targets.c (nlm32_alpha_vec): Declare. + + * libnlm.h (struct nlm_backend_data): New fields + optional_prefix_size, nlm_backend_object_p, nlm_write_prefix, + nlm_set_public_section, nlm_get_public_offset. Removed unused + nlm_write_reloc field. Changed nlm_write_import to remove + unnecessary symbol argument. Renamed nlm_write_externals to + nlm_write_external, and changed cound argument from bfd_vma to + bfd_size_type. + (nlm_optional_prefix_size, nlm_backend_object_p_func, + nlm_write_prefix_func, nlm_set_public_section_func, + nlm_get_public_offset_func): New accessor macros. + (nlm_write_reloc_func): Removed. + (nlm_write_external_func): Adjusted for field renaming. + * nlm32-i386.c (nlm_i386_write_import): Renamed from + nlm_i386_write_reloc. Removed old nlm_i386_write_import which + just called old nlm_i386_write_reloc. + (nlm_i386_write_external): Renamed from nlm_i386_write_externals. + Declared. Changed second argument from bfd_vma to bfd_size_type. + (nlm32_i386_backend): Adjusted for changes to fields and names. + * nlm32-sparc.c (nlm_sparc_mangle_relocs): Removed unused, + ifdeffed out code. + (nlm_sparc_write_import): Removed second argument. + (nlm_sparc_write_external): Renamed from + nlm_sparc_write_externals. Changed second argument from bfd_vma + to bfd_size_type. + (nlm32_sparc_backend): Adjusted for changes to fields and names. + * nlmcode.h: Removed some unused code. + (nlm_object_p): Don't destroy tdata pointer. Call + backend_object_p function if it exists. + (nlm_slurp_symbol_table): Removed unused variable rcount. Call + set_public_section_func if it exists instead of checking + NLM_HIBIT. + (nlm_compute_section_file_positions): Account for + optional_prefix_size. + (nlm_write_object_contents): Account for optional_prefix_size. + Removed useless variable write_reloc_func. Changed declaration + and call of write_import_func. Call write_prefix_func if it + exists. Removed unused variables len and temp. Call + get_public_offset_func if it exists rather than setting NLM_HIBIT. + * nlmswap.h: Declare functions. + + * bfd-in.h (uint64_typeLOW, uint64_typeHIGH): Fully parenthesize + for clarity. + (fprintf_vma, sprintf_vma): Use %lx, not %x. + * bfd-in2.h: Rebuilt. + * hosts/alphaosf.h (uint64_typeLOW, uint64_typeHIGH): Cast results + to unsigned long. + + * config.bfd: Don't set target64 here, as the setting is ignored. + * configure.in (ecoffalpha_little_vec): Set target64. + + * config/alphaosf.mt (TDEFINES): Removed; setting host parameters + in TDEFINES is wrong. + + * coff-alpha.c (alpha_ecoff_get_relocated_section_contents): + Remove unused variable output_section. + +Tue Nov 30 16:45:23 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * irix-core.c: New file for Irix 4 and Irix 5 core support. + Functions taken out of coff-mips.c. Handle vmap type VMAPFILE. + * coff-mips.c: Irix 4 core file support moved to irix-core.c. + * targets.c: If IRIX_CORE defined, include irix_core_vec in + target_vector. + * config/irix4.mh (HDEFINES): Add -DIRIX_CORE. + (HDEPFILES): Define to be irix-core.o. + * config/irix5.mh (HDEFINES): Define to be -DIRIX_CORE. + (HDEPFILES): Define to be irix-core.o. + * Makefile.in (OPTIONAL_BACKENDS): Added irix-core.o. Removed + sco-core.o, which no longer exists. + (CFILES): Added all *-core.c files. + Rebuilt dependencies. + +Wed Nov 24 02:02:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (map_program_segments): Restore check of file_size != + mem_size, but only if SHT_PROGBITS. + + * ecofflink.c: New file to hold ECOFF debug information linking + routines. + * ecoff.c (ecoff_clear_output_flags, ecoff_rel, ecoff_dump_seclet, + ecoff_add_string, ecoff_get_debug): Removed. Functionality now in + ecofflink.c. + (ecoff_get_extr, ecoff_set_index): New functions. + (ecoff_slurp_symbolic_info): Don't save raw_size. + (ecoff_bfd_seclet_link): Rewrote to use ecofflink.c functions. + (ecoff_compute_section_file_positions): Don't set EXEC_P just + because there is a start address. + (ecoff_write_object_contents): Handle external symbols here. Use + ecofflink.c functions to write out debugging information. + * elf32-mips.c (mips_elf_read_ecoff_info, mips_elf_get_extr, + mips_elf_set_index): New functions. + (mips_elf_seclet_link): Discard empty sections, the .options + section and .gptab sections. Handle linking .mdebug section. + * libecoff.h (ecoff_data_type): Removed raw_size and ifdbase. + * libelf.h (elf_symbol_type): Added mips_extr to tc_data union. + * bfd-in.h: Added prototypes for routines in ecofflink.c (some are + called by gas, so they are public). + * bfd-in2.h: Rebuilt. + * Makefile.in (BFD_LIBS): Added ecofflink.o. + (CFILES): Added ecofflink.c. + (ecofflink.o): New target. Rebuilt dependencies. + +Mon Nov 22 22:26:42 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (hppa_object_p): Also recognize SHARED_MAGIC_CNX as + a valid magic number if it's been defined. + +Mon Nov 22 14:17:36 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_mkobject): Don't create .scommon section; linker + no longer requires it. + (ecoff_bfd_seclet_link, ecoff_sizeof_headers, + ecoff_write_object_contents): Don't treat .scommon section + specially. + +Mon Nov 22 10:54:27 1993 Fred Fish (fnf@cygnus.com) + + Merged changes from kev@spuds.geg.mot.com (Kevin A. Buettner): + * bfd/config/delta88.mh (HDEFINES): Define this to be -DPTRACE_CORE. + * bfd/config/delta88.mh (HDEPFILES): Defined to be ptrace-core.o. + * bfd/ptrace-core.c: New file for dealing with core files with + start with the ptrace_user structure found on BCS compliant systems. + * bfd/targets.c (ptrace_core_vec): New vector. + +Mon Nov 22 02:33:12 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Minimal support for reading SOM fixup streams. Allows + objdump -r to do something reasonable. + * som.c (som_get_reloc_upper_bound): Implement. + (som_canonicalize_reloc): Implement. + (som_set_reloc_info, som_slurp_reloc_table): New functions. + +Sun Nov 21 13:46:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * hosts/lynx.h (FPRINTF_ALREADY_DECLARED): Define. + * hosts/sparclynx.h: Include lynx.h instead of duplicating it. + +Fri Nov 19 14:34:04 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coff-a29k.c (a29k_reloc): For R_IREL, don't left shift + signed_value before sign extending it. Don't subtract out + reloc_entry->address. This makes it compatible with what gas is + generating. + + * elfcode.h (elf_fake_sections): Accept .sbss as the name for a + SHT_NOBITS sections. + (map_program_segments): Don't leave the loop after the first + SHT_NOBITS section. + (assign_file_positions_except_relocs): Only force sh_offset and + sh_addr to match modulo maxpagesize for a section which is not + SHT_NOBITS. Changed the method used to force page alignment after + a SHT_NOBITS section to only do it for the last such consecutive + section, and to really force page alignment. + +Fri Nov 19 04:02:01 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * coffcode.h (coff_slurp_symbol_table): Print more verbose message + in the case of an unknown (or unhandled) storage class. + + * config/i386-lynx.mt (TDEFINES): FPRINTF_ALREADY_DECLARED should + not be defined here, since it is a host attribute, not a target + one. + * config/m68k-lynx.mt, config/sparc-lynx.mt: Ditto. + + * coffcode.h (coff_bfd_reloc_type_lookup): Don't define if already + defined. + + * coff-sparc.c: Define some relocations, based on ELF relocations. + (enum reloc_type, bfd_coff_generic_reloc, coff_sparc_howto_table, + struct coff_reloc_map, sparc_reloc_map, + coff_sparc_reloc_type_lookup): Borrowed from elf32-sparc.c and + elf.c, renamed. + (coff_bfd_reloc_type_lookup): Define to be coff_sparc_reloc_.... + (rtype2howto): Index into coff_sparc_howto_table using + dst->r_type. + +Thu Nov 18 11:45:39 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config.bfd (mips*-*-irix5*): New target; use mipsbelf. + * configure.host (mips-sgi-irix5*) New host; use irix5 (no + hosts/irix5.h created; just use std-host.h). + * config/irix5.mh: New file; like irix4.mh, but don't use -G or + -lmalloc. + * Makefile.in: Rebuilt dependencies. + + * ecoffswap.h: Changed type of internal pointers for swap out + functions to const *. + + * elf32-mips.c (mips_elf_got16_reloc): New function. Handle GOT16 + correctly for assembler, but linker support not implemented. + (elf_mips_howto_table): Use mips_elf_got16_reloc for GOT16. + (mips_elf_sym_is_global): New function; at least on Irix 5, all + non section symbols are considered global. + (elf_backend_sym_is_global): Define. + (mips_elf_final_write_processing): New function. Set the MIPS + architecture level correctly. + (elf_backend_final_write_processing): Define. + (mips_elf_section_from_shdr): Handle SHT_MIPS_OPTIONS. + (mips_elf_fake_sections): Set entsize of .mdebug or .reginfo + section to 1. Handle .options section. + (mips_elf_acom_section, mips_elf_acom_symbol, + mips_elf_acom_symbol_ptr): New static variables, used to build a + generic .acommon section to hold SHN_MIPS_ACOMMON symbols. + (mips_elf_symbol_processing): Handle SHN_MIPS_ACOMMON symbols by + putting them all in a global .acommon section. + + * elfcode.h (bfd_section_from_shdr): Don't dump core if target + section has no ELF section data. + (elf_make_sections): Set addralign of reloc section to 4. + (elf_fake_sections): Likewise. + (map_program_segments): Don't consider section 0. + (assign_file_positions_except_relocs): Don't consider section 0. + In the main loop, skip the symtab and strtab sections, since their + positions are set elsewhere. + (swap_out_syms): Set addralign of symtab section to 4. Set + addralign of strtab sections to 1. + (assign_file_positions_for_relocs): Don't consider section 0. + (write_object_contents): Don't write out section 0. + + * libelf.h (struct elf_backend_data): Added fields + elf_backend_sym_is_global and elf_backend_final_write_processing. + * elf32-target.h (elf32_bed): Added corresponding initializers. + * elf64-target.h (elf64_bed): Likewise. + * elfcode.h (sym_is_global): Take abfd argument. Call + elf_backend_sym_is_global if it is not NULL. + (elf_map_symbols): Pass abfd to sym_is_global. + (write_object_contents): Call elf_backend_final_write_processing + if it is defined. + +Wed Nov 17 18:43:28 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * libecoff.h: Include coff/ecoff.h. + (struct ecoff_backend_data): Move external debugging information + fields into a single field pointing to an ecoff_debug_swap + structure. + (ecoff_data_type): Move debugging information fields into a single + field pointing to an ecoff_debug_info structure. + * coff-alpha.c, coff-mips.c, ecoff.c: Corresponding changes. + +Wed Nov 17 17:38:58 1993 Sean Eric Fagan (sef@cygnus.com) + + * nlmswap.h: New file to swap fixed header. Included by NLM + backends. + * libnlm.h (struct reloc_and_sec): Define. + (struct nlm_backend_data): Add fields fixed_header_size, + nlm_read_import, nlm_write_import, nlm_swap_fhdr_in, + nlm_swap_fhdr_out. + (nlm_fixed_header_size, nlm_read_import_func, + nlm_write_import_func, nlm_swap_fixed_header_in_func, + nlm_swap_fixed_header_out_func, nlm_write_external_func): New + accessor macros. + * nlmcode.h: Use new functions. + * nlm32-i386.c: Provide new functions. + * nlm32-sparc.c: New file; SPARC NLM backend. + +Wed Nov 17 13:56:10 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * i386lynx.c (swap_std_reloc_in, swap_ext_reloc_in): Ignore + garbage bits appearing in the upper end of symbolnums. + + * config/sparc-lynx.mt (TDEFINES): Add -DFPRINTF_ALREADY_DECLARED. + +Tue Nov 16 17:03:41 1993 Stu Grossman (grossman at cygnus.com) + + * lynx-core.c (lynx_core_file_p): Change bfd_zalloc to bfd_alloc. + * m68klynx.c: Define core file macros. + * hosts/i386lynx.h, hosts/m68klynx.h, hosts/lynx.h: Move all + non-architecture specific stuff into lynx.h. + +Tue Nov 16 15:45:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * i386linux.c: Define new macro ZMAGIC_DISK_BLOCK_SIZE to 1024, and + change PAGE_SIZE to 4096. + +Mon Nov 15 11:48:08 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * Makefile.in (diststuff): New target. + + * VERSION: Updated. + +Sun Nov 14 23:33:01 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_object_setup): Do not create dummy ".text", ".data", + and ".bss" sections. + (setup_sections): Do not set SEC_HAS_CONTENTS if a section's size + is zero. Recognize BSS type sections and turn off SEC_LOAD and + SEC_DATA (so binutils/size works). Set the correct value for + a section's _raw_size. + (som_slurp_symbol_table): Program entry points, and millicode are + also functions. Mark them as such. Also mark L$* symbols as + debugging symbols. + + * bfd-in2.h: Rebuilt. + +Sat Nov 13 15:27:15 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_bfd_reloc_type_lookup): Add missing prototype. Returns + a pointer to constant data. Delete bogus #define which made the + function useless. + + * som.c (som_prep_for_fixups): New function. + (som_write_fixups): New function. + (som_write_space_strings): New function. + (som_write_symbol_strings): New function. + (som_begin_writing): New function. + +Fri Nov 12 15:29:36 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_write_object_contents): Do not abort. Flesh out. + (som_set_section_contents): Do not abort. Flesh out. + + * som.c (som_write_headers): New function. + (som_prep_headers): New function. + (som_build_and_write_symbol_table): New function. + + * som.c (som_sizeof_headers): Add missing prototype. + (som_set_arch_mach): Do not abort. + + * som.c (som_count_spaces): New function. + (som_count_subspaces): New function. + (compare_syms): New function. + (som_compute_checksum): New function. + + * som.c (hppa_som_gen_reloc_type): New function. + (som_bfd_reloc_type_lookup): New function. + + * som.c (try_prev_fixup): New function. + (som_reloc_skip): New function. + (som_reloc_addend): New function. + (som_reloc_call): New function. + + * som.c (som_initialize_reloc_queue): New function. + (som_reloc_queue_insert): Likewise. + (som_reloc_queue_fix): Likewise. + (som_reloc_queue_find): Likewise. + + * som.c (som_hppa_howto_table): SOM howto relocation table. + (hppa_som_reloc): New function. + + * som.c (struct reloc_queue): New structure to keep track of + the last four multibyte relocations emitted. + (enum pa_symbol_type): Type to fully describe the symbol types + associated with .import/.export assembler directives. + + * som.c: Include libhppa.h + + * som.c (bfd_som_set_section_attributes): New function. + (bfd_som_set_subsection_attributes): Likewise. + (bfd_som_set_symboL_type): Likewise. + (bfd_som_attach_unwind_info): Likewise. + * som.h: Declare new exported functions. + + * som.h (struct som_symbol): Add new fields to hold additional + information needed to build/write symbol tables and fixup streams. + (struct som_section_data_struct): Add new fields to hold additional + information needed to build/write space and subspace headers. + (som_symbol_data): New accessor macro for SOM symbol information. + (R_HPPA_*): Basic relocation types to be used by the assembler. + +Fri Nov 12 11:00:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * trad-core.c (trad_unix_core_file_p): If new hook + TRAD_CORE_ALLOW_ANY_EXTRA_SIZE defined, then skip the check for the + corefile being too big. + * hosts/i386sco.h: Define it. + +Thu Nov 11 15:16:28 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * bfd.c (struct _bfd): Add hppabsd_core_data. + * targets.c (target_vector): Add hppabsd_core_vec. + * hpux-core.c (hpux_core_core_file_p): Fail if an unknown core + section is encountered during core section scanning. + * hppabsd-core.c: New file. + * config/hppabsd.mh: Enable HPPA BSD core files. + + * elf32-hppa.c (hppa_elf_reloc): Remove DEFUN crud. Remove code + which is either commented out or ifdef'd out. Add, update and + clean comments. Fix various indention and spacing problems. Handle + problems related to using "ble" to jump to a stub rather than "bl" + (%r31 is trashed by "ble", but not by "bl"). + (NEW_INSTRUCTION): Put inside curly braces. + (CURRENT_STUB_OFFSET): Fix indention problems. + (hppa_elf_build_arg_reloc_stub): Fix indention and spacing problems. + Add, update and clean comments. Handle "ble" %r31 lossage problems. + (hppa_elf_build_long_branch_stub): Likewise. + (hppa_look_for_stubs_in_section): Likewise. + (hppa_elf_stub_check): Remove obsolete function. + + * hppa_stubs.h: Add new instructions to deal with %r31 lossage + problems. Delete unused instructions. + +Tue Nov 9 11:40:27 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * m68klynx.c (TARGET_IS_BIG_ENDIAN_P): Define. + +Tue Nov 9 11:26:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (elf_object_p): Rather than looking through an array + of architectures, get the ELF EM_xxx code from the backend + information. Let the generic ELF target match any EM_xxx code not + matched by another ELF target. Call elf_backend_object_p to let + the backend do more checks and set global information. + * libelf.h (struct elf_backend_data): Added elf_machine_code and + elf_backend_object_p fields. + (struct bfd_elf_arch_map): Removed. + (bfd_elf_arch_map, bfd_elf_arch_map_size): Don't declare. + * elf32-target.h, elf64-target.h: Initialize elf_machine_code + field with ELF_MACHINE_CODE. Initialize elf_backend_object_p + field with elf_backend_object_p (if it is defined). + * elf32-gen.c, elf32-hppa.c, elf32-i386.c, elf32-i860.c, + elf32-m68k.c, elf32-m88k.c, elf32-mips.c, elf32-sparc.c, + elf64-gen.c (ELF_MACHINE_CODE): Defined. + * elf32-mips.c: Include ecoffswap.h to get ECOFF swapping + routines. + (mips_elf_object_p): Set the right machine number. + (mips_elf_ecoff_debug_swap): Defined. + (elf_backend_object_p): Defined to be mips_elf_object_p. + (elf_backend_ecoff_debug_swap): Defined to be + mips_elf_ecoff_debug_swap. + * elf.c (bfd_elf_arch_map, bfd_elf_arch_map_size): Removed. + + * libbfd-in.h (target_vector, default_vector): Declare. + * libbfd.h: Rebuilt. + * format.c (target_vector, default_vector): Don't declare. + + * elf32-mips.c (elf_mips_howto_table): Don't complain on overflow + for R_MIPS_26. Correct overflow detection requires matching the + upper four bits of the destination against the PC. From Ted Lemon + . + + * bout.c (b_out_reloc_type_lookup): Return type should point to + const data. + * coff-i960.c (coff_i960_reloc_type_lookup): Likewise. + * elf32-hppa.c (elf_hppa_reloc_type_lookup): Likewise. + * mipsbsd.c (MY(reloc_howto_type_lookup)): Likewise. + * coff-i386.c (coff_i386_reloc): Made howto const. + * oasys.c (oasys_write_data): Made how const. + + * libelf.h: Added some comments. + (struct elf_backend_data): Added elf_backend_ecoff_debug_swap + field. Removed unused write_relocs field. + * elf32-target.h: Adjusted elf_backend_data initialization + accordingly. + * elf64-target.h: Corrected elf_backend_data initialization to + fill in all fields and to set elf_64_p to 1. + +Mon Nov 8 18:13:14 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (bfd_section_from_shdr): Remove duplicate assignment + to filepos in SHT_STRTAB case. + (assign_file_position_for_section): Set BFD section filepos as + well as ELF section sh_offset. + + * reloc.c: Use const instead of CONST. + (bfd_perform_relocation): Make variable howto a const pointer. + * bfd-in2.h, libbfd.h: Rebuilt. + +Mon Nov 8 12:19:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * Makefile.in (realclean): Don't remove generated headers. Reverts + change of 2 Jul 1993. + +Mon Nov 8 06:08:31 1993 D. V. Henkel-Wallace (gumby@cirdan.cygnus.com) + + * configure.bfd: make unixware equivalent to sysv4. + + * config/i386-nlm.mt: bring in elf config; make it the default. + +Sun Nov 7 20:21:38 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * libbfd.c (bfd_put_8): Add parens around reference to "val" + argument. + +Fri Nov 5 21:45:09 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * hosts/i386mach3.h (HOST_SEGMENT_SIZE), + i386mach3.c (SEGMENT_SIZE, TEXT_START_ADDR): Correct values (?). + +Fri Nov 5 15:17:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * coffcode.h (coff_write_object_contents): Zero out internal_a. + +Fri Nov 5 10:41:07 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * aoutx.h, archive.c, archures.c, bfd.c, cache.c, coffcode.h, + core.c, ctor.c, format.c, init.c, libbfd.c, opncls.c, reloc.c, + section.c, syms.c, targets.c: + Doc cleanup (spelling, punctuation, grammar, formatting). + * bfd-in2.h, libbfd.h: Rebuild. + +Thu Nov 4 14:46:14 1993 John Gilmore (gnu@rtl.cygnus.com) + + * bfd-in.h (bfd_get_cacheable, bfd_set_cacheable): New accessors. + * bfd.c, opncls.c: Improve comments on file descriptor cacheing. + +Thu Nov 4 08:54:30 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * From Pete Hoogenboom (hoogen@cs.utah.edu) + * elf32-hppa.c (hppa_elf_get_section_contents): Fix logic error + in last change. Always rebuild symbol extension section the first + time though if output sections exist (fixes ld -r problems). + +Thu Nov 04 08:08:46 1993 Jeffrey Wheat (cassidy@cygnus.com) + + * Makefile.in: Add .PHONY for check and installcheck rules. + +Tue Nov 2 14:42:27 1993 Bill Cox (bill@tarkas.cygnus.com) + + * libbfd-in.h (artdata): Use long, not time_t for portability, at + least to HPUX. File below is a derived file. + +Tue Nov 2 14:42:27 1993 Bill Cox (bill@tarkas.cygnus.com) + + * libbfd.h (artdata): Use long, not time_t for portability, at + least to HPUX. + +Tue Nov 2 09:32:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config.bfd: Use bigmips for mips*-*-bsd*. + +Mon Nov 1 14:30:09 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elfcode.h (elf_slurp_reloca_table, elf_slurp_reloc_table): + Handle symbol number of zero. + + * reloc.c (enum bfd_reloc_code_real): Added + BFD_RELOC_MIPS_LITERAL, BFD_RELOC_MIPS_GOT16, + BFD_RELOC_MIPS_CALL16, BFD_RELOC_MIPS_GPREL32. + * bfd-in2.h: Rebuilt. + * coff-mips.c (mips_bfd_reloc_type_lookup): Handle + BFD_RELOC_MIPS_LITERAL. + * elf32-mips.c (mips_reloc_map): Handle new relocs. + (mips_elf_hi16_reloc, mips_elf_lo16_reloc): Rearrange _gp_disp + checks slightly. + + * aout-target.h (MY_bfd_debug_info_start, MY_bfd_debug_info_end, + MY_bfd_debug_info_accumulat [sic]): Remove unused definitions. + (MY_bfd_get_relocated_section_contents, MY_bfd_relax_section, + MY_bfd_seclet_link): Define. + (MY_bfd_reloc_type_lookup): Rename from + MY_reloc_howto_type_lookup. + (MY_bfd_make_debug_symbol): Rename from MY_make_debug_symbol. + (MY(vec)): Use JUMP_TABLE rather than listing functions. + * hp300hpux.c (MY_get_symtab, MY_get_symtab_upper_bound, + MY_canonicalize_reloc, MY_write_object_contents): Don't define in + terms of MY, because that causes a recusive invocation of CAT when + expanded within JUMP_TABLE, and ANSI compilers don't expand + recursive macros. + * mipsbsd.c (MY_bfd_reloc_type_lookup): Rename from + MY_reloc_howto_type_lookup, and don't define in terms of MY. + (MY_canonicalize_reloc): Don't define in terms of MY. + (aout_mips_little_vec, aout_mips_big_vec): Use JUMP_TABLE rather + than listing functions. + +Mon Nov 1 09:12:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * config.bfd: Use m68k-elf for m68*-*-sysv4*. + +See file ChangeLog.1 + + +Local Variables: +mode: indented-text +left-margin: 8 +fill-column: 74 +version-control: never +End: diff --git a/gnu/usr.bin/binutils/bfd/Makefile.in b/gnu/usr.bin/binutils/bfd/Makefile.in new file mode 100644 index 00000000000..99f5d72afea --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/Makefile.in @@ -0,0 +1,976 @@ +# Makefile template for Configure for the BFD library. +# 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. + +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 +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@ + +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 + +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 + +# 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-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 \ + i386linux.o \ + i386lynx.o \ + i386msdos.o \ + i386netbsd.o \ + i386mach3.o \ + i386os9k.o \ + ieee.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 \ + stab-syms.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-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 \ + i386linux.c \ + i386lynx.c \ + i386msdos.c \ + i386netbsd.c \ + i386mach3.c \ + i386os9k.c \ + ieee.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 \ + stab-syms.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: + $(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 + +STAGESTUFF = $(TARGETLIB) $(OFILES) + +all: Makefile $(TARGETLIB) + @$(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@ + +ofiles : Makefile + rm -f ofiles + f=""; \ + for i in $(OFILES) ; do \ + case " $$f " in \ + *" $$i "*) ;; \ + *) f="$$f $$i" ;; \ + esac ; \ + done ; \ + echo $$f > ofiles + +$(TARGETLIB): $(OFILES) ofiles + rm -f $(TARGETLIB) + @echo ofiles = `cat ofiles` + $(AR) $(AR_FLAGS) $(TARGETLIB) `cat ofiles` + $(RANLIB) $(TARGETLIB) + +# When compiling archures.c and targets.c, supply the default target +# info from configure. + +targets.o: targets.c Makefile + $(CC) -c $(ALL_CFLAGS) $(TDEFAULTS) $< + +archures.o: archures.c Makefile + $(CC) -c $(ALL_CFLAGS) $(TDEFAULTS) $< + +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 +do_clean: do_mostlyclean + rm -f libbfd.a TAGS bfd.h stmp-bfd.h ofiles \ + elf32-target.h elf64-target.h +do_distclean: do_clean + rm -f Makefile config.status config.cache config.h stamp-h + +# Should we remove $(srcdir)/libcoff.h $(srcdir)/libbfd.h $(srcdir)/bfd-in2.h? +# make-stds.texi says it depends on whether they can be regenerated using +# this makefile. Well, they can, but only via an explicit "make headers"; +# the makefile does not regenerate them as needed. So I guess we should not +# remove them in realclean. +do_maintainer_clean: do_distclean + +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: + $(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: + $(INSTALL_DATA) libbfd.a $(libdir)/libbfd.a + $(RANLIB) $(libdir)/libbfd.a +# 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 + +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)) + + +# 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)/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 +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-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 \ + 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 +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 +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 +stab-syms.o: stab-syms.c libaout.h $(INCDIR)/bfdlink.h \ + $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab.def +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 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 \ + 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/gnu/usr.bin/binutils/bfd/PORTING b/gnu/usr.bin/binutils/bfd/PORTING new file mode 100644 index 00000000000..c8bfd77b96f --- /dev/null +++ b/gnu/usr.bin/binutils/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 . +( might be sun4, ...) +Create a file hosts/.mh. + +Porting to a new target +----------------------- +Pick a name for your target. Call that . +Call the name for your CPU architecture . +You need to create .c and config/.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/.mt is a Makefile fragment. +The following is usually enough: +DEFAULT_VECTOR=_vec +SELECT_ARCHITECTURES=bfd__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 .c is the hard part. It implements the +bfd_target _vec, which includes pointers to +functions that do the actual -specific methods. + +Porting to a 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 .c for +you automatically for many a.out systems. Do: + make gen-aout + ./gen-aout > .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 .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 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-" diff --git a/gnu/usr.bin/binutils/bfd/TODO b/gnu/usr.bin/binutils/bfd/TODO new file mode 100644 index 00000000000..08a3641b1ad --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/VERSION b/gnu/usr.bin/binutils/bfd/VERSION new file mode 100644 index 00000000000..5154b3f68e9 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/VERSION @@ -0,0 +1 @@ +2.6 diff --git a/gnu/usr.bin/binutils/bfd/acconfig.h b/gnu/usr.bin/binutils/bfd/acconfig.h new file mode 100644 index 00000000000..43bcf709004 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/acconfig.h @@ -0,0 +1,17 @@ +/* Do we need to use the b modifier when opening binary files? */ +#undef USE_BINARY_FOPEN + +/* Whether malloc must be declared even if is included. */ +#undef NEED_DECLARATION_MALLOC + +/* Whether free must be declared even if is included. */ +#undef NEED_DECLARATION_FREE + +/* Name of host specific header file to include in trad-core.c. */ +#undef TRAD_HEADER + +/* Define only if 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/gnu/usr.bin/binutils/bfd/aclocal.m4 b/gnu/usr.bin/binutils/bfd/aclocal.m4 new file mode 100644 index 00000000000..6560abf472f --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/aclocal.m4 @@ -0,0 +1,64 @@ +dnl +dnl This ugly hack is needed because the Cygnus configure script won't +dnl tell us what CC is going to be, and "cc" isn't always right. (The +dnl top-level Makefile will always override anything we choose here, so +dnl the usual gcc/cc selection is useless.) +dnl +dnl It knows where it is in the tree; don't try using it elsewhere. +dnl +undefine([AC_PROG_CC])dnl +AC_DEFUN(AC_PROG_CC, +[AC_BEFORE([$0], [AC_PROG_CPP])dnl +dnl +dnl The ugly bit... +dnl +AC_MSG_CHECKING([for CC]) +dnl Don't bother with cache. +test -z "$CC" && test -r ../Makefile && CC=`egrep '^CC *=' ../Makefile | tail -1 | sed 's/^CC *= *//'` +test -z "$CC" && CC=cc +AC_MSG_RESULT(setting CC to $CC) +AC_SUBST(CC) +dnl +dnl Find out if we are using GNU C, under whatever name. +dnl The semicolon is to pacify NeXT's syntax-checking cpp. +cat > conftest.c <&AC_FD_CC | egrep yes >/dev/null 2>&1; then + GCC=yes + if test "${CFLAGS+set}" != set; then + echo 'void f(){}' > conftest.c + if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + CFLAGS="-g -O" + else + CFLAGS="-O" + fi + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi +rm -f conftest* +])dnl +dnl +AC_DEFUN(BFD_BINARY_FOPEN, +[case "${host}" in +changequote(,)dnl +i[345]86-*-msdos* | i[345]86-*-go32* | i[345]86-*-win32) +changequote([,])dnl + AC_DEFINE(USE_BINARY_FOPEN) ;; +esac])dnl +dnl +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 diff --git a/gnu/usr.bin/binutils/bfd/aix386-core.c b/gnu/usr.bin/binutils/bfd/aix386-core.c new file mode 100644 index 00000000000..480d50fa7ef --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/aix386-core.c @@ -0,0 +1,289 @@ +/* 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 . + Converted to back end form by Ian Lance Taylor . + +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 +#include +#include + +#include + +#if defined (_AIX) && defined (_I386) +#define NOCHECKS /* this is for coredump.h */ +#define _h_USER /* avoid including user.h from coredump.h */ +#include +#include +#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) + { + bfd_set_error (bfd_error_no_memory); + 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_set_error (bfd_error_no_memory); + 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT), + + (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/gnu/usr.bin/binutils/bfd/aout-adobe.c b/gnu/usr.bin/binutils/bfd/aout-adobe.c new file mode 100644 index 00000000000..74dbec5ddbb --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/aout-adobe.c @@ -0,0 +1,532 @@ +/* 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) { + bfd_set_error (bfd_error_no_memory); + 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) { + bfd_set_error (bfd_error_no_memory); + 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, + true, /* data byte order is unknown (big assumed) */ + true, /* 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/gnu/usr.bin/binutils/bfd/aout-arm.c b/gnu/usr.bin/binutils/bfd/aout-arm.c new file mode 100644 index 00000000000..1d80ef77341 --- /dev/null +++ b/gnu/usr.bin/binutils/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 (abfd->xvec->header_byteorder_big_p) + { + *r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + *r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); + r_pcrel_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 (abfd->xvec->header_byteorder_big_p) + { + 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] + & (abfd->xvec->header_byteorder_big_p + ? 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 (abfd->xvec->header_byteorder_big_p) + 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 = 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 (abfd->xvec->header_byteorder_big_p != false) + { + 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, + false, /* target byte order (little) */ + false, /* 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, + true, /* target byte order (big) */ + true, /* 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/gnu/usr.bin/binutils/bfd/aout-encap.c b/gnu/usr.bin/binutils/bfd/aout-encap.c new file mode 100644 index 00000000000..c25f9037dce --- /dev/null +++ b/gnu/usr.bin/binutils/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 +#include "libbfd.h" +#include +#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/gnu/usr.bin/binutils/bfd/aout-ns32k.c b/gnu/usr.bin/binutils/bfd/aout-ns32k.c new file mode 100644 index 00000000000..39ab03671f4 --- /dev/null +++ b/gnu/usr.bin/binutils/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(abfd->xvec->header_byteorder_big_p == false); */ + *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 (abfd->xvec->header_byteorder_big_p == false); */ + 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 + +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/gnu/usr.bin/binutils/bfd/aout-target.h b/gnu/usr.bin/binutils/bfd/aout-target.h new file mode 100644 index 00000000000..3ae5b26d77f --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/aout-target.h @@ -0,0 +1,604 @@ +/* Define a target vector and some small routines for a variant of a.out. + Copyright (C) 1990, 1991, 1992, 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. */ + +#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_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 + true, /* target byte order (big) */ + true, /* target headers byte order (big) */ +#else + false, /* target byte order (little) */ + false, /* 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/gnu/usr.bin/binutils/bfd/aout0.c b/gnu/usr.bin/binutils/bfd/aout0.c new file mode 100644 index 00000000000..5bc7ae0f67f --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/aout32.c b/gnu/usr.bin/binutils/bfd/aout32.c new file mode 100644 index 00000000000..bfc40b46303 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/aout64.c b/gnu/usr.bin/binutils/bfd/aout64.c new file mode 100644 index 00000000000..84036c885a2 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/aoutf1.h b/gnu/usr.bin/binutils/bfd/aoutf1.h new file mode 100644 index 00000000000..75c2fc1f1a5 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/aoutf1.h @@ -0,0 +1,792 @@ +/* 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. + I needed to add M_UNKNOWN to recognize a 68000 object, so this will + probably no longer reject a NewsOS object. . */ +#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) + { + bfd_set_error (bfd_error_no_memory); + 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_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/aoutx.h b/gnu/usr.bin/binutils/bfd/aoutx.h new file mode 100644 index 00000000000..0a34a0fa93b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/aoutx.h @@ -0,0 +1,5355 @@ +/* BFD semi-generic back-end for a.out binaries. + 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. */ + +/* +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 + <>, <>, 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 "<>") 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 /* For strchr and friends */ +#include "bfd.h" +#include +#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, 16, false, 0, complain_overflow_bitfield,0,"BASE10", false, 0,0x0000ffff, false), + HOWTO(RELOC_BASE13, 0, 2, 13, false, 0, complain_overflow_bitfield,0,"BASE13", false, 0,0x00001fff, false), + HOWTO(RELOC_BASE22, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"BASE22", false, 0,0x00000000, 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) { + bfd_set_error (bfd_error_no_memory); + 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 + && (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) { + bfd_set_error (bfd_error_no_memory); + 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 <> for a particular + architecture and machine, or <> if that exact architecture + and machine can't be represented in a.out format. + + If the architecture is understood, machine type 0 (default) + 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_sparc64) + 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 *) + malloc ((size_t) count * EXTERNAL_NLIST_SIZE)); + if (syms == (struct external_nlist *) NULL && count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 + || (bfd_read (syms, 1, exec_hdr (abfd)->a_syms, abfd) + != exec_hdr (abfd)->a_syms)) + { + free (syms); + return false; + } +#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 *) malloc ((size_t) stringsize + 1); + if (strings == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + /* Skip space for the string count in the buffer for convenience + when using indexes. */ + if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD, + abfd) + != stringsize - BYTES_IN_WORD) + { + free (strings); + return false; + } +#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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + strcpy (copy, cache_ptr->symbol.name); + section = bfd_make_section (abfd, copy); + if (section == NULL) + return false; + } + + reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain)); + if (reloc == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + /* Build a relocation entry for the constructor. */ + switch (cache_ptr->type & N_TYPE) + { + case N_SETA: + into_section = bfd_abs_section_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) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + new->symbol.the_bfd = abfd; + + return &new->symbol; +} + +/* Translate a set of internal symbols into external symbols. */ + +boolean +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 *) malloc (cached_size); + if (cached == NULL && cached_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 *) malloc ((size_t) (count * sizeof (arelent))); + if (reloc_cache == NULL && count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + memset (reloc_cache, 0, count * sizeof (arelent)); + + relocs = malloc ((size_t) reloc_size); + if (relocs == NULL && reloc_size != 0) + { + free (reloc_cache); + bfd_set_error (bfd_error_no_memory); + return false; + } + + if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) + { + free (relocs); + free (reloc_cache); + return false; + } + + cache_ptr = reloc_cache; + if (each_size == RELOC_EXT_SIZE) + { + register struct reloc_ext_external *rptr = + (struct reloc_ext_external *) relocs; + + for (; counter < count; counter++, rptr++, cache_ptr++) + NAME(aout,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols, + 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) { + bfd_set_error (bfd_error_no_memory); + 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 = aout_stab_name(type_code); + static char buf[10]; + + if (stab_name == NULL) + { + sprintf(buf, "(%d)", type_code); + stab_name = buf; + } + ret->type = '-'; + 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 + { + adata (abfd).line_buf = buf = (char *) malloc (filelen + funclen + 2); + if (adata (abfd).line_buf == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_hash_entry *) ret; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct aout_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + if (ret) + { + /* Set local fields. */ + ret->written = false; + ret->indx = -1; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Initialize an a.out link hash table. */ + +boolean +NAME(aout,link_hash_table_init) (table, abfd, newfunc) + struct aout_link_hash_table *table; + bfd *abfd; + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); +{ + return _bfd_link_hash_table_init (&table->root, abfd, newfunc); +} + +/* Create an a.out link hash table. */ + +struct bfd_link_hash_table * +NAME(aout,link_hash_table_create) (abfd) + bfd *abfd; +{ + struct aout_link_hash_table *ret; + + ret = ((struct aout_link_hash_table *) + bfd_alloc (abfd, sizeof (struct aout_link_hash_table))); + if (ret == NULL) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_link_hash_table *) NULL; + } + if (! NAME(aout,link_hash_table_init) (ret, abfd, + NAME(aout,link_hash_newfunc))) + { + free (ret); + return (struct bfd_link_hash_table *) NULL; + } + return &ret->root; +} + +/* Given an a.out BFD, add symbols to the global hash table as + appropriate. */ + +boolean +NAME(aout,link_add_symbols) (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + switch (bfd_get_format (abfd)) + { + case bfd_object: + return aout_link_add_object_symbols (abfd, info); + case bfd_archive: + return _bfd_generic_link_add_archive_symbols + (abfd, info, aout_link_check_archive_element); + default: + bfd_set_error (bfd_error_wrong_format); + return false; + } +} + +/* Add symbols from an a.out object file. */ + +static boolean +aout_link_add_object_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + if (! aout_get_external_symbols (abfd)) + return false; + if (! aout_link_add_symbols (abfd, info)) + return false; + if (! info->keep_memory) + { + if (! aout_link_free_symbols (abfd)) + return false; + } + return true; +} + +/* Check a single archive element to see if we need to include it in + the link. *PNEEDED is set according to whether this element is + needed in the link or not. This is called from + _bfd_generic_link_add_archive_symbols. */ + +static boolean +aout_link_check_archive_element (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + if (! aout_get_external_symbols (abfd)) + return false; + + if (! aout_link_check_ar_symbols (abfd, info, pneeded)) + return false; + + if (*pneeded) + { + if (! aout_link_add_symbols (abfd, info)) + return false; + } + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; +} + +/* 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; + /* 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 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 *)); + +/* Do the final link step. This is called on the output BFD. The + INFO structure should point to a list of BFDs linked through the + link_next field which can be used to find each BFD which takes part + in the output. Also, each section in ABFD should point to a list + of bfd_link_order structures which list all the input sections for + the output section. */ + +boolean +NAME(aout,final_link) (abfd, info, callback) + bfd *abfd; + struct bfd_link_info *info; + void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); +{ + struct aout_final_link_info aout_info; + register bfd *sub; + bfd_size_type 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; + + /* 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 *) malloc (max_contents_size); + aout_info.relocs = (PTR) malloc (max_relocs_size); + aout_info.symbol_map = (int *) malloc (max_sym_count * sizeof (int *)); + aout_info.output_syms = ((struct external_nlist *) + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + } + + /* 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); + 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; + for (; sym < sym_end; sym++, sym_hash++, symbol_map++) + { + const char *name; + int type; + struct aout_link_hash_entry *h; + boolean skip; + asection *symsec; + bfd_vma val = 0; + boolean copy; + + *symbol_map = -1; + + type = bfd_h_get_8 (input_bfd, sym->e_type); + name = strings + GET_WORD (input_bfd, sym->e_strx); + + h = NULL; + + if (pass) + { + /* Pass this symbol through. It is the target of an + indirect or warning symbol. */ + val = GET_WORD (input_bfd, sym->e_value); + pass = false; + } + else if (skip_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; + + /* 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; + } + } + } + + /* 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_big_p + == output_bfd->xvec->header_byteorder_big_p); + + relocateable = finfo->info->relocateable; + syms = obj_aout_external_syms (input_bfd); + strings = obj_aout_external_strings (input_bfd); + sym_hashes = obj_aout_sym_hashes (input_bfd); + 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 (input_bfd->xvec->header_byteorder_big_p) + { + r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); + r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); + r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); + r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); + r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); + r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) + >> RELOC_STD_BITS_LENGTH_SH_BIG); + } + else + { + r_index = ((rel->r_index[2] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[0]); + r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); + r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); + r_baserel = (0 != (rel->r_type[0] + & RELOC_STD_BITS_BASEREL_LITTLE)); + r_jmptable= (0 != (rel->r_type[0] + & RELOC_STD_BITS_JMPTABLE_LITTLE)); + r_relative= (0 != (rel->r_type[0] + & RELOC_STD_BITS_RELATIVE_LITTLE)); + r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) + >> RELOC_STD_BITS_LENGTH_SH_LITTLE); + } + + howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel + + 16 * r_jmptable + 32 * r_relative); + BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); + howto = howto_table_std + howto_idx; + } +#endif + + if (relocateable) + { + /* We are generating a relocateable output file, and must + modify the reloc accordingly. */ + if (r_extern) + { + /* 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 (output_bfd->xvec->header_byteorder_big_p) + rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG; + else + rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE; + + /* Compute a new r_index. */ + output_section = h->root.u.def.section->output_section; + if (output_section == obj_textsec (output_bfd)) + r_index = N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + r_index = N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + r_index = N_BSS; + else + r_index = N_ABS; + + /* Add the symbol value and the section VMA to the + addend stored in the contents. */ + relocation = (h->root.u.def.value + + output_section->vma + + h->root.u.def.section->output_offset); + } + else + { + /* We must change r_index according to the symbol + map. */ + r_index = symbol_map[r_index]; + + if (r_index == -1) + { + 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 (output_bfd->xvec->header_byteorder_big_p) + { + rel->r_index[0] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[2] = r_index; + } + else + { + rel->r_index[2] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[0] = r_index; + } + } + else + { + asection *section; + + /* This is a relocation against a section. We must + adjust by the amount that the section moved. */ + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + } + + /* Change the address of the relocation. */ + PUT_WORD (output_bfd, + r_addr + input_section->output_offset, + rel->r_address); + + /* Adjust a PC relative relocation by removing the reference + to the original address in the section and including the + reference to the new address. */ + if (r_pcrel) + relocation -= (input_section->output_section->vma + + input_section->output_offset + - input_section->vma); + +#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; + + 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_big_p + == output_bfd->xvec->header_byteorder_big_p); + + relocateable = finfo->info->relocateable; + syms = obj_aout_external_syms (input_bfd); + strings = obj_aout_external_strings (input_bfd); + sym_hashes = obj_aout_sym_hashes (input_bfd); + 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 (input_bfd->xvec->header_byteorder_big_p) + { + r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) + >> RELOC_EXT_BITS_TYPE_SH_BIG); + } + else + { + r_index = ((rel->r_index[2] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[0]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) + >> RELOC_EXT_BITS_TYPE_SH_LITTLE); + } + + r_addend = GET_SWORD (input_bfd, rel->r_addend); + + BFD_ASSERT (r_type < 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 (output_bfd->xvec->header_byteorder_big_p) + rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG; + else + rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE; + + /* Compute a new r_index. */ + output_section = h->root.u.def.section->output_section; + if (output_section == obj_textsec (output_bfd)) + r_index = N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + r_index = N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + r_index = N_BSS; + else + r_index = N_ABS; + + /* Add the symbol value and the section VMA to the + addend. */ + relocation = (h->root.u.def.value + + output_section->vma + + h->root.u.def.section->output_offset); + + /* Now RELOCATION is the VMA of the final + destination. If this is a PC relative reloc, + then ADDEND is the negative of the source VMA. + We want to set ADDEND to the difference between + the destination VMA and the source VMA, which + means we must adjust RELOCATION by the change in + the source VMA. This is done below. */ + } + else + { + /* We must change r_index according to the symbol + map. */ + r_index = symbol_map[r_index]; + + if (r_index == -1) + { + 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 (output_bfd->xvec->header_byteorder_big_p) + { + rel->r_index[0] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[2] = r_index; + } + else + { + rel->r_index[2] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[0] = r_index; + } + } + else + { + /* 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; + + 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 = aout_link_hash_lookup (aout_hash_table (finfo->info), + pr->u.name, false, false, true); + if (h != (struct aout_link_hash_entry *) NULL + && h->indx >= 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 (finfo->output_bfd->xvec->header_byteorder_big_p) + { + srel.r_index[0] = r_index >> 16; + srel.r_index[1] = r_index >> 8; + srel.r_index[2] = r_index; + srel.r_type[0] = + ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) + | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) + | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) + | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) + | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) + | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG)); + } + else + { + srel.r_index[2] = r_index >> 16; + srel.r_index[1] = r_index >> 8; + srel.r_index[0] = r_index; + srel.r_type[0] = + ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0) + | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0) + | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0) + | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0) + | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0) + | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)); + } + } +#endif + rel_ptr = (PTR) &srel; + + /* We have to write the addend into the object file, since + standard a.out relocs are in place. It would be more + reliable if we had the current contents of the file here, + rather than assuming zeroes, but we can't read the file since + it was opened using bfd_openw. */ + if (pr->addend != 0) + { + bfd_size_type size; + bfd_reloc_status_type r; + bfd_byte *buf; + boolean ok; + + size = bfd_get_reloc_size (howto); + buf = (bfd_byte *) bfd_zmalloc (size); + if (buf == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + r = 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 (finfo->output_bfd->xvec->header_byteorder_big_p) + { + erel.r_index[0] = r_index >> 16; + erel.r_index[1] = r_index >> 8; + erel.r_index[2] = r_index; + erel.r_type[0] = + ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0) + | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG)); + } + else + { + erel.r_index[2] = r_index >> 16; + erel.r_index[1] = r_index >> 8; + erel.r_index[0] = r_index; + erel.r_type[0] = + (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0) + | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE); + } + + PUT_WORD (finfo->output_bfd, pr->addend, erel.r_addend); + + rel_ptr = (PTR) &erel; + } + + if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0 + || (bfd_write (rel_ptr, (bfd_size_type) 1, + obj_reloc_entry_size (finfo->output_bfd), + finfo->output_bfd) + != obj_reloc_entry_size (finfo->output_bfd))) + return false; + + *reloff_ptr += obj_reloc_entry_size (finfo->output_bfd); + + /* Assert that the relocs have not run into the symbols, and that n + the text relocs have not run into the data relocs. */ + BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) + && (reloff_ptr != &finfo->treloff + || (*reloff_ptr + <= obj_datasec (finfo->output_bfd)->rel_filepos))); + + return true; +} diff --git a/gnu/usr.bin/binutils/bfd/archive.c b/gnu/usr.bin/binutils/bfd/archive.c new file mode 100644 index 00000000000..07d1daad6fe --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/archive.c @@ -0,0 +1,2154 @@ +/* BFD back-end for archive files (libraries). + Copyright 1990, 91, 92, 93, 94 Free Software Foundation, Inc. + Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 <> to step through + the contents of an archive opened for input. You don't + have to read the entire archive if you don't want + to! Read it until you find what you want. + + Archive contents of output BFDs are chained through the + <> pointer in a BFD. The first one is findable through + the <> slot of the archive. Set it with + <> (q.v.). A given BFD may be in only one + 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 <>. + +*/ + +/* 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 +#include /* For memchr, strrchr and friends */ +#include + +#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) + { + bfd_set_error (bfd_error_no_memory); + 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 <> as the @var{previous} entry to get + the first one; returns <> when you've already + got the last one. + + A <> is a canonical archive symbol. The only + 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; +{ + bfd *nbfd; + + nbfd = _bfd_new_bfd_contained_in (obfd); + if (nbfd == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + return nbfd; +} + +/* +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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + new_cache->ptr = filepos; + new_cache->arelt = new_elt; + new_cache->next = (struct ar_cache *) NULL; + 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; +{ +#ifndef errno + extern int errno; +#endif + + struct ar_hdr hdr; + char *hdrp = (char *) &hdr; + unsigned int parsed_size; + struct areltdata *ared; + char *filename = NULL; + unsigned int namelen = 0; + unsigned int allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr); + char *allocptr = 0; + + if (bfd_read ((PTR) hdrp, 1, sizeof (struct ar_hdr), abfd) + != sizeof (struct ar_hdr)) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_no_more_archived_files); + return NULL; + } + if (strncmp (hdr.ar_fmag, ARFMAG, 2)) + { + bfd_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) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + filename = (allocptr + + sizeof (struct areltdata) + + sizeof (struct ar_hdr)); + if (bfd_read (filename, 1, namelen, abfd) != namelen) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_no_more_archived_files); + return NULL; + } + filename[namelen] = '\0'; + } + else + { + /* We judge the end of the name by looking for '/' or ' '. + Note: The SYSV format (terminated by '/') allows embedded + spaces, so only look for ' ' if we don't find '/'. */ + + namelen = 0; + while (hdr.ar_name[namelen] != '\0' && + hdr.ar_name[namelen] != '/') + { + namelen++; + if (namelen == (unsigned) ar_maxnamelen (abfd)) + { + namelen = 0; + while (hdr.ar_name[namelen] != ' ' + && namelen < (unsigned) ar_maxnamelen (abfd)) + namelen++; + break; + } + } + + allocsize += namelen + 1; + } + + if (!allocptr) + { + allocptr = bfd_zalloc (abfd, allocsize); + if (allocptr == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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; +} + +/* +FUNCTION + bfd_get_elt_at_index + +SYNOPSIS + bfd *bfd_get_elt_at_index(bfd *archive, int index); + +DESCRIPTION + Return the BFD which is referenced by the symbol in @var{archive} + indexed by @var{index}. @var{index} should have been returned by + <> (q.v.). + +*/ +bfd * +bfd_get_elt_at_index (abfd, index) + bfd *abfd; + int 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) + { + bfd_set_error (bfd_error_no_memory); + 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 the first file in the + archive can be recognized as an object file for this target. + If not, assume that this is the wrong format. + + 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)) + fail = true; + else if (first->xvec != abfd->xvec) + { + bfd_set_error (bfd_error_wrong_format); + fail = true; + } + if (fail) + { + bfd_error_type err; + + err = bfd_get_error (); + (void) bfd_close (first); + bfd_release (abfd, bfd_ardata (abfd)); + abfd->tdata.aout_ar_data = tdata_hold; + bfd_set_error (err); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + for (counter = 0, set = ardata->symdefs; + counter < ardata->symdef_count; + counter++, set++, rbase += BSD_SYMDEF_SIZE) + { + set->name = bfd_h_get_32 (abfd, rbase) + stringbase; + set->file_offset = bfd_h_get_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); + } + + ardata->first_file_filepos = bfd_tell (abfd); + /* Pad to an even boundary if you have to */ + ardata->first_file_filepos += (ardata->first_file_filepos) % 2; + /* 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + carsyms = ardata->symdefs; + stringbase = ((char *) ardata->symdefs) + carsym_size; + + /* Allocate and read in the raw offsets. */ + raw_armap = (int *) bfd_alloc (abfd, ptrsize); + if (raw_armap == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto release_symdefs; + } + if (bfd_read ((PTR) raw_armap, 1, ptrsize, abfd) != ptrsize + || bfd_read ((PTR) stringbase, 1, stringsize, abfd) != stringsize) + { + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + for (counter = 0, set = ardata->symdefs; + counter < ardata->symdef_count; + counter++, set++, rbase += BSD_SYMDEF_SIZE) + { + set->name = bfd_h_get_32 (abfd, rbase) + stringbase; + set->file_offset = bfd_h_get_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); + } + + ardata->first_file_filepos = bfd_tell (abfd); + /* Pad to an even boundary if you have to */ + ardata->first_file_filepos += (ardata->first_file_filepos) % 2; + /* 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 . 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + *tablen = total_namelen; + strptr = *tabloc; + + for (current = abfd->archive_head; current != NULL; current = + current->next) + { + const char *normal; + 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) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata)); + + /* ar headers are space padded, not null padded! */ + 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 *) malloc (orl_max * sizeof (struct orl)); + if (map == NULL) + goto no_memory_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 no_memory_return; + + /* Drop all the files called __.SYMDEF, we're going to make our + own */ + while (arch->archive_head && + strcmp (arch->archive_head->filename, "__.SYMDEF") == 0) + arch->archive_head = arch->archive_head->next; + + /* Map over each element */ + for (current = arch->archive_head; + current != (bfd *) NULL; + current = current->next, elt_no++) + { + 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 **) malloc ((size_t) syms_max); + if (syms == NULL) + goto no_memory_return; + } + symcount = bfd_canonicalize_symtab (current, syms); + if (symcount < 0) + goto error_return; + + /* Now map over all the symbols, picking out the ones we want */ + for (src_count = 0; src_count < symcount; src_count++) + { + flagword flags = (syms[src_count])->flags; + asection *sec = syms[src_count]->section; + + 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 *) + realloc ((PTR) map, + orl_max * sizeof (struct orl))); + if (new_map == (struct orl *) NULL) + goto no_memory_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 no_memory_return; + *(map[orl_count].name) = bfd_alloc (arch, namelen + 1); + if (*(map[orl_count].name) == NULL) + goto no_memory_return; + strcpy (*(map[orl_count].name), syms[src_count]->name); + (map[orl_count]).pos = (file_ptr) current; + (map[orl_count]).namidx = stridx; + + stridx += namelen + 1; + ++orl_count; + } + } + } + + /* 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; + + no_memory_return: + bfd_set_error (bfd_error_no_memory); + + error_return: + if (syms_max > 0) + free (syms); + if (map != NULL) + free (map); + if (first_name != NULL) + bfd_release (arch, first_name); + + return false; +} + +boolean +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/gnu/usr.bin/binutils/bfd/archures.c b/gnu/usr.bin/binutils/bfd/archures.c new file mode 100644 index 00000000000..f82007fd840 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/archures.c @@ -0,0 +1,712 @@ +/* BFD library support routines for architectures. + Copyright (C) 1990, 91, 92, 93, 94, 1995 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 + +/* + +SECTION + Architectures + + BFD keeps one atom in a BFD describing the + architecture of the data attached to the BFD: a pointer to a + <>. + + Pointers to structures can be requested independently of a BFD + 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 + <>. 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 +. +. bfd_arch_a29k, {* AMD 29000 *} +. bfd_arch_sparc, {* SPARC *} +.#define bfd_mach_sparc 1 +.#define bfd_mach_sparc64 2 +. 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 <> + 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 <> 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 <> is an item of + <> 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 <> + 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/gnu/usr.bin/binutils/bfd/bfd-in.h b/gnu/usr.bin/binutils/bfd/bfd-in.h new file mode 100644 index 00000000000..96be0b3c4e1 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/bfd-in.h @@ -0,0 +1,646 @@ +/* Main header file for the bfd library -- portable access to object files. + Copyright 1990, 1991, 1992, 1993, 1994, 1995 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 -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 +#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 . + For now, try to avoid breaking stuff by not including 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 + +/* 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. */ + char stab_other; /* Unused. */ + short stab_desc; /* Info for N_TYPE. */ + CONST char *stab_name; +} symbol_info; + +/* 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_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) + +/* 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 *)); + +/* 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_linux_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, struct sec **)); + +/* And more from the source. */ diff --git a/gnu/usr.bin/binutils/bfd/bfd-in2.h b/gnu/usr.bin/binutils/bfd/bfd-in2.h new file mode 100644 index 00000000000..4f0ad8d57ee --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/bfd-in2.h @@ -0,0 +1,2406 @@ +/* Main header file for the bfd library -- portable access to object files. + Copyright 1990, 1991, 1992, 1993, 1994, 1995 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 -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 +#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 . + For now, try to avoid breaking stuff by not including 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 + +/* 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. */ + char stab_other; /* Unused. */ + short stab_desc; /* Info for N_TYPE. */ + CONST char *stab_name; +} symbol_info; + +/* 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_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) + +/* 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 *)); + +/* 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_linux_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, 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 <>. 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 + <> | <>; a debug section could be + <> */ +#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 + + /* 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 <>, 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 + + bfd_arch_a29k, /* AMD 29000 */ + bfd_arch_sparc, /* SPARC */ +#define bfd_mach_sparc 1 +#define bfd_mach_sparc64 2 + 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 <>.) 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_LO7, + +/* Alpha ECOFF relocations. Some of these treat the symbol or "addend" +in some special way. +For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when +writing; when reading, it will be the absolute section symbol. The +addend is the displacement in bytes of the "lda" instruction from +the "ldah" instruction (which is at the address of this reloc). */ + BFD_RELOC_ALPHA_GPDISP_HI16, + +/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as +with GPDISP_HI16 relocs. The addend is ignored when writing the +relocations out, and is filled in with the file's GP value on +reading, for convenience. */ + BFD_RELOC_ALPHA_GPDISP_LO16, + +/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; +the assembler turns it into a LDQ instruction to load the address of +the symbol, and then fills in a register in the real instruction. + +The LITERAL reloc, at the LDQ instruction, refers to the .lita +section symbol. The addend is ignored when writing, but is filled +in with the file's GP value on reading, for convenience, as with the +GPDISP_LO16 reloc. + +The LITUSE reloc, on the instruction using the loaded address, gives +information to the linker that it might be able to use to optimize +away some literal section references. The symbol is ignored (read +as the absolute section symbol), and the "addend" indicates the type +of instruction using the register: +1 - "memory" fmt insn +2 - byte-manipulation (byte offset reg) +3 - jsr (target of branch) + +The GNU linker currently doesn't do any of this optimizing. */ + BFD_RELOC_ALPHA_LITERAL, + BFD_RELOC_ALPHA_LITUSE, + +/* The HINT relocation indicates a value that should be filled into the +"hint" field of a jmp/jsr/ret instruction, for possible branch- +prediction logic which may be provided on some processors. */ + BFD_RELOC_ALPHA_HINT, + +/* Bits 27..2 of the relocation address shifted right 2 bits; +simple reloc otherwise. */ + BFD_RELOC_MIPS_JMP, + +/* 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 + +/* 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, + +/* 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; <> in <>. The value + is the offset into the section of the data. */ +#define BSF_LOCAL 0x01 + + /* The symbol has global scope; initialized data in <>. 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: + <>, <>, <> or + <> */ + + /* 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 <> symbol + which is also <> 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 + + 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 `<>', 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. */ + char *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 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; + 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_get_elt_at_index PARAMS ((bfd *archive, int index)); + +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_som_flavour, + bfd_target_os9k_flavour, + bfd_target_versados_flavour, + bfd_target_msdos_flavour +}; + + /* Forward declaration. */ +typedef struct bfd_link_info _bfd_link_info; + +typedef struct bfd_target +{ + char *name; + enum bfd_flavour flavour; + boolean byteorder_big_p; + boolean header_byteorder_big_p; + 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,_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)); + 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/gnu/usr.bin/binutils/bfd/bfd.c b/gnu/usr.bin/binutils/bfd/bfd.c new file mode 100644 index 00000000000..a038a4fce05 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/bfd.c @@ -0,0 +1,1048 @@ +/* Generic BFD library interface and support routines. + 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 + <> + + A BFD has type <>; objects of this type are the + cornerstone of any application using BFD. Using BFD + consists of making references though the BFD and to data in the BFD. + + Here is the structure that defines the type <>. 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 `<>', 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. *} +. char *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 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; +. 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 +#else +#include +#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 + +/* 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 <> to set an error condition that callers + can check by calling <>. + If that returns <>, then check + <>. + + The easiest way to report a BFD error to the user is to + use <>. + +SUBSECTION + Type <> + + The values returned by <> are defined by the + enumerated type <>. + +CODE_FRAGMENT +. +.typedef enum bfd_error +.{ +. bfd_error_no_error = 0, +. bfd_error_system_call, +. bfd_error_invalid_target, +. bfd_error_wrong_format, +. bfd_error_invalid_operation, +. bfd_error_no_memory, +. bfd_error_no_symbols, +. bfd_error_no_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", + "#" + }; + +/* +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 <>. +*/ + +CONST char * +bfd_errmsg (error_tag) + bfd_error_type error_tag; +{ +#ifndef errno + extern int errno; +#endif + if (error_tag == bfd_error_system_call) + return strerror (errno); + + 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 + <>. 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 <> - The target bfd was not of object format. + o <> - The target bfd was open for reading. + o <> - + The flag word contained a bit which was not applicable to the + type of file. E.g., an attempt was made to set the <> bit + on a BFD format which does not support demand paging. + +*/ + +boolean +bfd_set_file_flags (abfd, flags) + bfd *abfd; + flagword flags; +{ + if (abfd->format != bfd_object) { + bfd_set_error (bfd_error_wrong_format); + return false; + } + + if (bfd_read_p (abfd)) { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + + bfd_get_file_flags (abfd) = flags; + if ((flags & bfd_applicable_file_flags (abfd)) != flags) { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + +return true; +} + +void +bfd_assert (file, line) + 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 <> on success, <> 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 <> 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; + + 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; +} + +/* +FUNCTION + bfd_scan_vma + +SYNOPSIS + bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base); + +DESCRIPTION + Convert, like <>, a numerical expression + @var{string} into a <> integer, and return that integer. + (Though without as many bells and whistles as <>.) + The expression is assumed to be unsigned (i.e., positive). + If given a @var{base}, it is used as the base for conversion. + A base of 0 causes the function to interpret the string + in hex if a leading "0x" or "0X" is found, otherwise + in octal if a leading zero is found, otherwise in decimal. + + Overflow is not detected. +*/ + +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 <> on success, <> on error. + Possible error returns are: + + o <> - + Not enough memory exists to create private data for @var{obfd}. + +.#define bfd_copy_private_bfd_data(ibfd, obfd) \ +. BFD_SEND (ibfd, _bfd_copy_private_bfd_data, \ +. (ibfd, obfd)) + +*/ + +/* +FUNCTION + 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 <> + on success, <> on error. Possible error returns are: + + o <> - + 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 <> on success, <> on error. Possible error + returns are: + + o <> - + 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); +} + + + diff --git a/gnu/usr.bin/binutils/bfd/binary.c b/gnu/usr.bin/binutils/bfd/binary.c new file mode 100644 index 00000000000..09ee91e9a52 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/binary.c @@ -0,0 +1,359 @@ +/* BFD back-end for binary objects. + Copyright 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. */ + +/* 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 + +#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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; +{ + asymbol *ret; + + ret = (asymbol *) bfd_alloc (abfd, sizeof (asymbol)); + if (ret == NULL) + bfd_set_error (bfd_error_no_memory); + return ret; +} + +#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 */ + true, /* byteorder_big_p */ + true, /* header_byteorder_big_p */ + 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/gnu/usr.bin/binutils/bfd/bout.c b/gnu/usr.bin/binutils/bfd/bout.c new file mode 100644 index 00000000000..cfb3f48b54b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/bout.c @@ -0,0 +1,1481 @@ +/* BFD back-end for Intel 960 b.out binaries. + 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 "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) { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (reloc_size); + if (!relocs && reloc_size != 0) { + bfd_set_error (bfd_error_no_memory); + return false; + } + reloc_cache = (arelent *) malloc ((count+1) * sizeof (arelent)); + if (!reloc_cache) { + if (relocs != NULL) + free ((char*)relocs); + bfd_set_error (bfd_error_no_memory); + return false; + } + + if (bfd_read ((PTR) relocs, 1, reloc_size, abfd) != reloc_size) { + free (reloc_cache); + if (relocs != NULL) + free (relocs); + return false; + } + + + + if (abfd->xvec->header_byteorder_big_p) { + /* 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 (abfd->xvec->header_byteorder_big_p) + { + 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 *) malloc (natsize)); + if (!native && natsize != 0) { + bfd_set_error (bfd_error_no_memory); + return false; + } + + if (abfd->xvec->header_byteorder_big_p) + { + /* 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 = stoi((*(g->sym_ptr_ptr))->flags); + } + } + else + { + /* Just an ordinary section */ + r_extern = 0; + r_idx = output_section->target_index; + } + + if (abfd->xvec->header_byteorder_big_p) { + 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 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_link_hash_lookup (link_info->hash, 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 **) malloc (reloc_size); + if (reloc_vector == NULL && reloc_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 **) malloc (reloc_size); + if (reloc_vector == NULL && reloc_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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, + false, /* data byte order is little */ + true, /* 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, + false, /* data byte order is little */ + false, /* 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/gnu/usr.bin/binutils/bfd/cache.c b/gnu/usr.bin/binutils/bfd/cache.c new file mode 100644 index 00000000000..0d4bae110b1 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/cache.c @@ -0,0 +1,343 @@ +/* BFD library -- caching of file descriptors. + Copyright 1990, 1991, 1992, 1994 Free Software Foundation, Inc. + Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com). + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 + <> maintains a least recently used list of + <> files, and exports the name + <>, 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 <> 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 + <> is returned if closing the file fails, <> is + returned if all is well. +*/ + +boolean +bfd_cache_close (abfd) + bfd *abfd; +{ + if (abfd->iostream == NULL) + 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 <> + (possibly <>) that results from this operation. Set up the + BFD so that future accesses know the file is open. If the <> + returned is <>, then it won't have been put in the + cache, so it won't have to be removed from it. +*/ + +FILE * +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 = (char *) fopen (abfd->filename, FOPEN_RB); + break; + case both_direction: + case write_direction: + if (abfd->opened_once == true) + { + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_RUB); + if (abfd->iostream == NULL) + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_WUB); + } + else + { + /*open for creat */ + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_WB); + abfd->opened_once = true; + } + break; + } + + if (abfd->iostream != NULL) + { + if (! bfd_cache_init (abfd)) + return NULL; + } + + return (FILE *) abfd->iostream; +} + +/* +INTERNAL_FUNCTION + bfd_cache_lookup_worker + +SYNOPSIS + FILE *bfd_cache_lookup_worker(bfd *abfd); + +DESCRIPTION + Called when the macro <> fails to find a + quick answer. Find a file descriptor for @var{abfd}. If + necessary, it open it. If there are already more than + <> files open, it tries to close one first, to + avoid running out of file descriptors. +*/ + +FILE * +bfd_cache_lookup_worker (abfd) + bfd *abfd; +{ + 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/gnu/usr.bin/binutils/bfd/cf-i386lynx.c b/gnu/usr.bin/binutils/bfd/cf-i386lynx.c new file mode 100644 index 00000000000..2a14bde8f12 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cf-m68klynx.c b/gnu/usr.bin/binutils/bfd/cf-m68klynx.c new file mode 100644 index 00000000000..8149dc68319 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cf-sparclynx.c b/gnu/usr.bin/binutils/bfd/cf-sparclynx.c new file mode 100644 index 00000000000..774a099fefb --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cisco-core.c b/gnu/usr.bin/binutils/bfd/cisco-core.c new file mode 100644 index 00000000000..adaa15c5ed3 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/cisco-core.c @@ -0,0 +1,322 @@ +/* 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 + +#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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_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/gnu/usr.bin/binutils/bfd/coff-a29k.c b/gnu/usr.bin/binutils/bfd/coff-a29k.c new file mode 100644 index 00000000000..7b0f8e8807d --- /dev/null +++ b/gnu/usr.bin/binutils/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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-alpha.c b/gnu/usr.bin/binutils/bfd/coff-alpha.c new file mode 100644 index 00000000000..763580bfe29 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-alpha.c @@ -0,0 +1,2103 @@ +/* BFD back-end for ALPHA Extended-Coff files. + Copyright 1993, 1994 Free Software Foundation, Inc. + Modified from coff-mips.c by Steve Chamberlain and + Ian Lance Taylor . + +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 "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 *)); + +/* 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 (abfd->xvec->header_byteorder_big_p == false); + + 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_NONE + || intern->r_symndx == RELOC_SECTION_ABS)) + abort (); + if (! intern->r_extern && intern->r_symndx == RELOC_SECTION_LITA) + intern->r_symndx = RELOC_SECTION_NONE; + } +} + +/* 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_NONE) + { + 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 (abfd->xvec->header_byteorder_big_p == false); + + 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; + if (intern->r_symndx == RELOC_SECTION_ABS) + intern->r_symndx = RELOC_SECTION_NONE; + 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 **) malloc (reloc_size); + if (reloc_vector == NULL && reloc_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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; + if (ecoff_data (abfd)->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; + } + ecoff_data (abfd)->gp = lo + 0x8000; + } + 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 + ecoff_data (abfd)->gp = (h->u.def.value + + h->u.def.section->output_section->vma + + h->u.def.section->output_offset); + } + } + gp = ecoff_data (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, and is marked with an ALPHA_R_IGNORE reloc. */ + { + unsigned long insn1, insn2; + bfd_vma addend; + + BFD_ASSERT (reloc_vector[1] != NULL + && reloc_vector[1]->howto->type == ALPHA_R_IGNORE + && (rel->address + rel->addend + == reloc_vector[1]->address)); + + /* 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 -= (reloc_vector[1]->addend + - (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; + 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; + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + + ecoff_data (input_bfd)->symndx_to_section = symndx_to_section; + } + + sym_hashes = ecoff_data (input_bfd)->sym_hashes; + + gp = ecoff_data (output_bfd)->gp; + if (gp == 0) + gp_undefined = true; + else + gp_undefined = false; + + BFD_ASSERT (output_bfd->xvec->header_byteorder_big_p == false); + BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p == false); + + 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. It marks the + position of the second instruction to be altered by the + GPDISP reloc, but 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, and is also marked with an ALPHA_R_IGNORE + reloc. */ + { + unsigned long insn1, insn2; + + BFD_ASSERT (ext_rel + 1 < ext_rel_end + && (((ext_rel + 1)->r_bits[0] + & RELOC_BITS0_TYPE_LITTLE) + >> RELOC_BITS0_TYPE_SH_LITTLE) == ALPHA_R_IGNORE + && (bfd_h_get_64 (input_bfd, + (bfd_byte *) (ext_rel + 1)->r_vaddr) + == r_vaddr - input_section->vma + r_symndx)); + + /* 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. */ + ecoff_data (output_bfd)->gp = gp = 4; + 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; +} + +/* 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 + }, + /* 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 +}; + +/* 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, + false, /* data byte order is little */ + false, /* 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 (_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) &alpha_ecoff_backend_data +}; diff --git a/gnu/usr.bin/binutils/bfd/coff-apollo.c b/gnu/usr.bin/binutils/bfd/coff-apollo.c new file mode 100644 index 00000000000..23bbfc6cd7f --- /dev/null +++ b/gnu/usr.bin/binutils/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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-arm.c b/gnu/usr.bin/binutils/bfd/coff-arm.c new file mode 100644 index 00000000000..3946fef0f72 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-arm.c @@ -0,0 +1,537 @@ +/* BFD back-end for Intel 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, + false, /* data byte order is little */ + false, /* 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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-go32.c b/gnu/usr.bin/binutils/bfd/coff-go32.c new file mode 100644 index 00000000000..be4adb24f52 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/coff-h8300.c b/gnu/usr.bin/binutils/bfd/coff-h8300.c new file mode 100644 index 00000000000..84fcb0ce107 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-h8300.c @@ -0,0 +1,640 @@ +/* BFD back-end for Hitachi H8/300 COFF binaries. + Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Written by Steve Chamberlain, . + +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/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), + +}; + + +/* 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; + 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_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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-h8500.c b/gnu/usr.bin/binutils/bfd/coff-h8500.c new file mode 100644 index 00000000000..ccb9f5d3d18 --- /dev/null +++ b/gnu/usr.bin/binutils/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, . + +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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-i386.c b/gnu/usr.bin/binutils/bfd/coff-i386.c new file mode 100644 index 00000000000..cc23a3e022c --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-i386.c @@ -0,0 +1,491 @@ +/* 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; + 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, + false, /* data byte order is little */ + false, /* 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/gnu/usr.bin/binutils/bfd/coff-i860.c b/gnu/usr.bin/binutils/bfd/coff-i860.c new file mode 100644 index 00000000000..57dfd88ca89 --- /dev/null +++ b/gnu/usr.bin/binutils/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 , 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, + false, /* data byte order is little */ + false, /* 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/gnu/usr.bin/binutils/bfd/coff-i960.c b/gnu/usr.bin/binutils/bfd/coff-i960.c new file mode 100644 index 00000000000..ad8f6d10809 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-i960.c @@ -0,0 +1,661 @@ +/* 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 + +#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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (symesz); + if (esym == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + 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, + false, /* data byte order is little */ + false, /* 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, + false, /* data byte order is little */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-m68k.c b/gnu/usr.bin/binutils/bfd/coff-m68k.c new file mode 100644 index 00000000000..6922ef2b391 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-m68k.c @@ -0,0 +1,201 @@ +/* BFD back-end for Motorola 68000 COFF binaries. + Copyright 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. */ + +#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) + +/* The page size is a guess based on ELF. */ +#define COFF_PAGE_SIZE 0x2000 + +/* 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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-m88k.c b/gnu/usr.bin/binutils/bfd/coff-m88k.c new file mode 100644 index 00000000000..b981bc444a7 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-m88k.c @@ -0,0 +1,158 @@ +/* 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 void rtype2howto PARAMS ((arelent *, struct internal_reloc *)); + +#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3) + +#undef HOWTO_PREPARE +/* Provided the symbol, returns the value reffed */ +#define HOWTO_PREPARE(relocation, symbol) \ + { \ + if (symbol != (asymbol *)NULL) { \ + if (bfd_is_com_section (symbol->section)) { \ + relocation = 0; \ + } \ + else { \ + relocation = symbol->value; \ + } \ + } \ + if (symbol->section != (asection *)NULL) { \ + relocation += symbol->section->output_section->vma + \ + symbol->section->output_offset; \ + } \ +} + +static bfd_reloc_status_type +howto_hvrt16 (abfd, reloc_entry, symbol_in, data, + ignore_input_section, ignore_bfd, error_message) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol_in; + PTR data; + asection *ignore_input_section; + bfd *ignore_bfd; + char **error_message; +{ + 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) >> 16; + + bfd_put_16(abfd, x, (bfd_byte *)data + addr); + return bfd_reloc_ok; +} + + + +static reloc_howto_type howto_table[] = +{ + HOWTO(R_PCR16L,02,1,16,true, 0,complain_overflow_signed, 0, "PCR16L",false,0x0000ffff,0x0000ffff,true), + HOWTO(R_PCR26L,02,2,26,true, 0,complain_overflow_signed, 0, "PCR26L",false,0x03ffffff,0x03ffffff,true), + HOWTO(R_VRT16, 00,1,16,false,0,complain_overflow_bitfield, 0, "VRT16", false,0x0000ffff,0x0000ffff,true), + HOWTO(R_HVRT16,16,1,16,false,0,complain_overflow_dont,howto_hvrt16,"HVRT16",false,0x0000ffff,0x0000ffff,true), + HOWTO(R_LVRT16,00,1,16,false,0,complain_overflow_dont, 0, "LVRT16",false,0x0000ffff,0x0000ffff,true), + HOWTO(R_VRT32, 00,2,32,false,0,complain_overflow_bitfield, 0, "VRT32", false,0xffffffff,0xffffffff,true), +}; + + +/* 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 + + +/* 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; + cache_ptr->addend += dst->r_offset << 16; + } + else + { + BFD_ASSERT (0); + } +} + +#define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst) + +#define BADMAG(x) MC88BADMAG(x) +#include "coffcode.h" + +#undef coff_write_armap + +const bfd_target m88kbcs_vec = +{ + "coff-m88kbcs", /* name */ + bfd_target_coff_flavour, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-mips.c b/gnu/usr.bin/binutils/bfd/coff-mips.c new file mode 100644 index 00000000000..90b64317c34 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-mips.c @@ -0,0 +1,2610 @@ +/* BFD back-end for MIPS Extended-Coff files. + Copyright 1990, 1991, 1992, 1993, 1994 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 abfd->xvec->byteorder_big_p; + + case MIPS_MAGIC_LITTLE: + case MIPS_MAGIC_LITTLE2: + case MIPS_MAGIC_LITTLE3: + return abfd->xvec->byteorder_big_p == false; + + 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 (abfd->xvec->header_byteorder_big_p != false) + { + 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 (abfd->xvec->header_byteorder_big_p != false) + { + 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 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. */ + if (ecoff_data (output_bfd)->gp == 0 + && (relocateable == false + || (symbol->flags & BSF_SECTION_SYM) != 0)) + { + if (relocateable != false) + { + /* Make up a value. */ + ecoff_data (output_bfd)->gp = + symbol->section->output_section->vma + 0x4000; + } + 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) + { + ecoff_data (output_bfd)->gp = bfd_asymbol_value (*sym); + break; + } + } + } + + if (i >= count) + { + /* Only get the error once. */ + ecoff_data (output_bfd)->gp = 4; + *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 - ecoff_data (output_bfd)->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_big_p + == output_bfd->xvec->header_byteorder_big_p); + + /* 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = ecoff_data (output_bfd)->gp; + 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. */ + ecoff_data (output_bfd)->gp = gp = 4; + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 (abfd->xvec->header_byteorder_big_p) + { + 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 *) malloc ((size_t) sec->_raw_size); + if (contents == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 + }, + /* 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 +}; + +/* 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, + false, /* data byte order is little */ + false, /* 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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-pmac.c b/gnu/usr.bin/binutils/bfd/coff-pmac.c new file mode 100644 index 00000000000..f3332d98959 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/coff-ppc.c b/gnu/usr.bin/binutils/bfd/coff-ppc.c new file mode 100644 index 00000000000..94ef048546d --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-ppc.c @@ -0,0 +1,2346 @@ +/* BFD back-end for PowerPC Microsoft Portable Executable files. + Copyright 1990, 1991, 1992, 1993, 1994 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" + +/* 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. */ + ret->toc_offset = 1; + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 + + +/* 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 */ +}; + + + + +/* 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\n", \ + n, r->r_symndx, r->r_vaddr); \ +} + +#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 +}; + +struct list_ele +{ + struct list_ele *next; + bfd_vma addr; + int offset; + const char *name; +}; + +extern struct list_ele *head; +extern struct list_ele *tail; + +static void +record_toc(toc_section, our_toc_offset, name) + asection *toc_section; + int our_toc_offset; + const char *name; +{ + /* add this entry to our toc addr-offset-name list */ + struct list_ele *t; + t = malloc(sizeof(struct list_ele)); + t->next = 0; + t->offset = our_toc_offset; + t->name = name; + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + obj_coff_local_toc_table(abfd) = local_syms; + for (i = 0; i < obj_raw_syment_count(abfd); ++i) + local_syms[i] = 1; + } + + if (local_syms[sym] == 1) + { + local_syms[sym] = global_toc_size; + ret_val = global_toc_size; + global_toc_size += 4; +#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 (h->toc_offset == 1) + { + h->toc_offset = global_toc_size; + ret_val = global_toc_size; + global_toc_size += 4; +#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; +} + +/* 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_TOCREL16) + && (howto->type != IMAGE_REL_PPC_IMGLUE); +} + +/* 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 \n", + TARGET_LITTLE_NAME, + input_section->name); + +#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 + { + 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, section addr of %s %p\n", + bfd_of_toc_owner, TOC_SECTION_NAME, toc_section); +#endif + + if ( toc_section == NULL ) + { + fprintf(stderr, "No Toc section!\n"); + abort(); + } + } + +#if 0 + if ( r_flags & IMAGE_REL_PPC_TOCDEFN ) + { + /* Somehow, we are to assume that the toc has already been + done for this one, and the offset is the value of + the symbol? */ + fprintf(stderr, + "Symbol value %d\n", val); + } +#endif + + /* + * 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 ((our_toc_offset & 1) != 0) + { + /* if it has been written out, it is marked with the + 1 bit. Fix up our offset, but do not write it out + again. + */ + our_toc_offset &= ~1; +#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, 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); + + local_toc_table[symndx] |= 1; + fixit = true; + } + } + else + { + const char *name = h->root.root.root.string; + our_toc_offset = h->toc_offset; + + if ((our_toc_offset & 1) != 0) + { + /* if it has been written out, it is marked with the + 1 bit. Fix up our offset, but do not write it out + again. + */ + our_toc_offset &= ~1; +#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, 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); + + h->toc_offset |= 1; + /* 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; + + fprintf(stderr, + " Toc Section reloc candidate\n"); + + if (coff_data(output_bfd)->pe) + addr -= pe_data(output_bfd)->pe_opthdr.ImageBase; + fwrite (&addr, 1,4, (FILE *) info->base_file); + } + + + /* FIXME: this test is conservative */ + if (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 \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 \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 (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__"; + else + abort(); + + 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; + } + } + + rstat = _bfd_relocate_contents (howto, + input_bfd, + val - + pe_data(output_bfd)->pe_opthdr.ImageBase, + loc); + } + break; + + case IMAGE_REL_PPC_ADDR16: + case IMAGE_REL_PPC_REL24: + 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) + { + addr -= pe_data(output_bfd)->pe_opthdr.ImageBase; + fprintf(stderr, + " adjusted down to %d", addr); + } + fprintf(stderr, "\n"); + + 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))) + return false; + } + } + + } + + return true; +} + +#ifdef COFF_IMAGE_WITH_PE + +long int global_toc_size = 0; + +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; + +void +dump_toc(vfile) + void *vfile; +{ + FILE *file = vfile; + struct list_ele *t; + + fprintf(file, + " Offset Offset Name if present\n"); + + for(t = head; t != 0; t=t->next) + { + fprintf(file, + " %2x %04lx %s\n", + t->offset - 32768, t->offset, t->name); + } +} + +boolean +ppc_allocate_toc_section (info) + struct bfd_link_info *info; +{ + asection *s; + bfd_byte *foo; + static char test_char = '1'; + +#ifdef DEBUG_TOC + fprintf(stderr, + "ppc_allocate_toc_section: allocating %s section of size %d\n", + TOC_SECTION_NAME, global_toc_size); +#endif + + 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; + +#if 0 + 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;relreloc_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: + 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. + */ + + 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_TOCREL16: + 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); + break; + case IMAGE_REL_PPC_IMGLUE: + DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal); + break; + default: + fprintf(stderr, + "Warning: Unsupported reloc %s [%d] used -- it may not work.\n", + ppc_coff_howto_table[r_type].name, + r_type); + break; + } + + relent->howto = ppc_coff_howto_table + r_type; + +} + +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); + +fprintf(stderr, + "coff_ppc_rtype_to_howto\n"); + + /* 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; + break; + case IMAGE_REL_PPC_ADDR16: + case IMAGE_REL_PPC_REL24: + case IMAGE_REL_PPC_ADDR24: + case IMAGE_REL_PPC_TOCREL16: + 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); + break; + case IMAGE_REL_PPC_IMGLUE: + DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel); + break; + default: + fprintf(stderr, + "Warning: Unsupported reloc %s [%d] used -- it may not work.\n", + ppc_coff_howto_table[r_type].name, + r_type); + break; + } + + howto = ppc_coff_howto_table + r_type; + 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_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_32, IMAGE_REL_PPC_ADDR32); + HOW2MAP(BFD_RELOC_RVA, IMAGE_REL_PPC_ADDR32NB); + default: + fprintf(stderr, + "\treturning NULL\n"); + 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 + +#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 +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 0 + if (bfd_of_toc_owner != 0) /* we already have a toc, so go home */ + return; +#endif + + 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 + + + +/* 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, + false, /* data byte order is little */ + false, /* 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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-rs6000.c b/gnu/usr.bin/binutils/bfd/coff-rs6000.c new file mode 100644 index 00000000000..3a4db943be0 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-rs6000.c @@ -0,0 +1,1413 @@ +/* BFD back-end for IBM RS/6000 "XCOFF" files. + Copyright 1990, 1991, 1992, 1993, 1994, 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. */ + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + + 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->toc_section == NULL) + ox->toc_section = NULL; + else + ox->toc_section = ix->toc_section->output_section; + if (ix->entry_section == NULL) + ox->entry_section = NULL; + else + ox->entry_section = ix->entry_section->output_section; + 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 "\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 + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-sh.c b/gnu/usr.bin/binutils/bfd/coff-sh.c new file mode 100644 index 00000000000..fe17bf895f9 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coff-sh.c @@ -0,0 +1,1540 @@ +/* BFD back-end for Hitachi Super-H COFF binaries. + Copyright 1993, 1994, 1995 Free Software Foundation, Inc. + Contributed by Cygnus Support. + Written by Steve Chamberlain, . + +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 *) malloc (sec->_raw_size); + if (contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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); + 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 *) malloc (o->_raw_size); + if (ocontents == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc (obj_raw_syment_count (input_bfd) + * sizeof (struct internal_syment))); + if (internal_syms == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + sections = (asection **) malloc (obj_raw_syment_count (input_bfd) + * sizeof (asection *)); + if (sections == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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, + true, /* data byte order is big */ + true, /* 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, + false, /* data byte order is little */ + false, /* 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/gnu/usr.bin/binutils/bfd/coff-sparc.c b/gnu/usr.bin/binutils/bfd/coff-sparc.c new file mode 100644 index 00000000000..5625ded0cd6 --- /dev/null +++ b/gnu/usr.bin/binutils/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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-u68k.c b/gnu/usr.bin/binutils/bfd/coff-u68k.c new file mode 100644 index 00000000000..97ea73fa9c6 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/coff-w65.c b/gnu/usr.bin/binutils/bfd/coff-w65.c new file mode 100644 index 00000000000..a6b960002cf --- /dev/null +++ b/gnu/usr.bin/binutils/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, . + +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, + false, /* data byte order is big */ + false, /* 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_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/gnu/usr.bin/binutils/bfd/coff-we32k.c b/gnu/usr.bin/binutils/bfd/coff-we32k.c new file mode 100644 index 00000000000..64aee85186a --- /dev/null +++ b/gnu/usr.bin/binutils/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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coff-z8k.c b/gnu/usr.bin/binutils/bfd/coff-z8k.c new file mode 100644 index 00000000000..ac0bb0e83d5 --- /dev/null +++ b/gnu/usr.bin/binutils/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, . + +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, + true, /* data byte order is big */ + true, /* 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/gnu/usr.bin/binutils/bfd/coffcode.h b/gnu/usr.bin/binutils/bfd/coffcode.h new file mode 100644 index 00000000000..ac5dba9a0ef --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coffcode.h @@ -0,0 +1,3463 @@ +/* Support for the generic parts of most COFF variants, for BFD. + Copyright 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. */ + +/* +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 + (<> 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 + <> field of the @code{asymbol}'s + @code{asection} @xref{Sections}. + + o <> + + 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 <> + + 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 <> is described in a + <>: + +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)); +. +.} 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)) +. +*/ + +/* 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; + + 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) +} +#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) + { + bfd_set_error (bfd_error_no_memory); + 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; + if (internal_a->o_sntoc == 0) + xcoff->toc_section = NULL; + else + xcoff->toc_section = + coff_section_from_bfd_index (abfd, internal_a->o_sntoc); + if (internal_a->o_snentry == 0) + xcoff->entry_section = NULL; + else + xcoff->entry_section = + coff_section_from_bfd_index (abfd, 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; + } + 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; +} + +#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. + +*/ + +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 = s->orelocation; + 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; + } + } + + 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; + 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 (abfd->xvec->byteorder_big_p) + *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 (abfd->xvec->byteorder_big_p) + *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 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 + { + /* 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; + +} + +#ifndef RS6000COFF_C + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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 /* ! defined (RS6000COFF_C) */ + + + +/* 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 . */ + if (strcmp (current->name, _LIB) == 0) + section.s_vaddr = 0; + else +#endif + section.s_vaddr = current->lma; + 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, §ion, &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 (!abfd->xvec->byteorder_big_p) + 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 (PAGEMAGICPEXECPAGED) + internal_a.magic = PAGEMAGICPEXECPAGED; +#endif +#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; +#ifndef RS6000COFF_C + 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; + + if (xcoff_data (abfd)->entry_section != NULL) + internal_a.o_snentry = xcoff_data (abfd)->entry_section->target_index; + else + { + internal_a.o_snentry = 0; + if (internal_a.entry == 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; + if (xcoff_data (abfd)->toc_section == NULL) + internal_a.o_sntoc = 0; + else + internal_a.o_sntoc = xcoff_data (abfd)->toc_section->target_index; + + 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 + /* 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 SVR3.2. Shared libraries should probably get more + generic support. Ian Taylor . */ + if (strcmp (section->name, _LIB) == 0) + ++section->lma; +#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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } /* on error */ + table_ptr = ((unsigned int *) + bfd_alloc (abfd, + (obj_raw_syment_count (abfd) + * sizeof (unsigned int)))); + + if (table_ptr == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 +#define coff_bfd_link_add_symbols _bfd_generic_link_add_symbols +#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 + +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 +}; + +#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/gnu/usr.bin/binutils/bfd/coffgen.c b/gnu/usr.bin/binutils/bfd/coffgen.c new file mode 100644 index 00000000000..9be641f9db0 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/coffgen.c @@ -0,0 +1,2167 @@ +/* Support for the generic parts of COFF, for BFD. + Copyright 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. */ + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + + /* s_paddr is presumed to be = to s_vaddr */ + + return_section->vma = hdr->s_vaddr; + return_section->lma = return_section->vma; + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (sec->reloc_count * relsz); + if (free_external == NULL && sec->reloc_count > 0) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc (sec->reloc_count + * sizeof (struct internal_reloc))); + if (free_internal == NULL && sec->reloc_count > 0) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + bfd_ptr->outsymbols = newsyms; + for (i = 0; i < symbol_count; i++) + if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0 + || (!bfd_is_und_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) + && ((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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + bfd_coff_swap_sym_out (abfd, &native->u.syment, buf); + if (bfd_write (buf, 1, symesz, abfd) != symesz) + return false; + bfd_release (abfd, buf); + + if (native->u.syment.n_numaux > 0) + { + bfd_size_type auxesz; + unsigned int j; + + auxesz = bfd_coff_auxesz (abfd); + buf = bfd_alloc (abfd, auxesz); + if (!buf) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + for (j = 0; j < native->u.syment.n_numaux; j++) + { + bfd_coff_swap_aux_out (abfd, + &((native + j + 1)->u.auxent), + type, + class, + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + for (s = abfd->sections; s != (asection *) NULL; s = s->next) + { + if (s->lineno_count) + { + asymbol **q = abfd->outsymbols; + 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; +} + +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; +} + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = malloc (size); + if (syms == NULL && size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 = malloc (strsize); + if (strings == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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_alloc (abfd, size); + if (internal == NULL && size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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); + internal_ptr->fix_value = 0; + internal_ptr->fix_tag = 0; + internal_ptr->fix_end = 0; + internal_ptr->fix_scnlen = 0; + symbol_ptr = internal_ptr; + + for (i = 0; + i < symbol_ptr->u.syment.n_numaux; + i++) + { + internal_ptr++; + raw_src += symesz; + + internal_ptr->fix_value = 0; + internal_ptr->fix_tag = 0; + internal_ptr->fix_end = 0; + internal_ptr->fix_scnlen = 0; + bfd_coff_swap_aux_in (abfd, (PTR) raw_src, + symbol_ptr->u.syment.n_type, + symbol_ptr->u.syment.n_sclass, + i, symbol_ptr->u.syment.n_numaux, + &(internal_ptr->u.auxent)); + 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) + { + bfd_set_error (bfd_error_no_memory); + return (NULL); + } /* on error */ + 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) + { + bfd_set_error (bfd_error_no_memory); + return (NULL); + } /* on error */ + memset (new, 0, sizeof *new); + new->symbol.section = 0; + new->native = 0; + new->lineno = (alent *) NULL; + 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) + { + bfd_set_error (bfd_error_no_memory); + return (NULL); + } /* on error */ + /* @@ This shouldn't be using a constant multiplier. */ + new->native = (combined_entry_type *) bfd_zalloc (abfd, sizeof (combined_entry_type) * 10); + if (!new->native) + { + bfd_set_error (bfd_error_no_memory); + return (NULL); + } /* on error */ + new->symbol.section = bfd_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, ignore_symbols, offset, filename_ptr, + functionname_ptr, line_ptr) + bfd *abfd; + asection *section; + asymbol **ignore_symbols; + bfd_vma offset; + CONST char **filename_ptr; + CONST char **functionname_ptr; + unsigned int *line_ptr; +{ + 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; + + *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; + } + + l = §ion->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->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/gnu/usr.bin/binutils/bfd/cofflink.c b/gnu/usr.bin/binutils/bfd/cofflink.c new file mode 100644 index 00000000000..2c0953c3d10 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/cofflink.c @@ -0,0 +1,2489 @@ +/* COFF specific linker code. + Copyright 1994, 1995 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" + +#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, 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; +}; + +static struct bfd_hash_entry *coff_debug_merge_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +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 *)); +static boolean coff_link_input_bfd + PARAMS ((struct coff_final_link_info *, bfd *)); +static boolean coff_write_global_sym + PARAMS ((struct coff_link_hash_entry *, PTR)); +static boolean coff_reloc_link_order + PARAMS ((bfd *, struct coff_final_link_info *, asection *, + struct bfd_link_order *)); + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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. */ + +static struct bfd_hash_entry * +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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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_generic_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) + { + bfd_set_error (bfd_error_no_memory); + 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_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]; + + 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 *) + malloc ((abfd->section_count + 1) + * sizeof (struct coff_link_section_info))); + if (finfo.section_info == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc (o->reloc_count * sizeof (struct internal_reloc))); + finfo.section_info[o->target_index].rel_hashes = + ((struct coff_link_hash_entry **) + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc (max_sym_count + * sizeof (struct internal_syment))); + finfo.sec_ptrs = (asection **) malloc (max_sym_count * sizeof (asection *)); + finfo.sym_indices = (long *) malloc (max_sym_count * sizeof (long)); + finfo.outsyms = ((bfd_byte *) + malloc ((size_t) ((max_sym_count + 1) * symesz))); + finfo.linenos = (bfd_byte *) malloc (max_lineno_count + * bfd_coff_linesz (abfd)); + finfo.contents = (bfd_byte *) malloc (max_contents_size); + finfo.external_relocs = (bfd_byte *) malloc (max_reloc_count * relsz); + if (! info->relocateable) + finfo.internal_relocs = ((struct internal_reloc *) + 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)) + { + bfd_set_error (bfd_error_no_memory); + 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 (! 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 (! 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 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), coff_write_global_sym, + (PTR) &finfo); + if (finfo.failed) + goto error_return; + + /* The outsyms buffer is used by 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 *) malloc (max_output_reloc_count * relsz); + if (external_relocs == NULL) + { + 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 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 , 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 = malloc ((size_t) sec->_raw_size); + if (!copy) + { + bfd_set_error (bfd_error_no_memory); + 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. */ + +static boolean +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; + struct coff_debug_merge_type *mtl; + + 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 == bfd_get_symbol_leading_char (input_bfd) + && (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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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. */ + 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 + && 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. */ + +static boolean +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. */ + +static boolean +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) + { + bfd_set_error (bfd_error_no_memory); + 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 = coff_link_hash_lookup (coff_hash_table (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/gnu/usr.bin/binutils/bfd/coffswap.h b/gnu/usr.bin/binutils/bfd/coffswap.h new file mode 100644 index 00000000000..ef1b6b3a913 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/config.bfd b/gnu/usr.bin/binutils/bfd/config.bfd new file mode 100644 index 00000000000..2b385d1b714 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/config.bfd @@ -0,0 +1,464 @@ +# 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) + 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* | i[345]86-*-freebsd*) + targ_defvec=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-*-win32 | 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* | m68*-cbm-*) + 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*-*-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 + ;; + + 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*) + targ_defvec=bfd_powerpcle_pe_vec + targ_selvecs="bfd_powerpcle_pei_vec bfd_powerpc_pei_vec bfd_powerpcle_pe_vec bfd_powerpc_pe_vec" + ;; + + powerpc-*-pe | powerpc-*-winnt*) + targ_defvec=bfd_powerpc_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-*-solaris2* | sparc-*-sysv4*) + targ_defvec=bfd_elf32_sparc_vec + targ_selvecs=sunos_big_vec + ;; + sparc64-*-aout*) + targ_defvec=sunos_big_vec + targ_underscore=yes + ;; + sparc64-*-elf* | sparc64-*-sysv4* | sparc64-*-solaris2*) + targ_defvec=bfd_elf64_sparc_vec + targ_selvecs=bfd_elf32_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/gnu/usr.bin/binutils/bfd/config.in b/gnu/usr.bin/binutils/bfd/config.in new file mode 100644 index 00000000000..d993fbca61c --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/config.in @@ -0,0 +1,58 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Do we need to use the b modifier when opening binary files? */ +#undef USE_BINARY_FOPEN + +/* Whether malloc must be declared even if is included. */ +#undef NEED_DECLARATION_MALLOC + +/* Whether free must be declared even if is included. */ +#undef NEED_DECLARATION_FREE + +/* Name of host specific header file to include in trad-core.c. */ +#undef TRAD_HEADER + +/* Define only if 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 header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H diff --git a/gnu/usr.bin/binutils/bfd/configure b/gnu/usr.bin/binutils/bfd/configure new file mode 100644 index 00000000000..adb5e46e008 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/configure @@ -0,0 +1,2005 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.4 +# 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 + --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 + +# 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.4" + 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 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 + + + +# Check whether --enable-64-bit-bfd or --disable-64-bit-bfd was given. +enableval="$enable_64_bit_bfd" +if test -n "$enableval"; then + 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. +enableval="$enable_targets" +if test -n "$enableval"; then + 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 --with-mmap or --without-mmap was given. +withval="$with_mmap" +if test -n "$withval"; then + 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 '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," + + +host64=false +target64=false + +# host stuff: + +# Permit host specific settings. +. ${srcdir}/configure.host + +echo $ac_n "checking for CC""... $ac_c" 1>&6 +test -z "$CC" && test -r ../Makefile && CC=`egrep '^CC *=' ../Makefile | tail -1 | sed 's/^CC *= *//'` +test -z "$CC" && CC=cc +echo "$ac_t""setting CC to $CC" 1>&6 + +cat > conftest.c <&5 | egrep yes >/dev/null 2>&1; then + GCC=yes + if test "${CFLAGS+set}" != set; then + echo 'void f(){}' > conftest.c + if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + CFLAGS="-g -O" + else + CFLAGS="-O" + fi + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi +rm -f conftest* + + + +# Extract the first word of "ar", so it can be a program name with args. +set dummy 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="ar" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_AR" && ac_cv_prog_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 "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 + +# 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' + + +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 </dev/null; then + ac_cv_c_cross=no +else + ac_cv_c_cross=yes +fi +fi +rm -fr conftest* +fi +cross_compiling=$ac_cv_c_cross +echo "$ac_t""$ac_cv_c_cross" 1>&6 + +# 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 < +Syntax Error +EOF +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +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 < +Syntax Error +EOF +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +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 +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +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 '[a-z]./\055' '[A-Z]___'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in fcntl.h sys/file.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 +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +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 '[a-z]./\055' '[A-Z]___'` + cat >> confdefs.h <&6 +fi +done + +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 < +/* 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 $ac_link; 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 '[a-z]' '[A-Z]'` + cat >> confdefs.h <&6 +fi +done + + +case "${host}" in +i[345]86-*-msdos* | i[345]86-*-go32* | i[345]86-*-win32) + 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 < +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +int main() { return 0; } +int t() { +char *(*pfn) = (char *(*)) malloc +; return 0; } +EOF +if eval $ac_compile; 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 + cat >> confdefs.h <<\EOF +#define NEED_DECLARATION_MALLOC 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 < +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +int main() { return 0; } +int t() { +int (*pfn) = (int (*)) free +; return 0; } +EOF +if eval $ac_compile; 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 + cat >> confdefs.h <<\EOF +#define NEED_DECLARATION_FREE 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=trad-core.o + cat >> confdefs.h <<\EOF +#define TRAD_HEADER "hosts/i386nbsd.h" +EOF + + ;; + 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=trad-core.o + cat >> confdefs.h <<\EOF +#define TRAD_HEADER "hosts/mipsnbsd.h" +EOF + + ;; + 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*-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=trad-core.o + cat >> confdefs.h <<\EOF +#define TRAD_HEADER "hosts/m68knbsd.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=trad-core.o + cat >> confdefs.h <<\EOF +#define TRAD_HEADER "hosts/ns32knbsd.h" +EOF + + ;; + 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=trad-core.o + cat >> confdefs.h <<\EOF +#define TRAD_HEADER "hosts/sparcnbsd.h" +EOF + + ;; + 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 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 < +int main() { return 0; } +int t() { +prstatus_t t; +; return 0; } +EOF +if eval $ac_compile; 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 stab-syms.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 stab-syms.o" ;; + aout_arm_big_vec) tb="$tb aout-arm.o aout32.o stab-syms.o" ;; + aout_arm_little_vec) tb="$tb aout-arm.o aout32.o stab-syms.o" ;; + aout_mips_big_vec) tb="$tb mipsbsd.o aout32.o stab-syms.o" ;; + aout_mips_little_vec) tb="$tb mipsbsd.o aout32.o stab-syms.o" ;; + apollocoff_vec) tb="$tb coff-apollo.o" ;; + b_out_vec_big_host) tb="$tb bout.o aout32.o stab-syms.o" ;; + b_out_vec_little_host) tb="$tb bout.o aout32.o stab-syms.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 stab-syms.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 stab-syms.o" ;; + hp300bsd_vec) tb="$tb hp300bsd.o aout32.o stab-syms.o" ;; + hp300hpux_vec) tb="$tb hp300hpux.o aout32.o stab-syms.o" ;; + i386aout_vec) tb="$tb i386aout.o aout32.o stab-syms.o" ;; + i386bsd_vec) tb="$tb i386bsd.o aout32.o stab-syms.o" ;; + i386dynix_vec) tb="$tb i386dynix.o aout32.o stab-syms.o" ;; + i386coff_vec) tb="$tb coff-i386.o cofflink.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 stab-syms.o" ;; + i386lynx_aout_vec) tb="$tb i386lynx.o lynx-core.o aout32.o stab-syms.o" ;; + i386lynx_coff_vec) tb="$tb cf-i386lynx.o cofflink.o lynx-core.o stab-syms.o" ;; + i386mach3_vec) tb="$tb i386mach3.o aout32.o stab-syms.o" ;; + i386netbsd_vec) tb="$tb i386netbsd.o aout32.o stab-syms.o" ;; + i386os9k_vec) tb="$tb i386os9k.o aout32.o stab-syms.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" ;; + m68klynx_aout_vec) tb="$tb m68klynx.o lynx-core.o aout32.o stab-syms.o" ;; + m68klynx_coff_vec) tb="$tb cf-m68klynx.o coff-m68k.o cofflink.o lynx-core.o stab-syms.o" ;; + m68knetbsd_vec) tb="$tb m68knetbsd.o aout32.o stab-syms.o" ;; + m68k4knetbsd_vec) tb="$tb m68k4knetbsd.o aout32.o stab-syms.o" ;; + m88kbcs_vec) tb="$tb coff-m88k.o" ;; + newsos3_vec) tb="$tb newsos3.o aout32.o stab-syms.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 stab-syms.o" ;; + nlm32_powerpc_vec) tb="$tb nlm32-ppc.o nlm32.o nlm.o" ;; + pc532netbsd_vec) tb="$tb ns32knetbsd.o aout-ns32k.o stab-syms.o" ;; + pc532machaout_vec) tb="$tb pc532-mach.o aout-ns32k.o stab-syms.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 stab-syms.o" ;; + sparclynx_coff_vec) tb="$tb cf-sparclynx.o lynx-core.o stab-syms.o" ;; + sparcnetbsd_vec) tb="$tb sparcnetbsd.o aout32.o stab-syms.o" ;; + sparccoff_vec) tb="$tb coff-sparc.o" ;; + srec_vec) tb="$tb srec.o" ;; + sunos_big_vec) tb="$tb sunos.o aout32.o stab-syms.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}'" + + +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 < +#include +#include + +#ifdef BSD +# ifndef BSD4_1 +# define HAVE_GETPAGESIZE +# endif +#endif + +#ifndef HAVE_GETPAGESIZE +# include +# 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 + +#ifdef __osf__ +# 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 = getpagesize()*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 $ac_link +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 < +/* 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 $ac_link; 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 '[a-z]' '[A-Z]'` + cat >> confdefs.h <&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 </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.4" + 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 + +# 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%@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%@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 <> $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 <> $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/gnu/usr.bin/binutils/bfd/configure.bat b/gnu/usr.bin/binutils/bfd/configure.bat new file mode 100644 index 00000000000..78fe79e9112 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/configure.host b/gnu/usr.bin/binutils/bfd/configure.host new file mode 100644 index 00000000000..41af344620c --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/configure.host @@ -0,0 +1,86 @@ +# 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: +# CC compiler to use (only if needed and not already set) +# CFLAGS override CFLAGS (only if needed and not already set) +# LDFLAGS override LDFLAGS (only if needed and not already set) +# AR archiver to use (only if needed and not already set) +# RANLIB ranlib to use (only if needed and not already set) +# HDEFINES host specific compiler options +# host64 set to true if this is a 64 bit host +# HOST_64BIT_TYPE host 64 bit type + +HDEFINES= +host64=false +HOST_64BIT_TYPE= + +case "${host}" in +# 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. +# +# Note that these entries cannot be fully alphabetical. Don't try. +# The order of matching is critical when multiple lines could match. + +alpha-*-*) host64=true; HOST_64BIT_TYPE=long ;; + +a29k-*-*) CC=${CC-u3cc}; AR=${AR-u3ar} ;; + +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 ;; +i[345]86-ncr*-sysv4*) CC=${CC-/usr/ccs/ATT/cc} + test -z "$CFLAGS" && CFLAGS=" " + ;; +i[345]86-*-go32*) test -z "$CC" && CC="i386-go32-gcc -fno-omit-frame-pointer -O2 -Wl,-S" + AR=${AR-i386-go32-ar} + RANLIB=${RANLIB-i386-go32-ranlib} + ;; +i[345]86-*-win32) test -z "$CC" && CC="i386-win32-gcc -O2" + AR=${AR-i386-win32-ar} + RANLIB=${RANLIB-i386-win32-ranlib} + ;; + +mips-dec-netbsd*) ;; +mips-dec-*) HDEFINES="-G 4" ;; +mips-sgi-irix3*) HDEFINES="-G 4" + test -z "$LDFLAGS" && LDFLAGS=-lmalloc + ;; +mips-sgi-irix4*) HDEFINES="-G 4" + test -z "$LDFLAGS" && LDFLAGS=-lmalloc + ;; +mips-*-sysv4*) ;; +mips-*-sysv*) HDEFINES="-G 4" ;; +mips-*-riscos*) HDEFINES="-G 4" ;; + +m68*-apollo*-sysv*) # sef@cygnus.com says this is how to compile + # on an apollo in the SysV environment. + test -z "$CC" && CC="cc -A nansi -A cpu,3000 -A runtype,any -A systype,any -DSHORT_ENUM_BUG -DUSG -U__STDC__ -Dm68000=mc68000" + ;; +m68*-hp-hpux*) HDEFINES=-DHOST_HP300HPUX ;; + +m88*-*-dgux*) test -z "$CC" && CC="gcc -Wall -ansi -D__using_DGUX" + ;; + +romp-*-*) # hc/pcc just can't cut it + CC=${CC-gcc} + ;; + +rs6000-*-aix4) HDEFINES=-DHOST_AIX ;; +rs6000-*-*) HDEFINES=-DHOST_AIX ;; +powerpc-*-aix4*) HDEFINES=-DHOST_AIX ;; +powerpc-*-aix*) HDEFINES=-DHOST_AIX ;; + +esac diff --git a/gnu/usr.bin/binutils/bfd/configure.in b/gnu/usr.bin/binutils/bfd/configure.in new file mode 100644 index 00000000000..8d649011eaf --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/configure.in @@ -0,0 +1,544 @@ +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_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: + +# Permit host specific settings. +. ${srcdir}/configure.host + +AC_PROG_CC +AC_SUBST(CFLAGS) +AC_SUBST(HDEFINES) +AC_CHECK_PROG(AR, ar, ar, :) +AC_PROG_RANLIB +AC_PROG_INSTALL + +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) +AC_CHECK_FUNCS(fcntl getpagesize) + +BFD_BINARY_FOPEN + +AC_MSG_CHECKING([whether malloc must be declared]) +AC_CACHE_VAL(bfd_cv_decl_needed_malloc, +[AC_TRY_COMPILE([ +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif], +[char *(*pfn) = (char *(*)) malloc], +bfd_cv_decl_needed_malloc=no, bfd_cv_decl_needed_malloc=yes)]) +AC_MSG_RESULT($bfd_cv_decl_needed_malloc) +if test $bfd_cv_decl_needed_malloc = yes; then + AC_DEFINE(NEED_DECLARATION_MALLOC) +fi + +AC_MSG_CHECKING([whether free must be declared]) +AC_CACHE_VAL(bfd_cv_decl_needed_free, +[AC_TRY_COMPILE([ +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif], +[int (*pfn) = (int (*)) free], +bfd_cv_decl_needed_free=no, bfd_cv_decl_needed_free=yes)]) +AC_MSG_RESULT($bfd_cv_decl_needed_free) +if test $bfd_cv_decl_needed_free = yes; then + AC_DEFINE(NEED_DECLARATION_FREE) +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 + 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=trad-core.o + AC_DEFINE(TRAD_HEADER,"hosts/i386nbsd.h") + ;; +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=trad-core.o + AC_DEFINE(TRAD_HEADER,"hosts/mipsnbsd.h") + ;; + 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*-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=trad-core.o + AC_DEFINE(TRAD_HEADER,"hosts/m68knbsd.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=trad-core.o + AC_DEFINE(TRAD_HEADER,"hosts/ns32knbsd.h") + ;; + 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=trad-core.o + AC_DEFINE(TRAD_HEADER,"hosts/sparcnbsd.h") + ;; + 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 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 ], + [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 stab-syms.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 stab-syms.o" ;; + aout_arm_big_vec) tb="$tb aout-arm.o aout32.o stab-syms.o" ;; + aout_arm_little_vec) tb="$tb aout-arm.o aout32.o stab-syms.o" ;; + aout_mips_big_vec) tb="$tb mipsbsd.o aout32.o stab-syms.o" ;; + aout_mips_little_vec) tb="$tb mipsbsd.o aout32.o stab-syms.o" ;; + apollocoff_vec) tb="$tb coff-apollo.o" ;; + b_out_vec_big_host) tb="$tb bout.o aout32.o stab-syms.o" ;; + b_out_vec_little_host) tb="$tb bout.o aout32.o stab-syms.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 stab-syms.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 stab-syms.o" ;; + hp300bsd_vec) tb="$tb hp300bsd.o aout32.o stab-syms.o" ;; + hp300hpux_vec) tb="$tb hp300hpux.o aout32.o stab-syms.o" ;; + i386aout_vec) tb="$tb i386aout.o aout32.o stab-syms.o" ;; + i386bsd_vec) tb="$tb i386bsd.o aout32.o stab-syms.o" ;; + i386dynix_vec) tb="$tb i386dynix.o aout32.o stab-syms.o" ;; + i386coff_vec) tb="$tb coff-i386.o cofflink.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 stab-syms.o" ;; + i386lynx_aout_vec) tb="$tb i386lynx.o lynx-core.o aout32.o stab-syms.o" ;; + i386lynx_coff_vec) tb="$tb cf-i386lynx.o cofflink.o lynx-core.o stab-syms.o" ;; + i386mach3_vec) tb="$tb i386mach3.o aout32.o stab-syms.o" ;; + i386netbsd_vec) tb="$tb i386netbsd.o aout32.o stab-syms.o" ;; + i386os9k_vec) tb="$tb i386os9k.o aout32.o stab-syms.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" ;; + m68klynx_aout_vec) tb="$tb m68klynx.o lynx-core.o aout32.o stab-syms.o" ;; + m68klynx_coff_vec) tb="$tb cf-m68klynx.o coff-m68k.o cofflink.o lynx-core.o stab-syms.o" ;; + m68knetbsd_vec) tb="$tb m68knetbsd.o aout32.o stab-syms.o" ;; + m68k4knetbsd_vec) tb="$tb m68k4knetbsd.o aout32.o stab-syms.o" ;; + m88kbcs_vec) tb="$tb coff-m88k.o" ;; + newsos3_vec) tb="$tb newsos3.o aout32.o stab-syms.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 stab-syms.o" ;; + nlm32_powerpc_vec) tb="$tb nlm32-ppc.o nlm32.o nlm.o" ;; + pc532netbsd_vec) tb="$tb ns32knetbsd.o aout-ns32k.o stab-syms.o" ;; + pc532machaout_vec) tb="$tb pc532-mach.o aout-ns32k.o stab-syms.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 stab-syms.o" ;; + sparclynx_coff_vec) tb="$tb cf-sparclynx.o lynx-core.o stab-syms.o" ;; + sparcnetbsd_vec) tb="$tb sparcnetbsd.o aout32.o stab-syms.o" ;; + sparccoff_vec) tb="$tb coff-sparc.o" ;; + srec_vec) tb="$tb srec.o" ;; + sunos_big_vec) tb="$tb sunos.o aout32.o stab-syms.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/gnu/usr.bin/binutils/bfd/corefile.c b/gnu/usr.bin/binutils/bfd/corefile.c new file mode 100644 index 00000000000..212f519ce8a --- /dev/null +++ b/gnu/usr.bin/binutils/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 <> if the core file attached to @var{core_bfd} + was generated by a run of the executable file attached to + @var{exec_bfd}, <> otherwise. +*/ +boolean +core_file_matches_executable_p (core_bfd, exec_bfd) + bfd *core_bfd, *exec_bfd; +{ + if ((core_bfd->format != bfd_core) || (exec_bfd->format != bfd_object)) { + bfd_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/gnu/usr.bin/binutils/bfd/cpu-a29k.c b/gnu/usr.bin/binutils/bfd/cpu-a29k.c new file mode 100644 index 00000000000..5bd25a47720 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-alpha.c b/gnu/usr.bin/binutils/bfd/cpu-alpha.c new file mode 100644 index 00000000000..0d66a8b74e8 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-arm.c b/gnu/usr.bin/binutils/bfd/cpu-arm.c new file mode 100644 index 00000000000..92103e632f0 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-h8300.c b/gnu/usr.bin/binutils/bfd/cpu-h8300.c new file mode 100644 index 00000000000..380dfb5556e --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-h8500.c b/gnu/usr.bin/binutils/bfd/cpu-h8500.c new file mode 100644 index 00000000000..e4abfd17807 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-hppa.c b/gnu/usr.bin/binutils/bfd/cpu-hppa.c new file mode 100644 index 00000000000..5201008dfe1 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-i386.c b/gnu/usr.bin/binutils/bfd/cpu-i386.c new file mode 100644 index 00000000000..404109033b7 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-i860.c b/gnu/usr.bin/binutils/bfd/cpu-i860.c new file mode 100644 index 00000000000..57c867cdb2c --- /dev/null +++ b/gnu/usr.bin/binutils/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 , 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/gnu/usr.bin/binutils/bfd/cpu-i960.c b/gnu/usr.bin/binutils/bfd/cpu-i960.c new file mode 100644 index 00000000000..f8a2bf1cd4b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/cpu-i960.c @@ -0,0 +1,156 @@ +/* BFD library support routines for the i960 architecture. + 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" + + +/* 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 + 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 + 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 MAX_ARCH ((int)CA) + + + + static CONST unsigned long matrix[MAX_ARCH+1][MAX_ARCH+1] = + { + { ERROR, CORE, KA, KB, MC, XA, CA }, + { CORE, CORE, KA, KB, MC, XA, CA }, + { KA, KA, KA, KB, MC, XA, ERROR }, + { KB, KB, KB, KB, MC, XA, ERROR }, + { MC, MC, MC, MC, MC, XA, ERROR }, + { XA, XA, XA, XA, XA, XA, ERROR }, + { CA, CA, ERROR, ERROR, ERROR, ERROR, CA }, + }; + + + 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,} + +#define LAST 0 + + +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, LAST), +}; + +const bfd_arch_info_type bfd_i960_arch = + N(bfd_mach_i960_core, "i960:core", true, &arch_info_struct[0]); diff --git a/gnu/usr.bin/binutils/bfd/cpu-m68k.c b/gnu/usr.bin/binutils/bfd/cpu-m68k.c new file mode 100644 index 00000000000..17a37391675 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-m88k.c b/gnu/usr.bin/binutils/bfd/cpu-m88k.c new file mode 100644 index 00000000000..c3716c5a394 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-mips.c b/gnu/usr.bin/binutils/bfd/cpu-mips.c new file mode 100644 index 00000000000..5e1934210a2 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-ns32k.c b/gnu/usr.bin/binutils/bfd/cpu-ns32k.c new file mode 100644 index 00000000000..e18e3cfc9ba --- /dev/null +++ b/gnu/usr.bin/binutils/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 + 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 + 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 + */ + +#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/gnu/usr.bin/binutils/bfd/cpu-powerpc.c b/gnu/usr.bin/binutils/bfd/cpu-powerpc.c new file mode 100644 index 00000000000..02464d62f3b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/cpu-powerpc.c @@ -0,0 +1,124 @@ +/* BFD PowerPC CPU definition + Copyright (C) 1994 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, + &arch_info_struct[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, + 0 + }; diff --git a/gnu/usr.bin/binutils/bfd/cpu-rs6000.c b/gnu/usr.bin/binutils/bfd/cpu-rs6000.c new file mode 100644 index 00000000000..9852ae9a053 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-sh.c b/gnu/usr.bin/binutils/bfd/cpu-sh.c new file mode 100644 index 00000000000..7f6dd68ba04 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-sparc.c b/gnu/usr.bin/binutils/bfd/cpu-sparc.c new file mode 100644 index 00000000000..8c5438bcdb7 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/cpu-sparc.c @@ -0,0 +1,54 @@ +/* BFD support for the SPARC architecture. + Copyright 1992, 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" + +static const bfd_arch_info_type sparc_arch_info = + { + 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 */ + bfd_default_compatible, + bfd_default_scan, + 0, + }; + +const bfd_arch_info_type bfd_sparc_arch = + { + 64, /* bits in a word */ + 64, /* bits in an address */ + 8, /* bits in a byte */ + bfd_arch_sparc, + bfd_mach_sparc64, + "sparc", + "sparc64", + 3, + false, + bfd_default_compatible, + bfd_default_scan, + &sparc_arch_info, + }; diff --git a/gnu/usr.bin/binutils/bfd/cpu-vax.c b/gnu/usr.bin/binutils/bfd/cpu-vax.c new file mode 100644 index 00000000000..bdc6d39e451 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-w65.c b/gnu/usr.bin/binutils/bfd/cpu-w65.c new file mode 100644 index 00000000000..c0bbf045219 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-we32k.c b/gnu/usr.bin/binutils/bfd/cpu-we32k.c new file mode 100644 index 00000000000..a38cbc1268b --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/cpu-z8k.c b/gnu/usr.bin/binutils/bfd/cpu-z8k.c new file mode 100644 index 00000000000..5cce8eb0689 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/demo64.c b/gnu/usr.bin/binutils/bfd/demo64.c new file mode 100644 index 00000000000..c91381d46e9 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/dep-in.sed b/gnu/usr.bin/binutils/bfd/dep-in.sed new file mode 100644 index 00000000000..1cbd786fb2e --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/doc/ChangeLog b/gnu/usr.bin/binutils/bfd/doc/ChangeLog new file mode 100644 index 00000000000..44e3afe6165 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/ChangeLog @@ -0,0 +1,262 @@ +Fri Nov 3 14:46:48 1995 Fred Fish + + * 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 + + * chew.c: Include . + +Fri Oct 6 16:23:34 1995 Ken Raeburn + + Mon Sep 25 22:49:32 1995 Andreas Schwab + + * Makefile.in (Makefile): Only remake this Makefile. + +Wed Oct 4 15:51:05 1995 Ken Raeburn + + * chew.c: Include . + +Tue Sep 12 18:14:50 1995 Ian Lance Taylor + + * Makefile.in (maintainer-clean): New target. + +Thu Aug 31 12:18:43 1995 Ian Lance Taylor + + * 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 + + * 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/gnu/usr.bin/binutils/bfd/doc/Makefile.in b/gnu/usr.bin/binutils/bfd/doc/Makefile.in new file mode 100644 index 00000000000..49619bd03e2 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/Makefile.in @@ -0,0 +1,308 @@ +# +# 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 \ + $(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 \ + $(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 \ + $(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/gnu/usr.bin/binutils/bfd/doc/bfd.texinfo b/gnu/usr.bin/binutils/bfd/doc/bfd.texinfo new file mode 100644 index 00000000000..424bb0e0f8b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/doc/bfd.texinfo @@ -0,0 +1,348 @@ +\input texinfo.tex +@setfilename bfd.info +@c $Id: bfd.texinfo,v 1.1.1.1 1996/01/08 11:05:17 niklas 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.1.1.1 $} % 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/gnu/usr.bin/binutils/bfd/doc/bfdsumm.texi b/gnu/usr.bin/binutils/bfd/doc/bfdsumm.texi new file mode 100644 index 00000000000..844531aff8c --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/doc/chew.c b/gnu/usr.bin/binutils/bfd/doc/chew.c new file mode 100644 index 00000000000..5c04404f7a6 --- /dev/null +++ b/gnu/usr.bin/binutils/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: + : ; + +*/ + +/* 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 <> 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 +#include "sysdep.h" +#include +#include +#include + +#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 <> 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\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/gnu/usr.bin/binutils/bfd/doc/doc.str b/gnu/usr.bin/binutils/bfd/doc/doc.str new file mode 100644 index 00000000000..93685996e06 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/doc/proto.str b/gnu/usr.bin/binutils/bfd/doc/proto.str new file mode 100644 index 00000000000..8431c16bd57 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/ecoff.c b/gnu/usr.bin/binutils/bfd/ecoff.c new file mode 100644 index 00000000000..0b121eae816 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/ecoff.c @@ -0,0 +1,4784 @@ +/* Generic ECOFF (Extended-COFF) routines. + Copyright 1990, 1991, 1992, 1993, 1994, 1995 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + 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 abfd->xvec->byteorder_big_p ? 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 (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)) + { + 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) + 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) malloc ((size_t) external_hdr_size); + if (raw == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1 + || (bfd_read (raw, external_hdr_size, 1, abfd) + != external_hdr_size)) + goto error_return; + internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; + (*backend->debug_swap.swap_hdr_in) (abfd, raw, internal_symhdr); + + if (internal_symhdr->magic != backend->debug_swap.sym_magic) + { + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + + /* Now we can get the correct number of symbols. */ + bfd_get_symcount (abfd) = (internal_symhdr->isymMax + + internal_symhdr->iextMax); + + if (raw != NULL) + free (raw); + return true; + error_return: + if (raw != NULL) + free (raw); + return false; +} + +/* Read in and swap the important symbolic information for an ECOFF + object file. This is called by gdb via the read_debug_info entry + point in the backend structure. */ + +/*ARGSUSED*/ +boolean +_bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug) + bfd *abfd; + asection *ignore; + struct ecoff_debug_info *debug; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + HDRR *internal_symhdr; + bfd_size_type raw_base; + bfd_size_type raw_size; + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + reloc_chain->relent.sym_ptr_ptr = + bfd_get_section (asym)->symbol_ptr_ptr; + reloc_chain->relent.address = section->_raw_size; + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = ""; + else if (indx == indexNil) + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0) + return false; + if (bfd_read (external_relocs, 1, external_relocs_size, abfd) + != external_relocs_size) + 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; + 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; + + /* If we're not in the .text section, we don't have any line + numbers. */ + if (strcmp (section->name, _TEXT) != 0 + || offset >= bfd_section_size (abfd, section)) + return false; + + /* 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) + { + bfd_set_error (bfd_error_no_memory); + 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 **) malloc (abfd->section_count + * sizeof (asection *)); + if (sorted_hdrs == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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]; + + /* Only deal with sections which have contents */ + if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0) + continue; + + /* For the Alpha ECOFF .pdata section the lnnoptr field is + supposed to indicate the number of .pdata entries that are + really in the section. Each entry is 8 bytes. We store this + away in line_filepos before increasing the section size. */ + if (strcmp (current->name, _PDATA) != 0) + alignment_power = current->alignment_power; + else + { + current->line_filepos = current->_raw_size / 8; + alignment_power = 4; + } + + /* On Ultrix, the data sections in an executable file must be + aligned to a page boundary within the file. This does not + affect the section size, though. FIXME: Does this work for + other platforms? It requires some modification for the + Alpha, because .rdata on the Alpha goes with the text, not + the data. */ + if ((abfd->flags & EXEC_P) != 0 + && (abfd->flags & D_PAGED) != 0 + && first_data != false + && (current->flags & SEC_CODE) == 0 + && (! ecoff_backend (abfd)->rdata_in_text + || strcmp (current->name, _RDATA) != 0) + && strcmp (current->name, _PDATA) != 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; + + 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 . */ + 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) malloc ((size_t) siz); + if (buff == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + } + + internal_f.f_nscns = 0; + if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0) + 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 = vma; + 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) §ion, 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) + { + 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 (! abfd->xvec->byteorder_big_p) + 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) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + reloc_ptr_ptr = current->orelocation; + reloc_end = reloc_ptr_ptr + current->reloc_count; + out_ptr = (char *) reloc_buff; + for (; + reloc_ptr_ptr < reloc_end; + reloc_ptr_ptr++, out_ptr += external_reloc_size) + { + arelent *reloc; + asymbol *sym; + struct internal_reloc in; + + memset ((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 + 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) + ^ (abfd->xvec->header_byteorder_big_p != false)) + || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN) + ^ (abfd->xvec->byteorder_big_p != false))) + { + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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] = + (abfd->xvec->header_byteorder_big_p + ? ARMAP_BIG_ENDIAN + : ARMAP_LITTLE_ENDIAN); + hdr.ar_name[ARMAP_OBJECT_MARKER_INDEX] = ARMAP_MARKER; + hdr.ar_name[ARMAP_OBJECT_ENDIAN_INDEX] = + abfd->xvec->byteorder_big_p ? 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return (const bfd_target *) NULL; + } + + bfd_ardata (abfd)->first_file_filepos = SARMAG; + bfd_ardata (abfd)->cache = NULL; + bfd_ardata (abfd)->archive_head = NULL; + bfd_ardata (abfd)->symdefs = NULL; + bfd_ardata (abfd)->extended_names = NULL; + bfd_ardata (abfd)->tdata = NULL; + + if (_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) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct ecoff_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + + if (ret) + { + /* Set local fields. */ + ret->indx = -1; + ret->abfd = NULL; + ret->written = 0; + ret->small = 0; + } + memset ((PTR) &ret->esym, 0, sizeof ret->esym); + + return (struct bfd_hash_entry *) ret; +} + +/* Create an ECOFF link hash table. */ + +struct bfd_link_hash_table * +_bfd_ecoff_bfd_link_hash_table_create (abfd) + bfd *abfd; +{ + struct ecoff_link_hash_table *ret; + + ret = ((struct ecoff_link_hash_table *) + bfd_alloc (abfd, sizeof (struct ecoff_link_hash_table))); + if (ret == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + if (! _bfd_link_hash_table_init (&ret->root, abfd, + ecoff_link_hash_newfunc)) + { + free (ret); + return (struct bfd_link_hash_table *) NULL; + } + return &ret->root; +} + +/* Look up an entry in an ECOFF link hash table. */ + +#define ecoff_link_hash_lookup(table, string, create, copy, follow) \ + ((struct ecoff_link_hash_entry *) \ + bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow))) + +/* Traverse an ECOFF link hash table. */ + +#define ecoff_link_hash_traverse(table, func, info) \ + (bfd_link_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \ + (info))) + +/* Get the ECOFF link hash table from the info structure. This is + just a cast. */ + +#define ecoff_hash_table(p) ((struct ecoff_link_hash_table *) ((p)->hash)) + +/* Given an ECOFF BFD, add symbols to the global hash table as + appropriate. */ + +boolean +_bfd_ecoff_bfd_link_add_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + switch (bfd_get_format (abfd)) + { + case bfd_object: + return ecoff_link_add_object_symbols (abfd, info); + case bfd_archive: + return ecoff_link_add_archive_symbols (abfd, info); + default: + bfd_set_error (bfd_error_wrong_format); + return false; + } +} + +/* Add the symbols from an archive file to the global hash table. + This looks through the undefined symbols, looks each one up in the + archive hash table, and adds any associated object file. We do not + use _bfd_generic_link_add_archive_symbols because ECOFF archives + already have a hash table, so there is no reason to construct + another one. */ + +static boolean +ecoff_link_add_archive_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + const bfd_byte *raw_armap; + struct bfd_link_hash_entry **pundef; + unsigned int armap_count; + unsigned int armap_log; + unsigned int i; + const bfd_byte *hashtable; + const char *stringbase; + + if (! bfd_has_map (abfd)) + { + /* 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 = _bfd_get_elt_at_filepos (abfd, file_offset); + if (element == (bfd *) NULL) + return false; + + if (! bfd_check_format (element, bfd_object)) + return false; + + /* Unlike the generic linker, we know that this element provides + a definition for an undefined symbol and we know that we want + to include it. We don't need to check anything. */ + if (! (*info->callbacks->add_archive_element) (info, element, name)) + return false; + if (! ecoff_link_add_object_symbols (element, info)) + return false; + + pundef = &(*pundef)->next; + } + + return true; +} + +/* This is called if we used _bfd_generic_link_add_archive_symbols + because we were not dealing with an ECOFF archive. */ + +static boolean +ecoff_link_check_archive_element (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) + = backend->debug_swap.swap_ext_in; + HDRR *symhdr; + bfd_size_type external_ext_size; + PTR external_ext = NULL; + size_t esize; + char *ssext = NULL; + char *ext_ptr; + char *ext_end; + + *pneeded = false; + + if (! ecoff_slurp_symbolic_header (abfd)) + goto error_return; + + /* If there are no symbols, we don't want it. */ + if (bfd_get_symcount (abfd) == 0) + goto successful_return; + + symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; + + /* Read in the external symbols and external strings. */ + external_ext_size = backend->debug_swap.external_ext_size; + esize = symhdr->iextMax * external_ext_size; + external_ext = (PTR) malloc (esize); + if (external_ext == NULL && esize != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbExtOffset, SEEK_SET) != 0 + || bfd_read (external_ext, 1, esize, abfd) != esize) + goto error_return; + + ssext = (char *) malloc (symhdr->issExtMax); + if (ssext == NULL && symhdr->issExtMax != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0 + || (bfd_read (ssext, 1, symhdr->issExtMax, abfd) != + (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: + def = true; + break; + default: + def = false; + break; + } + + if (! def) + continue; + + name = ssext + esym.asym.iss; + h = bfd_link_hash_lookup (info->hash, name, false, false, true); + + /* Unlike the generic linker, we do not pull in elements because + of common symbols. */ + if (h == (struct bfd_link_hash_entry *) NULL + || h->type != bfd_link_hash_undefined) + continue; + + /* Include this element. */ + if (! (*info->callbacks->add_archive_element) (info, abfd, name)) + goto error_return; + if (! ecoff_link_add_externals (abfd, info, external_ext, ssext)) + goto error_return; + + *pneeded = true; + goto successful_return; + } + + successful_return: + if (external_ext != NULL) + free (external_ext); + if (ssext != NULL) + free (ssext); + return true; + error_return: + if (external_ext != NULL) + free (external_ext); + if (ssext != NULL) + free (ssext); + return false; +} + +/* Add symbols from an ECOFF object file to the global linker hash + table. */ + +static boolean +ecoff_link_add_object_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + HDRR *symhdr; + bfd_size_type external_ext_size; + PTR external_ext = NULL; + size_t esize; + char *ssext = NULL; + boolean result; + + if (! ecoff_slurp_symbolic_header (abfd)) + return false; + + /* If there are no symbols, we don't want it. */ + if (bfd_get_symcount (abfd) == 0) + return true; + + symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; + + /* Read in the external symbols and external strings. */ + external_ext_size = ecoff_backend (abfd)->debug_swap.external_ext_size; + esize = symhdr->iextMax * external_ext_size; + external_ext = (PTR) malloc (esize); + if (external_ext == NULL && esize != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbExtOffset, SEEK_SET) != 0 + || bfd_read (external_ext, 1, esize, abfd) != esize) + goto error_return; + + ssext = (char *) malloc (symhdr->issExtMax); + if (ssext == NULL && symhdr->issExtMax != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0 + || (bfd_read (ssext, 1, symhdr->issExtMax, abfd) + != (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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + ecoff_data (abfd)->sym_hashes = sym_hash; + + ext_ptr = (char *) external_ext; + ext_end = ext_ptr + ext_count * external_ext_size; + for (; ext_ptr < ext_end; ext_ptr += external_ext_size, sym_hash++) + { + EXTR esym; + boolean skip; + bfd_vma value; + asection *section; + const char *name; + struct ecoff_link_hash_entry *h; + + *sym_hash = NULL; + + (*swap_ext_in) (abfd, (PTR) ext_ptr, &esym); + + /* Skip debugging symbols. */ + skip = false; + switch (esym.asym.st) + { + case stGlobal: + case stStatic: + case stLabel: + case stProc: + case stStaticProc: + break; + default: + skip = true; + break; + } + + if (skip) + continue; + + /* Get the information for this symbol. */ + value = esym.asym.value; + switch (esym.asym.sc) + { + default: + case scNil: + case scRegister: + case scCdbLocal: + case scBits: + case scCdbSystem: + case scRegImage: + case scInfo: + case scUserStruct: + case scVar: + case scVarRegister: + case scVariant: + case scBasedVar: + case scXData: + case scPData: + section = NULL; + break; + case scText: + section = bfd_make_section_old_way (abfd, ".text"); + value -= section->vma; + break; + case scData: + section = bfd_make_section_old_way (abfd, ".data"); + value -= section->vma; + break; + case scBss: + section = bfd_make_section_old_way (abfd, ".bss"); + value -= section->vma; + break; + case scAbs: + section = bfd_abs_section_ptr; + break; + case scUndefined: + section = bfd_und_section_ptr; + break; + case scSData: + section = bfd_make_section_old_way (abfd, ".sdata"); + value -= section->vma; + break; + case scSBss: + section = bfd_make_section_old_way (abfd, ".sbss"); + value -= section->vma; + break; + case scRData: + section = bfd_make_section_old_way (abfd, ".rdata"); + value -= section->vma; + break; + case scCommon: + if (value > ecoff_data (abfd)->gp_size) + { + section = bfd_com_section_ptr; + break; + } + /* Fall through. */ + case scSCommon: + if (ecoff_scom_section.name == NULL) + { + /* Initialize the small common section. */ + ecoff_scom_section.name = SCOMMON; + ecoff_scom_section.flags = SEC_IS_COMMON; + ecoff_scom_section.output_section = &ecoff_scom_section; + ecoff_scom_section.symbol = &ecoff_scom_symbol; + ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr; + ecoff_scom_symbol.name = SCOMMON; + ecoff_scom_symbol.flags = BSF_SECTION_SYM; + ecoff_scom_symbol.section = &ecoff_scom_section; + ecoff_scom_symbol_ptr = &ecoff_scom_symbol; + } + section = &ecoff_scom_section; + break; + case scSUndefined: + section = bfd_und_section_ptr; + break; + case scInit: + section = bfd_make_section_old_way (abfd, ".init"); + value -= section->vma; + break; + case scFini: + section = bfd_make_section_old_way (abfd, ".fini"); + value -= section->vma; + break; + } + + if (section == (asection *) NULL) + continue; + + name = ssext + esym.asym.iss; + + h = NULL; + if (! (_bfd_generic_link_add_one_symbol + (info, abfd, name, + 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 *)); + +/* ECOFF final link routine. This looks through all the input BFDs + and gathers together all the debugging information, and then + processes all the link order information. This may cause it to + close and reopen some input BFDs; I'll see how bad this is. */ + +boolean +_bfd_ecoff_bfd_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; + HDRR *symhdr; + PTR handle; + register bfd *input_bfd; + asection *o; + struct bfd_link_order *p; + + /* We accumulate the debugging information counts in the symbolic + header. */ + symhdr = &debug->symbolic_header; + symhdr->vstamp = 0; + symhdr->ilineMax = 0; + symhdr->cbLine = 0; + symhdr->idnMax = 0; + symhdr->ipdMax = 0; + symhdr->isymMax = 0; + symhdr->ioptMax = 0; + symhdr->iauxMax = 0; + symhdr->issMax = 0; + symhdr->issExtMax = 0; + symhdr->ifdMax = 0; + symhdr->crfd = 0; + symhdr->iextMax = 0; + + /* We accumulate the debugging information itself in the debug_info + structure. */ + debug->line = NULL; + debug->external_dnr = NULL; + debug->external_pdr = NULL; + debug->external_sym = NULL; + debug->external_opt = NULL; + debug->external_aux = NULL; + debug->ss = NULL; + debug->ssext = debug->ssext_end = NULL; + debug->external_fdr = NULL; + debug->external_rfd = NULL; + debug->external_ext = debug->external_ext_end = NULL; + + handle = bfd_ecoff_debug_init (abfd, debug, &backend->debug_swap, info); + if (handle == (PTR) NULL) + return false; + + /* Accumulate the debugging symbols from each input BFD. */ + for (input_bfd = info->input_bfds; + input_bfd != (bfd *) NULL; + input_bfd = input_bfd->link_next) + { + boolean ret; + + if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour) + { + /* Abitrarily set the symbolic header vstamp to the vstamp + of the first object file in the link. */ + if (symhdr->vstamp == 0) + symhdr->vstamp + = ecoff_data (input_bfd)->debug_info.symbolic_header.vstamp; + ret = ecoff_final_link_debug_accumulate (abfd, input_bfd, info, + handle); + } + else + ret = bfd_ecoff_debug_accumulate_other (handle, abfd, + debug, &backend->debug_swap, + input_bfd, info); + if (! ret) + return false; + + /* Combine the register masks. */ + ecoff_data (abfd)->gprmask |= ecoff_data (input_bfd)->gprmask; + ecoff_data (abfd)->fprmask |= ecoff_data (input_bfd)->fprmask; + ecoff_data (abfd)->cprmask[0] |= ecoff_data (input_bfd)->cprmask[0]; + ecoff_data (abfd)->cprmask[1] |= ecoff_data (input_bfd)->cprmask[1]; + ecoff_data (abfd)->cprmask[2] |= ecoff_data (input_bfd)->cprmask[2]; + ecoff_data (abfd)->cprmask[3] |= ecoff_data (input_bfd)->cprmask[3]; + } + + /* Write out the external symbols. */ + ecoff_link_hash_traverse (ecoff_hash_table (info), + ecoff_link_write_external, + (PTR) abfd); + + if (info->relocateable) + { + /* We need to make a pass over the link_orders to count up the + number of relocations we will need to output, so that we know + how much space they will take up. */ + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + o->reloc_count = 0; + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + if (p->type == bfd_indirect_link_order) + o->reloc_count += p->u.indirect.section->reloc_count; + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + ++o->reloc_count; + } + } + + /* Compute the reloc and symbol file positions. */ + ecoff_compute_reloc_file_positions (abfd); + + /* Write out the debugging information. */ + if (! bfd_ecoff_write_accumulated_debug (handle, abfd, debug, + &backend->debug_swap, info, + ecoff_data (abfd)->sym_filepos)) + return false; + + bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info); + + if (info->relocateable) + { + /* Now reset the reloc_count field of the sections in the output + BFD to 0, so that we can use them to keep track of how many + relocs we have output thus far. */ + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + o->reloc_count = 0; + } + + /* Get a value for the GP register. */ + if (ecoff_data (abfd)->gp == 0) + { + struct bfd_link_hash_entry *h; + + h = bfd_link_hash_lookup (info->hash, "_gp", false, false, true); + if (h != (struct bfd_link_hash_entry *) NULL + && h->type == bfd_link_hash_defined) + ecoff_data (abfd)->gp = (h->u.def.value + + h->u.def.section->output_section->vma + + h->u.def.section->output_offset); + else if (info->relocateable) + { + bfd_vma lo; + + /* Make up a value. */ + lo = (bfd_vma) -1; + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + if (o->vma < lo + && (strcmp (o->name, _SBSS) == 0 + || strcmp (o->name, _SDATA) == 0 + || strcmp (o->name, _LIT4) == 0 + || strcmp (o->name, _LIT8) == 0 + || strcmp (o->name, _LITA) == 0)) + lo = o->vma; + } + ecoff_data (abfd)->gp = lo + 0x8000; + } + else + { + /* If the relocate_section function needs to do a reloc + involving the GP value, it should make a reloc_dangerous + callback to warn that GP is not defined. */ + } + } + + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + { + if (p->type == bfd_indirect_link_order + && (bfd_get_flavour (p->u.indirect.section->owner) + == bfd_target_ecoff_flavour)) + { + if (! ecoff_indirect_link_order (abfd, info, o, p)) + return false; + } + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + { + if (! ecoff_reloc_link_order (abfd, info, o, p)) + return false; + } + else + { + if (! _bfd_default_link_order (abfd, info, o, p)) + return false; + } + } + } + + bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax; + + ecoff_data (abfd)->linker = true; + + return true; +} + +/* Accumulate the debugging information for an input BFD into the + output BFD. This must read in the symbolic information of the + input BFD. */ + +static boolean +ecoff_final_link_debug_accumulate (output_bfd, input_bfd, info, handle) + bfd *output_bfd; + bfd *input_bfd; + struct bfd_link_info *info; + PTR handle; +{ + struct ecoff_debug_info * const debug = &ecoff_data (input_bfd)->debug_info; + const struct ecoff_debug_swap * const swap = + &ecoff_backend (input_bfd)->debug_swap; + HDRR *symhdr = &debug->symbolic_header; + boolean ret; + +#define READ(ptr, offset, count, size, type) \ + if (symhdr->count == 0) \ + debug->ptr = NULL; \ + else \ + { \ + debug->ptr = (type) malloc ((size_t) (size * symhdr->count)); \ + if (debug->ptr == NULL) \ + { \ + bfd_set_error (bfd_error_no_memory); \ + ret = false; \ + goto return_something; \ + } \ + if ((bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) \ + != 0) \ + || (bfd_read (debug->ptr, size, symhdr->count, \ + input_bfd) != size * symhdr->count)) \ + { \ + ret = false; \ + goto return_something; \ + } \ + } + + /* If raw_syments is not NULL, then the data was already by read by + _bfd_ecoff_slurp_symbolic_info. */ + if (ecoff_data (input_bfd)->raw_syments == NULL) + { + READ (line, cbLineOffset, cbLine, sizeof (unsigned char), + unsigned char *); + READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR); + READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR); + READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR); + READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR); + READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext), + union aux_ext *); + READ (ss, cbSsOffset, issMax, sizeof (char), char *); + READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR); + READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR); + } +#undef READ + + /* We do not read the external strings or the external symbols. */ + + ret = (bfd_ecoff_debug_accumulate + (handle, output_bfd, &ecoff_data (output_bfd)->debug_info, + &ecoff_backend (output_bfd)->debug_swap, + input_bfd, debug, swap, info)); + + return_something: + if (ecoff_data (input_bfd)->raw_syments == NULL) + { + if (debug->line != NULL) + free (debug->line); + if (debug->external_dnr != NULL) + free (debug->external_dnr); + if (debug->external_pdr != NULL) + free (debug->external_pdr); + if (debug->external_sym != NULL) + free (debug->external_sym); + if (debug->external_opt != NULL) + free (debug->external_opt); + if (debug->external_aux != NULL) + free (debug->external_aux); + if (debug->ss != NULL) + free (debug->ss); + if (debug->external_fdr != NULL) + free (debug->external_fdr); + if (debug->external_rfd != NULL) + free (debug->external_rfd); + + /* Make sure we don't accidentally follow one of these pointers + into freed memory. */ + debug->line = NULL; + debug->external_dnr = NULL; + debug->external_pdr = NULL; + debug->external_sym = NULL; + debug->external_opt = NULL; + debug->external_aux = NULL; + debug->ss = NULL; + debug->external_fdr = NULL; + debug->external_rfd = NULL; + } + + return ret; +} + +/* Put out information for an external symbol. These come only from + the hash table. */ + +static boolean +ecoff_link_write_external (h, data) + struct ecoff_link_hash_entry *h; + PTR data; +{ + bfd *output_bfd = (bfd *) data; + + /* FIXME: We should check if this symbol is being stripped. */ + + if (h->written) + return true; + + if (h->abfd == (bfd *) NULL) + { + h->esym.jmptbl = 0; + h->esym.cobol_main = 0; + h->esym.weakext = 0; + h->esym.reserved = 0; + h->esym.ifd = ifdNil; + h->esym.asym.value = 0; + h->esym.asym.st = stGlobal; + + if (h->root.type != bfd_link_hash_defined + && h->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 + 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 *) malloc (raw_size >= cooked_size + ? (size_t) raw_size + : (size_t) cooked_size); + if (contents == NULL && raw_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + /* If we are relaxing, the contents may have already been read into + memory, in which case we copy them into our new buffer. We don't + simply reuse the old buffer in case cooked_size > raw_size. */ + if (section_tdata != (struct ecoff_section_tdata *) NULL + && section_tdata->contents != (bfd_byte *) NULL) + memcpy (contents, section_tdata->contents, (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) malloc ((size_t) external_relocs_size); + if (external_relocs == NULL && external_relocs_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 + || (bfd_read (external_relocs, 1, external_relocs_size, input_bfd) + != external_relocs_size)) + goto error_return; + } + + /* Relocate the section contents. */ + if (! ((*ecoff_backend (input_bfd)->relocate_section) + (output_bfd, info, input_bfd, input_section, contents, + external_relocs))) + goto error_return; + + /* Write out the relocated section. */ + if (! bfd_set_section_contents (output_bfd, + output_section, + (PTR) contents, + input_section->output_offset, + cooked_size)) + goto error_return; + + /* If we are producing relocateable output, the relocs were + modified, and we write them out now. We use the reloc_count + field of output_section to keep track of the number of relocs we + have output so far. */ + if (info->relocateable) + { + if (bfd_seek (output_bfd, + (output_section->rel_filepos + + output_section->reloc_count * external_reloc_size), + SEEK_SET) != 0 + || (bfd_write (external_relocs, 1, external_relocs_size, output_bfd) + != external_relocs_size)) + goto error_return; + output_section->reloc_count += input_section->reloc_count; + } + + if (contents != NULL) + free (contents); + if (external_relocs != NULL && section_tdata == NULL) + free (external_relocs); + return true; + + error_return: + if (contents != NULL) + free (contents); + if (external_relocs != NULL && section_tdata == NULL) + free (external_relocs); + return false; +} + +/* Generate a reloc when linking an ECOFF file. This is a reloc + requested by the linker, and does come from any input file. This + is used to build constructor and destructor tables when linking + with -Ur. */ + +static boolean +ecoff_reloc_link_order (output_bfd, info, output_section, link_order) + bfd *output_bfd; + struct bfd_link_info *info; + asection *output_section; + struct bfd_link_order *link_order; +{ + 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_link_hash_lookup (info->hash, 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = ecoff_link_hash_lookup (ecoff_hash_table (info), + link_order->u.reloc.p->u.name, + false, false, true); + if (h != (struct ecoff_link_hash_entry *) NULL + && h->indx != -1) + in.r_symndx = h->indx; + else + { + if (! ((*info->callbacks->unattached_reloc) + (info, link_order->u.reloc.p->u.name, (bfd *) NULL, + (asection *) NULL, (bfd_vma) 0))) + return false; + in.r_symndx = 0; + } + in.r_extern = 1; + } + else + { + CONST char *name; + + name = bfd_get_section_name (output_bfd, section); + if (strcmp (name, ".text") == 0) + in.r_symndx = RELOC_SECTION_TEXT; + else if (strcmp (name, ".rdata") == 0) + in.r_symndx = RELOC_SECTION_RDATA; + else if (strcmp (name, ".data") == 0) + in.r_symndx = RELOC_SECTION_DATA; + else if (strcmp (name, ".sdata") == 0) + in.r_symndx = RELOC_SECTION_SDATA; + else if (strcmp (name, ".sbss") == 0) + in.r_symndx = RELOC_SECTION_SBSS; + else if (strcmp (name, ".bss") == 0) + in.r_symndx = RELOC_SECTION_BSS; + else if (strcmp (name, ".init") == 0) + in.r_symndx = RELOC_SECTION_INIT; + else if (strcmp (name, ".lit8") == 0) + in.r_symndx = RELOC_SECTION_LIT8; + else if (strcmp (name, ".lit4") == 0) + in.r_symndx = RELOC_SECTION_LIT4; + else if (strcmp (name, ".xdata") == 0) + in.r_symndx = RELOC_SECTION_XDATA; + else if (strcmp (name, ".pdata") == 0) + in.r_symndx = RELOC_SECTION_PDATA; + else if (strcmp (name, ".fini") == 0) + in.r_symndx = RELOC_SECTION_FINI; + else if (strcmp (name, ".lita") == 0) + in.r_symndx = RELOC_SECTION_LITA; + else if (strcmp (name, "*ABS*") == 0) + in.r_symndx = RELOC_SECTION_ABS; + else + abort (); + in.r_extern = 0; + } + + /* Let the BFD backend adjust the reloc. */ + (*ecoff_backend (output_bfd)->adjust_reloc_out) (output_bfd, &rel, &in); + + /* Get some memory and swap out the reloc. */ + external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size; + rbuf = (bfd_byte *) malloc ((size_t) external_reloc_size); + if (rbuf == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + (*ecoff_backend (output_bfd)->swap_reloc_out) (output_bfd, &in, (PTR) rbuf); + + ok = (bfd_seek (output_bfd, + (output_section->rel_filepos + + output_section->reloc_count * external_reloc_size), + SEEK_SET) == 0 + && (bfd_write ((PTR) rbuf, 1, external_reloc_size, output_bfd) + == external_reloc_size)); + + if (ok) + ++output_section->reloc_count; + + free (rbuf); + + return ok; +} diff --git a/gnu/usr.bin/binutils/bfd/ecofflink.c b/gnu/usr.bin/binutils/bfd/ecofflink.c new file mode 100644 index 00000000000..8b248d8a78c --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/ecofflink.c @@ -0,0 +1,2490 @@ +/* Routines to link ECOFF debugging information. + Copyright 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. */ + +#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; + } + if (*buf == NULL) + newbuf = (char *) malloc (have + want); + else + newbuf = (char *) realloc (*buf, have + want); + if (newbuf == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (sizeof (struct accumulate)); + if (!ainfo) + { + bfd_set_error (bfd_error_no_memory); + 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); + +#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 *) malloc (strlen (name) + 20); + if (lookup == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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_big_p + == input_bfd->xvec->header_byteorder_big_p) + && 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) + { + bfd_set_error (bfd_error_no_memory); + 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) malloc ((size_t) swap->external_hdr_size); + if (buff == NULL && swap->external_hdr_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (i); + if (s == NULL && i != 0) + { + bfd_set_error (bfd_error_no_memory); + 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) malloc (ainfo->largest_file_shuffle); + if (space == NULL && ainfo->largest_file_shuffle != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (i); + if (s == NULL && i != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (i); + if (s == NULL && i != 0) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (len); + if (buffer == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/ecoffswap.h b/gnu/usr.bin/binutils/bfd/ecoffswap.h new file mode 100644 index 00000000000..4fa9c29c1cb --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/ecoffswap.h @@ -0,0 +1,830 @@ +/* Generic ECOFF swapping routines, for BFD. + Copyright 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. */ + +/* 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 *)); + +/* 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); + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 (abfd->xvec->header_byteorder_big_p != false) + { + 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 (abfd->xvec->header_byteorder_big_p != false) + { + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 (abfd->xvec->header_byteorder_big_p != false) { + 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 (abfd->xvec->header_byteorder_big_p != false) + { + 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 (abfd->xvec->header_byteorder_big_p != false, + &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 (abfd->xvec->header_byteorder_big_p != false) + { + 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 (abfd->xvec->header_byteorder_big_p != false, + &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/gnu/usr.bin/binutils/bfd/elf-bfd.h b/gnu/usr.bin/binutils/bfd/elf-bfd.h new file mode 100644 index 00000000000..a1abadad2bc --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elf-bfd.h @@ -0,0 +1,725 @@ +/* BFD back-end data structures for ELF files. + Copyright (C) 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. */ + +#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; + + /* 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 +}; + +/* 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. */ + size_t 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. */ + size_t 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)); +}; + +#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; + + /* 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)); + + /* A function to create any special program headers required by the + backend. PHDRS are the program headers, and PHDR_COUNT is the + number of them. If PHDRS is NULL, this just counts headers + without creating them. This returns an updated value for + PHDR_COUNT. */ + int (*elf_backend_create_program_headers) + PARAMS ((bfd *, Elf_Internal_Phdr *phdrs, int phdr_count)); + + /* 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; + + /* Put ELF and program headers in the first loadable segment. */ + unsigned want_hdr_in_seg : 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; +}; + +#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) + +/* 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 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; + + /* The linker ELF emulation code needs to let the backend ELF linker + know what filename should be used for a dynamic object if the + dynamic object is found using a search. This field is used to + hold that information. */ + const char *dt_needed_name; + + /* Irix 5 often screws up the symbol table, sorting local symbols + after global symbols. This flag is set if the symbol table in + this BFD appears to be screwed up. If it is, we ignore the + sh_info field in the symbol table header, and always read all the + symbols. */ + boolean bad_symtab; + + /* Records the result of `get_program_header_size'. */ + bfd_size_type program_header_size; + + /* 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 by PowerPC to determine if the e_flags field has been intiialized */ + boolean ppc_flags_init; +}; + +#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_dt_needed_name(bfd) (elf_tdata(bfd) -> dt_needed_name) +#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab) +#define elf_ppc_flags_init(bfd) (elf_tdata(bfd) -> ppc_flags_init) + +extern char * bfd_elf_string_from_elf_section PARAMS ((bfd *, unsigned, unsigned)); +extern char * bfd_elf_get_str_section PARAMS ((bfd *, unsigned)); + +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 *)); + +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 Elf32_External_Dyn *, Elf_Internal_Dyn *)); +extern void bfd_elf32_swap_dyn_out + PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf32_External_Dyn *)); +extern boolean bfd_elf32_add_dynamic_entry + PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma)); +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 Elf64_External_Dyn *, Elf_Internal_Dyn *)); +extern void bfd_elf64_swap_dyn_out + PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf64_External_Dyn *)); +extern boolean bfd_elf64_add_dynamic_entry + PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma)); +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/gnu/usr.bin/binutils/bfd/elf.c b/gnu/usr.bin/binutils/bfd/elf.c new file mode 100644 index 00000000000..e52ad75e1a7 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elf.c @@ -0,0 +1,2887 @@ +/* ELF 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. */ + +/* + +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 file_ptr map_program_segments PARAMS ((bfd *, file_ptr, + Elf_Internal_Shdr *, + Elf_Internal_Shdr **, + bfd_size_type)); +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 **)); + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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_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; +} + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_hash_entry *) ret; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct elf_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + if (ret != (struct elf_link_hash_entry *) NULL) + { + /* Set local fields. */ + ret->indx = -1; + ret->size = 0; + ret->dynindx = -1; + ret->dynstr_index = 0; + ret->weakdef = NULL; + ret->got_offset = (bfd_vma) -1; + ret->plt_offset = (bfd_vma) -1; + ret->type = STT_NOTYPE; + ret->elf_link_hash_flags = 0; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Initialize an ELF linker hash table. */ + +boolean +_bfd_elf_link_hash_table_init (table, abfd, newfunc) + struct elf_link_hash_table *table; + bfd *abfd; + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); +{ + table->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) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc)) + { + bfd_release (abfd, ret); + return NULL; + } + + return &ret->root; +} + +/* This is a hook for the ELF emulation code in the generic linker to + tell the backend linker what file name to use for the DT_NEEDED + entry for a dynamic object. 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) + elf_dt_needed_name (abfd) = name; +} + +/* Get the list of DT_NEEDED entries for a link. */ + +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; +} + +/* 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. */ + 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_NOTE: + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, where NUM is generally the index in the + program header table. For segments that are split (see below) we + generate the names segmenta and segmentb. + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + *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) + { + bfd_set_error (bfd_error_no_memory); + 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); + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (len - 2); + if (alc == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; +} + +/* Get the size of the program header. + + SORTED_HDRS, if non-NULL, is an array of COUNT pointers to headers sorted + by VMA. Non-allocated sections (!SHF_ALLOC) must appear last. All + section VMAs and sizes are known so we can compute the correct value. + (??? This may not be perfectly true. What cases do we miss?) + + If SORTED_HDRS is NULL we assume there are two segments: text and data + (exclusive of .interp and .dynamic). + + 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, sorted_hdrs, count, maxpagesize) + bfd *abfd; + Elf_Internal_Shdr **sorted_hdrs; + unsigned int count; + bfd_vma maxpagesize; +{ + 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 (sorted_hdrs != NULL) + { + unsigned int i; + unsigned int last_type; + Elf_Internal_Shdr **hdrpp; + /* What we think the current segment's offset is. */ + bfd_vma p_offset; + /* What we think the current segment's address is. */ + bfd_vma p_vaddr; + /* How big we think the current segment is. */ + bfd_vma p_memsz; + /* What we think the current file offset is. */ + bfd_vma file_offset; + bfd_vma next_offset; + + /* Scan the headers and compute the number of segments required. This + code is intentionally similar to the code in map_program_segments. + + The `sh_offset' field isn't valid at this point, so we keep our own + running total in `file_offset'. + + This works because section VMAs are already known. */ + + segs = 1; + /* Make sure the first section goes in the first segment. */ + file_offset = p_offset = sorted_hdrs[0]->sh_addr % maxpagesize; + p_vaddr = sorted_hdrs[0]->sh_addr; + p_memsz = 0; + last_type = SHT_PROGBITS; + + for (i = 0, hdrpp = sorted_hdrs; i < count; i++, hdrpp++) + { + Elf_Internal_Shdr *hdr; + + hdr = *hdrpp; + + /* Ignore any section which will not be part of the process + image. */ + if ((hdr->sh_flags & SHF_ALLOC) == 0) + continue; + + /* Keep track of where this and the next sections go. + The section VMA must equal the file position modulo + the page size. */ + file_offset += (hdr->sh_addr - file_offset) % maxpagesize; + next_offset = file_offset; + if (hdr->sh_type != SHT_NOBITS) + next_offset = file_offset + hdr->sh_size; + + /* If this section fits in the segment we are constructing, add + it in. */ + if ((file_offset - (p_offset + p_memsz) + == hdr->sh_addr - (p_vaddr + p_memsz)) + && (last_type != SHT_NOBITS || hdr->sh_type == SHT_NOBITS)) + { + bfd_size_type adjust; + + adjust = hdr->sh_addr - (p_vaddr + p_memsz); + p_memsz += hdr->sh_size + adjust; + file_offset = next_offset; + last_type = hdr->sh_type; + continue; + } + + /* The section won't fit, start a new segment. */ + ++segs; + + /* Initialize the segment. */ + p_vaddr = hdr->sh_addr; + p_memsz = hdr->sh_size; + p_offset = file_offset; + file_offset = next_offset; + + last_type = hdr->sh_type; + } + } + else + { + /* 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_create_program_headers) + segs = ((*bed->elf_backend_create_program_headers) + (abfd, (Elf_Internal_Phdr *) NULL, segs)); + + elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr; + return elf_tdata (abfd)->program_header_size; +} + +/* Create the program header. OFF is the file offset where the + program header should be written. FIRST is the first loadable ELF + section. SORTED_HDRS is the ELF sections sorted by section + address. PHDR_SIZE is the size of the program header as returned + by get_program_header_size. */ + +static file_ptr +map_program_segments (abfd, off, first, sorted_hdrs, phdr_size) + bfd *abfd; + file_ptr off; + Elf_Internal_Shdr *first; + Elf_Internal_Shdr **sorted_hdrs; + bfd_size_type phdr_size; +{ + Elf_Internal_Phdr phdrs[10]; + unsigned int phdr_count; + Elf_Internal_Phdr *phdr; + int phdr_size_adjust; + unsigned int i; + Elf_Internal_Shdr **hdrpp; + asection *sinterp, *sdyn; + unsigned int last_type; + Elf_Internal_Ehdr *i_ehdrp; + struct elf_backend_data *bed = get_elf_backend_data (abfd); + + BFD_ASSERT ((abfd->flags & (EXEC_P | DYNAMIC)) != 0); + BFD_ASSERT (phdr_size / sizeof (Elf_Internal_Phdr) + <= sizeof phdrs / sizeof (phdrs[0])); + + phdr_count = 0; + phdr = phdrs; + + if (bed->want_hdr_in_seg) + phdr_size_adjust = first->sh_offset - phdr_size; + else + phdr_size_adjust = 0; + + /* If we have a loadable .interp section, we must create a PT_INTERP + segment which must precede all PT_LOAD segments. We assume that + we must also create a PT_PHDR segment, although that may not be + true for all targets. */ + sinterp = bfd_get_section_by_name (abfd, ".interp"); + if (sinterp != NULL && (sinterp->flags & SEC_LOAD) != 0) + { + BFD_ASSERT (first != NULL); + + phdr->p_type = PT_PHDR; + + phdr->p_offset = off; + + /* Account for any adjustment made because of the alignment of + the first loadable section. */ + phdr_size_adjust = (first->sh_offset - phdr_size) - off; + BFD_ASSERT (phdr_size_adjust >= 0 && phdr_size_adjust < 128); + + /* The program header precedes all loadable sections. This lets + us compute its loadable address. This depends on the linker + script. */ + phdr->p_vaddr = first->sh_addr - (phdr_size + phdr_size_adjust); + + phdr->p_paddr = first->bfd_section->lma - (phdr_size + phdr_size_adjust); + phdr->p_filesz = phdr_size; + phdr->p_memsz = phdr_size; + + /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */ + phdr->p_flags = PF_R | PF_X; + + phdr->p_align = bed->s->file_align; + BFD_ASSERT ((phdr->p_vaddr - phdr->p_offset) % bed->s->file_align == 0); + + /* Include the ELF header in the first loadable segment. */ + phdr_size_adjust += off; + + ++phdr_count; + ++phdr; + + phdr->p_type = PT_INTERP; + phdr->p_offset = sinterp->filepos; + phdr->p_vaddr = sinterp->vma; + phdr->p_paddr = sinterp->lma; + phdr->p_filesz = sinterp->_raw_size; + phdr->p_memsz = sinterp->_raw_size; + phdr->p_flags = PF_R; + phdr->p_align = 1 << bfd_get_section_alignment (abfd, sinterp); + + ++phdr_count; + ++phdr; + } + + /* Look through the sections to see how they will be divided into + program segments. The sections must be arranged in order by + sh_addr for this to work correctly. */ + phdr->p_type = PT_NULL; + last_type = SHT_PROGBITS; + for (i = 1, hdrpp = sorted_hdrs; + i < elf_elfheader (abfd)->e_shnum; + i++, hdrpp++) + { + Elf_Internal_Shdr *hdr; + + hdr = *hdrpp; + + /* Ignore any section which will not be part of the process + image. */ + if ((hdr->sh_flags & SHF_ALLOC) == 0) + continue; + + /* If this section fits in the segment we are constructing, add + it in. */ + if (phdr->p_type != PT_NULL + && (hdr->sh_offset - (phdr->p_offset + phdr->p_memsz) + == hdr->sh_addr - (phdr->p_vaddr + phdr->p_memsz)) + && (hdr->sh_addr - hdr->bfd_section->lma + == phdr->p_vaddr - phdr->p_paddr) + && (last_type != SHT_NOBITS || hdr->sh_type == SHT_NOBITS)) + { + bfd_size_type adjust; + + adjust = hdr->sh_addr - (phdr->p_vaddr + phdr->p_memsz); + phdr->p_memsz += hdr->sh_size + adjust; + if (hdr->sh_type != SHT_NOBITS) + phdr->p_filesz += hdr->sh_size + adjust; + if ((hdr->sh_flags & SHF_WRITE) != 0) + phdr->p_flags |= PF_W; + if ((hdr->sh_flags & SHF_EXECINSTR) != 0) + phdr->p_flags |= PF_X; + last_type = hdr->sh_type; + continue; + } + + /* The section won't fit, start a new segment. If we're already in one, + move to the next one. */ + if (phdr->p_type != PT_NULL) + { + ++phdr; + ++phdr_count; + } + + /* Initialize the segment. */ + phdr->p_type = PT_LOAD; + phdr->p_offset = hdr->sh_offset; + phdr->p_vaddr = hdr->sh_addr; + phdr->p_paddr = hdr->bfd_section->lma; + if (hdr->sh_type == SHT_NOBITS) + phdr->p_filesz = 0; + else + phdr->p_filesz = hdr->sh_size; + phdr->p_memsz = hdr->sh_size; + phdr->p_flags = PF_R; + if ((hdr->sh_flags & SHF_WRITE) != 0) + phdr->p_flags |= PF_W; + if ((hdr->sh_flags & SHF_EXECINSTR) != 0) + phdr->p_flags |= PF_X; + phdr->p_align = bed->maxpagesize; + + if (hdr == first + && (bed->want_hdr_in_seg + || (sinterp != NULL + && (sinterp->flags & SEC_LOAD) != 0))) + { + phdr->p_offset -= phdr_size + phdr_size_adjust; + phdr->p_vaddr -= phdr_size + phdr_size_adjust; + phdr->p_paddr -= phdr_size + phdr_size_adjust; + phdr->p_filesz += phdr_size + phdr_size_adjust; + phdr->p_memsz += phdr_size + phdr_size_adjust; + } + + last_type = hdr->sh_type; + } + + if (phdr->p_type != PT_NULL) + { + ++phdr; + ++phdr_count; + } + + /* If we have a .dynamic section, create a PT_DYNAMIC segment. */ + sdyn = bfd_get_section_by_name (abfd, ".dynamic"); + if (sdyn != NULL && (sdyn->flags & SEC_LOAD) != 0) + { + phdr->p_type = PT_DYNAMIC; + phdr->p_offset = sdyn->filepos; + phdr->p_vaddr = sdyn->vma; + phdr->p_paddr = sdyn->lma; + phdr->p_filesz = sdyn->_raw_size; + phdr->p_memsz = sdyn->_raw_size; + phdr->p_flags = PF_R; + if ((sdyn->flags & SEC_READONLY) == 0) + phdr->p_flags |= PF_W; + if ((sdyn->flags & SEC_CODE) != 0) + phdr->p_flags |= PF_X; + phdr->p_align = 1 << bfd_get_section_alignment (abfd, sdyn); + + ++phdr; + ++phdr_count; + } + + /* Let the backend create additional program headers. */ + if (bed->elf_backend_create_program_headers) + phdr_count = (*bed->elf_backend_create_program_headers) (abfd, + phdrs, + phdr_count); + + /* Make sure the return value from get_program_header_size matches + what we computed here. Actually, it's OK if we allocated too + much space in the program header. */ + if (phdr_count > phdr_size / bed->s->sizeof_phdr) + { + ((*_bfd_error_handler) + ("%s: Not enough room for program headers (allocated %lu, need %u)", + bfd_get_filename (abfd), + (unsigned long) (phdr_size / bed->s->sizeof_phdr), + phdr_count)); + bfd_set_error (bfd_error_bad_value); + return (file_ptr) -1; + } + + /* Set up program header information. */ + i_ehdrp = elf_elfheader (abfd); + i_ehdrp->e_phentsize = bed->s->sizeof_phdr; + i_ehdrp->e_phoff = off; + i_ehdrp->e_phnum = phdr_count; + + /* Save the program headers away. I don't think anybody uses this + information right now. */ + elf_tdata (abfd)->phdr = ((Elf_Internal_Phdr *) + bfd_alloc (abfd, + (phdr_count + * sizeof (Elf_Internal_Phdr)))); + if (elf_tdata (abfd)->phdr == NULL && phdr_count != 0) + { + bfd_set_error (bfd_error_no_memory); + return (file_ptr) -1; + } + memcpy (elf_tdata (abfd)->phdr, phdrs, + phdr_count * sizeof (Elf_Internal_Phdr)); + + /* Write out the program headers. */ + if (bfd_seek (abfd, off, SEEK_SET) != 0) + return (file_ptr) -1; + + if (bed->s->write_out_phdrs (abfd, phdrs, phdr_count) != 0) + return (file_ptr) -1; + + return off + phdr_count * bed->s->sizeof_phdr; +} + +/* 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 int elf_sort_hdrs PARAMS ((const PTR, const PTR)); + +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); + + /* Start after the ELF header. */ + off = i_ehdrp->e_ehsize; + + if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) + { + Elf_Internal_Shdr **hdrpp; + unsigned int i; + + /* 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 + { + file_ptr phdr_off; + bfd_size_type phdr_size; + bfd_vma maxpagesize; + size_t hdrppsize; + Elf_Internal_Shdr **sorted_hdrs; + Elf_Internal_Shdr **hdrpp; + unsigned int i; + Elf_Internal_Shdr *first; + file_ptr phdr_map; + + /* We are creating an executable. */ + + maxpagesize = get_elf_backend_data (abfd)->maxpagesize; + if (maxpagesize == 0) + maxpagesize = 1; + + /* We must sort the sections. The GNU linker will always create + the sections in an appropriate order, but the Irix 5 linker + will not. We don't include the dummy first section in the + sort. We sort sections which are not SHF_ALLOC to the end. */ + hdrppsize = (i_ehdrp->e_shnum - 1) * sizeof (Elf_Internal_Shdr *); + sorted_hdrs = (Elf_Internal_Shdr **) malloc (hdrppsize); + if (sorted_hdrs == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + memcpy (sorted_hdrs, i_shdrpp + 1, hdrppsize); + qsort (sorted_hdrs, (size_t) i_ehdrp->e_shnum - 1, + sizeof (Elf_Internal_Shdr *), elf_sort_hdrs); + + /* We can't actually create the program header until we have set the + file positions for the sections, and we can't do that until we know + how big the header is going to be. */ + off = align_file_position (off, bed->s->file_align); + phdr_size = get_program_header_size (abfd, + sorted_hdrs, i_ehdrp->e_shnum - 1, + maxpagesize); + if (phdr_size == (bfd_size_type) -1) + return false; + + /* Compute the file offsets of each section. */ + phdr_off = off; + off += phdr_size; + first = NULL; + for (i = 1, hdrpp = sorted_hdrs; i < i_ehdrp->e_shnum; i++, hdrpp++) + { + Elf_Internal_Shdr *hdr; + + hdr = *hdrpp; + if ((hdr->sh_flags & SHF_ALLOC) == 0) + { + if (hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) + { + hdr->sh_offset = -1; + continue; + } + if (hdr == i_shdrpp[tdata->symtab_section] + || hdr == i_shdrpp[tdata->strtab_section]) + { + hdr->sh_offset = -1; + continue; + } + off = _bfd_elf_assign_file_position_for_section (hdr, off, + true); + } + else + { + if (first == NULL) + first = hdr; + + /* The section VMA must equal the file position modulo + the page size. This is required by the program + header. */ + off += (hdr->sh_addr - off) % maxpagesize; + off = _bfd_elf_assign_file_position_for_section (hdr, off, + false); + } + } + + /* Create the program header. */ + phdr_map = map_program_segments (abfd, phdr_off, first, sorted_hdrs, + phdr_size); + if (phdr_map == (file_ptr) -1) + return false; + BFD_ASSERT ((bfd_size_type) phdr_map + <= (bfd_size_type) phdr_off + phdr_size); + + free (sorted_hdrs); + } + + /* 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; +} + +/* Sort the ELF headers by VMA. We sort headers which are not + SHF_ALLOC to the end. */ +static int +elf_sort_hdrs (arg1, arg2) + const PTR arg1; + const PTR arg2; +{ + int ret; + const Elf_Internal_Shdr *hdr1 = *(const Elf_Internal_Shdr **) arg1; + const Elf_Internal_Shdr *hdr2 = *(const Elf_Internal_Shdr **) arg2; + +#define TOEND(x) (((x)->sh_flags & SHF_ALLOC)==0) + + if (TOEND (hdr1)) + if (TOEND (hdr2)) + return 0; + else + return 1; + + if (TOEND (hdr2)) + return -1; + + if (hdr1->sh_addr < hdr2->sh_addr) + return -1; + else if (hdr1->sh_addr > hdr2->sh_addr) + return 1; + + /* Put !SHT_NOBITS sections before SHT_NOBITS ones. + The main loop in map_program_segments requires this. */ + + ret = (hdr1->sh_type == SHT_NOBITS) - (hdr2->sh_type == SHT_NOBITS); + + if (ret != 0) + return ret; + if (hdr1->sh_size < hdr2->sh_size) + return -1; + if (hdr1->sh_size > hdr2->sh_size) + return 1; + return 0; +} + +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] = + abfd->xvec->byteorder_big_p ? 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 symbol, return the bfd index for that symbol. */ + 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; + BFD_ASSERT (idx != 0); + +#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 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; + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + + 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 (bfd_is_com_section (syms[idx]->section)) + sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT); + else if (bfd_is_und_section (syms[idx]->section)) + sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK) + ? STB_WEAK + : STB_GLOBAL), + ((flags & BSF_FUNCTION) + ? STT_FUNC + : STT_NOTYPE)); + 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; + int type = STT_OBJECT; + + if (flags & BSF_LOCAL) + bind = STB_LOCAL; + else if (flags & BSF_WEAK) + bind = STB_WEAK; + else if (flags & BSF_GLOBAL) + bind = STB_GLOBAL; + + if (flags & BSF_FUNCTION) + type = STT_FUNC; + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; +{ + const char *filename; + asymbol *func; + asymbol **p; + + if (symbols == NULL) + return false; + + filename = NULL; + func = NULL; + + 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 (func == NULL + || q->symbol.value <= offset) + func = (asymbol *) q; + 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, (Elf_Internal_Shdr **) NULL, 0, + (bfd_vma) 0); + 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/gnu/usr.bin/binutils/bfd/elf32-gen.c b/gnu/usr.bin/binutils/bfd/elf32-gen.c new file mode 100644 index 00000000000..385fda20860 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/elf32-hppa.c b/gnu/usr.bin/binutils/bfd/elf32-hppa.c new file mode 100644 index 00000000000..2da6eee0cdd --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elf32-hppa.c @@ -0,0 +1,3028 @@ +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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]; + 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 = malloc (len); + if (!new_name) + { + bfd_set_error (bfd_error_no_memory); + 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 = malloc (len); + if (!stub_name) + { + bfd_set_error (bfd_error_no_memory); + 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 = malloc (len); + if (new_name == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, + (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 *) malloc ((size_t) symextn_sec->_raw_size); + if (contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 = malloc (len); + if (new_name == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc (sizeof (struct elf32_hppa_stub_hash_table))); + if (!stub_hash_table) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc (sizeof (struct elf32_hppa_args_hash_table))); + if (!args_hash_table) + { + bfd_set_error (bfd_error_no_memory); + 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 **) malloc (sizeof (Elf_Internal_Sym *) * bfd_count); + if (all_local_syms == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *)malloc (symtab_hdr->sh_info + * sizeof (Elf_Internal_Sym)); + if (local_syms == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *)malloc (symtab_hdr->sh_info + * sizeof (Elf32_External_Sym)); + if (ext_syms == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (section->reloc_count * sizeof (Elf32_External_Rela)); + if (external_relocs == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (section->reloc_count * sizeof (Elf_Internal_Rela)); + if (internal_relocs == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 = malloc (strlen (sym_name) + 10); + if (new_name == 0) + { + 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; + } + 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 = malloc (len); + if (!stub_name) + { + bfd_set_error (bfd_error_no_memory); + + /* 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) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/elf32-hppa.h b/gnu/usr.bin/binutils/bfd/elf32-hppa.h new file mode 100644 index 00000000000..63ee52200e0 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/elf32-i386.c b/gnu/usr.bin/binutils/bfd/elf32-i386.c new file mode 100644 index 00000000000..ffa95d8b7a4 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elf32-i386.c @@ -0,0 +1,1525 @@ +/* Intel 80386/80486-specific support for 32-bit ELF + Copyright 1993, 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 "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) + { + bfd_set_error (bfd_error_no_memory); + 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 without + linking in any dynamic objects, in which case we don't + need to generate a procedure linkage table after all. */ + + /* If this is a local symbol, we resolve it directly without + creating a procedure linkage table entry. */ + if (h == NULL) + continue; + + /* 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_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 (! elf_hash_table (info)->dynamic_sections_created) + { + /* This case can occur if we saw a PLT32 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 PC32 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); + + /* 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. */ + 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) + { + bfd_set_error (bfd_error_no_memory); + 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]; + 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 + && (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)) + { + Elf_Internal_Rel 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, ".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); + outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32); + } + else + { + if (h == NULL) + outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + else + { + BFD_ASSERT (h->dynindx != -1); + 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 (h != NULL) + 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 0 +#define elf_backend_want_plt_sym 0 + +#include "elf32-target.h" diff --git a/gnu/usr.bin/binutils/bfd/elf32-i860.c b/gnu/usr.bin/binutils/bfd/elf32-i860.c new file mode 100644 index 00000000000..a8537a75508 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/elf32-m68k.c b/gnu/usr.bin/binutils/bfd/elf32-m68k.c new file mode 100644 index 00000000000..a70559d4009 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elf32-m68k.c @@ -0,0 +1,1558 @@ +/* Motorola 68k series 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 "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, 0x00000000, 0x00000000,false), + HOWTO(R_68K_32, 0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_32", false, 0xffffffff, 0xffffffff,false), + HOWTO(R_68K_16, 0, 1,16, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_16", false, 0x0000ffff, 0x0000ffff,false), + HOWTO(R_68K_8, 0, 0, 8, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_8", false, 0x000000ff, 0x000000ff,false), + HOWTO(R_68K_PC32, 0, 2,32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC32", false, 0xffffffff, 0xffffffff,true), + HOWTO(R_68K_PC16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC16", false, 0x0000ffff, 0x0000ffff,true), + HOWTO(R_68K_PC8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC8", false, 0x000000ff, 0x000000ff,true), + HOWTO(R_68K_GOT32, 0, 2,32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT32", false, 0xffffffff, 0xffffffff,true), + HOWTO(R_68K_GOT16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16", false, 0x0000ffff, 0x0000ffff,true), + HOWTO(R_68K_GOT8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8", false, 0x000000ff, 0x000000ff,true), + HOWTO(R_68K_GOT32O, 0, 2,32, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT32O", false, 0xffffffff, 0xffffffff,false), + HOWTO(R_68K_GOT16O, 0, 1,16, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16O", false, 0x0000ffff, 0x0000ffff,false), + HOWTO(R_68K_GOT8O, 0, 0, 8, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8O", false, 0x000000ff, 0x000000ff,false), + HOWTO(R_68K_PLT32, 0, 2,32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT32", false, 0xffffffff, 0xffffffff,true), + HOWTO(R_68K_PLT16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16", false, 0x0000ffff, 0x0000ffff,true), + HOWTO(R_68K_PLT8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8", false, 0x000000ff, 0x000000ff,true), + HOWTO(R_68K_PLT32O, 0, 2,32, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT32O", false, 0xffffffff, 0xffffffff,false), + HOWTO(R_68K_PLT16O, 0, 1,16, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16O", false, 0x0000ffff, 0x0000ffff,false), + HOWTO(R_68K_PLT8O, 0, 0, 8, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8O", false, 0x000000ff, 0x000000ff,false), + HOWTO(R_68K_COPY, 0, 0, 0, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_COPY", false, 0xffffffff, 0xffffffff,false), + HOWTO(R_68K_GLOB_DAT, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_GLOB_DAT", false, 0xffffffff, 0xffffffff,false), + HOWTO(R_68K_JMP_SLOT, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_JMP_SLOT", false, 0xffffffff, 0xffffffff,false), + HOWTO(R_68K_RELATIVE, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_RELATIVE", false, 0xffffffff, 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 address of .got + 4. */ + 0x4e, 0xfb, 0x01, 0x71, /* jmp ([%pc,addr]) */ + 0, 0, 0, 0, /* replaced with address of .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 ([addr]) */ + 0, 0, 0, 0, /* replaced with address of this symbol in .got. */ + 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: + case R_68K_GOT8O: + case R_68K_GOT16O: + case R_68K_GOT32O: + /* This symbol requires a global offset table entry. */ + + if (h != NULL + && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) + break; + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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: + case R_68K_PLT8O: + case R_68K_PLT16O: + case R_68K_PLT32O: + /* 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 this is a local symbol, we resolve it directly without + creating a procedure linkage table entry. */ + if (h == NULL) + continue; + + /* 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) + { + /* 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 (!elf_hash_table (info)->dynamic_sections_created) + { + /* This case can occur if we saw a PLT32 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 PC32 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); + + /* 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *sgotplt; + 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; + sgotplt = 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]; + 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 + && (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 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. */ + + if (sgot == NULL) + { + sgot = bfd_get_section_by_name (dynobj, ".got"); + BFD_ASSERT (sgot != NULL); + } + + if (sgotplt == NULL) + { + sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); + BFD_ASSERT (sgotplt != 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; + if (r_type == R_68K_GOT8O + || r_type == R_68K_GOT16O + || r_type == R_68K_GOT32O) + relocation -= sgotplt->output_offset; + } + 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_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 = 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; + if (r_type == R_68K_GOT8O + || r_type == R_68K_GOT16O + || r_type == R_68K_GOT32O) + relocation -= sgotplt->output_offset; + } + + 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 PLT32 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); + + if (h->plt_offset == (bfd_vma) -1) + { + /* We didn't make a PLT entry for this symbol. This + happens when statically linking PIC code. */ + break; + } + + if (splt == NULL) + { + splt = bfd_get_section_by_name (dynobj, ".plt"); + BFD_ASSERT (splt != NULL); + } + + relocation = h->plt_offset; + 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) + { + 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) + { + 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_68K_32) + { + outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); + outrel.r_addend = relocation + rel->r_addend; + } + else + { + long indx; + + sym = local_syms + r_symndx; + + BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION); + + sec = local_sections[r_symndx]; + 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; + } + + 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); + else + { + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset); + 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: + /* My reading of the SVR4 ABI indicates that the + procedure linkage table relocs (DT_JMPREL) should be + included in the overall relocs (DT_RELA). This is + what Solaris does. However, UnixWare can not handle + that case. 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. */ + /* FIXME: This comment is from elf32-i386.c, what about + the SVR4/m68k implementations? */ + 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/gnu/usr.bin/binutils/bfd/elf32-m88k.c b/gnu/usr.bin/binutils/bfd/elf32-m88k.c new file mode 100644 index 00000000000..f3c535e0776 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/elf32-mips.c b/gnu/usr.bin/binutils/bfd/elf32-mips.c new file mode 100644 index 00000000000..7bb714f3c6c --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elf32-mips.c @@ -0,0 +1,3017 @@ +/* MIPS-specific support for 32-bit ELF + Copyright 1993, 1994, 1995 Free Software Foundation, Inc. + + Most of the information added 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" +#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 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 boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *)); +static boolean mips_elf_object_p PARAMS ((bfd *)); +static void mips_elf_final_write_processing + PARAMS ((bfd *, boolean)); +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 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_add_symbol_hook + PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, + const char **, flagword *, asection **, bfd_vma *)); + +#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. */ + /* FIXME: This is not handled correctly. */ + 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. */ + /* FIXME: This is not handled correctly. */ + 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 */ + bfd_elf_generic_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; + } + + /* FIXME: The symbol _gp_disp requires special handling, which we do + not do. */ + if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0) + abort (); + + 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 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; +{ + /* FIXME: The symbol _gp_disp requires special handling, which we do + not do. */ + if (output_bfd == (bfd *) NULL + && strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0) + abort (); + + 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; + } + + /* 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 (); +} + +/* 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; + + /* 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; + } + + if (bfd_is_und_section (symbol->section) + && relocateable == false) + return bfd_reloc_undefined; + + /* Some of the code below assumes the output bfd is ELF too. */ + if (output_bfd->xvec->flavour != bfd_target_elf_flavour) + 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. */ + if (elf_gp (output_bfd) == 0 + && (relocateable == false + || (symbol->flags & BSF_SECTION_SYM) != 0)) + { + if (relocateable != false) + { + /* Make up a value. */ + elf_gp (output_bfd) = + symbol->section->output_section->vma + 0x4000; + } + 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) + { + elf_gp (output_bfd) = bfd_asymbol_value (*sym); + break; + } + } + } + + if (i >= count) + { + /* Only get the error once. */ + elf_gp (output_bfd) = 4; + *error_message = + (char *) "GP relative relocation when _gp not defined"; + return bfd_reloc_dangerous; + } + } + } + + return gprel16_with_gp (abfd, symbol, reloc_entry, input_section, + relocateable, data, elf_gp (output_bfd)); +} + +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 == 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; +} + +/* 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 } +}; + +/* 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); +} + +/* 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: + return; + } + + 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; + } + } +} + +/* 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; + hdr->sh_entsize = 1; + } + else if (strcmp (name, ".reginfo") == 0) + { + hdr->sh_type = SHT_MIPS_REGINFO; + 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 (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; + } + } + + 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; + +/* 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; + } +} + +/* 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 *) malloc ((size_t) swap->external_hdr_size); + if (ext_hdr == NULL && swap->external_hdr_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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) malloc ((size_t) (size * symhdr->count)); \ + if (debug->ptr == NULL) \ + { \ + bfd_set_error (bfd_error_no_memory); \ + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; +}; + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + + 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) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, + mips_elf_link_hash_newfunc)) + { + bfd_release (abfd, ret); + return NULL; + } + + 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; +{ + 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_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; + + 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 (h->root.root.type != bfd_link_hash_defined + && h->root.root.type != bfd_link_hash_defweak) + h->esym.asym.sc = scAbs; + else + { + asection *output_section; + const char *name; + + output_section = h->root.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, ".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) + { + asection *sec; + + 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; + h->esym.asym.value = (h->root.root.u.def.value + + sec->output_offset + + sec->output_section->vma); + } + + 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; +} + +/* 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; + 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; + } + } + + /* 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 (®info, 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; + + 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; + } + + /* 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 *) malloc (c * sizeof (Elf32_gptab)); + if (tab == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + realloc ((PTR) tab, + (c + 1) * sizeof (Elf32_gptab))); + if (new_tab == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + } + } + + /* 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 + 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. */ + } + } + + /* 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, ®info, &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; + } + + 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); +} + +/* 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; + Elf_Internal_Rela *rel; + Elf_Internal_Rela *relend; + + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + + 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; + } + + 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; + + 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 (elf_gp (output_bfd) == 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. */ + elf_gp (output_bfd) = 4; + } + + 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) - elf_gp (output_bfd); + } + 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 = - elf_gp (output_bfd); + } + 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 with an associated LO16, adjust + the addend accordingly. Otherwise, just + relocate. */ + if (r_type != R_MIPS_HI16 + || (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; + + /* This is a final link. */ + sym = NULL; + if (r_symndx < extsymoff + || (elf_bad_symtab (input_bfd) + && local_sections[r_symndx] != NULL)) + { + 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; + + indx = r_symndx - extsymoff; + h = elf_sym_hashes (input_bfd)[indx]; + 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_MIPS_HI16 + || (rel + 1) >= relend + || ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16) + r = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, rel->r_offset, + relocation, addend); + else + { + mips_elf_relocate_hi16 (input_bfd, rel, rel + 1, + contents, relocation + addend); + 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; +} + +/* 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 **) malloc (reloc_size); + if (reloc_vector == NULL && reloc_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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_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_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 elf_backend_relocate_section mips_elf_relocate_section +#define elf_backend_add_symbol_hook mips_elf_add_symbol_hook + +#include "elf32-target.h" diff --git a/gnu/usr.bin/binutils/bfd/elf32-ppc.c b/gnu/usr.bin/binutils/bfd/elf32-ppc.c new file mode 100644 index 00000000000..6490d422e79 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elf32-ppc.c @@ -0,0 +1,1521 @@ +/* PowerPC-specific support for 32-bit ELF + Copyright 1994, 1995 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, + R_PPC_max +}; + +static bfd_reloc_status_type ppc_elf_unsupported_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static bfd_reloc_status_type ppc_elf_std_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); + +static bfd_vma ppc_elf_addr16_ha_inner PARAMS ((bfd_vma)); +static bfd_reloc_status_type ppc_elf_addr16_ha_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static bfd_vma ppc_elf_got16_inner PARAMS ((asection *sec)); +static bfd_reloc_status_type ppc_elf_got16_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static bfd_vma ppc_elf_brtaken_inner PARAMS ((bfd_vma, enum ppc_reloc_type)); +static bfd_reloc_status_type ppc_elf_brtaken_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +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 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 **)); + +#define BRANCH_PREDICT_BIT 0x200000 + +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 */ + ppc_elf_std_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 */ + ppc_elf_std_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 */ + ppc_elf_std_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 */ + ppc_elf_std_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 */ + ppc_elf_std_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 */ + ppc_elf_std_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 */ + ppc_elf_addr16_ha_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 */ + ppc_elf_std_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 */ + ppc_elf_brtaken_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 */ + ppc_elf_brtaken_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 */ + ppc_elf_std_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 */ + ppc_elf_std_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 */ + ppc_elf_brtaken_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 */ + ppc_elf_brtaken_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 */ + ppc_elf_got16_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 */ + ppc_elf_got16_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 */ + ppc_elf_got16_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. FIXME: Not supported. */ + 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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_std_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 */ + ppc_elf_std_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 */ + ppc_elf_std_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_got16_reloc, /* special_function */ + "R_PPC_SDAREL16", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* These next 4 relocations were added by Sun. */ + /* 32-bit section relative relocation. FIXME: not supported. */ + 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 */ + ppc_elf_unsupported_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. FIXME: not supported. */ + 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 */ + ppc_elf_unsupported_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. FIXME: not supported. */ + 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 */ + ppc_elf_unsupported_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. FIXME: not supported. */ + 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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_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 */ + ppc_elf_unsupported_reloc, /* special_function */ + "R_PPC_EMB_NADDR16_HA", /* 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_PPC_TOC16: 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; + } + + 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_ppc_flags_init (abfd) + || elf_elfheader (abfd)->e_flags == flags); + + elf_elfheader (abfd)->e_flags = flags; + elf_ppc_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_ppc_flags_init (obfd) + || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags); + + elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; + elf_ppc_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_big_p != obfd->xvec->byteorder_big_p) + { + (*_bfd_error_handler) + ("%s: compiled for a %s endian system and target is %s endian.\n", + bfd_get_filename (ibfd), + (ibfd->xvec->byteorder_big_p) ? "big" : "little", + (obfd->xvec->byteorder_big_p) ? "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_ppc_flags_init (obfd)) /* First call, no flags set */ + { + elf_ppc_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\n", + 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\n", + bfd_get_filename (ibfd)); + } + else if ((new_flags & EF_PPC_RELOCATABLE_LIB) != 0) + elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE_LIB; + + new_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB); + old_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB); + + /* Warn about eabi vs. V.4 mismatch */ + if ((new_flags & EF_PPC_EMB) != 0 && (old_flags & EF_PPC_EMB) == 0) + { + new_flags &= ~EF_PPC_EMB; + error = true; + (*_bfd_error_handler) + ("%s: compiled for the eabi and linked with modules compiled for System V\n", + bfd_get_filename (ibfd)); + } + else if ((new_flags & EF_PPC_EMB) == 0 && (old_flags & EF_PPC_EMB) != 0) + { + old_flags &= ~EF_PPC_EMB; + error = true; + (*_bfd_error_handler) + ("%s: compiled for System V and linked with modules compiled for eabi\n", + bfd_get_filename (ibfd)); + } + + /* 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)\n", + bfd_get_filename (ibfd), (long)new_flags, (long)old_flags); + } + + if (error) + { + bfd_set_error (bfd_error_bad_value); + return false; + } + } + + return true; +} + + +/* 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*/ +static bfd_reloc_status_type +ppc_elf_std_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; +} + +/* Don't pretend we can deal with unsupported relocs. */ + +/*ARGSUSED*/ +static bfd_reloc_status_type +ppc_elf_unsupported_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_ASSERT (reloc_entry->howto != (reloc_howto_type *)0); + (*_bfd_error_handler) + ("%s: Relocation %s (%d) is not currently supported.\n", + bfd_get_filename (abfd), + reloc_entry->howto->name, + reloc_entry->howto->type); + + return bfd_reloc_notsupported; +} + +/* Internal function to return the adjustment to the addend for relocations + that return the upper 16 bits after sign extending the lower 16 bits, ie + for use with a ADDIS instruction followed by a memory reference using the + bottom 16 bits. */ + +INLINE +static bfd_vma +ppc_elf_addr16_ha_inner (relocation) + bfd_vma relocation; +{ + return (relocation & 0x8000) << 1; +} + +/* Handle the ADDR16_HA reloc by adjusting the reloc addend. */ + +/*ARGSUSED*/ +static bfd_reloc_status_type +ppc_elf_addr16_ha_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; + asection *sec; + + if (output_bfd != (bfd *) NULL) + return ppc_elf_std_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); + + sec = symbol->section; + relocation = (((bfd_is_com_section (sec)) ? 0 : symbol->value) + + sec->output_section->vma + + sec->output_offset + + reloc_entry->addend); + + reloc_entry->addend += ppc_elf_addr16_ha_inner (relocation); + return bfd_reloc_continue; +} + +/* Internal function to return the addjustment to the addend for GOT16 + entries */ + +INLINE +static bfd_vma +ppc_elf_got16_inner (sec) + asection *sec; +{ + 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 + || strcmp (bfd_get_section_name (abfd, sec), ".sdata") == 0 + || strcmp (bfd_get_section_name (abfd, sec), ".sbss") == 0) + + return -(sec->output_section->vma + 0x8000); +} + +/* Handle the GOT16 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. When and if we support PIC code, we will have to + change this, perhaps by switching off on the e_type field. */ + +/*ARGSUSED*/ +static bfd_reloc_status_type +ppc_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 (output_bfd != (bfd *) NULL) + return ppc_elf_std_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); + + reloc_entry->addend += ppc_elf_got16_inner (bfd_get_section (*reloc_entry->sym_ptr_ptr)); + return bfd_reloc_continue; +} + +/* Internal function to return the adjustment for relocations that set the + branch taken bit or branch not taken in B0 for conditional branches. + The dst_mask for these relocations allows this bit to be set as part + of the addend. */ + +INLINE +static bfd_vma +ppc_elf_brtaken_inner (relocation, ppc_reloc) + bfd_vma relocation; + enum ppc_reloc_type ppc_reloc; +{ + if (ppc_reloc == R_PPC_ADDR14_BRTAKEN || ppc_reloc == R_PPC_REL14_BRTAKEN) + return (relocation & 0x8000) ? 0 : BRANCH_PREDICT_BIT; /* branch taken */ + else + return (relocation & 0x8000) ? BRANCH_PREDICT_BIT : 0; /* branch not taken */ +} + +/* Handle the R_PPC_{ADDR,REL}14_BR{,N}TAKEN relocs by setting bit 10 to indicate + whether the branch is taken or not. */ + +/*ARGSUSED*/ +static bfd_reloc_status_type +ppc_elf_brtaken_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; + asection *sec; + long insn; + + if (output_bfd != (bfd *) NULL) + return ppc_elf_std_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); + + sec = symbol->section; + relocation = (((bfd_is_com_section (sec)) ? 0 : symbol->value) + + sec->output_section->vma + + sec->output_offset + + reloc_entry->addend); + + /* Set the branch prediction bit */ + insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + insn &= ~BRANCH_PREDICT_BIT; + insn |= ppc_elf_brtaken_inner (relocation - reloc_entry->address, + (enum ppc_reloc_type)reloc_entry->howto->type); + bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); + + return bfd_reloc_continue; +} + + +/* 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); + 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; + 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\n", + 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. */ + + /* Complain about known relocation that are not yet supported */ + if (howto->special_function == ppc_elf_unsupported_reloc) + { + (*_bfd_error_handler) + ("%s: Relocation %s (%d) is not currently supported.\n", + bfd_get_filename (input_bfd), + howto->name, + (int)r_type); + + bfd_set_error (bfd_error_bad_value); + ret = false; + continue; + } + + 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]; + 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: + break; + + case (int)R_PPC_ADDR14_BRTAKEN: /* branch prediction relocations */ + case (int)R_PPC_ADDR14_BRNTAKEN: + case (int)R_PPC_REL14_BRTAKEN: + case (int)R_PPC_REL14_BRNTAKEN: + BFD_ASSERT (sec != (asection *)0); + insn = bfd_get_32 (output_bfd, contents + offset); + insn &= ~BRANCH_PREDICT_BIT; + insn |= ppc_elf_brtaken_inner (relocation - offset, r_type); + bfd_put_32 (output_bfd, insn, contents + offset); + break; + + case (int)R_PPC_GOT16: /* GOT16 relocations */ + case (int)R_PPC_GOT16_LO: + case (int)R_PPC_GOT16_HI: + case (int)R_PPC_SDAREL16: + BFD_ASSERT (sec != (asection *)0); + addend += ppc_elf_got16_inner (sec); + break; + + case (int)R_PPC_ADDR16_HA: /* arithmetic adjust relocations */ + BFD_ASSERT (sec != (asection *)0); + addend += ppc_elf_addr16_ha_inner (relocation + addend); + break; + } + + +#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 + + 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_relocate_section ppc_elf_relocate_section + +#include "elf32-target.h" diff --git a/gnu/usr.bin/binutils/bfd/elf32-sparc.c b/gnu/usr.bin/binutils/bfd/elf32-sparc.c new file mode 100644 index 00000000000..2c05a1fd98b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elf32-sparc.c @@ -0,0 +1,1513 @@ +/* SPARC-specific support for 32-bit ELF + Copyright 1993, 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 "bfdlink.h" +#include "libbfd.h" +#include "elf-bfd.h" + +static reloc_howto_type *bfd_elf32_bfd_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 *)); + +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 elf_sparc_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), +}; + +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 }, + { 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 * +bfd_elf32_bfd_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 &elf_sparc_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; + Elf_Internal_Rela *dst; +{ + BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max); + cache_ptr->howto = &elf_sparc_howto_table[ELF32_R_TYPE(dst->r_info)]; +} + + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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: + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = elf_sparc_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]; + 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 + && (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_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: + 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) + { + 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; + + sym = local_syms + r_symndx; + + BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION); + + sec = local_sections[r_symndx]; + 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; + } + + 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 +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; +} + +#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_MAXPAGESIZE 0x10000 +#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 elf_backend_want_got_plt 0 +#define elf_backend_plt_readonly 1 +#define elf_backend_want_plt_sym 1 + +#include "elf32-target.h" diff --git a/gnu/usr.bin/binutils/bfd/elf32.c b/gnu/usr.bin/binutils/bfd/elf32.c new file mode 100644 index 00000000000..f2229694406 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/elf64-gen.c b/gnu/usr.bin/binutils/bfd/elf64-gen.c new file mode 100644 index 00000000000..5daf4ee9f17 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/elf64-sparc.c b/gnu/usr.bin/binutils/bfd/elf64-sparc.c new file mode 100644 index 00000000000..3e526c047d9 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elf64-sparc.c @@ -0,0 +1,438 @@ +/* SPARC-specific support for 64-bit ELF + Copyright 1993, 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. */ + +/* 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" + +static bfd_reloc_status_type sparc64_elf_wdisp16_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +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 *)); + +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, + + /* 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_LO7, + + 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", + + "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_LO7", +}; +#endif + +extern void abort (); +#define DIE ((bfd_reloc_status_type(*)())abort) + +static reloc_howto_type elf_sparc_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_bitfield, bfd_elf_generic_reloc, "R_SPARC_GOT10", false, 0, 0x000003ff, true), + HOWTO (R_SPARC_GOT13, 0, 2, 13, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_GOT13", false, 0, 0x00001fff, true), + HOWTO (R_SPARC_GOT22, 10, 2, 22, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_GOT22", false, 0, 0x003fffff, true), + HOWTO (R_SPARC_PC10, 0, 2, 10, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_PC10", false, 0, 0x000003ff, true), + HOWTO (R_SPARC_PC22, 0, 2, 22, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_PC22", false, 0, 0x003fffff, true), + HOWTO (R_SPARC_WPLT30, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_WPLT30", false, 0, 0x00000000, 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_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) 0xffffffff) << 32) + 0xffffffff, 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, sparc64_elf_wdisp16_reloc, "R_SPARC_WDISP16", false, 0, 0, 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_LO7, 0, 2, 7, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO7", false, 0, 0x0000007f, true), +}; + +/* Handle the WDISP16 reloc. */ + +static bfd_reloc_status_type +sparc64_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; +} + +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}, + {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?? */ + {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_LO7, R_SPARC_LO7}, +}; + +static reloc_howto_type * +bfd_elf64_bfd_reloc_type_lookup (abfd, code) + bfd *abfd; + bfd_reloc_code_real_type code; +{ + 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 &elf_sparc_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 = &elf_sparc_howto_table[ELF64_R_TYPE (dst->r_info)]; +} + +/* 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 = elf_sparc_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]; + 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_sparc64); +} + +#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 elf_backend_relocate_section sparc64_elf_relocate_section +#define elf_backend_object_p sparc64_elf_object_p + +#include "elf64-target.h" diff --git a/gnu/usr.bin/binutils/bfd/elf64.c b/gnu/usr.bin/binutils/bfd/elf64.c new file mode 100644 index 00000000000..69fb5b5e6e1 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/elfcode.h b/gnu/usr.bin/binutils/bfd/elfcode.h new file mode 100644 index 00000000000..eb597d9518a --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elfcode.h @@ -0,0 +1,1291 @@ +/* ELF executable support for BFD. + Copyright 1991, 1992, 1993, 1994, 1995 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 /* 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) + +#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)); + + int _bfd_elf_section_from_bfd_section PARAMS ((bfd *, struct sec *)); + +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 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, src, dst) + bfd *abfd; + const Elf_External_Dyn *src; + Elf_Internal_Dyn *dst; +{ + 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 (!abfd->xvec->header_byteorder_big_p) + goto got_wrong_format_error; + break; + case ELFDATA2LSB: /* Little-endian */ + if (abfd->xvec->header_byteorder_big_p) + 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_memory_error; + 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_memory_error; + 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_memory_error; + 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_memory_error: + bfd_set_error (bfd_error_no_memory); + 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 */ + +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 = 9999999; /* should always be written before use */ + + /* 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) + { + bfd_set_error (bfd_error_no_memory); + *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; + last_sym_idx = n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); + } + 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; + last_sym_idx = n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); + } + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return -1; + } + sym = symbase; + + /* Temporarily allocate room for the raw ELF symbols. */ + x_symp = ((Elf_External_Sym *) + malloc (symcount * sizeof (Elf_External_Sym))); + if (x_symp == NULL && symcount != 0) + { + bfd_set_error (bfd_error_no_memory); + 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; + } + + 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) malloc ((size_t) d->rel_hdr.sh_size); + if (allocated == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, +}; diff --git a/gnu/usr.bin/binutils/bfd/elfcore.h b/gnu/usr.bin/binutils/bfd/elfcore.h new file mode 100644 index 00000000000..690c9068438 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elfcore.h @@ -0,0 +1,484 @@ +/* ELF core file 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. */ +/* Core file support */ + +#ifdef HAVE_SYS_PROCFS_H /* Some core file support requires host /proc files */ +#include +#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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) 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) + { + bfd_set_error (bfd_error_no_memory); + 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 (abfd->xvec->byteorder_big_p == false) + goto wrong; + break; + case ELFDATA2LSB: /* Little-endian */ + if (abfd->xvec->byteorder_big_p == true) + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/elflink.c b/gnu/usr.bin/binutils/bfd/elflink.c new file mode 100644 index 00000000000..57a541f9544 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elflink.c @@ -0,0 +1,204 @@ +/* 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; +} diff --git a/gnu/usr.bin/binutils/bfd/elflink.h b/gnu/usr.bin/binutils/bfd/elflink.h new file mode 100644 index 00000000000..725aa930b13 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elflink.h @@ -0,0 +1,3146 @@ +/* ELF linker support. + 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. */ + +/* 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 *) malloc (c * sizeof (boolean)); + included = (boolean *) malloc (c * sizeof (boolean)); + if (defined == (boolean *) NULL || included == (boolean *) NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (extsymcount * sizeof (Elf_External_Sym)); + if (buf == NULL && extsymcount != 0) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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_needed_name, we use that. Otherwise, we just use the + file name. If the generic linker put a null string into + elf_dt_needed_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_needed_name (abfd) != NULL) + { + name = elf_dt_needed_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 *) malloc ((size_t) s->_raw_size); + if (dynbuf == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 (add_needed && 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; + + /* 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; + } + } + + 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 = false; + 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. */ + h = elf_link_hash_lookup (elf_hash_table (info), name, + true, false, false); + if (h == NULL) + goto error_return; + *sym_hash = h; + + 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. */ + type_change_ok = (h->root.type == bfd_link_hash_defweak + || h->root.type == bfd_link_hash_undefweak); + + /* 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. + */ + size_change_ok = (type_change_ok + || h->root.type == bfd_link_hash_undefined); + + /* 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.type == bfd_link_hash_defweak) + && 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); + if (s->contents == NULL) + newcontents = (bfd_byte *) malloc (newsize); + else + newcontents = (bfd_byte *) realloc (s->contents, newsize); + if (newcontents == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (size); + if (internal_relocs == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + } + + if (external_relocs == NULL) + { + alloc1 = (PTR) malloc ((size_t) rel_hdr->sh_size); + if (alloc1 == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 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; + 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. */ + if (elf_link_hash_lookup (elf_hash_table (info), "_init", false, + false, false) != NULL) + { + if (! elf_add_dynamic_entry (info, DT_INIT, 0)) + return false; + } + if (elf_link_hash_lookup (elf_hash_table (info), "_fini", false, + false, false) != NULL) + { + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 -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) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + p = ((struct elf_link_hash_entry **) + malloc (o->reloc_count + * sizeof (struct elf_link_hash_entry *))); + if (p == NULL && o->reloc_count != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc (finfo.symbuf_size * sizeof (Elf_External_Sym))); + if (finfo.symbuf == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + /* Start writing out the symbol table. The first symbol is always a + dummy symbol. */ + 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. */ + 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 *) malloc (max_contents_size); + finfo.external_relocs = (PTR) malloc (max_external_reloc_size); + finfo.internal_relocs = ((Elf_Internal_Rela *) + malloc (max_internal_reloc_count + * sizeof (Elf_Internal_Rela))); + finfo.external_syms = ((Elf_External_Sym *) + malloc (max_sym_count * sizeof (Elf_External_Sym))); + finfo.internal_syms = ((Elf_Internal_Sym *) + malloc (max_sym_count * sizeof (Elf_Internal_Sym))); + finfo.indices = (long *) malloc (max_sym_count * sizeof (long)); + finfo.sections = (asection **) 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)) + { + bfd_set_error (bfd_error_no_memory); + 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 (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; +{ + 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: + 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; + 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; + } + + /* If this is an inplace reloc, we must write the addend into the + object file. */ + if (howto->partial_inplace + && link_order->u.reloc.p->addend != 0) + { + bfd_size_type size; + bfd_reloc_status_type rstat; + bfd_byte *buf; + boolean ok; + + size = bfd_get_reloc_size (howto); + buf = (bfd_byte *) bfd_zmalloc (size); + if (buf == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + rstat = _bfd_relocate_contents (howto, output_bfd, + link_order->u.reloc.p->addend, buf); + switch (rstat) + { + case bfd_reloc_ok: + break; + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + if (! ((*info->callbacks->reloc_overflow) + (info, + (link_order->type == bfd_section_reloc_link_order + ? bfd_section_name (output_bfd, + link_order->u.reloc.p->u.section) + : link_order->u.reloc.p->u.name), + 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; + } + + /* 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; + + h = elf_link_hash_lookup (elf_hash_table (info), + link_order->u.reloc.p->u.name, + false, false, true); + 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; + } + } + + /* 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 = link_order->u.reloc.p->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; +} + diff --git a/gnu/usr.bin/binutils/bfd/elfxx-target.h b/gnu/usr.bin/binutils/bfd/elfxx-target.h new file mode 100644 index 00000000000..ebac006bc05 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/elfxx-target.h @@ -0,0 +1,443 @@ +/* Target definitions for NN-bit ELF + Copyright 1993, 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 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 + +#ifndef elf_backend_want_hdr_in_seg +#define elf_backend_want_hdr_in_seg 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_generic_bfd_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_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_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_create_program_headers +#define elf_backend_create_program_headers 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_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_create_program_headers, + 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, + elf_backend_want_hdr_in_seg, +}; + +#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_big_p: data is big endian */ + true, + + /* header_byteorder_big_p: header is also big endian */ + true, + + /* 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), + + /* 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 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_big_p: data is big endian */ + false, /* Nope -- this one's little endian */ + + /* header_byteorder_big_p: header is also big endian */ + false, /* Nope -- this one's little endian */ + + /* 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), + + /* 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 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/gnu/usr.bin/binutils/bfd/filemode.c b/gnu/usr.bin/binutils/bfd/filemode.c new file mode 100644 index 00000000000..fd790b36786 --- /dev/null +++ b/gnu/usr.bin/binutils/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 +#include + +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/gnu/usr.bin/binutils/bfd/format.c b/gnu/usr.bin/binutils/bfd/format.c new file mode 100644 index 00000000000..d51b04b3e05 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/format.c @@ -0,0 +1,322 @@ +/* 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 <> + + The BFD may contain data, symbols, relocations and debug info. + + o <> + + The BFD contains other BFDs and an optional index. + + o <> + + 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 <>, + <> or <>). + + If the BFD has been set to a specific target before the + call, only the named target and format combination is + checked. If the target has not been set, or has been set to + <>, then all the known target backends 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 <> on success, otherwise <> + with one of the following error codes: + + o <> - + if <> is not one of <>, <> or + <>. + + o <> - + if an error occured during a read - even some file mismatches + can cause bfd_error_system_calls. + + o <> - + none of the backends recognised the file format. + + o <> - + 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 <>, except when it returns false with + <> set to <>. In that + case, if @var{matching} is not NULL, it will be filled in with + a NULL-terminated list of the names of the formats that matched, + allocated with <>. + Then the user may choose a format and try again. + + When done with the list that @var{matching} points to, the caller + should free it. +*/ + +boolean +bfd_check_format_matches (abfd, format, matching) + bfd *abfd; + bfd_format format; + char ***matching; +{ + const bfd_target * const *target, *save_targ, *right_targ; + char **matching_vector = NULL; + int match_count; + + if (!bfd_read_p (abfd) || + ((int)(abfd->format) < (int)bfd_unknown) || + ((int)(abfd->format) >= (int)bfd_type_end)) { + bfd_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 **) malloc (sizeof (char *) * + (_bfd_target_vector_entries + 1)); + if (!matching_vector) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + matching_vector[0] = NULL; + *matching = matching_vector; + } + right_targ = 0; + + + /* 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 + <>, <>, <>, <>, or <>, + 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/gnu/usr.bin/binutils/bfd/gen-aout.c b/gnu/usr.bin/binutils/bfd/gen-aout.c new file mode 100644 index 00000000000..d2224f762d3 --- /dev/null +++ b/gnu/usr.bin/binutils/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 + +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/gnu/usr.bin/binutils/bfd/genlink.h b/gnu/usr.bin/binutils/bfd/genlink.h new file mode 100644 index 00000000000..5f080948574 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/hash.c b/gnu/usr.bin/binutils/bfd/hash.c new file mode 100644 index 00000000000..95b7c742067 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hash.c @@ -0,0 +1,739 @@ +/* hash.c -- hash table routines for BFD + Copyright (C) 1993, 94 Free Software Foundation, Inc. + Written by Steve Chamberlain + +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 <>. + +@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 <> (defined in <>) and call + <> (if you know approximately how many + entries you will need, the function <>, + which takes a @var{size} argument, may be used). + <> returns <> if some sort of + error occurs. + +@findex bfd_hash_newfunc + The function <> take as an argument a + function to use to create new entries. For a basic hash + table, use the function <>. @xref{Deriving + a New Hash Table Type} for why you would want to use a + different value for this argument. + +@findex bfd_hash_allocate + <> will create an obstack which will be + used to allocate new entries. You may allocate memory on this + obstack using <>. + +@findex bfd_hash_table_free + Use <> to free up all the memory that has + been allocated for a hash table. This will not free up the + <> 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 <> is used both to look up a + string in the hash table and to create a new entry. + + If the @var{create} argument is <>, <> + will look up a string. If the string is found, it will + returns a pointer to a <>. If the + string is not found in the table <> will + return <>. You should not modify any of the fields in + the returns <>. + + If the @var{create} argument is <>, the string will be + entered into the hash table if it is not already there. + Either way a pointer to a <> will be + returned, either to the existing structure or to a newly + created one. In this case, a <> return means that an + error occurred. + + If the @var{create} argument is <>, 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 <>, 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 <> may be used to traverse a + hash table, calling a function on each element. The traversal + is done in a random order. + + <> takes as arguments a function and a + generic <> pointer. The function is called with a + hash table entry (a <>) and the + generic pointer passed to <>. The function + must return a <> value, which indicates whether to + continue traversing the hash table. If the function returns + <>, <> 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 <>. The + functions are in <>. + + 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 <>, which is defined in + <>. 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 <>. + + For example, the linker hash table defines <> (in <>). The first field, + <>, is of type <>. Similarly, + the first field in <>, <>, + is of type <>. + +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 <>. + + 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 <>, 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 + <>, looks just like this example. + @var{function_name} is <<_bfd_link_hash_newfunc>>. + @var{entry_type} is <>. + @var{base_newfunc} is <>, the creation + routine for a basic hash table. + + <<_bfd_link_hash_newfunc>> also initializes the local fields + in a linker hash table entry: <>, <> and + <>. + +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 <>. + + 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 <> in + <> (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 + <> in <>. + + 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 <> and + <> 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (sizeof (struct bfd_strtab_hash)); + if (table == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/host-aout.c b/gnu/usr.bin/binutils/bfd/host-aout.c new file mode 100644 index 00000000000..2c0e9dbcfdb --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/host-aout.c @@ -0,0 +1,79 @@ +/* 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 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/gnu/usr.bin/binutils/bfd/hosts/alphalinux.h b/gnu/usr.bin/binutils/bfd/hosts/alphalinux.h new file mode 100644 index 00000000000..d9ba1b7ec6b --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/hosts/decstation.h b/gnu/usr.bin/binutils/bfd/hosts/decstation.h new file mode 100644 index 00000000000..a80c143d525 --- /dev/null +++ b/gnu/usr.bin/binutils/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 + +#include + +#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/gnu/usr.bin/binutils/bfd/hosts/delta68.h b/gnu/usr.bin/binutils/bfd/hosts/delta68.h new file mode 100644 index 00000000000..1a6a6e6f197 --- /dev/null +++ b/gnu/usr.bin/binutils/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 + +/* 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/gnu/usr.bin/binutils/bfd/hosts/dpx2.h b/gnu/usr.bin/binutils/bfd/hosts/dpx2.h new file mode 100644 index 00000000000..ea6395f2e5d --- /dev/null +++ b/gnu/usr.bin/binutils/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 +#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/gnu/usr.bin/binutils/bfd/hosts/hp300bsd.h b/gnu/usr.bin/binutils/bfd/hosts/hp300bsd.h new file mode 100644 index 00000000000..98287178207 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/hp300bsd.h @@ -0,0 +1,13 @@ +#include +#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/gnu/usr.bin/binutils/bfd/hosts/i386bsd.h b/gnu/usr.bin/binutils/bfd/hosts/i386bsd.h new file mode 100644 index 00000000000..ac0d8402edb --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/i386bsd.h @@ -0,0 +1,25 @@ +/* Intel 386 running any BSD Unix */ + +#include +#include + +#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/gnu/usr.bin/binutils/bfd/hosts/i386linux.h b/gnu/usr.bin/binutils/bfd/hosts/i386linux.h new file mode 100644 index 00000000000..13a51f1bd14 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/hosts/i386mach3.h b/gnu/usr.bin/binutils/bfd/hosts/i386mach3.h new file mode 100644 index 00000000000..dcc61e3c8e8 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/i386mach3.h @@ -0,0 +1,25 @@ +#include +#include + +/* 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/gnu/usr.bin/binutils/bfd/hosts/i386nbsd.h b/gnu/usr.bin/binutils/bfd/hosts/i386nbsd.h new file mode 100644 index 00000000000..1fd3bedf2db --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/i386nbsd.h @@ -0,0 +1,14 @@ +/* Intel 386 running NetBSD */ + +#ifndef hosts_i386bsd_H +#define hosts_i386bsd_H + +#include "hosts/nbsd.h" + +#define HOST_MACHINE_ARCH bfd_arch_i386 + +#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 +#endif + diff --git a/gnu/usr.bin/binutils/bfd/hosts/i386sco.h b/gnu/usr.bin/binutils/bfd/hosts/i386sco.h new file mode 100644 index 00000000000..ec8608c61dd --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/hosts/i860mach3.h b/gnu/usr.bin/binutils/bfd/hosts/i860mach3.h new file mode 100644 index 00000000000..edd2aa10a7b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/i860mach3.h @@ -0,0 +1,27 @@ +/* This file was hacked from i386mach3.h [dolan@ssd.intel.com] */ + +#include +#include + +/* 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/gnu/usr.bin/binutils/bfd/hosts/m68knbsd.h b/gnu/usr.bin/binutils/bfd/hosts/m68knbsd.h new file mode 100644 index 00000000000..8dccf674f39 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/m68knbsd.h @@ -0,0 +1,13 @@ +/* m68k hosts running NetBSD */ + +#ifndef hosts_m68knbsd_h +#define hosts_m68knbsd_h + +#include "hosts/nbsd.h" + +#define HOST_MACHINE_ARCH bfd_arch_m68k + +#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 +#endif diff --git a/gnu/usr.bin/binutils/bfd/hosts/m88kmach3.h b/gnu/usr.bin/binutils/bfd/hosts/m88kmach3.h new file mode 100644 index 00000000000..421553893ec --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/m88kmach3.h @@ -0,0 +1,11 @@ +#include +#include + +#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/gnu/usr.bin/binutils/bfd/hosts/mipsbsd.h b/gnu/usr.bin/binutils/bfd/hosts/mipsbsd.h new file mode 100644 index 00000000000..a2fad21fcf7 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/mipsbsd.h @@ -0,0 +1,12 @@ +#include +#include +#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/gnu/usr.bin/binutils/bfd/hosts/mipsmach3.h b/gnu/usr.bin/binutils/bfd/hosts/mipsmach3.h new file mode 100644 index 00000000000..c5c468d3742 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/mipsmach3.h @@ -0,0 +1,10 @@ +#include +#include +#include + +#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/gnu/usr.bin/binutils/bfd/hosts/mipsnbsd.h b/gnu/usr.bin/binutils/bfd/hosts/mipsnbsd.h new file mode 100644 index 00000000000..32e895a9908 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/mipsnbsd.h @@ -0,0 +1,13 @@ +/* mips running NetBSD */ + +#ifndef hosts_mips +#define hosts_mips + +#include "hosts/nbsd.h" + +#define HOST_MACHINE_ARCH bfd_arch_mips + +#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 +#endif diff --git a/gnu/usr.bin/binutils/bfd/hosts/nbsd.h b/gnu/usr.bin/binutils/bfd/hosts/nbsd.h new file mode 100644 index 00000000000..d773ee64960 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/nbsd.h @@ -0,0 +1,14 @@ +/* Architecture independant NetBSD host support */ + +#include +#include +#include +#include + +#define HOST_PAGE_SIZE NBPG +#define HOST_TEXT_START_ADDR USRTEXT +#define HOST_STACK_END_ADDR USRSTACK + +#if BYTE_ORDER == BIG_ENDIAN +#define HOST_BIG_ENDIAN_P +#endif diff --git a/gnu/usr.bin/binutils/bfd/hosts/news-mips.h b/gnu/usr.bin/binutils/bfd/hosts/news-mips.h new file mode 100644 index 00000000000..9e799bed904 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/news-mips.h @@ -0,0 +1,12 @@ +/* Sony News running NewsOS 3.2. */ + +#include +#include + +#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/gnu/usr.bin/binutils/bfd/hosts/news.h b/gnu/usr.bin/binutils/bfd/hosts/news.h new file mode 100644 index 00000000000..bf7946cdb99 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/news.h @@ -0,0 +1,9 @@ +/* Sony News running NewsOS 3.2. */ + +#include + +#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/gnu/usr.bin/binutils/bfd/hosts/ns32knbsd.h b/gnu/usr.bin/binutils/bfd/hosts/ns32knbsd.h new file mode 100644 index 00000000000..d072d6d1c0d --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/ns32knbsd.h @@ -0,0 +1,13 @@ +/* ns32k running NetBSD */ + +#ifndef hosts_ns32knbsd_h +#define hosts_ns32knbsd_h + +#include "hosts/nbsd.h" + +#define HOST_MACHINE_ARCH bfd_arch_ns32k + +#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 +#endif diff --git a/gnu/usr.bin/binutils/bfd/hosts/pc532mach.h b/gnu/usr.bin/binutils/bfd/hosts/pc532mach.h new file mode 100644 index 00000000000..ab96f597edd --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/pc532mach.h @@ -0,0 +1,24 @@ +#include +#include + +/* 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/gnu/usr.bin/binutils/bfd/hosts/riscos.h b/gnu/usr.bin/binutils/bfd/hosts/riscos.h new file mode 100644 index 00000000000..8ffa826bdcf --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/riscos.h @@ -0,0 +1,10 @@ +/* RISC/os 4.52C, and presumably other versions. */ + +#include +#include + +#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/gnu/usr.bin/binutils/bfd/hosts/sparcnbsd.h b/gnu/usr.bin/binutils/bfd/hosts/sparcnbsd.h new file mode 100644 index 00000000000..c0a4a8d4639 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/sparcnbsd.h @@ -0,0 +1,18 @@ +/* Sparc running NetBSD */ + +#ifndef hosts_sparcnbsd_h +#define hosts_sparcnbsd_h + +#include "hosts/nbsd.h" + +#define HOST_MACHINE_ARCH bfd_arch_sparc + +#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 +#define TRAD_CORE_REGPOS(core_bfd) \ + ((bfd_vma)(core_bfd)->tdata.trad_core_data->u.u_kproc.kp_proc.p_md.md_tf) + +#define CORE_FPU_OFFSET (sizeof(struct trapframe)) + +#endif diff --git a/gnu/usr.bin/binutils/bfd/hosts/symmetry.h b/gnu/usr.bin/binutils/bfd/hosts/symmetry.h new file mode 100644 index 00000000000..75717b31eb2 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/hosts/tahoe.h b/gnu/usr.bin/binutils/bfd/hosts/tahoe.h new file mode 100644 index 00000000000..716cee2a171 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/tahoe.h @@ -0,0 +1,12 @@ +#define NO_CORE_COMMAND + +#undef ALIGN /* They use it, we use it too */ +#include +#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/gnu/usr.bin/binutils/bfd/hosts/vaxbsd.h b/gnu/usr.bin/binutils/bfd/hosts/vaxbsd.h new file mode 100644 index 00000000000..ceb9ccedfaf --- /dev/null +++ b/gnu/usr.bin/binutils/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 , which trad-core.c, + the only place that uses this (I think), already includes. */ +#include +#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/gnu/usr.bin/binutils/bfd/hosts/vaxult.h b/gnu/usr.bin/binutils/bfd/hosts/vaxult.h new file mode 100644 index 00000000000..13731b7479f --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/vaxult.h @@ -0,0 +1,8 @@ +#include +#include +#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/gnu/usr.bin/binutils/bfd/hosts/vaxult2.h b/gnu/usr.bin/binutils/bfd/hosts/vaxult2.h new file mode 100644 index 00000000000..13731b7479f --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hosts/vaxult2.h @@ -0,0 +1,8 @@ +#include +#include +#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/gnu/usr.bin/binutils/bfd/hp300bsd.c b/gnu/usr.bin/binutils/bfd/hp300bsd.c new file mode 100644 index 00000000000..5767b18c179 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/hp300hpux.c b/gnu/usr.bin/binutils/bfd/hp300hpux.c new file mode 100644 index 00000000000..f42f97cab99 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hp300hpux.c @@ -0,0 +1,874 @@ +/* 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 + + 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); + + /* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + nomem: + bfd_set_error (bfd_error_no_memory); + return false; + } + + relocs = (PTR) bfd_alloc (abfd, reloc_size); + if (!relocs && reloc_size != 0) + { + bfd_release (abfd, reloc_cache); + goto nomem; + } + + if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) + { + bfd_release (abfd, relocs); + bfd_release (abfd, reloc_cache); + 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/gnu/usr.bin/binutils/bfd/hppa_stubs.h b/gnu/usr.bin/binutils/bfd/hppa_stubs.h new file mode 100644 index 00000000000..ee893e8a57b --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/hppabsd-core.c b/gnu/usr.bin/binutils/bfd/hppabsd-core.c new file mode 100644 index 00000000000..7bf1361c078 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/hppabsd-core.c @@ -0,0 +1,308 @@ +/* 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 +#include +#include +#include +#include +#include +#include /* After a.out.h */ +#include +#include + +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) + { + bfd_set_error (bfd_error_no_memory); + 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_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/gnu/usr.bin/binutils/bfd/hpux-core.c b/gnu/usr.bin/binutils/bfd/hpux-core.c new file mode 100644 index 00000000000..6caadd85b20 --- /dev/null +++ b/gnu/usr.bin/binutils/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 +#include + +#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 +#include +#include +#include +#include +#include +#include /* After a.out.h */ +#include +#include + +/* 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_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/gnu/usr.bin/binutils/bfd/i386aout.c b/gnu/usr.bin/binutils/bfd/i386aout.c new file mode 100644 index 00000000000..0801832d16d --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/i386bsd.c b/gnu/usr.bin/binutils/bfd/i386bsd.c new file mode 100644 index 00000000000..2328fe3e9e8 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/i386dynix.c b/gnu/usr.bin/binutils/bfd/i386dynix.c new file mode 100644 index 00000000000..ff50a1450a1 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/i386linux.c b/gnu/usr.bin/binutils/bfd/i386linux.c new file mode 100644 index 00000000000..5f27ed0f1d5 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/i386linux.c @@ -0,0 +1,768 @@ +/* BFD back-end for linux flavored i386 a.out binaries. + Copyright (C) 1992, 1993, 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. */ + +#define TARGET_PAGE_SIZE 4096 +#define ZMAGIC_DISK_BLOCK_SIZE 1024 +#define SEGMENT_SIZE 4096 +#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) + { + 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 *) 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_linux_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) + { + /* 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/gnu/usr.bin/binutils/bfd/i386lynx.c b/gnu/usr.bin/binutils/bfd/i386lynx.c new file mode 100644 index 00000000000..303fd585e11 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/i386lynx.c @@ -0,0 +1,570 @@ +/* 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 (abfd->xvec->header_byteorder_big_p != false) + { + 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 (abfd->xvec->header_byteorder_big_p != false) + { + 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 *) malloc (count * sizeof (arelent)); + if (!reloc_cache && count != 0) + { + nomem: + bfd_set_error (bfd_error_no_memory); + return false; + } + memset (reloc_cache, 0, count * sizeof (arelent)); + + relocs = (PTR) bfd_alloc (abfd, reloc_size); + if (!relocs && reloc_size != 0) + { + free (reloc_cache); + goto nomem; + } + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/i386mach3.c b/gnu/usr.bin/binutils/bfd/i386mach3.c new file mode 100644 index 00000000000..72a28f33bf0 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/i386msdos.c b/gnu/usr.bin/binutils/bfd/i386msdos.c new file mode 100644 index 00000000000..796be2dead3 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/i386msdos.c @@ -0,0 +1,260 @@ +/* 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 +typedef struct msdos_data_struct + { +#if 0 + srec_data_list_type *head; + unsigned int type; + + int done_symbol_read; + int count; + asymbol *symbols; + char *strings; + int symbol_idx; + int string_size; + int string_idx; +#endif + } +tdata_type; +#endif + +#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_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, + false, /* target byte order */ + false, /* 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/gnu/usr.bin/binutils/bfd/i386netbsd.c b/gnu/usr.bin/binutils/bfd/i386netbsd.c new file mode 100644 index 00000000000..e92b27a3fca --- /dev/null +++ b/gnu/usr.bin/binutils/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 4096 + +#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/gnu/usr.bin/binutils/bfd/i386os9k.c b/gnu/usr.bin/binutils/bfd/i386os9k.c new file mode 100644 index 00000000000..0faf6000f6e --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/i386os9k.c @@ -0,0 +1,373 @@ +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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, + false, /* data byte order is little */ + false, /* hdr byte order is big */ + (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/gnu/usr.bin/binutils/bfd/ieee.c b/gnu/usr.bin/binutils/bfd/ieee.c new file mode 100644 index 00000000000..a5b7f91b7bf --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/ieee.c @@ -0,0 +1,3437 @@ +/* BFD back-end for ieee-695 objects. + 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. */ + +#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" +#include "obstack.h" +#define obstack_chunk_alloc malloc +#define obstack_chunk_free free + +/* Functions for writing to ieee files in the strange way that the + standard requires. */ + +static void +ieee_write_byte (abfd, byte) + bfd *abfd; + bfd_byte byte; +{ + if (bfd_write ((PTR) & byte, 1, 1, abfd) != 1) + abort (); +} + +static void +ieee_write_twobyte (abfd, twobyte) + bfd *abfd; + int twobyte; +{ + bfd_byte b[2]; + b[1] = twobyte & 0xff; + b[0] = twobyte >> 8; + if (bfd_write ((PTR) & b[0], 1, 2, abfd) != 2) + abort (); +} + +static void +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) + abort (); +} + +static void +ieee_write_int (abfd, value) + bfd *abfd; + bfd_vma value; +{ + if (((unsigned) value) <= 127) + { + ieee_write_byte (abfd, (bfd_byte) 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; + + ieee_write_byte (abfd, + (bfd_byte) ((int) ieee_number_repeat_start_enum + length)); + switch (length) + { + case 4: + ieee_write_byte (abfd, (bfd_byte) (value >> 24)); + case 3: + ieee_write_byte (abfd, (bfd_byte) (value >> 16)); + case 2: + ieee_write_byte (abfd, (bfd_byte) (value >> 8)); + case 1: + ieee_write_byte (abfd, (bfd_byte) (value)); + } + } +} + +static void +ieee_write_id (abfd, id) + bfd *abfd; + CONST char *id; +{ + size_t length = strlen (id); + if (length <= 127) + { + ieee_write_byte (abfd, (bfd_byte) length); + } + else if (length < 255) + { + ieee_write_byte (abfd, ieee_extension_length_1_enum); + ieee_write_byte (abfd, (bfd_byte) length); + } + else if (length < 65535) + { + ieee_write_byte (abfd, ieee_extension_length_2_enum); + ieee_write_byte (abfd, (bfd_byte) (length >> 8)); + ieee_write_byte (abfd, (bfd_byte) (length & 0xff)); + } + else + { + BFD_FAIL (); + } + if (bfd_write ((PTR) id, 1, length, abfd) != length) + abort (); +} + + +/*************************************************************************** +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) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + bfd_get_string (ieee, string, length); + string[length] = 0; + return string; +} + +static void +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) + { + ieee_write_int (abfd, value); + term_count++; + } + + if (bfd_is_com_section (symbol->section) + || bfd_is_und_section (symbol->section)) + { + /* Def of a common symbol */ + ieee_write_byte (abfd, ieee_variable_X_enum); + ieee_write_int (abfd, symbol->value); + term_count++; + } + else if (! bfd_is_abs_section (symbol->section)) + { + /* Ref to defined symbol - */ + + ieee_write_byte (abfd, ieee_variable_R_enum); + ieee_write_byte (abfd, + (bfd_byte) (symbol->section->index + IEEE_SECTION_NUMBER_BASE)); + term_count++; + if (symbol->flags & BSF_GLOBAL) + { + ieee_write_byte (abfd, ieee_variable_I_enum); + ieee_write_int (abfd, symbol->value); + 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 */ + ieee_write_byte (abfd, ieee_variable_R_enum); /* or L */ + ieee_write_byte (abfd, + (bfd_byte) (symbol->section->index + IEEE_SECTION_NUMBER_BASE)); + ieee_write_int (abfd, symbol->value); + term_count++; + } + else + { + BFD_FAIL (); + } + } + + if (pcrel) + { + /* subtract the pc from here by asking for PC of this section*/ + 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); + } + + if (term_count == 1) + { + ieee_write_byte (abfd, 0); + } + else + { + while (term_count > 1) + { + ieee_write_byte (abfd, ieee_function_plus_enum); + term_count--; + } + } +} + + +/*****************************************************************************/ + +/* +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 void +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) + abort (); +} + +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; + + +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, 0xffffffff, + 0xffffffff, false); + +static +reloc_howto_type rel16_howto += HOWTO (1, 0, 1, 16, true, 0, complain_overflow_signed, 0, "rel16", true, 0x0000ffff, 0x0000ffff, false); + +static +reloc_howto_type rel8_howto += HOWTO (1, 0, 0, 8, true, 0, complain_overflow_signed, 0, "rel8", true, 0x000000ff, 0x000000ff, false); + + +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, + TOS.value = ieee->section_table[section_n]->vma + + ieee_per_section (ieee->section_table[section_n])->pc); + 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: + 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, value1 - value2); + } + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + 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, 'D'); + 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; + next_byte (&(ieee->h)); /* Skip prefix */ + next_byte (&(ieee->h)); + 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 63: + /* Module misc; followed by two fields which describe the + current module block. The first fired is the type id + number, the second is the number of asn records + associated with the directive */ + parse_int (&(ieee->h), &value); + parse_int (&(ieee->h), &value); + break; + + default: + 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) + { + bfd_set_error (bfd_error_no_memory); + 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)); + switch (section_type[0]) + { + case 0xC1: + /* Normal attributes for absolute sections */ + section_type[1] = this_byte (&(ieee->h)); + section->flags = SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS; + 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_LOAD | SEC_CODE; + break; + case 0xC4: + next_byte (&(ieee->h)); + section->flags |= SEC_LOAD | SEC_DATA; + /* Normal data */ + break; + case 0xD2: + next_byte (&(ieee->h)); + /* Normal rom data */ + section->flags |= SEC_LOAD | 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_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS; + switch (section_type[1]) + { + case 0xD0: /* Normal code (CP) */ + next_byte (&(ieee->h)); + section->flags |= SEC_LOAD | SEC_CODE; + break; + case 0xC4: /* Normal data (CD) */ + next_byte (&(ieee->h)); + section->flags |= SEC_LOAD | SEC_DATA; + break; + case 0xD2: /* Normal rom data (CR) */ + next_byte (&(ieee->h)); + section->flags |= SEC_LOAD | 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)); + 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)); + break; + case ieee_section_offset_enum: + (void) must_parse_int (&(ieee->h)); + (void) must_parse_int (&(ieee->h)); + break; + default: + return; + } + } + break; + default: + return; + } + } + } +} + + +/*********************************************************************** +* archive stuff +*/ + +const bfd_target * +ieee_archive_p (abfd) + bfd *abfd; +{ + char *library; + boolean loop; + + unsigned int i; + unsigned char buffer[512]; + struct obstack ob; + 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) + { + bfd_set_error (bfd_error_no_memory); + 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)); + /* This must be an IEEE archive, so we'll buy some space to do + things */ + + if (!obstack_begin (&ob, 128)) + { + bfd_set_error (bfd_error_no_memory); + return (const bfd_target *) NULL; + } + + 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++; + + obstack_grow (&ob, (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 *) obstack_finish (&ob); + if (!ieee->elements) + { + bfd_set_error (bfd_error_no_memory); + 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; + } + + } + 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 + + 50); + if (!IEEE_DATA (abfd)->h.first_byte) + { + bfd_set_error (bfd_error_no_memory); + 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 + 50, abfd); + + ieee_slurp_sections (abfd); + 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 ? + (CONST char *) "*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, /* + aout_symbol(symbol)->desc & 0xffff, + aout_symbol(symbol)->other & 0xff,*/ + symbol->name); + } + } + break; + } +} + +static boolean +do_one (ieee, current_map, location_ptr, s) + ieee_data_type *ieee; + ieee_per_section_type *current_map; + unsigned char *location_ptr; + asection *s; +{ + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, §ion); + r->relent.address = current_map->pc; + 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 (); + break; + } + } + 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; + } + } + } + } + } + } + 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; + per->data = (bfd_byte *) bfd_alloc (ieee->h.abfd, s->_raw_size); + if (!per->data) + { + bfd_set_error (bfd_error_no_memory); + 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]; + 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 true; + } + 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)) + 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)) + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 (! 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; + 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); + + while (src != (ieee_reloc_type *) NULL) + { + /* Work out which symbol to attach it this reloc to */ + switch (src->symbol.letter) + { + 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 void +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)) + { + ieee_write_byte (abfd, ieee_section_type_enum); + ieee_write_byte (abfd, (bfd_byte) (s->index + IEEE_SECTION_NUMBER_BASE)); + + if (abfd->flags & EXEC_P) + { + /* This image is executable, so output absolute sections */ + ieee_write_byte (abfd, ieee_variable_A_enum); + ieee_write_byte (abfd, ieee_variable_S_enum); + } + else + { + ieee_write_byte (abfd, ieee_variable_C_enum); + } + + switch (s->flags & (SEC_CODE | SEC_DATA | SEC_ROM)) + { + case SEC_CODE | SEC_LOAD: + case SEC_CODE: + ieee_write_byte (abfd, ieee_variable_P_enum); + break; + case SEC_DATA: + default: + ieee_write_byte (abfd, ieee_variable_D_enum); + break; + case SEC_ROM: + case SEC_ROM | SEC_DATA: + case SEC_ROM | SEC_LOAD: + case SEC_ROM | SEC_DATA | SEC_LOAD: + + ieee_write_byte (abfd, ieee_variable_R_enum); + } + + + ieee_write_id (abfd, s->name); +#if 0 + ieee_write_int (abfd, 0); /* Parent */ + ieee_write_int (abfd, 0); /* Brother */ + ieee_write_int (abfd, 0); /* Context */ +#endif + /* Alignment */ + 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); + + /* Size */ + 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); + if (abfd->flags & EXEC_P) + { + /* Relocateable sections don't have asl records */ + /* Vma */ + 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); + } + } + + } +} + + +static boolean +do_with_relocs (abfd, s) + bfd *abfd; + asection *s; +{ + 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 */ + ieee_write_byte (abfd, ieee_set_current_section_enum); + ieee_write_byte (abfd, (bfd_byte) (s->index + IEEE_SECTION_NUMBER_BASE)); + + ieee_write_twobyte (abfd, ieee_set_current_pc_enum); + ieee_write_byte (abfd, (bfd_byte) (s->index + IEEE_SECTION_NUMBER_BASE)); + ieee_write_expression (abfd, 0, s->symbol, 0, 0); + + if (relocs_to_go == 0) + { + /* If there arn'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 = 32; + run = MAXRUN; + if (run > s->_raw_size - current_byte_index) + { + run = s->_raw_size - current_byte_index; + } + + if (run != 0) + { + ieee_write_byte (abfd, ieee_load_constant_bytes_enum); + /* Output a stream of bytes */ + ieee_write_int (abfd, run); + if (bfd_write ((PTR) (stream + current_byte_index), + 1, + run, + abfd) + != run) + return false; + current_byte_index += run; + } + } + } + else + { + ieee_write_byte (abfd, ieee_load_with_relocation_enum); + + + /* 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = 32; + if (relocs_to_go) + { + run = (*p)->address - current_byte_index; + } + 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 */ + ieee_write_int (abfd, run); + 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_vma ov; + +#if 0 + if (r->howto->pc_relative) + { + r->addend += current_byte_index; + } +#endif + + switch (r->howto->size) + { + case 2: + + ov = bfd_get_32 (abfd, + stream + current_byte_index); + current_byte_index += 4; + break; + case 1: + ov = bfd_get_16 (abfd, + stream + current_byte_index); + current_byte_index += 2; + break; + case 0: + ov = bfd_get_8 (abfd, + stream + current_byte_index); + current_byte_index++; + break; + default: + ov = 0; + BFD_FAIL (); + } + ieee_write_byte (abfd, ieee_function_either_open_b_enum); +/* abort();*/ + + if (r->sym_ptr_ptr != (asymbol **) NULL) + { + ieee_write_expression (abfd, r->addend + ov, + *(r->sym_ptr_ptr), + r->howto->pc_relative, s->index); + } + else + { + ieee_write_expression (abfd, r->addend + ov, + (asymbol *) NULL, + r->howto->pc_relative, s->index); + } + + if (1 || r->howto->size != 2) + { + ieee_write_byte (abfd, ieee_comma); + ieee_write_int (abfd, 1 << r->howto->size); + } + ieee_write_byte (abfd, + ieee_function_either_close_b_enum); + + 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 void +do_as_repeat (abfd, s) + bfd *abfd; + asection *s; +{ + if (s->_raw_size) + { + 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); + } +} + +static void +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)) + { + do_as_repeat (abfd, s); + } + else + { + unsigned int i; + for (i = 0; i < s->_raw_size; i++) + { + if (stream[i] != 0) + { + do_with_relocs (abfd, s); + return; + } + } + do_as_repeat (abfd, s); + } + +} + + +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 void +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) + { +#if 0 + /* There is no debug info, so we'll fake some up */ + CONST static char fake[] = + { + 0xf8, 0xa, 0, 5, 't', 't', 't', 't', 't', 0, 2, 3, + '1', '.', '1', 0x82, 1991 >> 8, 1991 & 0xff, 9, 20, 11, 07, 50}; + ieee->w.r.debug_information_part = 0; + + + here; + + + /* bfd_write(fake, 1, sizeof(fake), abfd);*/ + /* Now write a header for each section */ + { + int i = 0; + asection *s = abfd->sections; + while (s) + { + if (s != abfd->abs_section) + { + + ieee_write_byte (abfd, 0xf8); + ieee_write_byte (abfd, 0x0b); + ieee_write_byte (abfd, 0); + ieee_write_byte (abfd, 0); + ieee_write_byte (abfd, 1); + ieee_write_byte (abfd, i + IEEE_SECTION_NUMBER_BASE); + ieee_write_expression (abfd, 0, s->symbol, 0, 0, 0); + ieee_write_byte (abfd, 0); + ieee_write_byte (abfd, 0xf9); + ieee_write_expression (abfd, s->size, + bfd_abs_section_ptr->symbol, 0, 0, 0); + i++; + } + + s = s->next; + + } + /* Close the scope */ + ieee_write_byte (abfd, 0xf9); + } +#endif + } + 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) + abort (); + 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 (); + +} + +/* write the data in an ieee way */ +static void +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) + { + /* Sort the reloc records so we can insert them in the correct + places */ + if (s->reloc_count != 0) + { + do_with_relocs (abfd, s); + } + else + { + do_without_relocs (abfd, s); + } + } +} + + +static boolean +init_for_output (abfd) + bfd *abfd; +{ + asection *s; + for (s = abfd->sections; s != (asection *) NULL; s = s->next) + { + if (s->_raw_size != 0) + { + ieee_per_section (s)->data = (bfd_byte *) (bfd_alloc (abfd, s->_raw_size)); + if (!ieee_per_section (s)->data) + { + bfd_set_error (bfd_error_no_memory); + 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 (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 void +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 .. */ + ieee_write_byte (abfd, ieee_external_reference_enum); + ieee_write_int (abfd, reference_index); + ieee_write_id (abfd, p->name); + p->value = reference_index; + reference_index++; + } + else if (bfd_is_com_section (p->section)) + { + /* This is a weak reference */ + 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); + ieee_write_int (abfd, BFD_FORT_COMM_DEFAULT_VALUE); + p->value = reference_index; + reference_index++; + } + else if (p->flags & BSF_GLOBAL) + { + /* This must be a symbol definition */ + + + ieee_write_byte (abfd, ieee_external_symbol_enum); + ieee_write_int (abfd, public_index); + ieee_write_id (abfd, p->name); + + ieee_write_twobyte (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 */ + + + /* Write out the value */ + ieee_write_2bytes (abfd, ieee_value_record_enum); + ieee_write_int (abfd, public_index); + if (! bfd_is_abs_section (p->section)) + { + if (abfd->flags & EXEC_P) + { + /* If fully linked, then output all symbols + relocated */ + ieee_write_int (abfd, + p->value + p->section->output_offset + p->section->output_section->vma); + + } + else + { + ieee_write_expression (abfd, + p->value + p->section->output_offset, + p->section->output_section->symbol + ,false, 0); + } + } + else + { + ieee_write_expression (abfd, + p->value, + bfd_abs_section_ptr->symbol, + false, 0); + } + 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; + +} + + +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 +void +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) + { + ieee->w.r.me_record = bfd_tell (abfd); + 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); + } + else + { + ieee->w.r.me_record = bfd_tell (abfd); + } + ieee_write_byte (abfd, ieee_module_end_enum); + +} + +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; + ieee_write_byte (abfd, ieee_module_beginning_enum); + + ieee_write_id (abfd, bfd_printable_name (abfd)); + ieee_write_id (abfd, abfd->filename); + + /* Fast forward over the variable bits */ + ieee_write_byte (abfd, ieee_address_descriptor_enum); + + /* Bits per MAU */ + ieee_write_byte (abfd, (bfd_byte) (bfd_arch_bits_per_byte (abfd))); + /* MAU's per address */ + ieee_write_byte (abfd, + (bfd_byte) (bfd_arch_bits_per_address (abfd) / bfd_arch_bits_per_byte (abfd))); + + 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) + ieee_write_byte (abfd, 0x1);/* Absolute */ + else + ieee_write_byte (abfd, 0x2);/* Relocateable */ + + 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 (); + + ieee_write_section_part (abfd); + /* + First write the symbols, this changes their values into table + indeces so we cant use it after this point + */ + ieee_write_external_part (abfd); + /* ieee_write_byte(abfd, ieee_record_seperator_enum);*/ + + + /* ieee_write_byte(abfd, ieee_record_seperator_enum);*/ + + + /* + Write any debugs we have been told about + */ + ieee_write_debug_part (abfd); + + /* + Can only write the data once the symbols have been written since + the data contains relocation information which points to the + symbols + */ + ieee_write_data_part (abfd); + + + /* + At the end we put the end ! + */ + ieee_write_me_part (abfd); + + + /* Generate the header */ + if (bfd_seek (abfd, old, SEEK_SET) != 0) + return false; + + for (i = 0; i < N_W_VARIABLES; i++) + { + 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 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) + { + bfd_set_error (bfd_error_no_error); + 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 + { + buf->st_size = 0x1; + buf->st_mode = 0666; + return !ieee_object_p (abfd); + } +} + +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) + { + bfd_set_error (bfd_error_no_memory); + 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_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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS + | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 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/gnu/usr.bin/binutils/bfd/init.c b/gnu/usr.bin/binutils/bfd/init.c new file mode 100644 index 00000000000..1fa1d505bee --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/irix-core.c b/gnu/usr.bin/binutils/bfd/irix-core.c new file mode 100644 index 00000000000..44fb01c3e4a --- /dev/null +++ b/gnu/usr.bin/binutils/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 + +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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_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/gnu/usr.bin/binutils/bfd/libaout.h b/gnu/usr.bin/binutils/bfd/libaout.h new file mode 100644 index 00000000000..7c4b012f5dc --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/libaout.h @@ -0,0 +1,613 @@ +/* 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 + +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 *)); + +/* Prototypes for functions in stab-syms.c. */ + +CONST char * +aout_stab_name PARAMS ((int code)); + +/* A.out uses the generic versions of these routines... */ + +#define aout_32_get_section_contents _bfd_generic_get_section_contents + +#define aout_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/gnu/usr.bin/binutils/bfd/libbfd-in.h b/gnu/usr.bin/binutils/bfd/libbfd-in.h new file mode 100644 index 00000000000..9c5a633b29d --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/libbfd-in.h @@ -0,0 +1,477 @@ +/* libbfd.h -- Declarations used by bfd library *implementation*. + (This include file is not for users of the library.) + Copyright 1990, 1991, 1992, 1993, 1994, 1995 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)) + +/* 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) + +char *bfd_zmalloc PARAMS ((bfd_size_type size)); + +extern bfd_error_handler_type _bfd_error_handler; + +/* These routines allocate and free things on the BFD's obstack. Note + that realloc can never occur in place. */ + +PTR bfd_alloc PARAMS ((bfd *abfd, size_t size)); +PTR bfd_zalloc PARAMS ((bfd *abfd, size_t size)); +PTR bfd_realloc PARAMS ((bfd *abfd, PTR orig, size_t 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)); +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 *)); + +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_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_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_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 *)); + +/* 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 *)); + +/* And more follows */ + diff --git a/gnu/usr.bin/binutils/bfd/libbfd.c b/gnu/usr.bin/binutils/bfd/libbfd.c new file mode 100644 index 00000000000..73805f9b326 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/libbfd.c @@ -0,0 +1,1118 @@ +/* Assorted BFD support routines, only used internally. + Copyright 1990, 91, 92, 93, 94 Free Software Foundation, Inc. + Written by Cygnus Support. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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; +} + + +#ifndef bfd_zmalloc +/* allocate and clear storage */ + +char * +bfd_zmalloc (size) + bfd_size_type size; +{ + char *ptr = (char *) malloc ((size_t) size); + + if (ptr && size) + memset(ptr, 0, (size_t) size); + + return ptr; +} +#endif /* bfd_zmalloc */ + +/* 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; + 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 +#include +#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)) + { + 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); + if (i->data) + i->data = (PTR) realloc (i->data, size_to_alloc); + else + i->data = (PTR) malloc (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 = 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; + + ptr = ftell (bfd_cache_lookup(abfd)); + + if (abfd->my_archive) + ptr -= abfd->origin; + abfd->where = ptr; + return ptr; +} + +int +bfd_flush (abfd) + bfd *abfd; +{ + 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; + 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; +#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. getshort 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 <> + to either <> or <>. + + In the put routines, @var{val} must be a <>. If we are on a + system without prototypes, the caller is responsible for making + sure that is true, with a cast if necessary. We don't cast + them in the macro definitions because that would prevent <> + or <> from detecting sins such as passing a pointer. + To detect calling these with less than a <>, use + <> on a host with 64 bit <>'s. + +. +.{* Byte swapping macros for user section data. *} +. +.#define bfd_put_8(abfd, val, ptr) \ +. (*((unsigned char *)(ptr)) = (unsigned char)(val)) +.#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 <> + 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) 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/gnu/usr.bin/binutils/bfd/libbfd.h b/gnu/usr.bin/binutils/bfd/libbfd.h new file mode 100644 index 00000000000..75cb5d8c475 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/libbfd.h @@ -0,0 +1,687 @@ +/* libbfd.h -- Declarations used by bfd library *implementation*. + (This include file is not for users of the library.) + Copyright 1990, 1991, 1992, 1993, 1994, 1995 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)) + +/* 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) + +char *bfd_zmalloc PARAMS ((bfd_size_type size)); + +extern bfd_error_handler_type _bfd_error_handler; + +/* These routines allocate and free things on the BFD's obstack. Note + that realloc can never occur in place. */ + +PTR bfd_alloc PARAMS ((bfd *abfd, size_t size)); +PTR bfd_zalloc PARAMS ((bfd *abfd, size_t size)); +PTR bfd_realloc PARAMS ((bfd *abfd, PTR orig, size_t 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)); +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 *)); + +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_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_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_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 *)); + +/* 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 *)); + +/* 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_LO7", + "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_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_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/gnu/usr.bin/binutils/bfd/libcoff-in.h b/gnu/usr.bin/binutils/bfd/libcoff-in.h new file mode 100644 index 00000000000..b7ae83b36b6 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/libcoff-in.h @@ -0,0 +1,339 @@ +/* BFD COFF object file private structure. + 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. */ + +#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; +} 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; + + /* Section holding TOC. */ + asection *toc_section; + + /* Section holding entry point. */ + asection *entry_section; + + /* .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 in cofflink.c. */ + +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 **)); + +#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/gnu/usr.bin/binutils/bfd/libcoff.h b/gnu/usr.bin/binutils/bfd/libcoff.h new file mode 100644 index 00000000000..80102ba16e4 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/libcoff.h @@ -0,0 +1,666 @@ +/* BFD COFF object file private structure. + 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. */ + +#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; +} 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; + + /* Section holding TOC. */ + asection *toc_section; + + /* Section holding entry point. */ + asection *entry_section; + + /* .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 in cofflink.c. */ + +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 **)); + +#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)); + +} 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)) + diff --git a/gnu/usr.bin/binutils/bfd/libecoff.h b/gnu/usr.bin/binutils/bfd/libecoff.h new file mode 100644 index 00000000000..6791a7a6f5f --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/libecoff.h @@ -0,0 +1,336 @@ +/* BFD ECOFF object file private structure. + 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. */ + +#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 *)); +}; + +/* 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; + + /* 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; +}; + +/* 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_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/gnu/usr.bin/binutils/bfd/libhppa.h b/gnu/usr.bin/binutils/bfd/libhppa.h new file mode 100644 index 00000000000..dd863aa32f3 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/libhppa.h @@ -0,0 +1,537 @@ +/* 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}; + +/* 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_PSEL = 0x9, + R_HPPA_LPSEL = 0xa, + R_HPPA_RPSEL = 0xb, + R_HPPA_TSEL = 0xc, + R_HPPA_LTSEL = 0xd, + R_HPPA_RTSEL = 0xe + }; + +/* /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_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_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 */ + 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 */ + 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 */ + 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/gnu/usr.bin/binutils/bfd/libieee.h b/gnu/usr.bin/binutils/bfd/libieee.h new file mode 100644 index 00000000000..c3729cbf517 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/libnlm.h b/gnu/usr.bin/binutils/bfd/libnlm.h new file mode 100644 index 00000000000..12d2e4e0cf8 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/liboasys.h b/gnu/usr.bin/binutils/bfd/liboasys.h new file mode 100644 index 00000000000..2d158137656 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/linker.c b/gnu/usr.bin/binutils/bfd/linker.c new file mode 100644 index 00000000000..2141b6ac066 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/linker.c @@ -0,0 +1,2725 @@ +/* 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 <> structure (defined in + <>) 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 <>, and use the + header file <>. As of this writing, the only back + ends which have implemented versions of these routines are + a.out (in <>) and ECOFF (in <>). 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 <> described in + <>. @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 <>. 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 <>. The a.out linker + hash table is created by the function + <>; 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 + <>. + +@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 <>. + + 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 <> + 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 <> for an example of how to + check the <> 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 + <> to read the symbols. The point of + providing this routine is to avoid the overhead of converting + the symbols into generic <> 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 <> or + <>. The section is a section in the object + file, or something like <> for an undefined + symbol or <> 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 + <> field of the <> 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 + <>, and most of the interesting + work is in <>. 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 + <> 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 <> 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 <> as the function + argument. <> calls + <>. 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 <> callback and then + <> calls + <> 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 <> 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 <>. + +@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 <> field of the <> structure + will point to a list of all the input files included in the + link. These files are linked through the <> field + of the <> structure. + + Each section in the output file will have a list of + <> structures attached to the <> + field (the <> structure is defined in + <>). 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 + <> structures attached to each section of the + output file. Each <> 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 <>). + + For efficiency, a <> of type + <> whose associated section belongs + to a BFD of the same format as the output BFD must be handled + specially. This type of <> 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 <> argument + which describes the relocation to perform. These functions + are defined in <>. + + The a.out function which handles reading, relocating, and + writing section contents is <>. The + actual relocation is done in <> + and <>. + +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 <> and <> fields of the + <> 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 <> structures, or it may be + done by stepping through the <> 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 <> field of the <> structure + controls which symbols are written out. The possible values + are listed in <>. If the value is <>, + then the <> field of the <> + 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 <> field of the <> structure + permits local symbols to be written out, the <> field + is used to further controls which local symbols are included + in the output file. If the value is <>, then all + local symbols which begin with a certain prefix are discarded; + this prefix is described by the <> and + <> fields of the <> structure. + + The a.out backend handles symbols by calling + <> on each input BFD and then + traversing the global hash table with the function + <>. It builds a string table + while writing out the symbols, which is written to the output + file at the end of <>. +*/ + +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; +} + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + 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; + + 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_link_hash_lookup (info->hash, 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 **) malloc ((size_t) relsize); + if (!relocs && relsize != 0) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + if (output_bfd->outsymbols == (asymbol **) NULL) + newsyms = (asymbol **) malloc (*psymalloc * sizeof (asymbol *)); + else + newsyms = (asymbol **) realloc (output_bfd->outsymbols, + *psymalloc * sizeof (asymbol *)); + if (newsyms == (asymbol **) NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 + 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; + BFD_ASSERT (strcmp (bfd_asymbol_name (sym), h->root.root.string) == 0); + } + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (size); + if (space == NULL && size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 + 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 *) + malloc ((size_t) bfd_section_size (input_bfd, input_section))); + if (contents == NULL && bfd_section_size (input_bfd, input_section) != 0) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/lynx-core.c b/gnu/usr.bin/binutils/bfd/lynx-core.c new file mode 100644 index 00000000000..7d2e3b3c8f7 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/lynx-core.c @@ -0,0 +1,251 @@ +/* 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 +#include +/* sys/kernel.h should define this, but doesn't always, sigh. */ +#ifndef __LYNXOS +#define __LYNXOS +#endif +#include +#include +#include +#include +#include +#include +#include + +/* 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)) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/m68k4knetbsd.c b/gnu/usr.bin/binutils/bfd/m68k4knetbsd.c new file mode 100644 index 00000000000..c1ecb434425 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/m68klynx.c b/gnu/usr.bin/binutils/bfd/m68klynx.c new file mode 100644 index 00000000000..7acdfbcad21 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/m68knetbsd.c b/gnu/usr.bin/binutils/bfd/m68knetbsd.c new file mode 100644 index 00000000000..3bff530fbc7 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/m88kmach3.c b/gnu/usr.bin/binutils/bfd/m88kmach3.c new file mode 100644 index 00000000000..7a564087300 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/makefile.dos b/gnu/usr.bin/binutils/bfd/makefile.dos new file mode 100644 index 00000000000..8a22c6af201 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/mipsbsd.c b/gnu/usr.bin/binutils/bfd/mipsbsd.c new file mode 100644 index 00000000000..007416d48b9 --- /dev/null +++ b/gnu/usr.bin/binutils/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, + false, /* target byte order (little) */ + false, /* 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, + true, /* target byte order (big) */ + true, /* 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/gnu/usr.bin/binutils/bfd/mpw-config.in b/gnu/usr.bin/binutils/bfd/mpw-config.in new file mode 100644 index 00000000000..c36a1346b0b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/mpw-config.in @@ -0,0 +1,69 @@ +# 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-idt-ecoff/ + 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/gnu/usr.bin/binutils/bfd/mpw-make.sed b/gnu/usr.bin/binutils/bfd/mpw-make.sed new file mode 100644 index 00000000000..3ecf8ebe41d --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/mpw-make.sed @@ -0,0 +1,55 @@ +# 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@// + +# 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 + diff --git a/gnu/usr.bin/binutils/bfd/netbsd.h b/gnu/usr.bin/binutils/bfd/netbsd.h new file mode 100644 index 00000000000..dd73d37e789 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/newsos3.c b/gnu/usr.bin/binutils/bfd/newsos3.c new file mode 100644 index 00000000000..7ec7a75a87c --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/nlm-target.h b/gnu/usr.bin/binutils/bfd/nlm-target.h new file mode 100644 index 00000000000..58e6a965f73 --- /dev/null +++ b/gnu/usr.bin/binutils/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_big_p: data is big endian */ + true, + + /* header_byteorder_big_p: header is also big endian */ + true, + + /* 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_big_p: data is big endian */ + false, /* Nope -- this one's little endian */ + + /* header_byteorder_big_p: header is also big endian */ + false, /* Nope -- this one's little endian */ + + /* 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/gnu/usr.bin/binutils/bfd/nlm.c b/gnu/usr.bin/binutils/bfd/nlm.c new file mode 100644 index 00000000000..590076ddd16 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/nlm.c @@ -0,0 +1,58 @@ +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/nlm32-alpha.c b/gnu/usr.bin/binutils/bfd/nlm32-alpha.c new file mode 100644 index 00000000000..af99d6f2b3f --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/nlm32-alpha.c @@ -0,0 +1,898 @@ +/* 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 (abfd->xvec->header_byteorder_big_p == false); + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + sym -> relocs = nlm_relocs; + sym -> rcnt = 0; + while (sym -> rcnt < rcount) + { + asection *section; + + if (nlm_alpha_read_reloc (abfd, sym, §ion, + &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 (abfd->xvec->header_byteorder_big_p == false); + + 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/gnu/usr.bin/binutils/bfd/nlm32-i386.c b/gnu/usr.bin/binutils/bfd/nlm32-i386.c new file mode 100644 index 00000000000..0c9dfc4c182 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/nlm32-i386.c @@ -0,0 +1,457 @@ +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + sym -> relocs = nlm_relocs; + sym -> rcnt = 0; + while (sym -> rcnt < rcount) + { + asection *section; + + if (nlm_i386_read_reloc (abfd, sym, §ion, + &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/gnu/usr.bin/binutils/bfd/nlm32-ppc.c b/gnu/usr.bin/binutils/bfd/nlm32-ppc.c new file mode 100644 index 00000000000..64a047c6dc7 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/nlm32-ppc.c @@ -0,0 +1,1051 @@ +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + sym -> relocs = nlm_relocs; + sym -> rcnt = 0; + while (sym -> rcnt < rcount) + { + asection *section; + + if (nlm_powerpc_read_reloc (abfd, sym, §ion, + &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/gnu/usr.bin/binutils/bfd/nlm32-sparc.c b/gnu/usr.bin/binutils/bfd/nlm32-sparc.c new file mode 100644 index 00000000000..54eb316f1b0 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/nlm32-sparc.c @@ -0,0 +1,446 @@ +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + sym -> relocs = nlm_relocs; + sym -> rcnt = 0; + while (sym -> rcnt < rcount) + { + asection *section; + + if (nlm_sparc_read_reloc (abfd, sym, §ion, + &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/gnu/usr.bin/binutils/bfd/nlm32.c b/gnu/usr.bin/binutils/bfd/nlm32.c new file mode 100644 index 00000000000..4730e4fd349 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/nlm64.c b/gnu/usr.bin/binutils/bfd/nlm64.c new file mode 100644 index 00000000000..5dcd96a2b3c --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/nlmcode.h b/gnu/usr.bin/binutils/bfd/nlmcode.h new file mode 100644 index 00000000000..95ae9db632b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/nlmcode.h @@ -0,0 +1,2087 @@ +/* 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 /* 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) malloc ((size_t) nlm_fixed_header_size (abfd)); + if (x_fxdhdr == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc ((size_t) nlm_fixed_header_size (abfd))); + if (fixed_header == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/nlmswap.h b/gnu/usr.bin/binutils/bfd/nlmswap.h new file mode 100644 index 00000000000..5a9ce7268d0 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/ns32knetbsd.c b/gnu/usr.bin/binutils/bfd/ns32knetbsd.c new file mode 100644 index 00000000000..3e3f08a9e58 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/oasys.c b/gnu/usr.bin/binutils/bfd/oasys.c new file mode 100644 index 00000000000..4b97d13e21e --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/oasys.c @@ -0,0 +1,1565 @@ +/* BFD back-end for oasys objects. + Copyright 1990, 1991, 1992, 1993, 1994, 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. */ + +#define UNDERSCORE_HACK 1 +#include "bfd.h" +#include "sysdep.h" +#include +#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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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_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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS + | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 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/gnu/usr.bin/binutils/bfd/opncls.c b/gnu/usr.bin/binutils/bfd/opncls.c new file mode 100644 index 00000000000..1ab924bcd99 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/opncls.c @@ -0,0 +1,608 @@ +/* opncls.c -- open and close a BFD. + 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. */ + +#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) + { + bfd_set_error (bfd_error_no_memory); + 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 <>) with the target + @var{target}. Return a pointer to the created BFD. + + Calls <>, so @var{target} is interpreted as by + that function. + + If <> is returned then an error has occured. Possible errors + are <>, <> or <> 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) { + bfd_set_error (bfd_error_no_memory); + 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 + <> is to <> much like <> is to <>. + It opens a BFD on a file already described by the @var{fd} + supplied. + + When the file is later <>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 + <>, and will not be affected by BFD operations on other + files. + + Possible errors are <>, <> and <>. +*/ + +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) { + bfd_set_error (bfd_error_no_memory); + 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 = (char *)fopen(filename, FOPEN_RB); +#else + /* (O_ACCMODE) parens are to avoid Ultrix header file bug */ + switch (fdflags & (O_ACCMODE)) { + case O_RDONLY: nbfd->iostream = (char *) fdopen (fd, FOPEN_RB); break; + case O_WRONLY: nbfd->iostream = (char *) fdopen (fd, FOPEN_RUB); break; + case O_RDWR: nbfd->iostream = (char *) 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 <>, 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) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + target_vec = bfd_find_target (target, nbfd); + if (target_vec == NULL) + { + bfd_set_error (bfd_error_invalid_target); + return NULL; + } + + nbfd->iostream = (char *) 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 * +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) { + bfd_set_error (bfd_error_no_memory); + 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 + <> 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 <>). + +RETURNS + <> is returned if all is ok, otherwise <>. +*/ + + +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 <> + 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 <> is called + to mark it as such. + + All memory attached to the BFD's obstacks is released. + +RETURNS + <> is returned if all is ok, otherwise <>. + +*/ + +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 + <>, 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 * +bfd_create (filename, templ) + CONST char *filename; + bfd *templ; +{ + bfd *nbfd = _bfd_new_bfd(); + if (nbfd == (bfd *)NULL) { + bfd_set_error (bfd_error_no_memory); + 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 <> and return a pointer to it. +*/ + + +PTR +bfd_alloc_by_size_t (abfd, size) + bfd *abfd; + size_t size; +{ + return obstack_alloc(&(abfd->memory), size); +} + +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; +{ + return obstack_finish(&(abfd->memory)); +} + +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/gnu/usr.bin/binutils/bfd/osf-core.c b/gnu/usr.bin/binutils/bfd/osf-core.c new file mode 100644 index 00000000000..a27ad37e7ee --- /dev/null +++ b/gnu/usr.bin/binutils/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 +#include +#include +#include + +/* 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_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/gnu/usr.bin/binutils/bfd/pc532-mach.c b/gnu/usr.bin/binutils/bfd/pc532-mach.c new file mode 100644 index 00000000000..73f4ac49e82 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/pe-arm.c b/gnu/usr.bin/binutils/bfd/pe-arm.c new file mode 100644 index 00000000000..322d69330dd --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/pe-arm.c @@ -0,0 +1,32 @@ +/* BFD back-end for Intel 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/gnu/usr.bin/binutils/bfd/pe-i386.c b/gnu/usr.bin/binutils/bfd/pe-i386.c new file mode 100644 index 00000000000..e23d1d6b91f --- /dev/null +++ b/gnu/usr.bin/binutils/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 1 +#include "coff-i386.c" diff --git a/gnu/usr.bin/binutils/bfd/pe-ppc.c b/gnu/usr.bin/binutils/bfd/pe-ppc.c new file mode 100644 index 00000000000..67fdda04e6c --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/pei-arm.c b/gnu/usr.bin/binutils/bfd/pei-arm.c new file mode 100644 index 00000000000..fd9d398432d --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/pei-i386.c b/gnu/usr.bin/binutils/bfd/pei-i386.c new file mode 100644 index 00000000000..e2282b444ae --- /dev/null +++ b/gnu/usr.bin/binutils/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 1 +#include "coff-i386.c" + + + diff --git a/gnu/usr.bin/binutils/bfd/pei-ppc.c b/gnu/usr.bin/binutils/bfd/pei-ppc.c new file mode 100644 index 00000000000..fc8f89fddb6 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/peicode.h b/gnu/usr.bin/binutils/bfd/peicode.h new file mode 100644 index 00000000000..0642d4bedcb --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/peicode.h @@ -0,0 +1,1572 @@ +/* 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->lma - 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; +#ifdef PPC + isize = 0; +#endif + for (sec = abfd->sections; sec; sec = sec->next) + { + int rounded = FA(sec->_raw_size); + 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 */ + + 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", + "Reserved", + "Reserved [first thunk address on PPC]", + "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 *) xmalloc ((size_t) bfd_section_size (abfd, + rel_section)); + 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:\n"); + fprintf (file, + " %04lx code-base %08lx toc (loadable) %08lx toc (actual) %08lx\n", + (unsigned long int) (abfd->start_address), + 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 *) xmalloc ((size_t) bfd_section_size (abfd, section)); + datasize = bfd_section_size (abfd, section); + + 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>> 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_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: Begin End EH EH PrologEnd\n"); + fprintf(file, + " Address Address Handler Data Address\n"); + + if (bfd_section_size (abfd, section) == 0) + return true; + + data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, section)); + datasize = bfd_section_size (abfd, section); + + 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) + { + /* We are probably into the padding of the + section now */ + break; + } + + fprintf (file, + " %04lx\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 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_pdata(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) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/ptrace-core.c b/gnu/usr.bin/binutils/bfd/ptrace-core.c new file mode 100644 index 00000000000..f431bcb82c3 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/ptrace-core.c @@ -0,0 +1,244 @@ +/* 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 +#include +#include +#include +#include +#include +#include +#include + + +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) { + bfd_set_error (bfd_error_no_memory); + 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) { + loser: + bfd_set_error (bfd_error_no_memory); + free ((void *)rawptr); + return 0; + } + core_datasec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection)); + if (core_datasec (abfd) == NULL) { + loser1: + free ((void *)core_stacksec (abfd)); + goto loser; + } + core_regsec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection)); + if (core_regsec (abfd) == NULL) { + free ((void *)core_datasec (abfd)); + goto loser1; + } + + 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_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/gnu/usr.bin/binutils/bfd/reloc.c b/gnu/usr.bin/binutils/bfd/reloc.c new file mode 100644 index 00000000000..28bd8f29be7 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/reloc.c @@ -0,0 +1,2350 @@ +/* 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 <> 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 <> 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 <>: + + o <> + + 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 + <> 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 <
> + + The <
> field gives the offset in bytes from the base of + the section data which owns the relocation record to the first + byte of relocatable information. The actual data relocated + will be relative to this point; for example, a relocation + 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 <> + + The <> is a value provided by the back end to be added (!) + to the relocation offset. Its interpretation is dependent upon + the howto. For example, on the 68k the code: + + +| 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 <>, 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 <>, 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 <> + + The <> field can be imagined as a + relocation instruction. It is a pointer to a structure which + contains information on what to do with all of the other + information in the reloc record and data section. A back end + would normally have a relocation instruction set and turn + relocations into pointers to the correct structure on input - + but it would be possible to create each howto field on demand. + +*/ + +/* +SUBSUBSECTION + <> + + 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 + <> + + The <> 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 <>: + +.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 + 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 + 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 + */ + +#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 <>, 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 + 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 + 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 + */ + +#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 <>, 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 <>.) 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_LO7 +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 +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 +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 **) malloc ((size_t) reloc_size); + if (reloc_vector == NULL && reloc_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/reloc16.c b/gnu/usr.bin/binutils/bfd/reloc16.c new file mode 100644 index 00000000000..7004178f941 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/reloc16.c @@ -0,0 +1,294 @@ +/* 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_link_hash_lookup (link_info->hash, 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 **) malloc (reloc_size); + if (!reloc_vector && reloc_size > 0) + { + bfd_set_error (bfd_error_no_memory); + 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 **)malloc((size_t) reloc_size); + if (!reloc_vector && reloc_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/riscix.c b/gnu/usr.bin/binutils/bfd/riscix.c new file mode 100644 index 00000000000..5cf4c1049dc --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/riscix.c @@ -0,0 +1,647 @@ +/* BFD back-end for RISC iX (Acorn, arm) binaries. + Copyright (C) 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. */ + + +/* 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 (abfd->xvec->header_byteorder_big_p != false) + { + 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) { + bfd_set_error (bfd_error_no_memory); + 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) { + bfd_set_error (bfd_error_no_memory); + 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 + && (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/gnu/usr.bin/binutils/bfd/rs6000-core.c b/gnu/usr.bin/binutils/bfd/rs6000-core.c new file mode 100644 index 00000000000..2be4fad2ba2 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/rs6000-core.c @@ -0,0 +1,414 @@ +/* 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 +#include +#include + + +/* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) { + bfd_set_error (bfd_error_no_memory); + /* bfd_release (abfd, ???? ) */ + 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) { + bfd_set_error (bfd_error_no_memory); + /* bfd_release (abfd, ???? ) */ + 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) { + bfd_set_error (bfd_error_no_memory); + /* bfd_release (abfd, ???? ) */ + 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) { + bfd_set_error (bfd_error_no_memory); + /* bfd_release (abfd, ???? ) */ + 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) + { + bfd_set_error (bfd_error_no_memory); + 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/gnu/usr.bin/binutils/bfd/section.c b/gnu/usr.bin/binutils/bfd/section.c new file mode 100644 index 00000000000..509a5057ed8 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/section.c @@ -0,0 +1,969 @@ +/* Object file "section" support for the BFD library. + Copyright (C) 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. */ + +/* +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 <>. + +@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, <> 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 + <>) to the sections attached to an already open + BFD. For example, the linker creates an extra section + <> for each input file's BFD to hold information about + common storage. + + The raw data is not necessarily read in when + the section descriptor is created. Some targets may leave the + data in place until a <> call is + made. Other back ends may read in all the data at once. For + example, an S-record file has to be read once to determine the + 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 <>. + + Any program that creates or combines sections (e.g., the assembler + and linker) must use the <> fields <> and + <> to indicate the file sections to which each + section must be written. (If the section is being created from + scratch, <> should probably point to the section + itself and <> should probably be zero.) + + The data to be written comes from input sections attached + (via <> pointers) to + the output sections. The output section structure can be + considered a filter for the input section: the output section + 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 <> + 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 <>. 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 <>. 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 +. <> | <>; a debug section could be +. <> *} +.#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 +. +. {* 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 <>, 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 + <>s whose name matches @var{name}, otherwise <>. + @xref{Sections}, for more information. + + This should only be used in special cases; the normal way to process + all sections of a given name is to use <> and + <> 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 <> - + If output has already started for this BFD. + o <> - + 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 <> and set <> on error; possible errors are: + o <> - If output has already started for @var{abfd}. + o <> - 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 = §->next; + sect = sect->next; + } + + newsect = (asection *) bfd_zalloc (abfd, sizeof (asection)); + if (newsect == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + newsect->name = name; + newsect->index = abfd->section_count++; + newsect->flags = SEC_NO_FLAGS; + + newsect->userdata = 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 <>, but return <> (without calling + bfd_set_error ()) without changing the section chain if there is already a + section named @var{name}. If there is an error, return <> and set + <>. +*/ + +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 <> on success, + <> on error. Possible error returns are: + + o <> - + The section cannot have one or more of the attributes + requested. For example, a .bss section in <> may not + have the <> field set. + +*/ + +/*ARGSUSED*/ +boolean +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 <> is returned, else <>. + + Possible error returns: + o <> - + 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 <> is returned, else <>. Possible error + returns are: + o <> - + The output section does not have the <> + 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 <> + flag set are requested or if the section does not have the + <> flag set, then the @var{location} is filled + with zeroes. If no errors occur, <> is returned, else + <>. + + + +*/ +boolean +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 <> on success, <> on error. Possible error + returns are: + + o <> - + Not enough memory exists to create private data for @var{osec}. + +.#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ +. BFD_SEND (ibfd, _bfd_copy_private_section_data, \ +. (ibfd, isection, obfd, osection)) +*/ diff --git a/gnu/usr.bin/binutils/bfd/som.c b/gnu/usr.bin/binutils/bfd/som.c new file mode 100644 index 00000000000..071e199adec --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/som.c @@ -0,0 +1,6047 @@ +/* bfd back-end for HP PA-RISC SOM objects. + Copyright (C) 1990, 1991, 1992, 1993, 1994, 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 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 +#include +#include +#include +#include +#include +#include + +/* 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= 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) + { + bfd_set_error (bfd_error_no_memory); + 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]) + { + bfd_set_error (bfd_error_no_memory); + 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]) + { + bfd_set_error (bfd_error_no_memory); + 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]) + { + bfd_set_error (bfd_error_no_memory); + 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]) + { + bfd_set_error (bfd_error_no_memory); + 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]) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + *final_types[0] = R_R_MODE; + final_types[1] = final_type; + final_types[2] = 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]) + { + bfd_set_error (bfd_error_no_memory); + 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]) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = malloc (file_hdr->space_strings_size); + if (!space_strings && file_hdr->space_strings_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 **) 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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: + 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: + 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 *) malloc (symtab_size); + if (som_symtab == NULL && symtab_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 = malloc (obj_som_stringtab_size (abfd)); + bzero (stringtab, obj_som_stringtab_size (abfd)); + if (stringtab == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + 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 *) + malloc (symbol_count * sizeof (som_symbol_type)); + bzero (symbase, symbol_count * sizeof (som_symbol_type)); + if (symbase == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + /* Read in the external SOM representation. */ + buf = malloc (symbol_count * symsize); + if (buf == NULL && symbol_count * symsize != 0) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = 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 *) malloc (fixup_stream_size); + if (external_relocs == (char *) NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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)) + { + bfd_set_error (bfd_error_no_memory); + 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)) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (lst_header->hash_size * sizeof (unsigned int)); + if (hash_table == NULL && lst_header->hash_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (lst_header->hash_size * sizeof (unsigned int)); + if (hash_table == NULL && lst_header->hash_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + som_dict = + (struct som_entry *) malloc (lst_header->module_count + * sizeof (struct som_entry)); + if (som_dict == NULL && lst_header->module_count != 0) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (lst.hash_size * sizeof (unsigned int)); + if (hash_table == NULL && lst.hash_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + som_dict = + (struct som_entry *) malloc (lst.module_count + * sizeof (struct som_entry)); + if (som_dict == NULL && lst.module_count != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + last_hash_entry = + ((struct lst_symbol_record **) + malloc (lst.hash_size * sizeof (struct lst_symbol_record *))); + if (last_hash_entry == NULL && lst.hash_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = malloc (nsyms * sizeof (struct lst_symbol_record)); + if (lst_syms == NULL && nsyms != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + strings = malloc (string_size); + if (strings == NULL && string_size != 0) + { + bfd_set_error (bfd_error_no_memory); + 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_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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | 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/gnu/usr.bin/binutils/bfd/som.h b/gnu/usr.bin/binutils/bfd/som.h new file mode 100644 index 00000000000..6290e88f948 --- /dev/null +++ b/gnu/usr.bin/binutils/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 +#include +#include + +/* 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 +#include +#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/gnu/usr.bin/binutils/bfd/sparclynx.c b/gnu/usr.bin/binutils/bfd/sparclynx.c new file mode 100644 index 00000000000..0885620283e --- /dev/null +++ b/gnu/usr.bin/binutils/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. + I needed to add M_UNKNOWN to recognize a 68000 object, so this will + probably no longer reject a NewsOS object. . */ +#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/gnu/usr.bin/binutils/bfd/sparcnetbsd.c b/gnu/usr.bin/binutils/bfd/sparcnetbsd.c new file mode 100644 index 00000000000..69240f5d158 --- /dev/null +++ b/gnu/usr.bin/binutils/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/gnu/usr.bin/binutils/bfd/srec.c b/gnu/usr.bin/binutils/bfd/srec.c new file mode 100644 index 00000000000..5f274c67cab --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/srec.c @@ -0,0 +1,1347 @@ +/* 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 . + +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
+ +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: + ($$ + (
)*) + $$ + + 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 + +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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (bytes * 2); + if (buf == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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->_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 *) malloc (bytes * 2); + if (buf == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS + | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS + | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 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/gnu/usr.bin/binutils/bfd/stab-syms.c b/gnu/usr.bin/binutils/bfd/stab-syms.c new file mode 100644 index 00000000000..5e4667d7c0b --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/stab-syms.c @@ -0,0 +1,75 @@ +/* Table of stab names for the BFD library. + 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. */ + +#include "bfd.h" + +#define ARCH_SIZE 32 /* Value doesn't matter. */ +#include "libaout.h" +#include "aout/aout64.h" + +/* Create a table of debugging stab-codes and corresponding names. */ + +#define __define_stab(NAME, CODE, STRING) __define_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 * +aout_stab_name (code) + int code; +{ +#if 0 /* This lookup table is slower than lots of explicit tests, at + least on the i386. One advantage is that the compiler can + eliminate duplicates from the code, whereas they can't easily + be eliminated from the lookup table. */ + +#define __define_name(CODE, STRING) {(int)CODE, STRING}, + static const struct { + int code; + char string[7]; + } aout_stab_names[] = { +#include "aout/stab.def" + EXTRA_SYMBOLS + }; + register int i = sizeof (aout_stab_names) / sizeof (aout_stab_names[0]); + while (--i >= 0) + if (aout_stab_names[i].code == code) + return aout_stab_names[i].string; + +#else + +#define __define_name(val, str) if (val == code) return str ; +#include "aout/stab.def" + EXTRA_SYMBOLS + +#endif + + return 0; +} diff --git a/gnu/usr.bin/binutils/bfd/sunos.c b/gnu/usr.bin/binutils/bfd/sunos.c new file mode 100644 index 00000000000..138555f165d --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/sunos.c @@ -0,0 +1,2776 @@ +/* BFD backend for SunOS binaries. + 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 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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
, %g1 */ +#define SPARC_PLT_PIC_WORD0 0x03000000 +/* jmp %g1 +
*/ +#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 010 + /* Symbol is defined by a dynamic object. */ +#define SUNOS_DEF_DYNAMIC 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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; + } + + h = sunos_link_hash_lookup (sunos_hash_table (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; + } + } + + /* 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; + } + } + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) realloc (s->contents, + (size_t) (s->_raw_size + add)); + if (contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 = 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 = malloc ((size_t) rel_size); + aout_section_data (sec)->relocs = relocs; + } + } + if (relocs == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 (abfd->xvec->header_byteorder_big_p) + { + 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 (abfd->xvec->header_byteorder_big_p) + 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 (abfd->xvec->header_byteorder_big_p) + { + r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) + >> RELOC_EXT_BITS_TYPE_SH_BIG); + } + else + { + r_index = ((rel->r_index[2] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[0]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) + >> RELOC_EXT_BITS_TYPE_SH_LITTLE); + } + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 (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 + || (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. */ + if ((h->flags & SUNOS_DEF_REGULAR) == 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); + if (s->contents == NULL) + contents = (bfd_byte *) malloc (len + 1); + else + contents = (bfd_byte *) realloc (s->contents, + (size_t) (s->_raw_size + len + 1)); + if (contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 (output_bfd->xvec->header_byteorder_big_p) + { + 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 (output_bfd->xvec->header_byteorder_big_p) + { + 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 (input_bfd->xvec->header_byteorder_big_p) + { + 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 (input_bfd->xvec->header_byteorder_big_p) + 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 (input_bfd->xvec->header_byteorder_big_p) + 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 (input_bfd->xvec->header_byteorder_big_p) + 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 (dynobj->xvec->header_byteorder_big_p) + { + 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 (dynobj->xvec->header_byteorder_big_p) + { + 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 (dynobj->xvec->header_byteorder_big_p) + { + 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 (dynobj->xvec->header_byteorder_big_p) + { + 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/gnu/usr.bin/binutils/bfd/syms.c b/gnu/usr.bin/binutils/bfd/syms.c new file mode 100644 index 00000000000..1bcf5293be9 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/syms.c @@ -0,0 +1,674 @@ +/* Generic symbol-table support for the BFD library. + Copyright (C) 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. */ + +/* +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 <> 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 <>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 <>. 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 <> 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 <> function will read the symbols + into memory in an internal form. It will return a <> + pointer to a block of memory, a symbol count, and the size of + each symbol. The pointer is allocated using <>, and + should be freed by the caller when it is no longer needed. + + The function <> will take a pointer + to a minisymbol, and a pointer to a structure returned by + <>, and return a <> structure. + The return value may or may not be the same as the value from + <> which was passed in. + +*/ + + + +/* +DOCDD +INODE +typedef asymbol, symbol handling functions, Mini Symbols, Symbols + +*/ +/* +SUBSECTION + typedef asymbol + + An <> 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; <> in <>. The value +. is the offset into the section of the data. *} +.#define BSF_LOCAL 0x01 +. +. {* The symbol has global scope; initialized data in <>. 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: +. <>, <>, <> or +. <> *} +. +. {* 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 <> symbol +. which is also <> 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 +. +. 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 "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 <> 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 both BSF_FUNCTION and BSF_FILE. */ + 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' : ' '); +} + + +/* +FUNCTION + bfd_make_empty_symbol + +DESCRIPTION + Create a new <> 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 <>. Building your own + <> 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 <> 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'}, + {".data", 'd'}, + {".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'}, + {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 <> on success, <> on error. Possible error + returns are: + + o <> - + 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 **) malloc ((size_t) storage); + if (syms == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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; +} diff --git a/gnu/usr.bin/binutils/bfd/sysdep.h b/gnu/usr.bin/binutils/bfd/sysdep.h new file mode 100644 index 00000000000..d7764063db8 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/sysdep.h @@ -0,0 +1,107 @@ +/* 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 +#endif + +#include +#include +#include + +#include +#ifndef errno +extern int errno; +#endif + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#else +extern char *strchr (); +extern char *strrchr (); +extern char *strstr (); +#endif +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef USE_BINARY_FOPEN +#include "fopen-bin.h" +#else +#include "fopen-same.h" +#endif + +#ifdef HAVE_FCNTL_H +#include +#else +#ifdef HAVE_SYS_FILE_H +#include +#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/gnu/usr.bin/binutils/bfd/targets.c b/gnu/usr.bin/binutils/bfd/targets.c new file mode 100644 index 00000000000..391c1711603 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/targets.c @@ -0,0 +1,868 @@ +/* Generic target-file-type support for the BFD library. + Copyright 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. */ + +#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 <>, 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 <> with the + target string supplied to <> and the new BFD pointer. + + o If a null target string was provided to <>, + look up the environment variable <> and use + that as the target string. + + o If the target string is still <>, or the target string is + <>, then use the first item in the target vector + as the target type, and set <> in the BFD to + cause <> to loop through all the targets. + @xref{bfd_target}. @xref{Formats}. + + o Otherwise, 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 <> to + <>. + + o <> attempts to open the file using + <>, 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 + <> on the BFD with a suggested format. + If <> has been set, each possible target + type is tried to see if it recognizes the specified format. + <> returns <> 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 <> + member. + + The macros below are used to dispatch to functions through the + <> vector. They are used in a number of macros further + down in @file{bfd.h}, and are also used when calling various + routines by hand inside the BFD implementation. The @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 + <> member of the struct <> 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_som_flavour, +. bfd_target_os9k_flavour, +. bfd_target_versados_flavour, +. bfd_target_msdos_flavour +.}; +. +.{* 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. + +. boolean byteorder_big_p; + +The order of bytes within the header parts of a file. + +. boolean header_byteorder_big_p; + +A mask of all the flags which an executable may have set - +from the set <>, <>, ...<>. + +. flagword object_flags; + +A mask of all the flags which a section may have set - from +the set <>, <>, ...<>. + +. flagword section_flags; + +The character normally found at the front of a symbol +(if any), perhaps `_'. + +. 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 <> 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 <>. + +. 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,_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)); +. 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 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 m68kcoff_vec; +extern const bfd_target m68kcoffun_vec; +extern const bfd_target m68klynx_aout_vec; +extern const bfd_target m68klynx_coff_vec; +extern const bfd_target 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; + +/* 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, + &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, + &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, + +/* 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 <>, choose the + one in the environment variable <>; if that is null or not + defined, then choose the first entry in the target list. + Passing in the string "default" or setting the environment + variable to "default" will cause the first entry in the target + list to be returned, and "target_defaulted" will be set in the + BFD. This causes <> to loop over all the + targets to find the one that matches the file being read. +*/ + +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) { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + for (target = &bfd_target_vector[0]; *target != NULL; target++) + *(name_ptr++) = (*target)->name; + + return name_list; +} diff --git a/gnu/usr.bin/binutils/bfd/tekhex.c b/gnu/usr.bin/binutils/bfd/tekhex.c new file mode 100644 index 00000000000..f082072fb00 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/tekhex.c @@ -0,0 +1,1049 @@ +/* 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 . + +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 + % + +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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, + true, /* target byte order */ + true, /* 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/gnu/usr.bin/binutils/bfd/trad-core.c b/gnu/usr.bin/binutils/bfd/trad-core.c new file mode 100644 index 00000000000..04c9c233f09 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/trad-core.c @@ -0,0 +1,327 @@ +/* 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 +#include +#include +#include +#include + +#include /* 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) { + bfd_set_error (bfd_error_no_memory); + 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_zmalloc (sizeof (asection)); + if (core_stacksec (abfd) == NULL) { + loser: + bfd_set_error (bfd_error_no_memory); + free ((void *)rawptr); + return 0; + } + core_datasec (abfd) = (asection *) bfd_zmalloc (sizeof (asection)); + if (core_datasec (abfd) == NULL) { + loser1: + free ((void *)core_stacksec (abfd)); + goto loser; + } + core_regsec (abfd) = (asection *) bfd_zmalloc (sizeof (asection)); + if (core_regsec (abfd) == NULL) { + free ((void *)core_datasec (abfd)); + goto loser1; + } + + 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_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/gnu/usr.bin/binutils/bfd/versados.c b/gnu/usr.bin/binutils/bfd/versados.c new file mode 100644 index 00000000000..9d4122e0384 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/versados.c @@ -0,0 +1,909 @@ +/* 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 . + + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS + | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 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/gnu/usr.bin/binutils/bfd/xcofflink.c b/gnu/usr.bin/binutils/bfd/xcofflink.c new file mode 100644 index 00000000000..eca1d1a13a1 --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/xcofflink.c @@ -0,0 +1,5814 @@ +/* POWER/PowerPC XCOFF linker support. + Copyright 1995 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 "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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + return xcoff_link_add_dynamic_symbols (abfd, info); + + 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 + + /* 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 non dynamic + 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 (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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc ((abfd->section_count + 1) + * sizeof (struct reloc_info_struct))); + if (reloc_info == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 **) malloc (o->reloc_count * sizeof (asection *)); + if (reloc_info[o->target_index].csects == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (o->lineno_count * linesz); + if (linenos == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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. */ + *sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (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 *) malloc (lsec->_raw_size); + if (buf == NULL && lsec->_raw_size > 0) + { + bfd_set_error (bfd_error_no_memory); + 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 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) + { + bfd_set_error (bfd_error_no_memory); + 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))) + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (strlen (h->root.root.string) + 2); + if (fnname == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 = xcoff_link_hash_lookup (xcoff_hash_table (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; + /* 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. */ + +boolean +bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry, + file_align, maxstack, maxdata, gc, + modtype, textro, 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; + 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)) + return true; + + ldinfo.failed = false; + ldinfo.output_bfd = output_bfd; + ldinfo.info = info; + 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; + if (hentry->root.type == bfd_link_hash_defined + || hentry->root.type == bfd_link_hash_defweak) + xcoff_data (output_bfd)->entry_section = + hentry->root.u.def.section->output_section; + } + + /* 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) malloc (subdeb->_raw_size); + if (debug_contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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; + + /* 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, 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) + && (! 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; + bfd_set_error (bfd_error_no_memory); + 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; + + if (ldinfo->strings == NULL) + newstrings = (bfd_byte *) malloc (newalc); + else + newstrings = ((bfd_byte *) + realloc ((PTR) ldinfo->strings, newalc)); + if (newstrings == NULL) + { + ldinfo->failed = true; + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc ((abfd->section_count + 1) + * sizeof (struct xcoff_link_section_info))); + if (finfo.section_info == NULL) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc (o->reloc_count * sizeof (struct internal_reloc))); + finfo.section_info[o->target_index].rel_hashes = + ((struct xcoff_link_hash_entry **) + 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) + { + bfd_set_error (bfd_error_no_memory); + 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 *) + malloc (max_sym_count + * sizeof (struct internal_syment))); + finfo.sym_indices = (long *) malloc (max_sym_count * sizeof (long)); + finfo.outsyms = ((bfd_byte *) + malloc ((size_t) ((max_sym_count + 1) * symesz))); + finfo.linenos = (bfd_byte *) malloc (max_lineno_count + * bfd_coff_linesz (abfd)); + finfo.contents = (bfd_byte *) malloc (max_contents_size); + finfo.external_relocs = (bfd_byte *) 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)) + { + bfd_set_error (bfd_error_no_memory); + 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; + } + + *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 + { + finfo->toc_symindx = output_index; + xcoff_data (finfo->output_bfd)->toc = + ((*csectpp)->output_section->vma + + (*csectpp)->output_offset + + isym.n_value + - (*csectpp)->vma); + xcoff_data (finfo->output_bfd)->toc_section = + (*csectpp)->output_section; + 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) + { + bfd_set_error (bfd_error_no_memory); + 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, 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 = xcoff_data (output_bfd)->toc_section; + + ++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 = xcoff_link_hash_lookup (xcoff_hash_table (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) + { + bfd_set_error (bfd_error_no_memory); + 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]; + 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/gnu/usr.bin/binutils/binutils/ChangeLog b/gnu/usr.bin/binutils/binutils/ChangeLog new file mode 100644 index 00000000000..94ecf748115 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/ChangeLog @@ -0,0 +1,3337 @@ +Thu Nov 16 17:30:11 1995 Ken Raeburn + + Version 2.6 released. + * Makefile.in (VERSION): Updated to 2.6. + +Wed Nov 15 12:14:17 1995 Ian Lance Taylor + + * Makefile.in (CC_FOR_TARGET): Define. + (check): Pass CC and CFLAGS to runtest. + + * nm.c (display_rel_file): Don't require a DYNAMIC object when + dumping the dynamic symbol table. + + * objdump.c (compare_symbols): Sort global symbols before local + symbols before debugging symbols. + (objdump_print_address): Don't futz around looking for a global + symbol with the same value. + +Tue Nov 14 17:19:11 1995 Ian Lance Taylor + + * dlltool.c: Use FOPEN_* macros rather than "r" or "w". + + * dlltool.c (fill_ordinals): Correct memset call. + +Sun Nov 12 12:56:05 1995 Stan Shebs + + * mpw-make.sed (DEMANGLER_PROG): Edit out attempts to do anything + with the man page. + +Fri Nov 10 11:41:22 1995 Ian Lance Taylor + + * objcopy.c (setup_section): Copy the section lma independently of + the vma. + +Wed Nov 8 11:33:00 1995 Ian Lance Taylor + + * arsup.c (ar_open): Cast malloc return value. + +Tue Nov 7 09:01:26 1995 Kim Knuttila + + * configure.in, configure (DLLTOOL_DEFS): Added ppc target. + * dlltool.c (MPPC): Added basic PPC definitions. + +Tue Nov 7 14:02:57 1995 Ian Lance Taylor + + * configure.in: Don't treat rs6000-*-lynx* specially. + * configure: Rebuild. + * config/rslynx: Remove. + * Makefile.in: Remove @target_makefile_fragment@. + +Mon Nov 6 15:00:50 1995 Ian Lance Taylor + + * bucomm.h: Include . + * ar.c: Don't include or . + * bucomm.c, dlltool.c, nlmconv.c, objcopy.c, objdump.c: Likewise. + +Fri Nov 3 12:38:09 1995 Ian Lance Taylor + + * objdump.c: Include . + + Permit user to override DEMANGLER_PROG from command line. From + Manfred Hollstein . + * Makefile.in ($(DEMANGLER_PROG)): Depend upon + $(DEMANGLER_PROG).1. + (install): Don't depend upon $(DEMANGLER_PROG).1. Only install + $(DEMANGLER_PROG).1 if $(DEMANGLER_PROG) is not empty. + +Wed Nov 1 15:04:57 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 + + * Makefile.in (syslex.o): add -I$(srcdir) if compiling in a + separate directory. + +Mon Oct 30 14:24:18 1995 Ian Lance Taylor + + * objdump.c (objdump_print_value): New static function. + (objdump_print_address): Use it. If we need the right section for + the symbol, and we can't find it, print an offset from the section + rather than using a symbol from some other section. + +Thu Oct 26 10:23:14 1995 steve chamberlain + + * dlltool.c (no_idata4, no_idata5): New. + (arm_jtab): Use correct encoding of jump instruction. + (usage, main, make_head, make_tail): Act on no_idata4, no_idata5. + +Wed Oct 25 12:10:07 1995 Stan Shebs + + * mpw-make.sed: Edit paths to generated y.tab.[ch] files. + +Fri Oct 20 18:40:34 1995 Ian Lance Taylor + + * binutils.texi: Change --with-targets to --enable-targets. + +Thu Oct 19 17:47:41 1995 Fred Fish + + * Makefile.in: Remove extraneous tab on otherwise empty line, + which confuses many non-GNU versions of "make". + +Wed Oct 18 16:31:58 1995 steve chamberlain + + * dlltool.c (i386_jtab, arm_jtab): New + (gen_lib_file): Rewritten to use bfd. + +Fri Oct 13 16:10:07 1995 Michael Meissner + + * Makefile.in (install): Don't give error message if dlltool + wasn't built. + +Fri Oct 13 11:04:37 1995 steve chamberlain + + * deflex.l: Allow quoting of IDs. + * defparse.y (%union): string deleted. + (command): DESCRIPTION takes ID. + * dlltool.c (gen_def_file): Quote outgoing name if + necessary. Preserve NONAME. + (gen_lib_file): Run ranlib. + (workout_prefix): Deleted. + (main, usage, long_options): Add --as, --ranlib, --ar options. + +Wed Oct 11 13:36:13 1995 steve chamberlain + + * dlltool.c (mtable): HOW_ALIGN_LONG, new. + (d_ord): Deleted. + (d_low_ord, d_high_ord, d_named_funcs): New. + (gen_exp_file): Create noname entries correctly. + (gen_lib_file): Dump exports alphabetically. + (process_duplicates): Count nonamed functions. + (fill_ordinals): Keep track of highest ord too. + (mangle_defs): Create alphabetically ordered list of names. + +Tue Oct 10 09:39:09 1995 steve chamberlain + + * Makefile.in (TOOL_PROGS): Include DLLTOOL_PROG. + +Mon Oct 9 13:06:31 1995 steve chamberlain + + * dlltool.c (add_underscore): New. + (xlate): Use new name. + (main, usage): Update. + +Fri Oct 6 14:08:51 1995 Ken Raeburn + + * sysinfo.y: Eliminate unused terminals "[" and "]" and unused + nonterminal "name". One s/r conflict remains. + + Mon Sep 25 22:49:32 1995 Andreas Schwab + + * nm.c (print_symname): Don't try to demangle an empty + name. + * objdump.c (slurp_symtab): Reset symcount if there are + no symbols. + (slurp_dynamic_symtab): Likewise, for dynsymcount. + (disassemble_data): Fix memory leak: free sorted_syms when done. + (display_bfd): Likewise, for syms and dynsyms. + (dump_relocs): Don't print header before possibly generating an + error message. + (dump_dynamic_relocs): Likewise. + + * ar.1, nm.1, objdump.1, size.1, strings.1, strip.1: Fix typos and + formatting bugs. + +Fri Oct 6 12:00:25 1995 Ian Lance Taylor + + * ar.c (do_quick_append): Comment out. + (replace_members): Add quick argument. + (main): Don't call do_quick_append. + (open_inarch): Don't call quick_append to create an empty archive. + Instead call bfd_openw/bfd_set_format/bfd_close. + +Thu Oct 5 20:53:08 1995 Ken Raeburn + + * bucomm.c: Always include time.h. + +Thu Oct 5 17:25:21 1995 Ian Lance Taylor + + * objdump.c (compare_symbols): Sort gnu_compiled and gcc2_compiled + symbols after other symbols with the same value. Likewise for + symbols which look like file names. + (objdump_print_address): Always chose the first reasonable symbol + with a given value. + +Tue Oct 3 22:38:55 1995 Ian Lance Taylor + + * arsup.c (ar_save): Use rename, not unlink/link/unlink. + +Mon Oct 2 12:10:25 1995 Ian Lance Taylor + + * strings.c (main): Exit with zero status if no files are given + and standard input is read. + +Thu Sep 28 20:03:07 1995 Stan Shebs + + * mpw-config.in: Calculate underscore and put into makefile + fragment, generate config.h. + * mpw-make.sed: New file, sed commands to edit Unix makefile + into MPW syntax. + * mpw-make.in: Remove. + * mac-binutils.r: New file, Mac resources. + +Thu Sep 28 15:49:00 1995 steve chamberlain + + * dlltool.c: (gen_exp_file): Always emit a .reloc section if + relocatable. + (imp_name_lab): New. + (gen_def_file): New. + (gen_lib_file): Use imp_name_lab. + (main): Initialize imp_name_lab. + +Mon Sep 25 12:05:34 1995 Ian Lance Taylor + + * configure.in: Call AC_HEADER_SYS_WAIT. + * configure: Rebuild. + * config.in: Rebuild. + * dlltool.c: Include "libiberty.h" and "bucomm.h". Don't include + , , or . Don't include . + Include . Use HAVE_SYS_WAIT_H to control whether to + include or define the wait macros by hand. Don't + declare xmalloc. + (gen_lib_file): Don't assume that sprintf returns the number of + characters; use strlen instead. + +Fri Sep 22 17:16:41 1995 Ian Lance Taylor + + * objdump.c (disassemble_data): Don't use the old BFD based + disassembler interface. Make info a const pointer. + +Wed Sep 13 18:33:44 1995 Ian Lance Taylor + + * objdump.c (start_address): New variable. + (stop_address): New variable. + (usage): Mention --start-address and --stop-address. + (OPTION_START_ADDRESS, OPTION_STOP_ADDRESS): Define. + (long_options): Add "start-address" and "stop-address". + (disassemble_data): Handle start_address and stop_address. + (dump_data, dump_reloc_set): Likewise. + (main): Don't set seenflag for -l. Handle OPTION_START_ADDRESS + and OPTION_STOP_ADDRESS. + * objcopy.c (parse_vma): Move to bucomm.c. + * bucomm.c (parse_vma): New function, moved in from objcopy.c. + * bucomm.h (parse_vma): Declare. + * binutils.texi, objdump.1: Document new objdump options. + +Tue Sep 12 12:37:39 1995 Ian Lance Taylor + + * Makefile.in (maintainer-clean): New target. + + * ar.c (replace_members): Don't call write_archive if nothing + changed. + + * objdump.c (disassemble_data): Add casts to avoid gcc warnings. + +Thu Sep 7 12:12:17 1995 Ian Lance Taylor + + * config.in: Rename from config.h.in. + * configure.in: Call AC_CONFIG_HEADER with config.h:config.in. + Check for config.h:config.in when creating stamp-h. + * configure: Rebuild. + * Makefile.in (stamp-h): Depend upon config.in rather than + config.h.in. Set CONFIG_HEADERS to config.h:config.in when + calling config.status. + + * Makefile.in (distclean): Remove config.h, stamp-h, and + config.log. + + * nm.c (value_format): Initialize based on BFD64 and + BFD_HOST_64BIT_LONG. + (print_radix): New static variable. + (set_print_radix): Set print_radix. Adjust changes to + value_format. + (print_value): New static function, to print 64 bit octal and + decimal values correctly. + (print_symbol_info_bsd): Check BFD64, not BFD_HOST_64_BIT. Use + print_value. + (print_symbol_info_sysv): Use print_value. + (print_symbol_info_posix): Likewise. + +Wed Sep 6 15:02:55 1995 Ian Lance Taylor + + * Makefile.in (*.o): Remove incorrect dependencies on + $(BFDDIR)/hosts/std-host.h. + + * Makefile.in (INSTALL_DATA): Add -m 644. + (INSTALL_XFORM1): Likewise. + (CC_FOR_BUILD): Set to @CC_FOR_BUILD@ rather than $(CC). + (mostlyclean): Remove config.log. + (distclean): Remove config.cache. + + * configure.in: Call BFD_CC_FOR_BUILD and BFD_BINARY_FOPEN. + * configure: Rebuild. + +Tue Sep 5 20:22:42 1995 Ian Lance Taylor + + * configure.in: Rewrite to use autoconf. + * aclocal.m4: New file. + * configure: New file, built by autoconf. + * acconfig.h: New file. + * config.h.in: New file, built by autoheader. + * Makefile.in: Various changes for new configure script. Also: + (PROGS): Remove $(SYSINFO_PROG). + (ALL_CFLAGS): Remove $(TDEFINES). + (version.o): Use $(ALL_CFLAGS). + (cplus-dem.o, dlltool.o, nlmconv.o): Likewise. + (sysdump.o): Depend upon bucomm.h and config.h. + (srconv.o, arsup.o, strings.o): Depend upon config.h. + (filemode.o): Don't depend upon ../bfd/sysdep.h. + (bucomm.o): Depend upon config.h, not ../bfd/sysdep.h. + (size.o, objdump.o, nm.o, ar.o, objcopy.o): Likewise. + (nlmheader.o, nlmconv.o): Likewise. + (distclean): Don't remove sysdep.h. + * bucomm.h: Include "ansidecl.h", , and "config.h". + Include "fopen-same.h" or "fopen-bin.h", based on + USE_BINARY_FOPEN. Include , and declare errno if it is + not a macro. Include , , , + , and if they are present. Declare strchr, + strrchr, and strstr if no string header file exists. Include + if it exists and does not. Define + O_RDONLY and O_RDWR if necessary. + * ar.c: Don't include "sysdep.h". Do include and + . Use HAVE_GOOD_UTIME_H rather than POSIX_UTIME. Use + HAVE_UTIMES rather than !USE_UTIME. Don't include , and + don't declare errno. + * arsup.c: Don't include . + * bucomm.c: Don't include "sysdep.h". Include , + , and . Include if it defines + time_t. Define time_t if necessary. + * coffdump.c: Don't include "sysdep.h". + * coffgrok.c, filemode.c, nlmconv.c, size.c: Likewise. + * srconv.c, strings.c: Likewise. + * nm.c: Don't include "sysdep.h". Don't try to define HAVE_SBRK. + * objcopy.c: Don't include "sysdep.h". Include and + . + (simple_copy): Use creat rather than assuming that O_CREAT is + defined. + * objdump.c: Don't include "sysdep.h". Use + NEED_DECLARATION_PRINTF rather than !FPRINTF_ALREADY_DECLARED. + * sysdump.c: Include "bfd.h" and "bucomm.h". Don't include + "sysdep.h" or . + (dump_symbol_info): Rename from symbol_info. Change all callers. + +Mon Sep 4 14:30:00 1995 Ian Lance Taylor + + * configure.in (host_makefile_frag): Don't set. Substitute for + @CC@, @CFLAGS@, @HDEFINES@ and @LDFLAGS@ in Makefile. + * Makefile.in (AR_FLAGS): Set to rc rather than qv. + (CC): Define as @CC@. + (CFLAGS): Set to @CFLAGS@. + (LDFLAGS): Define as @LDFLAGS@. + (ALL_CFLAGS): Use @HDEFINES@ rather than $(HDEFINES). + + * configure.in: Don't bother to call config.bfd for each target. + Just call it for the default target, and use the shell variable to + decide whether underscores are used. + +Thu Aug 31 19:21:48 1995 Jason Molenda (crash@phydeaux.cygnus.com) + + * configure.in: match i[3-6]86-*-win32, not just i386-*-win32. + +Thu Aug 31 16:30:22 1995 steve chamberlain + + * dlltool.c (add_indirect): New. + (asm_prefix): New + (gen_exp_file): Timestamp should be 0. Insert prefix when + needed. New code for indirection. + (gen_lib_file): Timestamp should be 0. Insert prefix + when needed. + (usage): Document --add-indirect. + (main): Cope with new option. + + * objdump.c (dump_private_headers): New. + (usage): Document new option. + (long_option): Add private-headers. + (dump_bfd_private_header): New. + (main): Cope with new option. + +Thu Aug 31 04:09:16 1995 Doug Evans + + * dlltool.c (run): Add missing 3rd arg to waitpid. + +Wed Aug 30 11:02:11 1995 steve chamberlain + + * Makefile.in (TOOL_PROGS): Include dlltool if needed. + +Tue Aug 29 13:25:21 1995 steve chamberlain + + * dlltool.c (rva): Deleted. + (rvaafter, rva_before): Use new assembler pseudo. + (flush_page, gen_exp_file, gen_lib_file): Use new way of RVAing. + (gen_exp_file): Don't generate .edata if no need. + (gen_lib_file): Don't make timestamp. + Put _iname in idata$7. + (workout_prefix): Fix memory initialization bug. + (usage): Tidy up, delete many single char options. + (main): rva option is gone. + +Mon Aug 21 18:41:28 1995 steve chamberlain + + * dlltool.c (options): image-base is a synonym for rva. + (gen_lib_file): Put dll name into ibase$7. + +Sun Aug 20 09:59:00 1995 steve chamberlain + + Modified to generate archives and objects rather than .s files. + * dlltool.c (run) New function. + (gen_exp_file, gen_lib_file): Use run. + (workout_prefix): New. + (usage): Document new options. + (main): Parse new options. + +Wed Aug 16 16:26:52 1995 steve chamberlain + + * dlltool.c (gen_exp_file): Fix RVA handling. + (rva_s, rva_n): Delete. + +Fri Aug 11 18:27:18 1995 Ian Lance Taylor + + * nm.c (main): Ignore -e. + +Thu Aug 10 17:35:00 1995 Ken Raeburn + + * Makefile.in (config.texi): New target. Write out a setting for + texinfo variable VERSION. + (binutils.dvi, binutils.info): Depend on it. + * binutils.texi: Include it, and reference @value{VERSION} instead + of explicitly specifying 2.2(!). + +Thu Aug 10 16:07:53 1995 Ian Lance Taylor + + * coffgrok.c (do_type): Handle array dimensions the same way gdb + does. + +Tue Aug 8 17:10:42 1995 steve chamberlain + + * dlltool.c (mtable): New fields. + (ASM_RVA_BEFORE, ASM_RVA_AFTER): New. + (flush_page): Use new macros. + +Sat Aug 5 00:16:37 1995 Jeff Law (law@snake.cs.utah.edu) + + * objcopy.c (mark_symbols_used_in_relocations): Handle sections + with no relocations. + * coffgrok.c (do_sections_p1): Likewise. + +Mon Jul 31 12:51:06 1995 Ian Lance Taylor + + * strings.c (print_strings): For compatibility with existing + strings programs, print strings which are not terminated with a + null byte or a newline. + * binutils.texi, strings.1: Update documentation accordingly. + + * ar.c (replace_members): For compatibility with existing ar + programs, permit users to add the same file multiple times. + +Tue Jul 25 11:21:53 1995 Ian Lance Taylor + + * strings.c (DATA_FLAGS): Remove SEC_DATA. + (main): If no file names are given, scan standard input. + * binutils.texi, strings.1: strings now scans non-data sections by + default. + +Mon Jul 24 13:52:28 1995 J.T. Conklin + + * srconv.c (wr_hd): Set afl field to 4 for bfd_arch_sh. + (writeINT): When size == -2, use 2 bytes for the h8300 and 4 bytes + for the sh. + + * sysdump.c (fillup): Return size - 1, the last byte is a checksum + and shouldn't be counted. + * sysroff.info (hd): Changed segment identifier from a byte to a 1 + bit field. The sysroff 2.0-01 specification seems to be in error + here. Reduce width of following "spare" field from 4 to 3 bits. + (rl): Changed order and width of first 4 bitfields to correspond + to sysroff specification. + (dln_head, dln_inside, dln_tail): Removed. + +Tue Jul 18 23:00:03 1995 Fred Fish + + * nm.c (sort_symbols_by_size): Enclose expression being casted + in parens so result is casted, not just first operand. Can't + do pointer arithmetic on void* pointers. + +Fri Jul 14 13:42:42 1995 J.T. Conklin + + * sysdump.c (dh): Changed format of output to be 16 hex digits + followed by 16 ascii characters, similar to Emacs' hexl-mode, + to make it easier to read. + (xcalloc): fix typo. + +Thu Jul 13 15:27:44 1995 J.T. Conklin + + * srconv.c (wr_tr): Write out handcrafted tr block. + (walk_tree_symbol): Use evallen and evalue instead of + vallen & value because of corresponding changes in + sysroff.info. + + * sysdump.c (sysroff_swap_tr_in, sysroff_print_tr_out): New + functions. + + * sysroff.info (tr): the tr block is a special case --- a block + without contents --- which can't be handled by generated code. + (den, dpp): only first byte is present for DENend, DPPend. + (dsy): describe a conditional portion of block, rename some fields. + (dps): describe a conditional portion of block. + (dfl): removed. + + * sysinfo.y (yyerror): write error message to standard error. + +Thu Jul 13 10:43:59 1995 Ian Lance Taylor + + * Makefile.in (DISTSTUFF): Add arparse.h and sysinfo.h. + (mostlyclean): Remove y.output. + (clean): Remove sysroff, sysroff.c, sysroff.h, and sysinfo. + + * nlmconv.c (powerpc_mangle_relocs): Cast memset arg to size_t. + * objcopy.c (copy_object): Likewise. + + * nm.c (HAVE_SBRK): Define execpt on amigados and WINDOWS_NT. + (struct size_sym): Define. + (show_stats): New static variable. + (long_options): Add undocumented option "stats". + (main): Print memory stats if requested. + (sort_bfd, sort_dynamic, sort_x, sort_y): New static variables. + (numeric_forward): Use minisymbols rather than asymbols. + (non_numeric_forward): Likewise. + (size_forward1): Rename from size_forward. Use minisymbols. + (size_forward2): New static function. + (sort_symbols_by_size): Take new arguments dynamic, size, and + symsizep. Use minisymbols. Don't store the size back in the + symbol; store in a newly allocate struct size_sym array. + (display_rel_file): Read minisymbols rather than asymbols. Set + sort_* variables. Call print_size_symbols if sorting by size. + (filter_symbols): Take new arguments dynamic and size. Use + minisymbols. + (print_symbols): Likewise. Call print_symbol for actual printing. + (print_size_symbols): New static function. + (print_symbol): New static function. + +Wed Jul 12 10:43:05 1995 Ian Lance Taylor + + * objdump.c (dump_section_stabs): Only print each stabs section + once. + (compare_relocs): Make it clear to gcc that this always returns a + value. + +Wed Jul 12 10:40:23 1995 H.J. Lu + + * objcopy.c (simple_copy): Preserve errno on failure. + (smart_rename): Print error mesage if simple_copy fails. + +Tue Jul 11 13:10:52 1995 J.T. Conklin + + * sysdump.c: re-indented file. + (module): read blocks sequentially instead of trying to parse + them, as that would require changing the parser recognize the + difference between a DPSstart and DPSend block. + (getone): Add break's between switch blocks as appropriate. + (object_body_list): parse blocks according to sysroff spec. + +Mon Jul 10 12:37:25 1995 J.T. Conklin + + * sysroff.info: re-indented file, prior formatting was confusing + because it was indentation did not reflect nesting of conditional + records. Change "space size within segment" record in hd record + from bit to byte. + + * sysinfo.y (cond_it_field): Use xcalloc instead of calloc. + + * srconv.c (wr_cs): Reformatted cs header array, tag each byte + with a comment describing the field. + (wr_unit_info): Use SEEK_SET macro instead of constant 0. + (main): Use FOPEN_WB macro instead of literal "wb". + * sysroff.info: Remove fdl (dfl) field from cs block. Compare + ptr->type with ED_TYPE_CONST instead of constant 2 in ed block. + +Tue Jul 4 14:48:42 1995 Ian Lance Taylor + + * nm.c (size_forward): Check yf against yn, not xn. + + * objcopy.c (copy_archive): Record all output BFD's, and close + them before unlinking them and removing the temporary directory, + to avoid NFS problems. + + * ar.c (replace_members): In verbose messages, use 'r' when + replacing a member, and 'a' when adding one. + + * ar.c (ar_truncate): New static variable. + (normalize): Change return type to const char *. Add abfd + argument. Change all callers. If ar_truncate, chop the filename + to abfd->ar_max_namelen. + (main): For the 'f' modifier, set ar_truncate to true. Don't + change quick_append to replace if ar_truncate is true. + (do_quick_append): If ar_truncate, set BFD_TRADITIONAL_FORMAT. + (write_archive): Likewise. + * binutils.texi, ar.1: Document 'f' modifier. + + * objcopy.c (enum strip_action): Define strip_unneeded. + (OPTION_STRIP_UNNEEDED): Define. + (strip_options): Add "strip-unneeded". + (copy_options): Likewise. + (copy_usage): Mention --strip-unneeded. + (strip_usage): Likewise. + (is_strip_section): Strip debugging sections if strip_unneeded. + (filter_symbols): If strip_unneeded, only keep BSF_KEEP symbols. + (copy_object): If strip_all, discard symbols without checking + discard_locals. + (copy_object): Call filter_symbols if strip_unneeded. + (setup_section): Strip debugging sections if strip_unneeded. + (copy_section): Likewise. + (strip_main): Handle OPTION_STRIP_UNNEEDED. + (copy_main): Likewise. + * binutils.texi, objcopy.1, strip.1: Document --strip-unneeded. + +Mon Jul 3 14:16:47 1995 Steve Chamberlain + + * configure.in (i386-*-win32): New configuration. + * dlltool.c (killat, xlate, usage, long_options, main): + Understand and cope with -k option. + +Sat Jul 1 12:25:15 1995 Fred Fish + + * ar.c: (extract_file): Change "#if POSIX_UTIME" to + "#ifdef POSIX_UTIME" to match other tests of POSIX_UTIME + and avoid lossage when POSIX_UTIME is not defined at all. + +Wed Jun 28 17:51:24 1995 Steve Chamberlain + + * ar.c: (print_contents.c, extract_file, do_quick_append): + Malloc buffers rather than allocate on stack (so it works + on NT). + * deflex.l: Names can have an @ in them. + * dlltool.c: Loads of stuff. Can now generate .imp files which + work with NT .dlls. + +Thu Jun 22 19:10:50 1995 Stan Shebs + + * mpw-make.in (demangle.c.o): Remove. + (arparse.h): Depend on arparse.c instead of arparse.y. + +Wed Jun 21 17:32:45 1995 Ken Raeburn + + * Makefile.in (DISTSTUFF): Don't include info here. + (diststuff): Include it here. + (realclean): Remove *.info. + + * objdump.c (compare_relocs): If relocation entries have the same + address, keep them in file order. + +Mon Jun 19 09:06:49 1995 Steve Chamberlain + + * dlltool.c: Change names of generated files. .*.s-> -*.s + + * objdump.c (dump_section_stabs): Check for names + which are supersets of selected names. + +Wed Jun 14 19:43:52 1995 Doug Evans + + * dlltool.c (mtable, ARM jump): Must redirect via pc offsetable ptr. + +Wed Jun 14 13:27:22 1995 Steve Chamberlain + + * deflex.l, defparse.y, dlltool.c: New files. + * Makefile.in, configure.in: Support for them. + +Mon Jun 12 11:27:54 1995 Steve Chamberlain + + * sysdump.c: Include sysdep.h + (main): Open input with FOPEN_RB. + +Fri Jun 9 17:26:11 1995 Michael Meissner + + * objdump.c (wide_output): New flag variable. + (usage): Print new -w, --wide options. + (long_options): Add --wide support. + (dump_section_header): If --wide, don't print a newline between + the section's first line and the flags. + (objdump_print_address): Use unsigned comparisons for the binary + search, not signed. + (disassemble_data): If --wide, don't put a \n between the + disassembly output and relocation information. + (main): Support -w option being the same as --wide. + +Thu Jun 1 17:09:27 1995 Ken Raeburn + + Sat May 6 08:52:24 1995 H.J. Lu (hjl@nynexst.com) + + * objcopy.c (smart_rename): make it smarter, clean up + if rename () fails. + +Tue May 30 14:24:15 1995 Ken Raeburn + + * Makefile.in: Delete lines with lots of #### because four or more + indicate a point for makefile fragment substitution. + +Tue May 9 17:17:05 1995 Michael Meissner + + * configure.in: Don't build nlmconv on PowerPC eabi any more, it + is not needed. + +Thu Apr 27 20:21:24 1995 Doug Evans + + * Makefile.in (EXPECT): Define. + (RUNTEST): Use one in source tree if present. + (check): Set `rootme' for $(EXPECT). + +Wed Apr 26 18:26:21 1995 Steve Chamberlain + + * srconv.c (main): Add support for -n option which disables + prescan of common symbols. + (wr_ob): If reading past the end of a section, fill with zeros. + +Tue Apr 25 19:14:37 1995 Ken Raeburn + + * objdump.c (dump_section_header): Display load address after + virtual memory (run-time) address. + +Wed Apr 19 09:44:06 1995 Jason Merrill + + * Makefile.in (cplus-dem.o): Pass -DVERSION='"$(VERSION)"' to the + compile. + (DEMANGLER_PROG): No longer uses version.o. + +Mon Apr 10 13:29:49 1995 Stan Shebs + + Merge in support for Mac MPW as a host. + (Old change descriptions retained for informational value.) + + * mpw-config.in (TDEFINES): Define as empty in makefile frag. + + * mpw-config.in: Create mk.tmp, define ARCHDEFS in it. + + * mpw-config.in: New file, MPW configure fragment for binutils. + * mpw-make.in (install-only): New target. + (install): Also depend on install-only. + + * mpw-make.in (cplusfilt): Renamed from c++filt. + (INCLUDES): Add more paths. + + * mpw-make.in: New file, MPW makefile fragment for binutils. + (Normally automatically generated from Makefile.in.) + +Mon Mar 27 11:52:57 1995 Ian Lance Taylor + + * ar.c (write_archive): Call make_tempname to get output file + name, rather than using a fixed name based on the input file. + + * objcopy.c (make_tempname): Copy from here... + * bucomm.c (make_tempname): ...to here, and make global. + * bucomm.h (make_tempname): Declare. + +Fri Mar 24 11:47:42 1995 Ian Lance Taylor + + * strings.c: Include "bfd.h" before other headers. Include + "sysdep.h". + * bucomm.c (print_arelt_descr): Cast st_uid and st_gid to long, + and print them with %ld. + +Fri Mar 10 13:09:42 1995 Ian Lance Taylor + + * objcopy.c (strip_options): Add --keep-symbol. + (copy_options): Likewise. + (copy_usage): Mention --keep-symbol and -K. + (strip_usage): Likewise. + (keep_symbols): New static variable. + (is_strip_symbol): Adjust the return value according to + keep_symbols. + (strip_main): Handle -K. For -N, check that -K was not given. + (copy_main): Likewise. + * binutils.texi, objcopy.1, strip.1: Document -K. + +Mon Mar 6 13:33:47 1995 Stan Shebs + + * objcopy.c (copy_archive): Check result of mkdir. + (copy_main): Cast an xmalloc result. + + * objdump.c (usage): Break long format string into shorter ones. + +Mon Mar 6 13:46:12 1995 Ian Lance Taylor + + * bucomm.c (list_supported_targets): New function. + * bucomm.h (list_supported_targets): Declare. + * ar.c (usage): Call list_supported_targets. + * nm.c (usage): Likewise. + * objcopy.c (copy_usage, strip_usage): Likewise. + * objdump.c (usage): Likewise. + * size.c (usage): Likewise. + * strings.c (usage): Likewise. + +Tue Feb 28 15:13:58 1995 Ian Lance Taylor + + * bucomm.c (print_arelt_descr): Cast st_size to long before + passing it to fprintf. + +Fri Feb 17 13:36:45 1995 Ian Lance Taylor + + * objcopy.c (struct section_list): Add fields remove, set_flags, + and flags. Change adjust from boolean to enum. + (remove_sections): Remove static variable. + (sections_removed): New static variable. + (copy_options): Add --set-section-flags. + (copy_usage): Mention --set-section-flags. + (parse_flags): New static function. + (find_section_list): New static function. + (is_strip_symbol): Change return type from int to boolean. + (is_strip_section): New static function. + (filter_symbols): Call is_strip_section. + (copy_object): When adding sections, check for specified flags or + VMA. Call filter_symbols if any sections are being removed. + (setup_section): Use find_section_list function rather than + looking through remove_sections and adjust_sections. Handle + --set-section-flags. + (copy_section): Use find_section_list rather than looking through + remove_sections. + (strip_main): Use find_section_list instead of adding items to + sections_removed. + (copy_main): Use find_section_list instead of adding items to + sections_removed and adjust_sections. Handle --set-section-flags. + * binutils.texi, objcopy.1: Document --set-section-flags. + +Tue Feb 14 18:03:03 1995 Ian Lance Taylor + + * objdump.c (with_source_code): New global variable. + (usage): Mention -S/--source. + (long_options): Add --source. + (prev_functionname, prev_line): New static variables. + (struct print_file_list): Define. + (print_files): New static variable. + (skip_to_line, show_line): New static functions. + (disassemble_data): Call show_line to handle -l and -S. + (main): Handle -S. + * binutils.texi, objdump.1: Document -S/--source. + +Thu Feb 9 16:11:53 1995 Ian Lance Taylor + + * objcopy.c (copy_usage): Rename parameter to avoid shadowing. + (strip_usage): Likewise. + + * objcopy.c (struct section_add): Define. + (add_sections): New static variable. + (copy_options): Accept --add-section. + (copy_usage): Mention --add-section. + (copy_object): Add sections from the add_sections list. + (copy_main): Handle --add-section. + * binutils.texi, objcopy.1: Document --add-section. + +Wed Feb 1 15:04:57 1995 Ken Raeburn + + * objdump.c (disassemble_data): Pass section offset, not absolute + address, to bfd_find_nearest_line. + + * nlmconv.c (powerpc_mangle_relocs): Don't use const with + reloc_howto_type. + +Thu Jan 26 18:50:06 1995 Ian Lance Taylor + + * objdump.c (compare_symbols): Use bfd_asymbol_value (VAR) rather + than VAR->value. + (objdump_print_address): Likewise. + (disassemble_data): Don't change the symbol values. It can + confuse bfd_canonicalize_reloc. + +Thu Jan 26 12:03:56 1995 Michael Meissner + + * configure.in: Add support for powerpc-*-ebai. + +Wed Jan 18 10:02:12 1995 Steve Chamberlain + + * coffdump.c: Include sysdep.h. + (dump_coff_type): Handle coff_secdef_type. + * coffgrok.c : Include sysdep.h. + * srconv.c: Include libiberty.h + (absolute_p, dty_start, dty_end, dump_tree_structure): Remove. + +Wed Jan 18 12:24:14 1995 Ian Lance Taylor + + * coffdump.c (dump_coff_scope): Cast pointer to unsigned long for + printf. + * coffgrok.c: Include bucomm.h. Don't declare xmalloc. + (push_scope): Declare type of parameter link. + * size.c: Include libiberty.h. + * srconv.c: Include bucomm.h. + (find_base): Declare at top of file. + (wr_hd): Add default case to architecture switch. + (wr_dps_start): Declare type of parameter nest. + (wr_du): Comment out variables used only in commented out blocks. + (wr_dus): Remove unused variable i. + (wr_sc): Remove unused variables myinfo, low, and high. + * strings.c: Include libiberty.h. + * sysdump.c: Include . + +Tue Dec 20 19:13:44 1994 Ian Lance Taylor + + * ar.c (main): Ignore 'f' modifier used on HP/UX 9. + +Thu Dec 15 17:34:12 1994 Stan Shebs + + * ar.c, nm.c, objcopy.c, objdump.c: Include progress.h. + * ar.c, nm.c, objcopy.c, objdump.c (main): Add START_PROGRESS + and END_PROGRESS. + * ar.c (map_over_members, open_inarch): Call PROGRESS. + * nm.c (main, display_archive, filter_symbols, print_symbols): + Call PROGRESS. + + * objcopy.c (copy_usage): Break up long usage string. + +Wed Dec 14 15:51:56 1994 Ken Raeburn + + * objcopy.c (copy_object): Don't bother setting status after + nonfatal() "call", because it won't return. + +Fri Dec 9 00:22:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (powerpc_mangle_relocs): Don't switch a reloc to use + the section symbol if the symbol is undefined. + +Thu Dec 8 14:45:50 1994 Ken Raeburn + + * objcopy.c (add_strip_symbol): Cast return value of xmalloc. + +Wed Nov 30 11:05:43 1994 Ian Lance Taylor + + * ar.c (replace_members): Pass current->filename to normalize when + checking for duplicates, because the filename of a newly added + file will not have been normalized yet. + +Thu Nov 17 15:00:13 1994 Ian Lance Taylor + + * ar.c (main): Don't call do_quick_append if any of the archive + names are longer than 14 characters. + + * objcopy.c (main): Fix is_strip test. From + pirker@eiunix.tuwien.ac.at (Martin Pirker). + +Thu Nov 17 15:37:19 1994 Mark W. Eichin + + * objcopy.c (add_strip_symbol): New function, adds a name to an + explicit list of symbols to strip. + (is_strip_symbol): New function, reports whether the name argument + is in the explicit list. + (filter_symbols): Check against is_strip_symbol above all. + (strip_main): Recognize -N option. If used, don't default to + strip_all. + (copy_main): Recognize -N option. + (strip_usage): Document -N and --strip-symbol options. + (copy_usage): Ditto. + * objcopy.1, strip.1, binutils.texi: Document -N and + --strip-symbol options. + +Tue Nov 8 13:12:54 1994 Ian Lance Taylor + + * objdump.c (display_target_list, display_info_table): Pass an + array to tmparg, rather than NULL, since some systems can't handle + NULL. + + * objcopy.c (copy_archive): Keep a list of the names of the + temporary files we created. Close each input BFD after we open + its successor. + +Mon Nov 7 15:48:39 1994 Ken Raeburn + + * Makefile.in (VERSION): Bump to 2.5.3. + +Thu Nov 3 19:04:34 1994 Ken Raeburn + + * Makefile.in (install-info): Install info files from whatever + directory they were found in. + + Patch from DJ Delorie: + * configure.bat: do c++filt -> cxxfilt right + + * sysinfo.y: Include system header files early, so any potential + declaration of abort() occurs before its use. + + * strings.c (strings_file): Try opening the file in binary mode + first. + +Wed Nov 2 15:44:13 1994 Ian Lance Taylor + + * ar.c (main): Treat ar qs like ar rs. + +Tue Oct 25 16:19:25 1994 Ian Lance Taylor + + * objcopy.c (gap_fill): Explicitly initialize, for clarity. + (pad_to_set, pad_to): New static variables. + (copy_options): Accept --pad-to. + (copy_usage): Mention --pad-to. + (copy_object): Support --pad-to. + (compare_section_vma): Sort non loadable sections to the front. + Sort sections with the same VMA by size. + (copy_main): Handle --pad-to. + * binutils.texi, objcopy.1: Document --pad-to. + +Thu Oct 20 13:51:31 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (gap_fill_set, gap_fill): New static variables. + (copy_options): Accept --gap-fill. + (copy_usage): Mention --gap-fill. + (copy_object): Support --gap-fill. + (get_sections, compare_section_vma): New static functions. + (copy_main): Handle --gap-fill. + * binutils.texi, objcopy.1: Document --gap-fill. + +Wed Oct 19 14:09:16 1994 Ian Lance Taylor + + * Makefile.in (check): Add a dummy else clause to the if + statement. + + * objcopy.c (copy_object): Revert yesterday's change. + * binutils.texi, objcopy.1: Remove special mention of --set-start + and `binary' output format. + +Tue Oct 18 11:12:01 1994 Ian Lance Taylor + + * objcopy.c (copy_object): If the output file format is `binary', + and the start address was not set using --set-start, default the + start address to zero. This hack is because the `binary' output + file format uses the start address to set the virtual address of + the first byte in the file. + * binutils.texi, objcopy.1: Add some notes on generating S-records + and binary files. + + * nm.c (print_symdef_entry): Call print_symname to print the + symbol name, so that --demangle works. + + * Makefile.in (mostlyclean): Remove tmpdir. + + * objcopy.c (struct section_list): Add fields used, adjust, val. + (adjust_start, set_start_set, set_start): New static variables. + (adjust_section_vma, adjust_sections): New static variables. + (copy_options): Add --adjust-start, --adjust-vma, + --adjust-section-vma, --adjust-warnings, --no-adjust-warnings, + --set-start. + (parse_vma): New static function. + (copy_usage): Mention new options. + (copy_object): Handle --set-start and --adjust-start. + (setup_section): Correct type of last argument to PTR. Set used + field if section is removed. Handle --adjust-vma and + --adjust-section-vma. + (copy_section): Correct type of last argument to PTR. + (mark_symbols_used_in_relocations): Likewise. + (strip_main): Clear used field when handling -R. + (copy_main): Handle new options. + * binutils.texi (objcopy): Document new options. + * objcopy.1: Document new options. + +Fri Oct 14 14:38:13 1994 Ian Lance Taylor + + * configure.in (configdirs): Remove definition--testsuite is no + longer configured. + * Makefile.in (testsuite): Remove target. + (site.exp): New target. + (check): Rewrite. + (clean, distclean): Don't recur into testsuite directory. + +Thu Oct 13 19:24:09 1994 Ken Raeburn + + * Makefile.in (VERSION): Updated to 2.5. + * Version 2.5 released. + +Tue Oct 11 15:26:42 1994 Ian Lance Taylor + + * Makefile.in (sysdump.o): Depends upon sysroff.c. + +Mon Oct 10 13:50:30 1994 J.T. Conklin (jtc@rtl.cygnus.com) + + * nlmconv.c (link_inputs): Pass -Ur flag to ld so that the + ctor/dtor tables needed by C++ programs are built. + +Sun Oct 9 18:04:00 1994 Jim Wilson (wilson@sphagnum.cygnus.com) + + * Makefile.in (srconv.o): Add dependence on sysroff.c. + +Tue Oct 4 12:19:51 1994 Ian Lance Taylor + + * configure.in: Use ${config_shell} when running config.bfd. + + * Makefile.in (sysroff.h): Split target away from sysroff.c. + (srconv.o, sysdump.o): New targets. + (srconv, sysdump): Don't depend upon sysroff.c. + +Wed Sep 28 13:04:34 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * Makefile.in (arparse.c): Don't ignore errors from mv. + (sysinfo.c): Likewise. Also, depend upon arparse.c, to prevent a + parallel make from trying to build both arparse.c and sysinfo.c + simultaneously. + (nlmheader.c): Similar change. + (arparse.h): Separate target from arparse.c, so that a parallel + make does not try to build both at once. Depend upon arparse.c. + (sysinfo.h): Similar change. + + * objdump.c (disassemble_data): Pass the reloc buffer to free, not + the pointer used to loop over the relocs. + +Sat Sep 24 16:16:57 1994 Stan Shebs (shebs@andros.cygnus.com) + + * objdump.c (disassemble_data): Cast result of xmalloc. + +Wed Sep 21 19:30:35 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (sorted_syms, sorted_symcount): New global variables. + (objdump_print_address): Use sorted_syms and sorted_symcount + instead of syms and symcount. + (disassemble_data): Don't bother to get the relocs before looping + over the sections. Before filtering and sorting the symbol table, + copy it into sorted_syms. + +Fri Sep 16 11:27:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (struct objdump_disasm_info): Add field require_sec. + (objdump_print_address): If aux->require_sec, require that the + symbol be in aux->sec even if HAS_RELOC is not set. If we can't + find a smaller symbol in the right section, look for a larger one. + (disassemble_data): Set aux.require_sec around the + objdump_print_address call for the instruction address. + +Thu Sep 15 21:43:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ar.c: Call xexit rather than exit. + (output_filename, output_file, output_bfd): New static variables. + (remove_output): New static function. + (main): Call xatexit (remove_output). Call xexit rather than + returning. + (extract_file): Set output_filename and output_file while output + file is open. + (write_archive): Likewise, but use output_bfd, not output_file. + * arsup.c: Include libiberty.h. Call xexit rather than exit. + * bucomm.c: Likewise. + + * objdump.c (disassemble_all): New global variable. + (usage): Document --disassemble-all. + (long_options): Add disassemble-all as a synonym for -D. + (compare_symbols): Make pointers const. + (compare_relocs): New static function. + (disassemble_data): Rename disassemble to disassemble_fn to avoid + shadowing. If dump_reloc_info, print relocs along with + disassembly. Skip sections which are not SEC_CODE unless + disassemble_all or only is set. + (display_bfd): Don't call dump_relocs if disassemble is set. + (main): Accept and handle -D. + * binutils.texi: Document -D/--disassemble-all. + * objdump.1: Likewise. + +Wed Sep 14 12:19:07 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (disassemble_data): Initialize prevline to 0. Make + prev_function non const. Copy functionname into an malloc buffer + when setting prev_function, instead of assuming that the string + will last forever. + + * nm.c: Include libiberty.h. + (sort_by_size): New static variable. + (long_options): Add --size-sort. + (usage): Mention --size-sort. + (numeric_forward): Make static. Change from void * to PTR. + (numeric_reverse): Likewise. + (non_numeric_forward, non_numeric_reverse): Likewise. + (sorters): Change declaration from void * to PTR. + (size_forward, sort_symbol_by_size): New static functions. + (display_rel_file): Handle sort_by_size. + (filter_symbols): If sort_by_size, discard absolute and undefined + symbols. + * binutils.texi (nm): Document --size-sort. + * nm.1: Document --size-sort. + +Tue Sep 13 21:06:06 1994 Jeff Law (law@snake.cs.utah.edu) + + * objcopy.c (copy_main): Initialize input_filename and + output_filename to NULL. + +Tue Sep 13 14:17:24 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * Makefile.in (version.o): Depend upon Makefile, so that version.o + gets rebuilt when make variable VERSION is changed. + + * objdump.c (dump_section_header): Print the SEC_NEVER_LOAD flag. + +Wed Aug 24 12:40:09 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * configure.in: Change i[34]86 to i[345]86. + +Tue Aug 23 11:00:40 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * ar.c (ranlib_touch): Don't update the archive map if there isn't + one. + +Mon Aug 22 16:02:18 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * ar.c: Include libiberty.h. + (inarch): Remove variable. + (map_over_members): Make static. Add arch argument, and use it + instead of inarch. Change all callers. + (main): Treat --version as -v. Accept -t argument. Accept any + number of archive arguments. Catch and use open_inarch return + value, rather than using inarch. + (open_inarch): Return newly opened BFD, rather than using inarch. + (do_quick_append): Make archive_filename const. + (write_archive): Add iarch argument, and use it instead of inarch. + Change all callers. + (delete_members, move_members, replace_members): Likewise. + (ranlib_only): Don't exit on success. Catch and use open_inarch + return value. + (ranlib_touch): New function. + * arsup.h (map_over_members): Don't declare. + (ar_end, ar_extract): Declare. + (open_inarch): Change return value in declaration to bfd *. + * arsup.c (map_over_list): Make static. Always pass two arguments + to function. Add arch argument, and use it instead of inarch. + Change all callers. + (ar_directory_doer): Make static. Add ignored second argument. + Change all callers. + (ar_directory): Use open_inarch return value rather than inarch. + (ar_addlib_doer): Make static. + (ar_addlib): Use open_inarch return value rather than inarch. + (ar_extract): Remove unused local variable abfd. + +Thu Aug 11 14:55:57 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + Add support for removing named sections to objcopy and strip. + * objcopy.c (struct section_list): Define. + (remove_sections): New static variable. + (strip_options, copy_options): Add remove-section. + (copy_usage, strip_usage): Mention -R and --remove-section. + (setup_section): If section is in remove_sections list, ignore it. + (copy_section): Likewise. + (strip_main, copy_main): Handle -R. + * binutils.texi, objcopy.1, strip.1: Document new options. + +Wed Aug 10 10:19:55 1994 Stan Shebs (shebs@andros.cygnus.com) + + * nlmconv.c (powerpc_mangle_relocs): Rename symvalue to sym_value, + so as not to conflict with the symvalue typedef in bfd.h. + +Mon Aug 1 13:19:09 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * nlmheader.y: Per current NetWare docs, accept a revision number + of 0 and treat a revision number greater than 26 as 0. + +Mon Jul 25 12:58:36 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (objdump_print_address): Correct handling of end of + symbols when looking for next symbol with a different value. + +Fri Jul 22 16:48:34 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * nm.c (numeric_forward): Treat undefined symbols as "less than" + defined symbols with zero values. If numeric values are equal, or + both symbols are undefined, sort alphabetically. Don't assume + that the difference of two bfd_vma values will truncate to "int" + and still have the same sign. + (numeric_reverse): Call numeric_forward and negate the result. + (print_symbol_info_bsd): For undefined symbols, print leading + spaces equivalent to the width of a printed bfd_vma, rather than + assuming that 8 will look right. + +Fri Jul 22 10:36:50 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coffgrok.c (doit): Zero all fields of new structure. + * srconv.c (sysroff_swap_*_out): Remove redundant trailing arg. + * sysinfo.y: Generate sysroff_swap_*_out without requiring extra + arg. + +Fri Jul 22 10:09:53 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * nlmheader.y: Make "stack" and "stacksize" synonyms in the lexer + rather than the parser. + +Thu Jul 21 10:25:09 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/mh-alphaosf, config/mh-apollo68v, config/mh-delta88: + Remove; obsolete. + +Sat Jul 16 22:34:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (slurp_dynamic_symtab): Try to get the dynamic symbols + even if the bfd is not marked DYNAMIC. ELF executables are not + marked DYNAMIC, but do have dynamic symbols. + +Fri Jul 15 01:41:35 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coffgrok.c (do_where): Make data with no type 'int'. + (do_define): Keep info on source file of a symbol. + * coffgrok.h (coff_symbol): New field. + * srconv.c (PROGRAM_VERSION): Now 1.3 + (wr_rl): Use external ref number for symbol. + (wr_dus): Only keep one source file per debug unit. + (wr_dln): Always emit line numbers for first source file, + (wr_globals): Emit globals in the du of their owning source file. + +Mon Jul 11 15:59:03 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * nlmheader.y: Null terminate var_hdr->threadName. + +Fri Jul 8 17:33:22 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (syslex.o, sysinfo.o): Permit C source files to be + in $(srcdir), as they will be for FSF releases. + +Wed Jul 6 01:13:14 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (setup_sections): Preserve existing section flags when + copying in flags from a new section. + +Tue Jul 5 15:56:01 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objcopy.c: Include libiberty.h. + (copy_file): If output_target is NULL, set it to the target of the + input file. + +Wed Jun 29 17:17:14 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * nlmconv.c (link_inputs): Fixed memory allocation bug. + +Thu Jun 23 12:52:46 1994 David J. Mackenzie (djm@rtl.cygnus.com) + + * configure.in: Change --with-targets to --enable-targets. + +Tue Jun 21 12:53:21 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * Makefile.in (sysinfo): Does not depend upon $(ADDL_LIBS). + + * nlmconv.c (powerpc_build_stubs): Don't generate the PowerPC + NetWare custom header; no longer needed. + (powerpc_mangle_relocs): Convert relocs against the uninitialized + data section into relocs against the data section. + + * configure.in: Set nlmconv_defs to -DNLMCONV_cputype for all the + netware targets. Write it into Makefile as NLMCONV_DEFS. + * Makefile.in (nlmconv.o): Pass $(NLMCONV_DEFS) to $(CC). + * nlmconv.c: Only compile code for specific CPU types if + NLMCONV_cputype is defined. + + * nlmconv.c (main): Change uses of bfd_abs_section, etc., to use + bfd_abs_section_ptr or bfd_is_abs_section, etc. + (i386_mangle_relocs, alpha_mangle_relocs): Likewise. + (powerpc_build_stubs): Likewise. + * nm.c (filter_symbols, print_symbols): Likewise. + * objcopy.c (filter_symbols): Likewise. + (mark_symbols_used_in_relocations): Likewise. + * objdump.c (remove_useless_symbols, dump_relocs): Likewise. + * size.c (sysv_internal_printer): Likewise. + +Mon Jun 20 16:43:03 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (MANPAGES): Remove $(DEMANGLER_PROG). + (install): Install it explicitly, from build dir, not srcdir. + +Mon Jun 20 16:29:54 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c: Don't include elf/internal.h. + (bfd_elf_find_section): Don't declare. + (read_section_stabs): No special handling for ELF. Always read + using BFD sections. + +Thu Jun 16 17:25:20 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * configure.in: Set UNDERSCORE in Makefile based on result of + invoking config.bfd with a second argument of ``_''. + * Makefile.in (underscore.c): Depend upon Makefile. Don't try to + run $(CC) and $(NM), just use $(UNDERSCORE). Create via temporary + file. + (demangle.o): Remove target. + ($(NM_PROG)): Don't depend upon demangle.o, and don't link against + demangle.o. It's in libiberty anyhow. + (cplus-dem.o): Don't depend upon demangle.o. + * binutils.texi: Mention -n and --no-strip-underscores arguments + to c++filt. + +Wed Jun 15 12:10:31 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nm.c (long_options): Add --no-demangle to turn off --demangle, + and --no-cplus for Linux compatibility. + (usage): Mention --no-demangle. + * binutils.texi: Document --no-demangle. + +Fri Jun 10 15:41:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nm.c: HOST_64_BIT was renamed to BFD_HOST_64_BIT. + + * objcopy.c (copy_archive): Make the temporary directory in the + same directory as the output BFD, since we may not have write + permission on the current directory. Set the permissions of the + new directory to 0700, not 0777. + +Mon Jun 6 21:36:43 1994 D. V. Henkel-Wallace (gumby@cygnus.com) + + * configure.in: if this is an rs6000 (and we're not building for + any other bfd targets) then build only nm (collect needs it on + rs6000-lynx). + + * Makefile.in: define TOOL_PROGS which the list of programes to + install in $tooldir -- replaces a hard-coded list. + +Fri Jun 3 10:59:18 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (display_target_list): Remove unused local ok. + +Thu May 26 18:05:52 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/mh-alphaosf (CFLAGS): Don't specify both -g and -O; + they're not compatible under native cc. Use -O1 instead. + + * Makefile.in (VERSION): Updated to cygnus-2.4.1. + + Changes from binutils-2.4 net release: + + * Makefile.in (MANPAGES): Use $(DEMANGLER_PROG). + ($(DEMANGLER_PROG).1): Build from cxxfilt.man, using sed. + * cxxfilt.man: Renamed from c++filt.1, replaced "c++filt" with + magic token to be replaced by sed. + + Wed May 11 22:32:00 1994 DJ Delorie (dj@ctron.com) + + * configure.bat: update for latest makefile.in + +Fri May 13 23:25:13 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * bucomm.c: Check ANSI_PROTOTYPES rather than __STDC__. + +Tue May 10 18:22:06 1994 Jason Molenda (crash@sendai.cygnus.com) + + * objcopy.c (copy_section): Set section size correctly if using + interleave. + +Sat May 7 16:49:36 1994 Steve Chamberlain (sac@cygnus.com) + + * Makefile.in: Add rule for sysinfo.h + +Fri May 6 12:18:33 1994 Steve Chamberlain (sac@cygnus.com) + + * Makefile.in (SRCONV_PROG): Define. + (PROGS): Use $(SRCONV_PROG) too. + +Thu May 5 19:41:43 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (DISTSTUFF): Add sysinfo.c, syslex.c, in case + someone configures with `targets=all'. + (distclean): Remove y.*. + (syslex.o): Depend on sysinfo.h. + (sysinfo.c): Rename y.tab.h to sysinfo.h. + (install-info): Don't try to install into $(infodir)/$(srcdir). + * syslex.l: Include sysinfo.h, not y.tab.h. + +Thu May 5 11:50:55 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * syslex.l (yywrap): Define as function if not defined as a macro. + + * Makefile.in (objdump.o): Deleted special rule. + * configure.in: Don't bother building ARCHDEFS variable for + Makefile. + * objdump.c (ARCH_*): Deleted handling. + (disassemble_data): Call `disassembler' from opcodes library. + +Thu May 5 13:28:42 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (install): Correct handling of $(tooldir) and + $(bindir) being on different devices. + +Fri Apr 29 09:50:38 1994 Steve Chamberlain (sac@cygnus.com) + + * sysdump.c (h8300, sh): Add declarations. + +Wed Apr 27 11:25:18 1994 Steve Chamberlain (sac@cygnus.com) + + * Makefile.in (syslex, sysinfo): Use CC_FOR_BUILD. + * coffdump.c, coffgroc.c, coffgrog.h, srconv.c, sysdump.c, + sysroff.info: Major changes. + +Tue Apr 26 18:18:24 1994 Stan Shebs (shebs@andros.cygnus.com) + + * objdump.c (print_section_stabs): Indicate the stab header symbol + more clearly, print numbers of unrecognized stab n_type values. + +Tue Apr 26 16:22:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (copy_sections): Copy arelent pointers, not arelents. + +Mon Apr 25 16:14:32 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (distclean): Remove $(PROGS) and underscore.c. + +Fri Apr 22 11:14:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (setup_sections): Remove special handling of .reginfo + section. + (copy_sections): Likewise. + (alpha_mangle_relocs): Use bfd_ecoff_get_gp_value rather than the + special ECOFF .reginfo section. + + * objcopy.c (copy_object): Call bfd_copy_private_bfd_data after + copying everything else, to let it fiddle with the file in its + final state. + + * objdump.c: Include libiberty.h. + (display_target_list): If a format fails, just go on to the next + one. Check return value of bfd_set_format. + (display_info_table): Likewise. Don't increment loop variable in + for loop test, since that skips the first element. + (display_target_tables): Rewrite loop for clarity. Ensure that it + always prints at least one element. + + * nlmconv.c (main): Use CyGnUsEx rather than CyGnUsSeCs for + sections header. Rename from cygnus_sections to cygnus_ext. + +Thu Apr 21 12:12:26 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (_DUMMY_NAME_): Don't define. + (display_target_list): Use tmpnam to get a file name rather than + using _DUMMY_NAME_. Unlink it when done. + (display_info_table): Likewise. + + * nlmconv.c (secsec): New static variable. + (main): Create .nlmsections section in output BFD. Store + information about it in sections header. + (setup_sections): Allocate space in sections header. + (copy_sections): Copy zero sized sections. Put information about + each section in the sections header. + +Wed Apr 20 14:34:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (powerpc_build_stubs): Take new outbfd argument. + Change caller. Create custom header for new PowerPC NetWare + format. + + * Makefile.in (nlmheader.o, nlmconv.o): Update dependencies. + * nlmconv.c: Include bfd.h and libiberty.h with "", not <>. + * nlmheader.y: Include bfd.h with "", not <>. + +Wed Apr 13 10:52:50 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c: Do an ifdef on __GO32__, not unix. + +Wed Apr 6 21:54:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Added -D (--dynamic) option to nm and -T (--dynamic-syms) and -R + (--dynamic-reloc) arguments to objdump. + * nm.c (dynamic): New static variable. + (long_options): Added "dynamic". + (usage): Mention -D and --dynamic. + (main): Add D to getopt string. Handle -D by setting dynamic. + (display_rel_file): If dynamic is non-zero, read dynamic symbols + rather than normal symbols. + * nm.1: Updated for -D (--dynamic) option. + * objdump.c (dump_dynamic_symtab): New global variable. + (dump_dynamic_reloc_info): New global variable. + (dynsyms, dynsymcount): New global variables. + (usage): Mention -R, -T, --dynamic-syms and --dynamic-reloc. + (long_options): Added "dynamic-reloc" and "dynamic-syms". + (slurp_symtab): If no symbols, return rather than exit. + (slurp_dynamic_symtab): New function. + (display_bfd): Handle dump_dynamic_symtab and + dump_dynamic_reloc_info. + (dump_symbols): Take new dynamic argument, indicating whether to + display dynamic symbols. + (dump_relocs): Move most printing into dump_reloc_set. + (dump_dynamic_relocs): New function. + (dump_reloc_set): New function, extracted from dump_relocs. + (main): Add R and T to getopt string. Handle -T by setting + dump_dynamic_symtab and -R by setting dump_dynamic_reloc_info. + * objdump.1: Updated for -R (--dynamic-reloc) and -T + (--dynamic-syms) options. + * binutils.texi: Updated for new nm and objdump options. + +Wed Mar 30 15:52:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Update for recent BFD changes to symbol and reloc reading. Rename + all uses of get_symtab_upper_bound to bfd_get_symtab_upper_bound. + Also: + * coffgrok.c (symcount): Change to long. + (do_sections_p1): Check for error return from + bfd_get_reloc_upper_bound. Change relcount to long, and check for + error from bfd_canonicalize_reloc. + (coff_grok): Change storage to long. Check for error from + bfd_get_symtab_upper_bound and bfd_canonicalize_symtab. + * nlmconv.c (main): Change symcount, newsymalloc, newsymcount, and + i to long. Check for error from bfd_get_symtab_upper_bound and + bfd_canonicalize_symtab. + (copy_sections): Change reloc_size and reloc_count to long. Check + for error from bfd_get_reloc_upper_bound and + bfd_canonicalize_reloc. + (mangle_relocs, i386_mangle_relocs, alpha_mangle_relocs): Change + reloc_count_ptr argument to long *. Make corresponding changes to + variables loaded from *reloc_count_ptr. + * nm.c (display_rel_file): Change storage and symcount to long. + Check for errors from bfd_get_symtab_upper_bound and + bfd_canonicalize_symtab. + * objcopy.c (filter_symbols): Change symcount, src_count and + dst_count to long. + (copy_object): Change symcount to long. Pass another argument to + fprintf. Check for errors from bfd_get_symtab_upper_bound and + bfd_canonicalize_symtab. + (copy_section): Change relcount to long. Check for errors from + bfd_get_reloc_upper_bound and bfd_canonicalize_reloc. + (mark_symbols_used_in_relocations): Change relcount and i to long. + Check for errors form bfd_get_reloc_upper_bound and + bfd_canonicalize_reloc. + * objdump.c (storage): Remove global variable. + (symcount): Changed to long. + (slurp_symtab): New local variable storage. Check for errors from + bfd_get_symtab_upper_bound and bfd_canonicalize_symtab. + (remove_useless_symbols): Change return value and count to long. + (objdump_print_address): Change min, max, thisplace and i to long. + (disassemble_data): Change i to long. + (dump_symbols): Change count to long. + (dump_relocs): Change relcount to long. Check for errors from + bfd_ret_reloc_upper_bound and bfd_canonicalize_reloc. + (display_info_table): Add casts when passing LONGEST_ARCH for + printf %* argument. + +Tue Mar 29 14:59:04 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nm.c (display_archive): Close each archive element after it has + been displayed. + * objdump.c (display_file): Likewise. + +Mon Mar 28 13:04:08 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * configure.in: Change error message to refer to bfd/config.bfd + rather than bfd/configure.in. + +Sun Mar 27 16:23:39 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * More fixes for object formats which allow multiple sections + with the same name: + * objcopy.c (setup_section): Make a new output section even if + one already exists with the given name. + (copy_section): Use isection->output_section rather than trying + to look the output section up by its (possibly non-unique) name. + + * Makefile.in (install-info): Look for binutils.info in the + current directory, then in $(srcdir). Don't use $<. + +Mon Mar 21 12:55:45 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (objdump_print_address): Make static. Declare with + prototype. Change vardiff from int to bfd_signed_vma. Correct + binary search termination condition. When looking for same + section symbol in relocatable file, handle final symbol correctly. + +Sun Mar 20 11:26:36 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Makefile.in: Avoid bug in hpux sed. + + * objcopy.c: Changes to keep it from stripping symbols used + in output relocations. + (mark_symbols_used_in_relocations): New function. Mark symbols + used in output relocations with BSF_KEEP. + (filter_symbols): Do not strip symbols marked with BSF_KEEP. + (copy_object): Reorder actions. First setup sections, then + build the output symbol table, then copy the section contents. + +Fri Mar 18 10:53:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ar.c (write_archive): Allocate space for the null byte. From + Robert Lipe . + +Thu Mar 17 16:20:28 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in: Built nm.new and strip.new to avoid problems with + collect when . is in PATH. + (STRIP_PROG): Change from strip to strip.new. + (NM_PROG): Change from nm to nm.new. + (install): Remove the .new when installing. + +Wed Mar 16 16:27:05 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (powerpc_build_stubs): Set BSF_DYNAMIC flag for each + symbol for which we build a stub. + (powerpc_mangle_relocs): Only reset TOC pointer for a call to a + symbol with BSF_DYNAMIC flag set. + +Tue Mar 15 23:04:13 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * objcopy.c (filter_symbols): Use bfd_is_local_label to determine + if a symbol represents a compiler-generated local label. + (copy_object): Give the BFD backends a chance to copy any private + bfd data from the input BFD to the output BFD. + (setup_section): Give the BFD backends a chance to copy any private + section data from the input section to the output section. + +Mon Mar 14 11:15:58 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * objcopy.c (mangle_section): Delete unused function. + (setup_section): Set osection here instead of calling + mangle section to do it. + +Mon Mar 14 12:11:01 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ar.c (write_archive): Close inarch before unlinking it. + +Fri Mar 11 22:20:48 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): For PowerPC, call powerpc_build_stubs and + powerpc_resolve_stubs. Use __GOT0, not __toc_start. Handle it if + the start and end symbols are not in the text section. + (struct powerpc_stub): New struct definition. + (powerpc_stubs, powerpc_stub_insns): New static variables. + (powerpc_initial_got_size): New static variable. + (powerpc_build_stubs): New function. + (powerpc_resolve_stubs): New function. + (powerpc_mangle_relocs): Clear extraneous data in .got section. + Rearrange reloc handling to handle ELF relocs that are not + partial_inplace. Resolve PC relative relocs. + +Wed Mar 9 13:48:11 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * ar.c (move_members): Fix it so that the abi positional modifiers + don't delete all archive members following the insert point. + +Tue Mar 8 13:14:43 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coffgrok.[ch]: New files, understand coff objects. + * coffdump.c: Uses coffgrok to dump out the debug info of a coff + file. + * sysroff.info: Description of a SYSROFF object file. + * sysinfo.y, syslex.l: Parse info file, generate a reader, writer, + header files and a printer. + * srconv.c: Uses coffgrok.c and sysroff.info to convert a coff + file to a SYSROFF file. + +Sat Feb 26 13:35:26 1994 Stan Shebs (shebs@andros.cygnus.com) + + * ar.c (do_quick_append): Pad with a genuine character 10, + rather than whatever '\n' might happen to be. + +Tue Feb 22 18:25:52 1994 Ian Lance Taylor (ian@cygnus.com) + + * nlmconv.c (main): Ignore debugging symbols when looking for + special symbols by name. + +Sun Feb 20 18:47:42 1994 Ian Lance Taylor (ian@lisa.cygnus.com) + + * nlmconv.c: Include libiberty.h. + + Support for PowerPC NetWare. + * nlmconv.c (main): For PowerPC NetWare, automatically define the + special symbols __toc_start. + (select_output_format): Handle bfd_arch_powerpc. + (mangle_relocs): Likewise. + (powerpc_mangle_relocs): New function. + +Thu Feb 17 09:28:23 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * ar.c, bucomm.c, nlmconv.c, nm.c, objcopy.c, objdump.c, + size.c: Use bfd_get_error and bfd_set_error and new error names. + +Fri Feb 11 15:54:51 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (strip_main, copy_main): Add missing 'break' in switch. + +Mon Feb 7 19:45:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Handle bfd_arch_powerpc. + +Sun Feb 6 22:08:20 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * strings.c objdump.c nlmconv.c objcopy.c nm.c ar.c size.c (main): + Call xmalloc_set_program_name. + +Fri Feb 4 10:46:01 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (filter_bytes): Make MEMHUNK a char *, not PTR, so we + can do arithmetic on it. + +Thu Feb 3 14:06:41 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objdump.c (dump_section_stabs, read_section_stabs, + print_section_stabs): Functions broken out of dump_stabs_1. + Free the stabs and strings when done with them. + +Wed Feb 2 13:42:23 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * nlmconv.c (main): Use bfd_get_flavour instead of struct member. + * ar.c (print_contents, extract_file), size.c + (print_berkeley_format, print_sysv_format): Use bfd_get_filename and + bfd_my_archive instead of dereferencing the structs directly. + + * ar.c: Use bfd_fatal and bfd_nonfatal instead of bfd_perror and exit. + Indent. Remove DEFUNs. + + * nlmconv.c (main), objcopy.c (copy_file): Print matching formats + if ambiguous match. + * nm.c (display_file, display_archive), size.c (display_bfd): + Eliminate gotos. + Print matching formats if there is an ambiguous match. Use + bfd_nonfatal instead of hardcoded error message if nothing matches. + + * arsup.c, ar.c, objdump.c: Use bfd_get_filename instead of + abfd->filename. + + * nm.c (display_archive): New function, from code in display_file. + (display_rel_file): Renamed from do_one_rel_file. + + * size.c: Indent. + (display_archive): New function from code in display_file. + (display_file): Check bfd_close error return. + + * strings.c (strings_object_file): Check bfd_check_format + error return. + + * strings.c, objdump.c, size.c: Use bfd_nonfatal instead of bfd_perror. + + * bucomm.c: Delete references to exit_handler. It wasn't set + anywhere, and now that we're using the libiberty xmalloc, it + wouldn't always get called before exiting. + (list_matching_formats): Function moved from objdump.c. + * bucomm.h: Declare it. + + * objdump.c (disassemble_data): Move some variable decls closer to + their use. Add some comments. Replace a nested block with a + return. + +Mon Jan 31 18:50:41 1994 Stan Shebs (shebs@andros.cygnus.com) + + * objdump.c (display_target_list, display_info_table): Check that + the bfd of the dummy output file is not null. + +Wed Jan 26 13:13:18 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (filter_bytes): New function. + (copy_section): Call it. + (copy_options, copy_usage, copy_main): Add --byte option to + activate it. Appropriate the -b option (which was an undocumented + synonym for -F) for it, also. Add --interleave, -i option for + additional control. + (setup_section, copy_section, mangle_section): Renamed with no `s' + on the end. + * objcopy.1, binutils.texi: Document the new options. + + * objdump.c (display_target_tables, display_target_list): + New functions broken out of display_info. + Eliminate some magic constants. Use more meaningful variable names. + (dump_bfd_header): New function broken out of display_bfd. + (dump_section_header): New function broken out of dump_headers. + (remove_useless_symbols): Don't shadow global variable name with + parameter. + (objdump_print_address): Fix backward test. + +Tue Jan 25 19:40:54 1994 Stan Shebs (shebs@andros.cygnus.com) + + * bucomm.c (print_arelt_descr): Change decl of `when' to time_t. + * objdump.h: Removed. + +Mon Jan 24 13:29:02 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objdump.c (display_file): Remove call to list_matching_formats. + It would never be called. + (list_matching_formats): Take an arg giving the list of matching + formats. + (display_bfd): Pass the arg, and get it filled in by calling + bfd_check_format_matches instead of bfd_check_format. + (display_info, display_info_table): target_vector was renamed to + bfd_target_vector. + + * binutils.texi (objdump): Note some limitations of -h section + address printing. + +Sat Jan 22 16:20:46 1994 Stan Shebs (shebs@andros.cygnus.com) + + * Makefile.in (MALLOC): Set to emptiness by default. + (ALL_CFLAGS): Add and use. + (arparse.h): Make it depend on arparse.y. + * ar.c (libbfd.h): Don't require to be in ../bfd. + * objdump.c (comp): Rename to compare_symbols. + +Fri Jan 21 20:22:30 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objdump.c (list_matching_formats): If the file format is ambiguous, + print the matching names so the user can choose one. + (display_bfd): Call it. + (display_file): Call it. + +Fri Jan 21 19:17:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Support bfd_arch_rs6000. + +Mon Jan 17 13:57:25 1994 Stan Shebs (shebs@andros.cygnus.com) + + * objdump.c (stab_name): Allocate dynamically. + (stab_print): Use pointers to strings instead of char arrays. + (dump_stabs): Change alloc and init of arrays appropriately. + (dump_stabs_1): Always decide whether to print stab_name or + the stab's type number, if unnamed. + +Fri Jan 14 14:42:48 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (strip_main, copy_main): Don't clobber the input file + if copy_file fails. + + * nlmconv.c (main): Warn about an attempt to use a shared library + with uninitialized data. + + * nlmconv.c (setup_sections): Make sure that we align the + output_offset of each input section appropriately. + +Thu Jan 13 17:32:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (dump_relocs): Don't crash if section name is NULL. + +Tue Jan 11 19:46:33 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * filemode.c (filemodestring): Commented out; not used. + (mode_string): Use POSIX definitions. + (ftypelet): Likewise. + (rwx): Removed; no longer used. + * bucomm.c: Include bucomm.h. + (bfd_nonfatal, bfd_fatal): Argument is const. + (fatal): Make __STDC__ version. + * bucomm.h (mode_string): Declare. + * Makefile.in (bucomm.o): Depend upon bucomm.h + +Sun Jan 9 12:03:20 1994 Ken Raeburn (raeburn@rtl.cygnus.com) + + * bucomm.c (xmalloc, xrealloc): Deleted. + * bucomm.h (xmalloc, xrealloc): Fix prototypes, to correspond to + libiberty version of functions. + +Thu Jan 6 06:18:15 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * binutils.texi: Add a chapter summarizing the ways to select + aspects of the target for each program. + + * objdump.c (long_options, usage): Add long equivalents for all + remaining short options that lacked them. + * binutils.texi objdump.1: Document them. + + * size.c (usage): Tweak usage message. + * size.1: Add missing `=' in examples. + + * binutils.texi strip.1 objcopy.1 nlmconv.1 objcopy.c nlmconv.c: + Use "--target=bfdname" as the option to select the BFD target, + like nm and size already do. + Reserve "--format=format" for textual output selection options, but + for now keep old option names as obsolete for backward compatibility. + + * strings.c (main, strings_object_file, usage): Add --target option. + * binutils.texi strings.1: Document it. + +Sat Jan 1 13:58:24 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * ar.c (main): Add \n in error message. + +Thu Dec 23 12:23:11 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + gcc -Wall lint: + * ar.c (main): Put parens around assignment used as truth value. + * objcopy.c (strip_main): Remove unused variables. Return 0. + (copy_main): Remove unused variables. Return 0. + * objdump.c (display_bfd): Declare return value as void. + (stab_print): Use "" instead of 0 to initialize array. + (dump_stabs_1): Print vma using printf_vma. + (display_info): Put parens around assignment used as truth value. + * strings.c (print_strings): Cast printf arguments. + + * objcopy.c (copy_main): Use copy_options, not strip_options. + + * nlmheader.y (command): Warn about illegal date values. + +Wed Dec 15 11:18:03 1993 David J. MacKenzie (djm@frosty.eng.umd.edu) + + * bucomm.c bucomm.h: Run through indent. De-ansidecl-ify. + (bfd_nonfatal): New function. + (bfd_fatal): Call it. + + * objcopy.c (smart_rename): Do a copy if the dest file has + multiple hard links. Remove source file on successful copy. + Try to preserve mode and owner on successful rename. + + * objcopy.c: Run through indent. Clean up a bit. + Make global variables static. + Make {input,output}_{target,filename}, show_version local + to various functions. + New global variable `status' for exit status. + (strip_main, copy_main): New functions with code from main. + (nonfatal): New macro. Use it globally instead of bfd_perror and + bfd_fatal. + + (copy_object): Call mangle_sections with bfd_map_over_sections. + (mangle_sections): Adjust for new calling convention. + +Fri Dec 10 11:28:11 1993 Ian Lance Taylor (ian@deneb.cygnus.com) + + * nlmheader.y (command): Accept MAP and FULLMAP without arguments. + * nlmconv.c (main): Change error message for MAP and FULLMAP. + +Thu Dec 9 17:47:19 1993 Ian Lance Taylor (ian@deneb.cygnus.com) + + * nlmconv.c (main): Warn about imported symbols that are not in + the IMPORT list even if the IMPORT keyword is not used. + + * nlmconv.c (debug, unlink_on_exit): New static variables. + (long_options): Add "debug" and "linker". + (main): Handle -d and -l arguments. Make command line input and + output files optional. Parse the command file before opening the + BFD's, which requires storing more information in local variables. + If INPUT names multiple files, link them together. Use OUTPUT for + the output file name if not named on command line. + (show_usage): Changed for new options. + (link_inputs): New function to automatically invoke linker to + handle multiple INPUT files. + (choose_temp_base_try, choose_temp_base, pexecute): New functions, + mostly copied from gcc/gcc.c. + * nlmconv.h (input_files, output_file): Declare. + * nlmheader.y (input_files, output_file): Define. + (command): Support INPUT with a string_list argument. Support + OUTPUT. + (string_list): Renamed from module_list. + * Makefile.in (nlmconv.o): Define LD_NAME based on + program_transform_name. + +Wed Dec 8 10:09:04 1993 Ian Lance Taylor (ian@deneb.cygnus.com) + + * nlmheader.y (nlmheader_identify): New function. Use it to print + the program name just once, instead of with every error message. + +Mon Dec 6 16:11:32 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (long_options): Changed --header-info to --header-file + to match documentation and usage message. + +Sun Dec 5 01:31:01 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * objdump.c (dump_relocs): Avoid dereferencing a NULL sym_ptr_ptr + in a relocation. + +Thu Dec 2 16:00:06 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): Change various types from bfd_size_type to + size_t, since they have to be arguments to fread and fwrite. + Change set from char * to unsigned char *. + (select_output_format): Make mach argument unsigned. Handle + bfd_arch_alpha. + (setup_sections): Don't copy the .reginfo section of an ECOFF + file. Call bfd_set_reloc to initialize the relocation fields. + (copy_sections): Don't copy the .reginfo section of an ECOFF file. + Combine all relocs for a section. + (mangle_relocs): Change type of relocs to permit specific + functions to change it. Call alpha_mangle_relocs for alpha, + default_mangle_relocs for other architectures. + (default_mangle_relocs): New function. Adjust the address of all + relocs by the output_offset. + (i386_mangle_relocs): Change type of relocs argument. Cast length + argument to memmove to size_t. + (alpha_mangle_relocs): New function. + +Wed Nov 17 17:38:58 1993 Sean Eric Fagan (sef@cygnus.com) + + * nlmconv.c (select_output_format): Use nlm32-sparc for + bfd_arch_sparc. + +Wed Nov 17 14:41:35 1993 Jeffrey Osier (jeffrey@thepub.cygnus.com) + + * nlmconv.1: added man page + * objcopy.1: fixed format errors + +Wed Nov 17 12:03:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in: Use CFLAGS as well as LDFLAGS when linking. + +Wed Nov 17 04:50:55 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * strings.1: Fix typo. + +Mon Nov 15 12:03:20 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * Makefile.in (DISTSTUFF): Build "info". + (VERSION): Updated to cygnus-2.3.1; 2.3 has gone out. + +Sun Nov 14 00:27:24 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * objdump.c (dump_stabs): Handle stabs-in-som as implemented + by the new BFD SOM assembler. + +Sat Nov 13 07:14:05 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * ar.1 c++filt.1 nm.1 objcopy.1 objdump.1 ranlib.1 size.1 + strings.1 strip.1: Replace \(em in NAME section with \- so + makewhatis can grok it. + +Tue Nov 9 15:22:12 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (i386_mangle_relocs): Adjust reloc address by + section output_offset. + +Fri Nov 5 12:11:52 1993 Jeffrey Osier (jeffrey@thepub.cygnus.com) + + * binutils.texi: added nlmconv chapter + +Wed Nov 3 16:10:50 1993 Jeffrey Wheat (cassidy@cygnus.com) + + * Makefile.in: Change RUNTESTFLAGS to RUNTEST_FLAGS + +Wed Nov 3 15:09:23 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * Makefile.in (distclean): Don't get rid of dvi or info files. + +Tue Nov 2 13:29:59 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * objcopy.c (S_ISLNK): Define as 0 if there's no S_IFLNK. + +Fri Oct 29 16:02:34 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * binutils.texi: Move objcopy docs into alphabetical order. + + * objdump.c: Use xmalloc instead of malloc. + +Fri Oct 29 11:11:14 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * objdump.c (info): Rename to formats_info. + (dump_stabs_1): Better comments and formatting. + +Thu Oct 28 19:43:16 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * ar.c (main): Always create the archive when quick appending, + even if no input files have been given. + +Wed Oct 27 12:03:06 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): Set sharedDebugRecordOffset and + sharedDebugRecordCount fields in extended header. + + * nlmconv.c (main): Force moduleName field to upper case. + +Mon Oct 25 16:45:42 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (main): Give a usage message if there are too many + arguments. + +Mon Oct 25 10:37:08 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * Makefile.in (install-info): Rewrite to take advantage of VPATH, + so FSF distributions (with info files in $(srcdir)) install + properly. + (DISTSTUFF): Build nlmheader.c too. + +Fri Oct 22 11:43:23 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * ar.c (program_name): Don't define here. + * objdump.c: Include "bucomm.h". + (xmalloc): Don't declare here. + (program_name): Don't define here. + (program_version): Fixed type in declaration. + * size.c: Include "bucomm.h". + (program_name): Don't declare here. + +Fri Oct 22 14:10:41 1993 Mark Eichin (eichin@cygnus.com) + + * objdump.c (fprintf): hide declaration in FPRINTF_ALREADY_DECLARED + +Fri Oct 1 12:43:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (i386_mangle_relocs): Resolve and remove PC relative + relocs against defined symbols in the same section. + +Thu Sep 30 16:46:26 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) + + * Makefile.in (binutils.dvi): use TEXIDIR to find texinfo.tex + +Sat Sep 25 18:09:29 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (simple_copy, smart_rename): New functions. + (main): Use them. + +Fri Sep 24 15:38:29 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (clean, distclean): Recurse into testsuite. + +Thu Sep 23 01:05:06 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (setup_sections, copy_sections): If stripping, don't + copy SEC_DEBUGGING sections. + * objdump.c (dump_headers): Print SEC_DEBUGGING flag. + + * objdump.c (usage): Mention --stabs. + + * objcopy.c (copy_object): Copy all applicable file flags. + (copy_file): Don't copy EXEC_P specially here. + +Mon Sep 20 19:28:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): Adjust data section size to correspond to bss + alignment adjustment. Clear BSF_SECTION_SYM if symbol is moved to + a different section. Use time_t for time variable. + (setup_sections): Only put sections with contents in output NLM. + (i386_mangle_relocs): No symbols are common at this point. Add + casts to avoid warnings. + +Fri Sep 10 11:00:40 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * objdump.c: Made the --stabs option work for stabs-in-coff. + (ELF_STAB_DISPLAY): Removed. + (dump_elf_stabs): Renamed to dump_stabs, changed to run for + any object file format. + (dump_elf_stabs_1): Renamed to dump_stabs_1, added calls to + generic BFD routines for non-ELF case, changed format of message + for no-section-found case. + (display_bfd): Always call dump_stabs if requested. + (dump_data): Call bfd_section_size to get section size. + +Fri Sep 10 08:12:23 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in (install): Don't put strings in tooldir/bin. + +Mon Sep 6 15:39:04 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (total_bss_size): Removed. + (main): Set the bss vma to always follow the data section. Move + symbols into new sections, and adjust values by output_offset. + (setup_sections): Don't copy all sections, but instead point all + text sections to .text, all data sections to .data, and all bss + sections to .bss. + (copy_sections): Adjust accordingly. + +Thu Sep 2 12:34:03 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Only build nlmconv if configured for a NetWare target. + * configure.in: If we have some *-*-netware* target, or are using + all targets, set BUILD_NLMCONV to $(NLMCONV_PROG) in Makefile. + * Makefile.in (PROGS): Use $(BUILD_NLMCONV) rather than + $(NLMCONV_PROG). + +Tue Aug 31 14:13:35 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * objdump.c (ARCH_all): Define ARCH_hppa too. + (dump_headers): Don't test for SEC_BALIGN if it's not defined by + bfd.h. + +Tue Aug 31 13:29:12 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): Force creation of .bss section. Set up the + sections before looking at the symbols. Move all common symbols + into .bss section. Automatically define _edata and _end. Only + export symbols in the export list, with multiple prefixes if + necessary. Warn if no version. Always create extended header. + Set date automatically if not already set. + (setup_sections): Count size of bss sections. + (mangle_relocs, i386_mangle_relocs): Accept section argument, and + take reloc_count as a changeable pointer; changed callers. + (i386_mangle_relocs): Remove PC relative relocs within a section, + as they require no adjustment. + * nlmheader.y: Fixed memory allocation throughout: token STRING is + now allocated on the heap, and freed if not needed. Null + terminated copyright message. Accept version with only two + strings. + (symbol_list_opt): New nonterminal, either symbol_list or empty. + (symbol_list): Use left recursion to avoid overflowing parser + stack. + (yylex): Rearranged beginning of line check. Accept quoted + strings using single quotes. End generic argument at comment + character or parentheses. + (string_list_append): Fixed. + (string_list_append1): New function. + + * bucomm.h: The first argument to xrealloc is PTR, not char *. + * bucomm.c (xrealloc): Use PTR rather than char *. + * Makefile.in (objdump.o): Depend upon config.status to notice + --with-targets changes. + (nlmconv.o): Depend upon bucomm.h. + +Tue Aug 17 09:46:01 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * configure.in: Don't pass cpu to config.bfd. + +Thu Aug 12 16:43:04 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in ($(NM_PROG)): Depend on demangle.o. + (demangle.o): New target. + (cplus-dem.o): Depend on it, to force compilation order when doing + parallel compiles. + + * nm.c (print_symbol_info_{bsd,sysv,posix}): Take a bfd arg. + (struct output_fns print_symbol_info): Ditto. + (long_options, usage, main): Add -C --demangle option. + (print_symname): New function, demangling if requested. + (print_symbols, print_symbol_info_{bsd,sysv,posix}): Use it. + +Wed Aug 11 22:57:23 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in: Put CFLAGS last in compilation rules and omit from + linking rules. Use ARCHDEFS to compile objdump.c. + Update dependencies. + * configure.in: Construct ARCHDEFS based on the BFD target makefile + fragments. + * objdump.c: Conditionalize calls to the print_insn_ARCH functions + according to ARCHDEFS. + +Thu Aug 12 08:06:15 1993 Ian Lance Taylor (ian@cygnus.com) + + * ar.c: Removed obsolete and non-functional GNU960 code. + +Wed Aug 11 13:08:26 1993 Ian Lance Taylor (ian@cygnus.com) + + * size.c (berkeley_sum): New function. + (bsssize, datasize, textsize): New global variables. + (bss_section_name, data_section_name, text_section_name): Removed. + (print_berkeley_format): Map berkeley_sum over all the sections, + rather than only reporting sizes of specifically named sections. + * Makefile.in ($(OBJDUMP_PROG)): Removed dependency on size.o. + +Tue Aug 10 10:46:01 1993 Ian Lance Taylor (ian@cygnus.com) + + * nlmconv.c, nlmconv.h, nlmheader.y: New files for program to + convert object files into NetWare Loadable Modules. + * Makefile.in (NLMCONV_PROG): New macro, define to be nlmconv. + (PROGS): Add NLMCONV_PROG. + (nlmheader.c, nlmheader.o, nlmconv.o, $(NLMCONV_PROG)): New + targets. + +Thu Aug 5 15:48:32 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * Makefile.in: define MAKEOVERRIDES to an empty string + +Wed Aug 4 17:08:08 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (copy_file): Make failures to process a file nonfatal. + +Mon Aug 2 11:28:23 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * nm.c: Add -B option, like --format=bsd. + +Tue Jul 27 16:29:54 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (copy_file): If the file is neither an object nor an + archive, give an error rather than returning success. + +Mon Jul 19 16:13:40 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * objdump.c (objdump_print_address): Prefer non-local symbols over + local ones, and especially discriminate against debugging symbols. + Also, for relocateable files, try to find a symbol in the current + section, instead of picking one from some random section with a + convenient value (read, section offset). + (disassemble_data): Cast argument to malloc to size_t first. + (dump_data): Likewise. + (dump_relocs): If a single section name is specified, show relocs + only for that section. Otherwise, silently omit sections without + relocs. Format table nicely even if values are printed using 16 + digits instead of 8. + +Fri Jul 16 15:19:59 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * nm.c: Changes for final version of POSIX.2. + (print_symbol_filename_{bsd,sysv,posix}): New functions. + (formats): Add an element for a pointer to them. + (print_symbols): Call it. + (print_object_filename_posix, print_archive_member_posix): Produce + output according to new POSIX.2 spec. + + * strings.c (print_strings): Handle STREAM being NULL. + (strings_a_section): Pass a NULL. + (main): Don't open /dev/null. + +Thu Jul 15 12:44:09 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Handle the m88k. + (display_bfd): Use bfd_errmsg, rather than just claiming that the + bfd is not an object file. + +Mon Jul 12 17:55:34 1993 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in (TAGS): make work again by naming directories + explicitly rather than depending on undefined macros. + (INSTALL_XFORM): correct bad install target. + +Fri Jul 2 16:58:34 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * strings.c: Doc fixes. + +Sun Jun 27 13:35:24 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in: Note dependencies on bucomm.h. + (cplus-dem.o): Link c++filt with version.o. + + * strings.c: Include bucomm.h and add prototypes to other decls. + Remove -h option. + + * bucomm.h: Declare xrealloc. + + * nm.c, objcopy.c, objdump.c, size.c, strings.c (main, usage): Add + --help option. Put "GNU" in the version message. + (usage): Take stream and exit status as args. + (main): Pass new args to usage. + +Fri Jun 25 23:12:12 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * strings.c, strings.1: New files. + * binutils.texi: Document strings. + * Makefile.in: Add rules for it. + +Fri Jun 25 20:44:43 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * objdump.c: Use size-independent bfd elf section names. + +Sun Jun 20 23:09:06 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * objdump.c (objdump_print_address): Handle wide offsets by + calling sprintf_vma. + +Fri Jun 18 14:29:12 1993 Per Bothner (bothner@deneb.cygnus.com) + + * objdump.c (syms2): Removed unused variable. + * objdump.c (remove_useless_symbols): New function. + * objdump.c (comp): Simplify. + * objdump.c (dis-assemble_data): Make simpler and more + efficient how we filter out useless symbols: Just filter + BEFORE the sort (using remove_useless_symbols). + * objdump.c (objdump_print_address): Simplify. + Change output syntax to match gdb. + +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) + +Mon Jun 14 12:13:22 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com) + + * Makefile.in (install, install-info): remove parentdir support, + use INSTALL_XFORM; define INSTALL_XFORM + +Thu Jun 10 17:29:21 1993 Per Bothner (bothner@cygnus.com) + + * objcopy.c (copy_object): Fix bad size passed to xmalloc(). + +Mon Jun 7 12:41:12 1993 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in (INCLUDES): Add -I../bfd for sysdep.h and bfd.h. + * configure.in: No longer need to configure to get sysdep.h. + * objcopy.c (copy_object): Fix symbol table handling. + +Fri Jun 4 17:20:03 1993 Per Bothner (bothner@cygnus.com) + + * objcopy.c (filter_symbols): Cannot filter the symbols + in place, because that confuses the relocs, so take separate + parameter for output array. + * objcopy.c (sympp): Make two variables: isympp and osympp. + * objcopy.c (copy_object): Allocate separate array (osympp) + for filtered symbols. + +Fri Jun 4 10:51:44 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: change recursion test to presence of a configured + testsuite directory + +Thu Jun 3 14:05:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * Makefile.in (underscore.c): Hack the backquoted command so it + doesn't cause Solaris make to bomb. + +Thu Jun 3 10:40:19 1993 Jeffrey Osier (jeffrey@cygnus.com) + + * Makefile.in: added c++filt and objcopy to MANPAGES variable + * .Sanitize: keep c++filt.1 and objcopy.1 + +Thu Jun 3 00:32:52 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: rename LOADLIBES to EXTRALIBS + +Wed Jun 2 18:30:24 1993 Jeffrey Osier (jeffrey@cygnus.com) + + * c++filt.1, objcopy.1: new man pages + +Fri May 28 15:01:24 1993 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in (install): Also install ar and ranlib in + $(tooldir)/bin; needed for building libgcc.a. + * objdump.c (objdump_print_address): Fix the check + "coincidental" label matches by dis-allowing undefined + or com symbols. + +Thu May 27 16:58:31 1993 Jeffrey Osier (jeffrey@cygnus.com) + + * biutils.texi: revised c++filt chapter + +Wed May 26 17:24:17 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (FLAGS_TO_PASS): Pass down CC and CFLAGS. + +Tue May 25 00:26:47 1993 Ken Raeburn (raeburn@cygnus.com) + + * objdump.c (slurp_symtab): Print warning for bad symbol table. + (bfd_elf32_find_section, Elf32_Internal_Shdr): Updated + declarations and uses. + + * Makefile.in (DISTSTUFF): Don't build binutils.mm. + +Fri May 21 10:51:19 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * nm.c: Add -f/--format, -P/--portability, -t/--radix options. + Make global variables static. + (main): Make -v like -n, not -V, and make -A like -o, for POSIX.2. + (set_print_radix, set_output_format, + print_{object_filename,archive_filename,archive_member,symbol_info} + {bsd,sysv,posix}): New functions. + (display_file, print_symbols): Call them. + + * ar.c: Improve error messages. + + * nm.c (main): Handle long options that just set a flag. + + * nm.c (main), ar.c (do_show_version), objcopy.c (main), size.c + (main): Exit after printing the version number, per the GNU coding + standards. + +Mon May 17 13:20:25 1993 Per Bothner (bothner@cygnus.com) + + * README, Makefile.in: Minor updates for 2.2. + +Fri May 14 11:12:26 1993 Per Bothner (bothner@cygnus.com) + + * Makefile.in (underscore.c): Automatically generate + (using nm) a file with the variable prepends_underscore. + * Makefile.in (c++filt): Link underscore.o with cplus-dem.o + so that initial underscores get removed iff appropriate. + * binutils.texi: Preliminary documentation for c++filt. + * Makefile.in, binutils.texi: Set to version 2.2. + + * NEWS: Mention copy->objcopy renaming and new c++filt program. + +Wed May 12 12:05:36 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (cplus-dem.o, $(DEMANGLER_PROG)): Build the + demangler via cplus-dem.o, rather than directly from the .c file. + + * objcopy.c: Renamed from copy.c, updated comments accordingly. + * Makefile.in, binutils.texi: Renamed copy to objcopy. + * is-strip.c, maybe-strip.c, not-strip.c: Updated comments for + rename of copy to objcopy. + +Mon May 10 17:20:18 1993 Per Bothner (bothner@cygnus.com) + + * binutils.texi (strip, -v option): Fix typo. + +Fri May 7 13:57:50 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (RUNTEST): Define. + (FLAGS_TO_PASS): Pass down RUNTEST. + +Tue May 4 10:06:50 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (DEMANGLER_PROG): Name it c++filt. + (PROG): Also build and install COPY_PROG. + +Mon May 3 19:11:48 1993 Per Bothner (bothner@cygnus.com) + + * Makefile.in: Change definition of $(tooldir) to match FSF. + +Wed Apr 28 23:41:32 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * size.c (usage): Add missing options. + (main): Clean up option parser. + + * objdump.c (usage): Add missing options. + (display_file): Print program name before calling + bdf_perror. + + * nm.c (usage): Add missing options. + (main): Clean up option parser. + (display_file): Print program name before calling + bdf_perror. + + * copy.c (copy_usage, strip_usage): Add missing options. + + * ar.c (usage): New function. + (main): Call it. + (open_inarch, do_quick_append): Print program name before calling + bdf_perror. + +Thu Apr 22 15:01:35 1993 Ian Lance Taylor (ian@cygnus.com) + + * nm.c (main): Accept and ignore -A and -B for MIPS compatibility. + +Mon Apr 19 14:06:59 1993 Rob Savoye (rob@cygnus.com) + + * Makefile.in: Added FLAGS_TO_PASS so tests get run on freshly + built binaries if they exist. (otherwise the path) + +Wed Apr 7 22:22:50 1993 Rob Savoye (rob@cygnus.com) + + * Makefile.in: Changed check target to use DejaGnu. + +Thu Apr 1 12:37:13 1993 Jim Kingdon (kingdon@cygnus.com) + + * Makefile.in: Remove am29k-pinsn.c, i960-pinsn.c. + objdump.c: a29k and i960 are `disassemble' not `print'. + + * objdump.c: Rename print_address to objdump_print_address + and change parameters. + (disassemble_data): Use objdump_print_address. + +Wed Mar 31 10:25:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * objdump.c (disassemble_data): print_insn_sparc is now a + `disassemble' not a `print'. + Makefile.in: Remove sparc-pinsn.c (now in libopcodes.a). + + * objdump.c (disassemble_data): Use new read_memory_func stuff. + +Thu Mar 25 10:38:11 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * objdump.c (fprintf): Declaration of variadic function had better + be a prototype for ANSI C systems. + +Mon Mar 22 23:19:46 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: rename test-install to install-check + +Fri Mar 19 14:40:08 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * objdump.c (disassemble_data): Add H8500. + +Fri Mar 19 10:56:51 1993 Jim Kingdon (kingdon@cygnus.com) + + * objdump.c (usage): Mention long options. + +Thu Mar 18 14:22:17 1993 Per Bothner (bothner@rtl.cygnus.com) + + * nm.c: Modify behavior of -o flag for archives to match + BSD4.4 and Sunos 4: Prefix archive name before each line. + + * m68k-pinsn.c: Removed. Subsumed by ../opcodes/m68k-dis.c. + * i386-pinsn.c: Removed. Subsumed by ../opcodes/i386-dis.c. + * Makefile.in: Adjust accordingly. + * objdump.c: Support new-style disassemblers (ones that use + the interface of ../include/dis-asm.h). + +Thu Feb 25 15:57:00 1993 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: When making tar file, remove texinfo/*, + except for texinfo/texinfo.tex. + * ardup.c: Add extern declaration of strdup. + * Makefile.in (testsuite): Add 'else true' since otherwise + Ultrix /bin/sh complains. + +Wed Feb 24 19:44:18 1993 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Set VERSION to 2.1. + * README, NEWS: Updates. + * nm.c: Add -v as a synonym for -V. + +Tue Feb 23 19:00:50 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * configure.in: added testsuite to configdirs. + * Makefile.in: added support for building testsuite. + +Mon Feb 22 22:52:10 1993 Per Bothner (bothner@rtl.cygnus.com) + + * objdump.c (disassemble_data): Print function names when + given by bfd_find_nearest_line. If not - still print + line numbers. + +Mon Feb 22 07:54:03 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * binutils/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. + +Mon Feb 22 10:27:24 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * objdump.c (dump_data): Free up section contents each time + through the loop. Reported by minyard@bnr.ca. + +Sun Feb 21 10:55:55 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * binutils/testsuite: Initial creation of binutils/testsuite. + Migrated dejagnu testcases and support files for testing nm to + binutils/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 12 10:05:20 1993 Fred Fish (fnf@cygnus.com) + + * Makefile.in (LIBIBERTY_SRC_DIR, LIBIBERTY_BIN_DIR): New macros. + * Makefile.in (LIBIBERTY): Use LIBIBERTY_BIN_DIR. + * Makefile.in (DEMANGLER_PROG): New program to build. Add macro + and rule. + * Makefile.in (PROGS): Add DEMANGLER_PROG. + +Tue Jan 26 11:56:33 1993 Ian Lance Taylor (ian@cygnus.com) + + * copy.c, nm.c, objdump.c, size.c: Use new bfd_is_com_section + macro rather than checking for equality to bfd_com_section. + +Fri Jan 8 15:50:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Fix code to find first useless + symbol. + +Thu Jan 7 13:13:31 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Use mips_print_insn for MIPS. + Don't core dump if bfd_find_nearest_line returns false. + +Wed Jan 6 17:14:01 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * objdump.c (disassemble_data): know how to disassemble z8000s + too. + +Wed Jan 6 15:16:27 1993 Per Bothner (bothner@cygnus.com) + + * arsup.h (interactive), bucomm.h (program_name): Prefix + with 'extern', to avoid warnings from some compilers. + +Wed Jan 6 15:14:11 1993 Per Bothner (bothner@rtl.cygnus.com) + + * arparse.y: fix unnecessary shift/reduce + +Tue Dec 22 15:46:56 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Make check depend on all. + * Makefile.in (distclean): Remove sysdep.h. + * size.c: Use %u format where appropriate. + * objdump.c: Standardize: L_SET -> SEEK_SET. + * objdump.c: Use new macro bfd_asymbol_bfd. + * configure.in: Allow std-host as the default ${mys_host}. + +Thu Dec 17 19:38:19 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: added dvi target, define and use TEXI2DVI + +Tue Dec 15 18:05:07 1992 Per Bothner (bothner@cygnus.com) + + * Makefile.in (dist): Fix permissions before release. + * size.c: Use bfd_size_type (and long) where appropriate. + * ar.c: Make writing a map the default, to be compatible + with SYSV and Posix.2. Remove some bogus kludges that + handled __.SYMDEF directly. + * NEWS: New file. + +Mon Nov 9 13:36:53 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: flex no longer needs the -S flag + +Sat Nov 7 15:06:13 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * ar.c (extract_file): utime needs a pointer to a utimbuf + + * Makefile.in: handle -I includes better, adding $(BASEDIR)/bfd to + the list (since some of the bfd/hosts/*.h files include other + files from that directory) + +Fri Nov 6 00:12:51 1992 John Gilmore (gnu@cygnus.com) + + * i960-pinsn.c (MEM_MAX, MEM_SIZ): Set upper bound properly. + +Thu Nov 5 03:37:15 1992 John Gilmore (gnu@cygnus.com) + + Clean up some old BFD ansification macros. + + * arsup.h, bucomm.h, objdump.h: Remove EXFUN from binutils. + It still remains as a local macro in gmalloc.c, which is derived + from some other copy of GNU Malloc somewhere (FIXME). + + * ar.c, objdump.c, size.c: Replace EXFUN with PROTO. Make static + fns really static. + * arsup.h: Declare extract_files. + +Mon Nov 2 12:42:11 1992 Ian Lance Taylor (ian@cygnus.com) + + * ar.c (extract_file): instead of checking USG: if POSIX_UTIME, + use utime and utimbuf structure, otherwise if USE_UTIME use utime + and array of two longs, otherwise use utimes. + +Thu Oct 15 13:57:35 1992 Per Bothner (bothner@cygnus.com) + + * binutils.tex: Document yesterday's changes to strip and copy. + +Wed Oct 14 13:22:14 1992 Per Bothner (bothner@cygnus.com) + + * copy.c: Re-do command-line parsing to use getopt_long(). + Add long option names. Re-think option letters to be more + consistent. + * copy.c: New function filter_symbols() for stripping only + debug-symbols and/or local symbols. Use these to support + the previously-missing options of the old FSF strip. + +Tue Oct 13 01:24:20 1992 John Gilmore (gnu@cygnus.com) + + * configure.in (host): Use ${srcdir}/../bfd/configure.host rather + than repeating a copy of it here. + +Wed Oct 7 12:53:52 1992 Ken Raeburn (raeburn@cygnus.com) + + * copy.c (main): Even if is_strip, accept -d argument indicating + alternate output format. Needed by gdb for Nindy. + + * m68k-pinsn.c (print_insn_arg): Handle new "`" operand type. + +Tue Oct 6 16:33:56 1992 Jeffrey Osier (jeffrey@cygnus.com) + + * binutils.texi: added documentation for "copy" + +Tue Oct 6 14:22:56 1992 Per Bothner (bothner at PersSony) + + * Makefile.in (*clean rules): Some cleaning up. + * Makefile.in (dist): Make diststuff in gprof for a dist. + + * ar.c (do_show_version): New function. + * ar.c (main): Fix so "ar -V" works. + +Thu Oct 1 22:44:45 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: now uses the cpu-vendor-os triple instead of + nested cases. + +Fri Sep 25 22:41:08 1992 John Gilmore (gnu@cygnus.com) + + * i960-pinsn.c: Change bzero to memset. + * sparc-pinsn.c: Change index to strchr. + +Mon Sep 21 14:39:56 1992 Ian Lance Taylor (ian@cygnus.com) + + * m68k-pinsn (print_insn_arg, fetch_arg): added support for + operands to memory management instructions, from WRS. + +Tue Sep 15 15:26:38 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (install): if $(tooldir) exists, install nm and + strip in $(tooldir)/bin. + +Thu Sep 3 11:57:40 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Let's call it version 2.0. + +Wed Sep 2 00:25:13 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Bump to version 0.98. + * TODO, README: Minor updates. + + * Makefile.in: Added mostlyclean, distclean rules, + and cleaned up clean, realclean. + +Sun Aug 30 21:18:59 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in: map program names through program_transform_name + when installing. + +Sun Aug 30 18:09:03 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Bump to versions 1.97.90. + * cplus-dem.c: Removed. Was nowhere used - and if some + programs are changed to to demangling should now use the + versions in libiberty. + +Thu Aug 27 12:58:09 1992 Brendan Kehoe (brendan@cygnus.com) + + * configure.in: add we32k + +Mon Aug 24 14:53:42 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * ar.c (map_over_members): if the element of the archive has a + null name, fill it in. + + * nm.c (do_one_rel_file): only warn if a bfd's flags say there + will be symbols and there aren't any. + +Wed Aug 19 11:20:25 1992 Ian Lance Taylor (ian@cygnus.com) + + * m68k-pinsn.c: handle new operand type 'r', introduced for cas2. + +Tue Aug 18 20:45:48 1992 Rob Savoye (rob@cygnus.com) + + * nm.c objdump.c: Added support for a +version (-V) + to print the version number. + + * ar.c, copy.c: Added support for a -V option to print + the version number. + +Tue Aug 18 13:28:44 1992 Ian Lance Taylor (ian@cygnus.com) + + * config/mh-apollo68v: removed -g from CC definition. + + * Makefile.in: always create installation directories. + +Mon Aug 17 18:33:41 1992 Per Bothner (bothner@rtl.cygnus.com) + + * m68k-pinsn.c: Minor fix in style of output (don't use + range to indicate floating point control registers). + +Tue Aug 11 23:42:21 1992 Per Bothner (bothner@cygnus.com) + + * ar.c (main): Don't *always* set the verbose flag! + +Wed Aug 5 11:25:27 1992 Per Bothner (bothner@rtl.cygnus.com) + + * copy.c: When is_strip (because it is invoked as the strip + program), follow traditional argv processing: + 'strip file1 file2' now strips file1 and file2, rather + than stripping file1 (as input), leaving output in file2. + +Mon Jul 27 16:28:08 1992 Per Bothner (bothner@rtl.cygnus.com) + + * objdump.c (display_info, display_info_table): Call + bfd_set_format() on dummy bfd before using it (twice). + * ar.c: Make sure archive is created on command 'r' + even when no elements are inserted. (Clean up and + simplify some non-working related code.) + +Mon Jul 20 02:48:38 1992 D. V. Henkel-Wallace (gumby@cygnus.com) + + * configure.in: hppa support doesn't assume hp OS (from sef). + +Sat Jul 18 14:35:22 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: recognize hppa hosts (bsd & hpux), error messages + to stderr, not stdout + +Fri Jul 17 18:39:44 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * ar.1, binutils.texi, i960-pinsn.c, nm.1, objdump.1, ranlib.1, + size.1, sparc-pinsn.c, strip.1: removed rcsid's. + +Thu Jul 16 16:55:24 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.dos: removed rcsid. + +Thu Jul 16 08:23:07 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * objdump.c (display_bfd): print state of BFD_IS_RELAXABLE too + +Tue Jun 30 20:26:15 1992 D. V. Henkel-Wallace (gumby@cygnus.com) + + * Makefile.in: Add program_suffix (parallel to program_prefix) + +Thu Jun 25 04:52:45 1992 John Gilmore (gnu at cygnus.com) + + * nm.c (sorters): Lint. Remove excess whitespace. + +Wed Jun 24 13:48:07 1992 Per Bothner (bothner@cygnus.com) + + * nm.c (valueof macro): Add missing parentheses. + (Their lack screwed up numeric_forward().) + +Sun Jun 14 10:33:27 1992 John Gilmore (gnu at cygnus.com) + + * objdump.c (dump_elf_stabs): Also dump .stab.index and + .stab.excl sections. + (dump_elf_stabs_1): Split out main body of old dump_elf_stabs. + * objdump.1, binutils.texi: Document new sections dumped. + +Fri Jun 12 22:23:35 1992 John Gilmore (gnu at cygnus.com) + + * size.c, objdump.c, bucomm.c: Lint. + +Thu Jun 11 01:19:06 1992 John Gilmore (gnu at cygnus.com) + + * objdump.c (dump_elf_stabs): New feature: --stabs prints out a + .stab section from an ELF file. Installed under #ifdef + ELF_STAB_DISPLAY so it can be easily disabled, since it requires + bfd-internals header files and such. + * objdump.1, binutils.texi: Update for --stabs. Also fix + objdump's doc to use -- rather than + for long options. + (FIXME: Not yet fixed everywhere in binutils.texinfo.) + +Wed Jun 10 07:53:24 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * objdump.c(display_info), patches from + mohring@informatik.tu-muenchen.de to print the table much more + nicely. + +Thu May 28 13:36:16 1992 Per Bothner (bothner@rtl.cygnus.com) + + * objdump.c: Add another enum->int cast, for the sake of + old compilers (such as PCC). + +Wed May 27 13:01:44 1992 Per Bothner (bothner@rtl.cygnus.com) + + * arlex.l: Don't include (unneeded conflicts). + Add declaration of strdup(). + +Fri May 22 13:40:37 1992 Per Bothner (bothner@cygnus.com) + + * Makefile.in: Use srcdir instead of VPATH in ldgram/ldlex + rules, since these are used when building a distribution. + * Makefile.in (arlex.c): Don't re-direct output, since that + leaves a bogus output files if it fails. + + * arlex.l: Make work with lex, for what it's worth. + * Makefile.in: Better lex support. + * Makefile.in (dist): Generate flex and bison outputs + for distribution. + +Thu May 14 17:17:59 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: get BISON definition right. + +Fri May 8 07:47:08 1992 K. Richard Pixley (rich@cygnus.com) + + * sanity.sh: default TMPDIR to ".". + +Thu May 7 12:34:50 1992 Roland H. Pesch (pesch@fowanton.cygnus.com) + + * binutils.texi: add doc for ar command language. + +Wed May 6 18:05:36 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * arparse.y: make END call ar_end + * arsup.c (ar_end): added, deletes temp file if archive session + aborted. + + +Wed May 6 11:08:53 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: use bison & flex from ../ if they exist. Also, + FLEX->LEX. + + * sanity.sh: remove temporary directory when finished. + +Tue May 5 12:00:58 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Bump to version 1.97. + * ar.c: Declare errno for machines that need it. + +Mon May 4 23:29:51 1992 John Gilmore (gnu@cygnus.com) + + * objdump.c (display_info): Handle error cases without coredump. + Close the dummy temporary file we open in the loop. + * Makefile.in (arsup.o): Add kludge to build with Sun Make. + +Fri May 1 16:20:23 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: added test-install target. + + * sanity.sh: new file. + + * Makefile.in: use sanity test on make check. + +Tue Apr 21 13:38:37 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: rework CFLAGS so that they can be passed on the + command line to make. Remove MINUS_G. Default CFLAGS to -g. + +Wed Apr 15 14:33:07 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * arsup.c, arsup.h, arparse.y, arlex.l: support for archive + scripting language. + +Fri Mar 6 21:54:53 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: added check target. + +Thu Mar 5 21:35:49 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: added clean-info target. + +Tue Mar 3 15:36:37 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: remove $(COPY_PROG) from PROGS. It shouldn't be + installed. added tooldir and program_prefix. + +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. + +Sun Feb 16 12:53:02 1992 Per Bothner (bothner at cygnus.com) + + * Makefile.in: Bump version to 1.96, and remove -beta + suffix from distribution name. + * m68k-pinsn.c: New macro COERCE_SIGNED_CHAR to extract + the signed value of a character (even if chars are unsigned). + * sparc-pinsn.c: Add new operand types. + +Thu Feb 6 12:14:19 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * objdump.c (disassemble_data): don't print a section's contents + if it's not loadable (eg bss) + +Tue Jan 28 11:11:06 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * m68k-pinsn.c (print_insn_arg): fixed so that -ve branch + displacements don't get printed as large +ve ones. + +Fri Jan 24 14:47:53 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * copy.c, nm.c, objdump.c, size.c : changed to use the + new reloc scheme. + + +Mon Dec 30 18:34:41 1991 Per Bothner (bothner at cygnus.com) + + * bucomm.c (print_arelt_descr): Tweek the output format + so that 'ar tv' output follows Posix 1003.2/D11. + Output is now also identical to Sun's (except __.SYMDEF). + +Mon Dec 30 06:09:53 1991 John Gilmore (gnu at cygnus.com) + + * Makefile.in: Make `make' output more readable. + +Wed Dec 18 15:04:45 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in: Bump to version 1.94. + +Wed Dec 11 16:48:09 1991 Steve Chamberlain (sac at cygnus.com) + + * ar.c: added "b" to fopens for dos + * configdj.bat, makefile.dos new files from DJ + +Tue Dec 10 04:07:26 1991 K. Richard Pixley (rich at rtl.cygnus.com) + + * Makefile.in: infodir belongs in datadir. + +Sat Dec 7 17:09:37 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + * bucomm.h: created to hold prototypes of bucomm.c + * objdump.h: created to hold prototyes of objdump.c + * am29k-pinsn.c: include objdump.h + * ar.c: include bucomm.h, get ar.h from the right place and + include libbfd.h + * bucomm.c: defunize bfd_fatal + * copy.c: include bucomm.h, lint. + * i960-pinsn.h: include bucomm.h + * m68k-pinsn.h: lint + * nm.c: include bucomm.h, lint + * objdump.c: lint + * sparc-pinsn.c: include objdump.h + + + +Fri Dec 6 23:02:14 1991 K. Richard Pixley (rich at rtl.cygnus.com) + + * Makefile.in: added standards.text support. install using + INSTALL_PROGRAM and INSTALL_DATA. + + * configure.in: configure now does all of it's work from objdir so + make file existence tests against ${srcdir}. + +Thu Dec 5 22:46:22 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. + +Wed Dec 4 22:42:03 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in: Bump to version 1.93. + * Makefile.in: Add make-strip.o:maybe-strip.c dependency + for make versions that provide half-baked VPATH-support (e.g. Sun's). + * size.c: Improvements suggested by + "david d [zoo] zuhn" : + - Don't emit (Berkeley) headers if no files were found. + - Return a non-zero return code on failure. + +Sat Nov 30 21:34:19 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + Changes due to include file renaming: + * am29k-pinsn.c: a29k-opcode.h -> opcode/a29k.h + * sparc-pinsn.c: sparc-opcode.h -> opcode/sparc.h + * m68k-pinsn.c: m68k-opcode.h -> opcode/m68k.h + * nm.c: stab.gnu.h -> aout/stab_gnu.h + +Tue Nov 19 19:20:43 1991 Per Bothner (bothner at cygnus.com) + + * README: Mention MINIMIZE flag for bfd's make. + +Mon Nov 18 12:05:37 1991 Per Bothner (bothner at cygnus.com) + + * README: Various improvements. + +Sun Nov 17 23:40:59 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in: Bump to version 1.92. + * version.c, Makefile.in: Get version string from Makefile. + * copy.c, is-strip.c, not-strip.c, maybe-strip.c, Makefile.in: + Make the same change that we earlier did for ar/ranlib: + Generate two different binaries for strip and copy and use + a global variable with different values to distinguish + ostrip from copy. (-1 means to use argv[0] to decide, + so you can get the old behavior, but it is no longer the default). + * copy.c (copy_file): Set EXEC_P of output bfd if input is so. + * copy.c (main): If is_strip==-1, compare last 5 chars + of argv[0], not the whole path. + * copy.c (main): Return 0, not 1. + * copy.c (setup_sections): Fix due to change in bfd_make_section + now failing if asked for a duplicate section. + * strip.c, ostrip.c: Removed obsolete files. + * ar.c, not-ranlib.c, maybe-ranlib.c: + Change encoding of is_ranlib variable to be consistent + with is_strip for strip.copy (i.e -1 to means use argv[0]). + +Thu Nov 14 20:11:02 1991 Per Bothner (bothner at cygnus.com) + + * version.c (program_version): Update to version 1.92. + +Tue Nov 12 16:17:53 1991 Per Bothner (bothner at cygnus.com) + + * ar.c (get_pos_bfd): Previous fix was missing a "break". + +Thu Nov 7 08:55:56 1991 Steve Chamberlain (sac at cygnus.com) + + * am29k-pinsn.c: Fixed bug in mtacc, dmac and fmac instruction + encodings. (Thaks to David Wood) + +Sun Nov 3 14:50:23 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in ($(DIST_NAME).tar.Z), TODO: Various fixes. + * ar.c (get_pos_bfd): Fix to handling of before/after + positioning options. + * bucomm.c (fatal): MISSING_VFPRINTF is no longer an issue, + since libiberty contains vfprintf etc if otherwise missing. + * m68k-pinsn.c (print_insn_arg): Support BB/BW/BL + type operands, as used by branch instructions. + * nm.c: Delegate printing of symbols to BFD, + by using bfd_print_symbol to do the formatting. + +Mon Oct 28 11:20:47 1991 Steve Chamberlain (steve at cygnus.com) + + * ar.c (write_archive.c): added unlink before rename since some + systems can't rename onto an existant file. + +Mon Oct 21 09:47:23 1991 Steve Chamberlain (steve at rtl.cygnus.com) + + * nm.c: now doesn't crash if a symbol with no section and no + SEC_ABS appears. + +Thu Oct 17 15:25:50 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in, version.c: Bump to version 1.91. + +Wed Oct 16 11:45:36 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in, ar.c, bucomm.c, copy.c, cplus-dem.c, filemode.c, + i960-pinsn.c, m68k-pinsn.c, nm.c, objdump.c, size.c, sparc-pinsn.c, + * strip.c: Add or update Copyright notice. + * TODO: Add note on 'nm -a'. + * version.c: Update version number to 1.90. + * Makefile.in: Fix making of documentation for dist. + +Tue Oct 15 00:17:17 1991 Per Bothner (bothner at cygnus.com) + + * README: New file. + * Makefile.in: New kludgy rules for making a tarfile. + * Makefile.in: Fix bindir path. + +Mon Oct 14 17:34:29 1991 Roland H. Pesch (pesch at cygnus.com) + + * Makefile.in: add targets binutils.mm, binutils.me + +Fri Oct 11 22:44:21 1991 John Gilmore (gnu at cygnus.com) + + * Makefile.in: Avoid Sun Make VPATH bugs by adding dependencies. + +Fri Oct 11 12:51:33 1991 Roland H. Pesch (pesch at cygnus.com) + + * Makefile.in: add target "binutils.ms" + + * binutils.texinfo: minor restructuring for texi2roff comfort. + +Fri Oct 11 04:12:28 1991 John Gilmore (gnu at cygnus.com) + + Restructure configuration scheme for bfd, binutils, ld. + + * include/sys/h-*.h: Move to bfd/hosts/h-*.h. + * configure.in: Revise to symlink sysdep.h to ../bfd/hosts/h-xxx.h. + Change some config names to match other dirs. + * *.c: Include bfd.h before sysdep.h, so ansidecl and PROTO() + get defined first. + * Makefile.in: Use -I. to get sysdep.h. + +Wed Oct 9 22:42:56 1991 Per Bothner (bothner at cygnus.com) + + * nm.c (print_symbols): Handle NULL name field of symbol. + * Makefile.in: Removed spurious comment. + +Tue Oct 8 16:55:03 1991 Roland H. Pesch (pesch at cygnus.com) + + * binutils.texinfo: minor typos, phrasing, formatting fixes. + +Tue Oct 8 15:13:20 1991 Per Bothner (bothner at cygnus.com) + + * configure.in: Get host file from ../bfd/config, not config. + * config/*: Remove config directory and its files. + +Tue Oct 8 13:58:59 1991 Roland H. Pesch (pesch at cygnus.com) + + * Makefile.in: new targets binutils.dvi, binutils.info + + * binutils.texinfo: remove most remaining FIXME's, delete + references to __.SYMDEF by name + + +Tue Oct 8 10:23:44 1991 Steve Chamberlain (steve at cygnus.com) + + * objdump.c (print_address) Print addresses nicely. + +Mon Oct 7 11:31:05 1991 Per Bothner (bothner at cygnus.com) + + * ar.c, Makefile.in, new files {is,not,maybe}-ranlib.c: + Make two different binaries for ar and ranlib, instead of + distinguishing them at run time using argv[0]. + (Old behavior is still available if you "make ar_with_ranlib", + but it is not the default.) + * ranlib.sh (new): An alternative one-line + shell implementation of ranlib. + +Fri Oct 4 21:49:44 1991 John Gilmore (gnu at cygnus.com) + + * objdump.c: Cope with renames of a few BFD types & enums. + +Fri Oct 4 19:08:09 1991 Roland H. Pesch (pesch at cygnus.com) + + * binutils.texinfo: add new file (rudimentary docn) + +Mon Sep 30 12:30:39 1991 Per Bothner (bothner at cygnus.com) + + * config/hmake-news: Add new file (for Sony NEWSOS3). + * bucomm.c (fatal): Conditionally compile fatal() depending on + MISSING_VFPRINTF, and don't confuse the issue with NO_VARARGS. + * objdump.c (dump_headers): Trivial output format change. + * objdump.c (display_info): Loop over integers, not enums, + to appease old compilers. + +Mon May 20 16:14:07 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + *objdump.c *nm.c *copy.c :hanged some types to work with 64 bit object files + +Thu May 16 16:06:55 1991 Steve Chamberlain (steve at cygint.cygnus.com) + from bother + * objdump.c (print_address): Make disasembled output more + consistent with gdb and as: Add 0x when printing hex. + Don't print extra leading zeros. + Attempt to not print "filename.o". + * objdump.c: Add some enum-to-int casts to accomodate old compilers. + + +Fri May 3 22:21:44 1991 John Gilmore (gnu at cygint.cygnus.com) + + * copy.c: Change =& constructs to = &, since they confuse older + C compilers. + + +Local Variables: +mode: indented-text +left-margin: 8 +fill-column: 74 +version-control: never +End: diff --git a/gnu/usr.bin/binutils/binutils/Makefile.in b/gnu/usr.bin/binutils/binutils/Makefile.in new file mode 100644 index 00000000000..a683f49be23 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/Makefile.in @@ -0,0 +1,694 @@ +# Makefile for GNU binary-file utilities +# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. + +# This file is part of GNU binutils. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public 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@ + +target_alias = @target_alias@ +prefix = @prefix@ + +program_transform_name = @program_transform_name@ +exec_prefix = @exec_prefix@ +bindir = $(exec_prefix)/bin +libdir = $(exec_prefix)/lib +tooldir = $(exec_prefix)/$(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) -m 644 +INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)' +INSTALL_XFORM1 = $(INSTALL_XFORM) -b=.1 -m 644 + +AR = ar +AR_FLAGS = rc +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +MAKEINFO = makeinfo +TEXI2DVI = texi2dvi +RANLIB = ranlib +BISONFLAGS = -d +TEXI2ROFF=texi2roff +MAKEOVERRIDES= +CC_FOR_BUILD = @CC_FOR_BUILD@ +NM_FOR_TARGET = nm +NM = $(NM_FOR_TARGET) +SYMLINK = ln -s + +BISON = bison -y +# Comment these out if using lex. +LEX_OPTIONS = -I -Cem +LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi` + +# Distribution version +VERSION=2.6 +# Distribution name +DIST_NAME=binutils-${VERSION} + +version=`./../gcc/gcc -dumpversion` + +# Where to find texinfo.tex to format docn with TeX +TEXIDIR = $(srcdir)/../texinfo + +#CC=gcc -Wall +CC=cc +# these two are almost the same program +AR_PROG=ar +RANLIB_PROG=ranlib + +# objcopy and strip should be the same program +OBJCOPY_PROG=objcopy +STRIP_PROG=strip.new + +STRINGS_PROG=strings + +# These should all be the same program too. +SIZE_PROG=size +NM_PROG=nm.new +OBJDUMP_PROG=objdump + +# This is the demangler, as a standalone program. +# Note: This one is used as the installed name too, unlike the above. +DEMANGLER_PROG=c++filt + +NLMCONV_PROG=nlmconv +DLLTOOL_PROG=dlltool + +SRCONV_PROG=srconv sysdump coffdump + + + +MANPAGES= ar nm objdump ranlib size strings strip objcopy nlmconv + +PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ +STAGESTUFF = $(PROGS) *.o +# Files that can be generated, but should be in the distribution. +# Don't build $(DEMANGLER_PROG).1, since its name may vary with the +# configuration. +DISTSTUFF=arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h syslex.c + +# Stuff that goes in tooldir/ if appropriate +TOOL_PROGS = nm.new strip.new ar ranlib $(DLLTOOL_PROG) + +BASEDIR = $(srcdir)/.. +BFDDIR = $(BASEDIR)/bfd +INCDIR = $(BASEDIR)/include +INCLUDES = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) + +ALL_CFLAGS = $(INCLUDES) @HDEFINES@ $(CFLAGS) + +.c.o: + $(CC) -c $(ALL_CFLAGS) $< + +# +## Random definitions +# Hopefully all these may be flushed once we get configuration down pat. + +# alloca only needed for systems which don't have it and when cc != gcc. +# ALLOCA = alloca.o + +# nm tries to malloc enough space for the string table. The old GNU malloc +# rounds this up to a power of two (e.g. 5M becomes 8M), and so it might +# fail unnecessarily. I've also seen some Unix malloc's fail, even when +# there is enough memory. So use the new GNU malloc. +# MALLOC = gmalloc.o +# Use this if the system malloc is good enough. +MALLOC = + +# Use the GNU getopt unless you have problems with it. +# The IRIS version could probably benefit from being assembled with +# libmalloc rather than the ordinary malloc. +LIBIBERTY = ../libiberty/libiberty.a + +# Code shared by all the binutils. +BULIBS = bucomm.o version.o filemode.o + +ADDL_LIBS = $(MALLOC) $(BULIBS) $(BFD) $(LIBIBERTY) + +BFD = ../bfd/libbfd.a +OPCODES = ../opcodes/libopcodes.a + +EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \ + echo $${rootme}/../expect/expect ; \ + else echo expect ; fi` +RUNTEST = `if [ -f ${srcdir}/../dejagnu/runtest ] ; then \ + echo ${srcdir}/../dejagnu/runtest ; \ + else echo runtest ; fi` +RUNTESTFLAGS = + +CC_FOR_TARGET = ` \ + if [ -f $$r/../gcc/xgcc ] ; then \ + if [ -f $$r/../newlib/Makefile ] ; then \ + echo $$r/../gcc/xgcc -B$$r/../gcc/ -idirafter $$r/../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 \ + echo gcc | sed '$(program_transform_name)'; \ + fi; \ + fi` + +FLAGS_TO_PASS = \ + "CC=$(CC)" \ + "CFLAGS=$(CFLAGS)" \ + "RUNTEST=$(RUNTEST)" \ + "RUNTESTFLAGS=$(RUNTESTFLAGS)" +# +## The rules + +all: $(ADDL_LIBS) $(PROGS) + +# These targets are for the dejagnu testsuites. The file site.exp +# contains global variables that all the testsuites will use. + +site.exp: ./config.status Makefile + @echo "Making a new config file..." + @rm -f ./tmp? + @touch site.exp + @mv site.exp site.bak + @echo "## variables are automatically generated by make ##" > ./tmp0 + @echo "# Do not edit here. If you wish to override these" >> ./tmp0 + @echo "# values, add them to the last section" >> ./tmp0 + @echo "# HOST AND TARGET INFO" >> ./tmp0 + @echo "set host_os @host_os@" >> ./tmp0 + @echo "set host_alias @host_alias@" >> ./tmp0 + @echo "set host_cpu @host_cpu@" >> ./tmp0 + @echo "set host_vendor @host_vendor@" >> ./tmp0 + @echo "set target_os @target_os@" >> ./tmp0 + @echo "set target_alias @target_alias@" >> ./tmp0 + @echo "set target_cpu @target_cpu@" >> ./tmp0 + @echo "set target_vendor @target_vendor@" >> ./tmp0 + @echo "set host_triplet @host@" >> ./tmp0 + @echo "set target_triplet @target@" >> ./tmp0 + @echo "# DIRECTORY INFO" >> ./tmp0 + @echo "set objdir `pwd`" >> ./tmp0 + @echo "" >> ./tmp0 + @echo "## Variables generated by configure. Do Not Edit ##" >> ./tmp0 + @cat ./tmp0 > site.exp + @cat site.bak | sed \ + -e '1,/^## Variables generated by.*##/ d' >> site.exp + -@rm -f ./tmp? + +check: site.exp + rootme=`pwd`; export rootme ; \ + srcroot=`cd ${srcdir}; pwd` ; export srcroot ; \ + EXPECT=${EXPECT} ; export EXPECT ; \ + if [ -f $$rootme/../expect/expect ] ; then \ + TCL_LIBRARY=$${srcroot}/../tcl/library ; \ + export TCL_LIBRARY ; else true; fi ; \ + $(RUNTEST) --tool binutils --srcdir $(srcdir)/testsuite \ + $(RUNTESTFLAGS) CC="$(CC_FOR_TARGET)" CFLAGS="$(CFLAGS)" + +installcheck: + /bin/sh $(srcdir)/sanity.sh $(bindir) + +info: binutils.info + +dvi: binutils.dvi + +$(SIZE_PROG): $(ADDL_LIBS) size.o $(BFD) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(SIZE_PROG) size.o $(ADDL_LIBS) $(EXTRALIBS) + +$(OBJCOPY_PROG): $(ADDL_LIBS) objcopy.o not-strip.o $(BFD) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(OBJCOPY_PROG) objcopy.o not-strip.o $(ADDL_LIBS) $(EXTRALIBS) + +$(STRINGS_PROG): $(ADDL_LIBS) strings.o $(BFD) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(STRINGS_PROG) strings.o $(ADDL_LIBS) $(EXTRALIBS) + +$(STRIP_PROG): $(ADDL_LIBS) objcopy.o is-strip.o $(BFD) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(STRIP_PROG) objcopy.o is-strip.o $(ADDL_LIBS) $(EXTRALIBS) + +$(NM_PROG): $(ADDL_LIBS) nm.o $(BFD) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(NM_PROG) nm.o $(ADDL_LIBS) $(EXTRALIBS) + +$(OBJDUMP_PROG): $(ADDL_LIBS) objdump.o $(BFD) $(OPCODES) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(OBJDUMP_PROG) objdump.o $(OPCODES) $(ADDL_LIBS) $(EXTRALIBS) + +underscore.c: Makefile + rm -f underscore.c + echo '/*WARNING: This file is automatically generated!*/' >underscore.t + echo "int prepends_underscore = @UNDERSCORE@;" >>underscore.t + mv -f underscore.t underscore.c + +version.o: version.c Makefile + $(CC) -DVERSION='"$(VERSION)"' $(ALL_CFLAGS) -c $(srcdir)/version.c + +cplus-dem.o: $(BASEDIR)/libiberty/cplus-dem.c $(INCDIR)/getopt.h + $(CC) -c -DMAIN -DVERSION='"$(VERSION)"' $(ALL_CFLAGS) $(BASEDIR)/libiberty/cplus-dem.c + +$(DEMANGLER_PROG): cplus-dem.o $(LIBIBERTY) underscore.o $(DEMANGLER_PROG).1 + $(CC) $(CFLAGS) $(LDFLAGS) -o $(DEMANGLER_PROG) cplus-dem.o $(LIBIBERTY) $(EXTRALIBS) underscore.o + +arparse.c: arparse.y + $(BISON) $(BISONFLAGS) $(srcdir)/arparse.y + mv -f y.tab.c arparse.c + mv -f y.tab.h arparse.h + +# Separate from arparse.c so that a parallel make doesn't try to build +# both arparse.c and arparse.h simultaneously. +arparse.h: arparse.c + +arlex.c: arlex.l + $(LEX) $(LEX_OPTIONS) $(srcdir)/arlex.l + mv lex.yy.c arlex.c + +$(AR_PROG): $(ADDL_LIBS) ar.o arparse.o arlex.o not-ranlib.o $(BFD) arsup.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $(AR_PROG) ar.o arparse.o arlex.o arsup.o not-ranlib.o $(ADDL_LIBS) $(EXTRALIBS) + +$(RANLIB_PROG): $(ADDL_LIBS) ar.o is-ranlib.o arparse.o arlex.o arsup.o $(BFD) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(RANLIB_PROG) ar.o arparse.o arlex.o arsup.o is-ranlib.o $(ADDL_LIBS) $(EXTRALIBS) + +# This rule creates a single binary that switches between ar and ranlib +# by looking at argv[0]. Use this kludge to save some disk space. +# However, you have to install things by hand. +# (That is after 'make install', replace the installed ranlib by a link to ar.) + +# Alternatively, you can install ranlib.sh as ranlib. + +ar_with_ranlib: $(ADDL_LIBS) ar.o maybe-ranlib.o $(BFD) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(AR_PROG) ar.o maybe-ranlib.o $(ADDL_LIBS) $(EXTRALIBS) + -rm -f $(RANLIB_PROG) + -ln $(AR_PROG) $(RANLIB_PROG) + +# objcopy and strip in one binary that uses argv[0] to decide its action. + +objcopy_with_strip: $(ADDL_LIBS) objcopy.o maybe-strip.o $(BFD) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(OBJCOPY_PROG) objcopy.o maybe-strip.o $(ADDL_LIBS) $(EXTRALIBS) + -rm -f $(STRIP_PROG) + -ln $(OBJCOPY_PROG) $(STRIP_PROG) + +sysroff.c: sysinfo sysroff.info + ./sysinfo -c <$(srcdir)/sysroff.info >sysroff.c + ./sysinfo -i <$(srcdir)/sysroff.info >>sysroff.c + ./sysinfo -g <$(srcdir)/sysroff.info >>sysroff.c + +sysroff.h: sysinfo sysroff.info + ./sysinfo -d <$(srcdir)/sysroff.info >sysroff.h + +# Depend upon arparse.c to avoid building both arparse.c and sysinfo.c +# simultaneously. +sysinfo.c: sysinfo.y arparse.c + $(BISON) -tvd $(srcdir)/sysinfo.y + rm -f sysinfo.c + mv -f y.tab.c sysinfo.c + mv -f y.tab.h sysinfo.h + +# Separate from sysinfo.c so that a parallel make doesn't try to build +# both sysinfo.c and sysinfo.h simultaneously. +sysinfo.h: sysinfo.c + +syslex.c : syslex.l + $(LEX) $(LEX_OPTIONS) $(srcdir)/syslex.l + mv lex.yy.c syslex.c + +sysinfo: sysinfo.o syslex.o + $(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o $@ sysinfo.o syslex.o + +syslex.o: syslex.c sysinfo.h + if [ -r syslex.c ]; then \ + $(CC_FOR_BUILD) -c -I. $(CFLAGS) syslex.c ; \ + else \ + $(CC_FOR_BUILD) -c -I. -I$(srcdir) $(CFLAGS) $(srcdir)/syslex.c ;\ + fi + +sysinfo.o: sysinfo.c + if [ -r sysinfo.c ]; then \ + $(CC_FOR_BUILD) -c -I. $(CFLAGS) sysinfo.c ; \ + else \ + $(CC_FOR_BUILD) -c -I. $(CFLAGS) $(srcdir)/sysinfo.c ; \ + fi + +srconv.o: srconv.c sysroff.h sysroff.c coffgrok.h $(INCDIR)/coff/internal.h \ + ../bfd/libcoff.h config.h + +srconv: srconv.o coffgrok.o $(ADDL_LIBS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ srconv.o coffgrok.o $(ADDL_LIBS) $(EXTRALIBS) + +dlltool:dlltool.o defparse.o deflex.o cplus-dem.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ dlltool.o defparse.o deflex.o $(ADDL_LIBS) $(EXTRALIBS) + +defparse.c:defparse.y + $(BISON) $(BISONFLAGS) $(srcdir)/defparse.y + mv -f y.tab.c defparse.c + mv -f y.tab.h defparse.h + +defparse.h: defparse.c + +deflex.c:deflex.l + $(LEX) $(LEX_OPTIONS) $(srcdir)/deflex.l + mv lex.yy.c deflex.c + +dlltool.o:dlltool.c + $(CC) -c @DLLTOOL_DEFS@ $(ALL_CFLAGS) $(srcdir)/dlltool.c + +coffdump: coffdump.o coffgrok.o $(ADDL_LIBS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ coffdump.o coffgrok.o $(ADDL_LIBS) $(EXTRALIBS) + +sysdump.o: sysdump.c sysroff.h sysroff.c bucomm.h config.h + +sysdump: sysdump.o $(ADDL_LIBS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ sysdump.o $(ADDL_LIBS) $(EXTRALIBS) + +# Depend upon sysinfo.c to avoid building both nlmheader.c and sysinfo.c +# simultaneously. +nlmheader.c: nlmheader.y sysinfo.c + $(BISON) $(srcdir)/nlmheader.y + rm -f nlmheader.c + mv -f y.tab.c nlmheader.c + +nlmconv.o: nlmconv.c + ldname=`echo ld | sed '$(program_transform_name)'`; \ + $(CC) -c -DLD_NAME="\"$${ldname}\"" @NLMCONV_DEFS@ $(ALL_CFLAGS) $(srcdir)/nlmconv.c + +$(NLMCONV_PROG): nlmconv.o nlmheader.o $(ADDL_LIBS) $(BFD) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ nlmconv.o nlmheader.o $(ADDL_LIBS) $(EXTRALIBS) + +# This list of dependencies was generated by doing a make with gcc -MM +# saving the output in a file and removing the gcc commands +# changing "../../devo/binutils/../bfd" to "$(BFDDIR)" +# removing "../../devo/binutils/" +# changing "../include" to "$(INCDIR)" + +bucomm.o: bucomm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h \ + $(INCDIR)/fopen-same.h bucomm.h config.h +filemode.o: filemode.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h \ + $(INCDIR)/fopen-same.h +size.o: size.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h \ + $(INCDIR)/fopen-same.h $(INCDIR)/getopt.h config.h +objdump.o: objdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h \ + $(INCDIR)/fopen-same.h $(INCDIR)/getopt.h \ + $(INCDIR)/dis-asm.h $(INCDIR)/aout/aout64.h \ + $(INCDIR)/elf/internal.h $(INCDIR)/aout/stab.def config.h +nm.o: nm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h \ + $(INCDIR)/fopen-same.h bucomm.h config.h $(INCDIR)/getopt.h \ + $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def \ + $(INCDIR)/aout/ranlib.h $(INCDIR)/demangle.h +ar.o: ar.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h \ + $(INCDIR)/fopen-same.h bucomm.h config.h $(INCDIR)/aout/ar.h \ + $(BFDDIR)/libbfd.h arsup.h +arparse.o: arparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h arsup.h +arlex.o: arlex.c ./arparse.h +not-ranlib.o: not-ranlib.c +arsup.o: arsup.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h arsup.h bucomm.h config.h +strings.o: strings.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h bucomm.h config.h +objcopy.o: objcopy.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h \ + $(INCDIR)/fopen-same.h bucomm.h config.h +is-strip.o: is-strip.c +is-ranlib.o: is-ranlib.c +not-strip.o: not-strip.c +nlmheader.o: nlmheader.c ../bfd/bfd.h \ + $(INCDIR)/fopen-same.h bucomm.h config.h \ + $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h nlmconv.h +nlmconv.o: nlmconv.c ../bfd/bfd.h $(INCDIR)/libiberty.h \ + $(INCDIR)/fopen-same.h bucomm.h config.h \ + $(BFDDIR)/libnlm.h $(INCDIR)/nlm/common.h \ + $(INCDIR)/nlm/internal.h $(INCDIR)/nlm/external.h nlmconv.h \ + $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h + +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 ; 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 + +### +# DOCUMENTATION TARGETS +config.texi: Makefile + rm -f config.texi + echo '@set VERSION $(VERSION)' > config.texi +# TeX output +binutils.dvi: $(srcdir)/binutils.texi config.texi + TEXINPUTS=$(TEXIDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/binutils.texi + +# info file for online browsing +binutils.info: $(srcdir)/binutils.texi config.texi + $(MAKEINFO) -o binutils.info $(srcdir)/binutils.texi + +$(DEMANGLER_PROG).1: cxxfilt.man Makefile + sed -e 's/@PROGRAM@/$(DEMANGLER_PROG)/' < $(srcdir)/cxxfilt.man \ + > $(DEMANGLER_PROG).1 + +# different targets for -ms, -mm, -me +# 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 + +# roff output (-ms) +binutils.ms: $(srcdir)/binutils.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)/binutils.texi | \ + $(TEXI2ROFF) -ms | \ + sed -e 's/---/\\(em/g' \ + >binutils.ms + +# roff output (-mm) +# '@noindent's removed due to texi2roff-2 mm bug; if yours is newer, +# try leaving them in +binutils.mm: $(srcdir)/binutils.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)/binutils.texi | \ + $(TEXI2ROFF) -mm | \ + sed -e 's/---/\\(em/g' \ + >binutils.mm + +# roff output (-me) +binutils.me: $(srcdir)/binutils.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)/binutils.texi | \ + $(TEXI2ROFF) -me | \ + sed -e 's/---/\\(em/g' \ + >binutils.me + + +### + +mostlyclean: + -rm -f *.o *~ \#* core binutils.?? binutils.??? y.output config.log + -rm -rf tmpdir +clean: mostlyclean + -rm -f $(PROGS) underscore.c sysroff sysroff.c sysroff.h sysinfo +distclean: + -rm -f Makefile config.status *.o *~ \#* core y.* \ + binutils.?? binutils.??s binutils.aux binutils.log binutils.toc + -rm -f $(PROGS) underscore.c config.h stamp-h config.cache config.log +maintainer-clean realclean: clean distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + -rm -f $(DISTSTUFF) *.info TAGS + +etags tags: TAGS + +TAGS: force + etags $(INCDIR)/*.h $(srcdir)/*.[hc] + +install: all + for i in $(PROGS) ; do \ + $(INSTALL_XFORM) $$i $(bindir)/`echo $$i | sed -e 's/.new//'` ; \ + done + for i in $(MANPAGES) ; do \ + $(INSTALL_XFORM1) $(srcdir)/$$i.1 $(man1dir)/$$i.1 ; \ + done + if [ x$(DEMANGLER_PROG) != x ]; then \ + $(INSTALL_XFORM1) $(DEMANGLER_PROG).1 $(man1dir)/$(DEMANGLER_PROG).1; \ + fi + -if [ -d $(tooldir) ]; then \ + if [ -d $(tooldir)/bin ]; then true; else mkdir $(tooldir)/bin; fi; \ + for i in $(TOOL_PROGS) ; do \ + if [ -f $$i ]; then \ + j=`echo $$i | sed -e 's/.new//'`; \ + rm -f $(tooldir)/bin/$$j; \ + k=`echo $$j | sed '$(program_transform_name)'`; \ + ln $(bindir)/$$k $(tooldir)/bin/$$j >/dev/null 2>/dev/null \ + || $(INSTALL_PROGRAM) $$i $(tooldir)/bin/$$j; \ + fi; \ + done; \ + else true; fi + +# This little path search is required because in the FSF net releases, +# the info files are included in the source tree, and that may not be +# the same as the build directory. +install-info: binutils.info + if [ -r binutils.info ]; then \ + dir=. ; \ + else \ + dir=$(srcdir) ; \ + fi ; \ + for i in `cd $$dir; echo binutils.info*` ; do \ + $(INSTALL_DATA) $$dir/$$i $(infodir)/$$i ; \ + done + +clean-info: + -rm -rf *.info* + +# Making a dist: +# cvs rtag binutils-x-yy ld+utils +# cvs co -r binutils-x-yy ld+utils +# Sanitize +# cd {HERE}; make dist [-f Makefile.in] + +dist: $(DIST_NAME).tar.z + +diststuff: $(DISTSTUFF) info + +$(DIST_NAME).tar.z: + cd ../..; rm -f $(DIST_NAME); ln -s devo $(DIST_NAME) + make diststuff -f Makefile.in + cd ../ld; make diststuff -f Makefile.in + cd ../gprof; make diststuff -f Makefile.in + cd ../texinfo; mv texinfo.tex ..; rm -rf *; mv ../texinfo.tex . + # Take out texinfo from configurable dirs + mv ../configure.in tmp; \ + sed -e '/^host_tools=/s/texinfo //' ../configure.in; rm tmp + cd ..; chmod og=u `find . -print` + cd ../..; tar chf - $(DIST_NAME) | gzip >$(DIST_NAME).tar.z + rm -rf ../../$(DIST_NAME) + +#----------------------------------------------------------------------------- +# '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 + + +# Dummy target to force execution of dependent targets. +# +force: + +# Target to uncomment host-specific lines in this makefile. Such lines must +# have the following string beginning in column 1: #____# +# Original Makefile is backed up as 'Makefile.old'. +# +# Invoke with: make make HOST=xxx +# +make: + -@if test $(HOST)x = x ; then \ + echo 'Specify "make make HOST=???"'; \ + exit 1; \ + fi ; \ + grep -s "^#The next line was generated by 'make make'" Makefile; \ + if test $$? = 0 ; then \ + echo "Makefile has already been processed with 'make make'";\ + exit 1; \ + fi ; \ + mv -f Makefile Makefile.old; \ + echo "#The next line was generated by 'make make'" >Makefile ; \ + echo "HOST=$(HOST)" >>Makefile ; \ + echo >>Makefile ; \ + sed "s/^#__$(HOST)__#//" < Makefile.old >>Makefile + +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 + $(SHELL) ./config.status --recheck + +### Local Variables: *** +### mode:fundamental *** +### page-delimiter: "^# " *** +### End: *** +### end of file diff --git a/gnu/usr.bin/binutils/binutils/NEWS b/gnu/usr.bin/binutils/binutils/NEWS new file mode 100644 index 00000000000..26a144e759b --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/NEWS @@ -0,0 +1,91 @@ +-*- text -*- + +Changes since binutils 2.5 + +* Added -N/--strip-symbol and -K/--keep-symbol arguments to strip and objcopy. + +* Added several arguments to objcopy to provide some control over how the new + file is laid out in memory. Also added binary output format to BFD to permit + generating plain binary files. + +* Added --start-address and --stop-address options to objdump. + +* ar and ranlib now work on AIX. The tools are now built by default on AIX. + +Changes since binutils 2.4 + +* Changed objdump -dr to dump the relocs interspersed with the assembly + listing, for a more useful listing of relocateable files. + +* Changed objdump -d/--disassemble to only disassemble SEC_CODE sections. + Added -D/--disassemble-all option to disassemble all sections. + +* Added --size-sort option to nm. + +* strip and objcopy should now be able to handle dynamically linked ELF + executables. + +Changes since binutils 2.3 + +* Support for HP-PA (by Jeff Law), i386 Mach (by David Mackenzie), RS/6000 and + PowerPC (except ar and ranlib; by Ian Taylor). + +* Support for Irix 5. + +* Programs `strip' and `objcopy' will not attempt to write dynamically linked + ELF output files, since BFD currently can't create them properly. + +Changes since binutils 2.2 + +* A new --stabs argument has been added to objdump to dump stabs sections in + ELF and COFF files. + +* A new program, nlmconv, has been added. It can convert object files into + Novell NetWare Loadable Modules. + +* The strings program has been added. + +Changes since binutils 2.1 + +* The 'copy' program has been renamed to 'objcopy', for consistency with + 'objdump', and because 'copy' might more plausibly be used as a synonym for + 'cp'. + +* The new stand-alone program c++filt is a filter that converts encoded + (mangled) C++ assembly-level identifiers to user-level names. (Note: This + may get moved to the gcc distribution.) + +* nm -o on an archive now prefixes each line with the archive name, matching + the output from BSD nm. + +* ar (and ld) can now read (but not write) BSD4.4-style archives. + +* New support for H8500, Z8000, and the Hitach SH. + +* Dis-assembler interface changed to allow sharing with gdb. + +* There is new Elf code, but it is not yet ready for general use. + +* There is the beginnings of a test suite. + +Changes since binutils 2.0 + +* There is now support for writing ECOFF files, so ld and the other utilities + should work on Risc/Ultrix and Irix. Please let us know how well this works. + +* ar now automatically creates a symbol table (a __.SYMDEF member, in the BSD + version), if there are any object files in the archive. So running ranlib is + now redundant (unless the non-standard q command is used). This is required + for Posix.2 conformance. + +* The archive-reading code now reads both BSD-style and SYSV-style archives + independently of the selected target format. This is to encourage people to + switch to SYSV-format, which has a number of advantages. + +* The strip and copy programs now have options to remove debug-symbols only + and/or local symbols only. They now also support long options. + + +Local variables: +fill-column: 79 +End: diff --git a/gnu/usr.bin/binutils/binutils/README b/gnu/usr.bin/binutils/binutils/README new file mode 100644 index 00000000000..777d04edb01 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/README @@ -0,0 +1,95 @@ +This is a beta release of a completely rewritten binutils distribution. +(Rewritten since binutils 1.x, that is.) + +The linker (ld) has been moved into a separate directory, which should be +../ld. Linker-specific notes are in ../ld/README. + +As of version 2.5, the assembler (as) is also included in this package, in +../gas. Assembler-specific notes can be found in ../gas/README. + +These programs have been tested on various architectures. +However, since this is a beta release taken directly from an +evolving source tree, there might be some problems. In particular, +the programs have not been ported to as many machines as the +old binutils. There are also features of the old versions +that are missing on the new programs. We would appreciate +patches to make things run on other machines; especially welcome +are fixes for what used to work on the old programs! +(See ./TODO, as well a ../bfd/TODO and ../ld/TODO.) + +Recent changes are in ./NEWS, ../ld/NEWS, and ../gas/NEWS. + +Unpacking and Installation -- quick overview +========================== + +In this release, the binary utilities, the linker, the generic GNU include +files, the BFD ("binary file description") library, gprof, and getopt all +have directories of their own underneath the binutils-2.5 directory. +The idea is that a variety of GNU tools can +share a common copy of these things. 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 binutils-2.5.tar.gz file, you'll get a directory +called something like `binutils-2.5', which contains: + + COPYING bfd/ configure* libiberty/ + COPYING.LIB binutils/ configure.in move-if-change* + CYGNUS build-all.mk etc/ opcodes/ + ChangeLog config/ gprof/ test-build.mk + Makefile.in config.guess* inc + +To build binutils, you can just do: + + cd binutils-2.5 + ./configure [ --enable-targets='target1,target2...' ] + make + make install # copies the programs files into /usr/local/bin + # by default. + +This will configure and build all the libraries as well as binutils +and the linker. + +The --enable-targets option adds support for more binary file +formats besides the default. By default, support for only the +selected target file format is compiled in. To add support for more +formats, list them as the argument to --enable-targets, separated by +commas. For example: + + ./configure --enable-targets=sun3,rs6000-aix,decstation + +The name 'all' compiles in support for all valid BFD targets (this was +the default in previous releases): + + ./configure --enable-targets=all + +The binutils can be used in a cross-development environment. +The file etc/configure.texi contains more information. + +Porting +======= +Binutils-2.5 supports many different architectures, but there +are many more not supported, including some that were supported +by earlier versions. We are hoping for volunteers to +improve this situation. + +The major effort in porting binutils to a new host and/or target +architecture involves the BFD library. There is some documentation +in ../bfd/doc. The file ../gdb/doc/gdbint.texinfo (distributed +with gdb-4.x) may also be of help. + +If your system uses some variant of old-style a.out-format, +you can start with a copy of bfd/newsos3.c, and edit it to fit. +(You may also need to tweak bfd/aout-target.h.) +Alternatively, you could use the host-aout.c target. This is a +special kludge that only works for native (non-cross) configurations. + +Reporting bugs +============== +If you can't track down a bug and send suggestions/patches +for fixes, you should probably *not* be using this release. +We have little time to spend tracking down whatever random bugs you +may run into (except for configurations that Cygnus supports for +its customers). The general place to send bug reports or patches +is to bug-gnu-utils@ai.mit.edu; you can also send them directly to +raeburn@cygnus.com or ian@cygnus.com. diff --git a/gnu/usr.bin/binutils/binutils/TODO b/gnu/usr.bin/binutils/binutils/TODO new file mode 100644 index 00000000000..7953c6122e6 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/TODO @@ -0,0 +1,20 @@ +o - size + Currently assumes that the only relevant sections are named .text, + .data and either .bss or .stack. This is not very general, and it + doesn't work for ECOFF. + +o - strip + Make faster by using ftruncate if available (and format is suitable). + +o - nm, objdump + Add option to demangle C++ names. + +o - nm, BFD + Print more information about the symbols for more object file formats. + Print the symbol size in POSIX format. + +o - See also ../ld/TODO and ../bfd/TODO. + +o - ar q is flakey: e.g., doesn't handle long file names properly. + +o - objdump -d: Print relocatable addresses intelligently. diff --git a/gnu/usr.bin/binutils/binutils/acconfig.h b/gnu/usr.bin/binutils/binutils/acconfig.h new file mode 100644 index 00000000000..1ae1eae752b --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/acconfig.h @@ -0,0 +1,14 @@ +/* Is the type time_t defined in ? */ +#undef HAVE_TIME_T_IN_TIME_H + +/* Is the type time_t defined in ? */ +#undef HAVE_TIME_T_IN_TYPES_H + +/* Does define struct utimbuf? */ +#undef HAVE_GOOD_UTIME_H + +/* Whether fprintf must be declared even if is included. */ +#undef NEED_DECLARATION_FPRINTF + +/* Do we need to use the b modifier when opening binary files? */ +#undef USE_BINARY_FOPEN diff --git a/gnu/usr.bin/binutils/binutils/aclocal.m4 b/gnu/usr.bin/binutils/binutils/aclocal.m4 new file mode 100644 index 00000000000..7adc0045571 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/aclocal.m4 @@ -0,0 +1 @@ +sinclude(../bfd/aclocal.m4) diff --git a/gnu/usr.bin/binutils/binutils/alloca.c b/gnu/usr.bin/binutils/binutils/alloca.c new file mode 100644 index 00000000000..9639def3142 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/alloca.c @@ -0,0 +1,191 @@ +/* + alloca -- (mostly) portable public-domain implementation -- D A Gwyn + + last edit: 86/05/30 rms + include config.h, since on VMS it renames some symbols. + Use xmalloc instead of malloc. + + 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. + + It should work under any C implementation that uses an + actual procedure stack (as opposed to a linked list of + frames). 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. +*/ +#ifndef lint +static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */ +#endif + +#ifdef emacs +#include "config.h" +#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 */ + +#ifdef X3J11 +typedef void *pointer; /* generic pointer type */ +#else +typedef char *pointer; /* generic pointer type */ +#endif + +#define NULL 0 /* null pointer constant */ + +extern void free(); +extern pointer xmalloc(); + +/* + 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 (/* void */) +{ + static char *addr = NULL; /* address of first + `dummy', once known */ + auto char dummy; /* to get stack address */ + + if (addr == NULL) + { /* initial entry */ + addr = &dummy; + + find_stack_direction (); /* recurse once */ + } + else /* second entry */ + if (&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; + +/* + alloca( size ) returns 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. +*/ + +static header *last_alloca_header = NULL; /* -> last alloca header */ + +pointer +alloca (size) /* returns pointer to storage */ + unsigned size; /* # bytes to allocate */ +{ + auto char probe; /* probes stack depth: */ + register char *depth = &probe; + +#if STACK_DIRECTION == 0 + if (STACK_DIR == 0) /* unknown growth direction */ + find_stack_direction (); +#endif + + /* Reclaim garbage, defined as all alloca()ed 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 = xmalloc (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)); + } +} + diff --git a/gnu/usr.bin/binutils/binutils/ar.1 b/gnu/usr.bin/binutils/binutils/ar.1 new file mode 100644 index 00000000000..a138e4ac061 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/ar.1 @@ -0,0 +1,487 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH ar 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +ar \- create, modify, and extract from archives. + +.SH SYNOPSIS +.hy 0 +.na +.BR ar " [\|" "-" "\|]"\c +.I {dmpqrtx}[abcilosuvV] \c +[\|\c +.I membername\c +\&\|] \c +.I archive\c +\& \c +.I files\c +\&.\|.\|. + +.ad b +.hy 1 +.SH DESCRIPTION +The GNU \c +.B ar\c +\& program creates, modifies, and extracts from +archives. An \c +.I archive\c +\& is a single file holding a collection of +other files in a structure that makes it possible to retrieve +the original individual files (called \c +.I members\c +\& of the archive). + +The original files' contents, mode (permissions), timestamp, owner, and +group are preserved in the archive, and may be reconstituted on +extraction. + +GNU \c +.B ar\c +\& can maintain archives whose members have names of any +length; however, depending on how \c +.B ar\c +\& is configured on your +system, a limit on member-name length may be imposed (for compatibility +with archive formats maintained with other tools). If it exists, the +limit is often 15 characters (typical of formats related to a.out) or 16 +characters (typical of formats related to coff). + +\c +.B ar\c +\& is considered a binary utility because archives of this sort +are most often used as \c +.I libraries\c +\& holding commonly needed +subroutines. + +\c +.B ar\c +\& will create an index to the symbols defined in relocatable +object modules in the archive when you specify the modifier `\|\c +.B s\c +\|'. +Once created, this index is updated in the archive whenever \c +.B ar\c +\& +makes a change to its contents (save for the `\|\c +.B q\c +\|' update operation). +An archive with such an index speeds up linking to the library, and +allows routines in the library to call each other without regard to +their placement in the archive. + +You may use `\|\c +.B nm \-s\c +\|' or `\|\c +.B nm \-\-print\-armap\c +\|' to list this index +table. If an archive lacks the table, another form of \c +.B ar\c +\& called +\c +.B ranlib\c +\& can be used to add just the table. + +\c +.B ar\c +\& insists on at least two arguments to execute: one +keyletter specifying the \c +.I operation\c +\& (optionally accompanied by other +keyletters specifying \c +.I modifiers\c +\&), and the archive name to act on. + +Most operations can also accept further \c +.I files\c +\& arguments, +specifying particular files to operate on. + +.SH OPTIONS +GNU \c +.B ar\c +\& allows you to mix the operation code \c +.I p\c +\& and modifier +flags \c +.I mod\c +\& in any order, within the first command-line argument. + +If you wish, you may begin the first command-line argument with a +dash. + +The \c +.I p\c +\& keyletter specifies what operation to execute; it may be +any of the following, but you must specify only one of them: + +.TP +.B d +\c +.I Delete\c +\& modules from the archive. Specify the names of modules to +be deleted as \c +.I files\c +\&; the archive is untouched if you +specify no files to delete. + +If you specify the `\|\c +.B v\c +\|' modifier, \c +.B ar\c +\& will list each module +as it is deleted. + +.TP +.B m +Use this operation to \c +.I move\c +\& members in an archive. + +The ordering of members in an archive can make a difference in how +programs are linked using the library, if a symbol is defined in more +than one member. + +If no modifiers are used with \c +.B m\c +\&, any members you name in the +\c +.I files\c +\& arguments are moved to the \c +.I end\c +\& of the archive; +you can use the `\|\c +.B a\c +\|', `\|\c +.B b\c +\|', or `\|\c +.B i\c +\|' modifiers to move them to a +specified place instead. + +.TP +.B p +\c +.I Print\c +\& the specified members of the archive, to the standard +output file. If the `\|\c +.B v\c +\|' modifier is specified, show the member +name before copying its contents to standard output. + +If you specify no \c +.I files\c +\&, all the files in the archive are printed. + +.TP +.B q +\c +.I Quick append\c +\&; add \c +.I files\c +\& to the end of \c +.I archive\c +\&, +without checking for replacement. + +The modifiers `\|\c +.B a\c +\|', `\|\c +.B b\c +\|', and `\|\c +.B i\c +\|' do \c +.I not\c +\& affect this +operation; new members are always placed at the end of the archive. + +The modifier `\|\c +.B v\c +\|' makes \c +.B ar\c +\& list each file as it is appended. + +Since the point of this operation is speed, the archive's symbol table +index is not updated, even if it already existed; you can use `\|\c +.B ar s\c +\|' or +\c +.B ranlib\c +\& explicitly to update the symbol table index. + +.TP +.B r +Insert \c +.I files\c +\& into \c +.I archive\c +\& (with \c +.I replacement\c +\&). This +operation differs from `\|\c +.B q\c +\|' in that any previously existing members +are deleted if their names match those being added. + +If one of the files named in \c +.I files\c +\& doesn't exist, \c +.B ar\c +\& +displays an error message, and leaves undisturbed any existing members +of the archive matching that name. + +By default, new members are added at the end of the file; but you may +use one of the modifiers `\|\c +.B a\c +\|', `\|\c +.B b\c +\|', or `\|\c +.B i\c +\|' to request +placement relative to some existing member. + +The modifier `\|\c +.B v\c +\|' used with this operation elicits a line of +output for each file inserted, along with one of the letters `\|\c +.B a\c +\|' or +`\|\c +.B r\c +\|' to indicate whether the file was appended (no old member +deleted) or replaced. + +.TP +.B t +Display a \c +.I table\c +\& listing the contents of \c +.I archive\c +\&, or those +of the files listed in \c +.I files\c +\& that are present in the +archive. Normally only the member name is shown; if you also want to +see the modes (permissions), timestamp, owner, group, and size, you can +request that by also specifying the `\|\c +.B v\c +\|' modifier. + +If you do not specify any \c +.I files\c +\&, all files in the archive +are listed. + +If there is more than one file with the same name (say, `\|\c +.B fie\c +\|') in +an archive (say `\|\c +.B b.a\c +\|'), `\|\c +.B ar t b.a fie\c +\|' will list only the +first instance; to see them all, you must ask for a complete +listing\(em\&in our example, `\|\c +.B ar t b.a\c +\|'. + +.TP +.B x +\c +.I Extract\c +\& members (named \c +.I files\c +\&) from the archive. You can +use the `\|\c +.B v\c +\|' modifier with this operation, to request that +\c +.B ar\c +\& list each name as it extracts it. + +If you do not specify any \c +.I files\c +\&, all files in the archive +are extracted. + +.PP + +A number of modifiers (\c +.I mod\c +\&) may immediately follow the \c +.I p\c +\& +keyletter, to specify variations on an operation's behavior: + +.TP +.B a +Add new files \c +.I after\c +\& an existing member of the +archive. If you use the modifier \c +.B a\c +\&, the name of an existing archive +member must be present as the \c +.I membername\c +\& argument, before the +\c +.I archive\c +\& specification. + +.TP +.B b +Add new files \c +.I before\c +\& an existing member of the +archive. If you use the modifier \c +.B b\c +\&, the name of an existing archive +member must be present as the \c +.I membername\c +\& argument, before the +\c +.I archive\c +\& specification. (same as `\|\c +.B i\c +\|'). + +.TP +.B c +\c +.I Create\c +\& the archive. The specified \c +.I archive\c +\& is always +created if it didn't exist, when you request an update. But a warning is +issued unless you specify in advance that you expect to create it, by +using this modifier. + +.TP +.B f +Truncate names in the archive. +.B ar +will normally permit file names of any length. This will cause it to +create archives which are not compatible with the native +.B ar +program on some systems. If this is a concern, the +.B f +modifier may be used to truncate file names when putting them in the +archive. + +.TP +.B i +Insert new files \c +.I before\c +\& an existing member of the +archive. If you use the modifier \c +.B i\c +\&, the name of an existing archive +member must be present as the \c +.I membername\c +\& argument, before the +\c +.I archive\c +\& specification. (same as `\|\c +.B b\c +\|'). + +.TP +.B l +This modifier is accepted but not used. + +.TP +.B o +Preserve the \c +.I original\c +\& dates of members when extracting them. If +you do not specify this modifier, files extracted from the archive +will be stamped with the time of extraction. + +.TP +.B s +Write an object-file index into the archive, or update an existing one, +even if no other change is made to the archive. You may use this modifier +flag either with any operation, or alone. Running `\|\c +.B ar s\c +\|' on an +archive is equivalent to running `\|\c +.B ranlib\c +\|' on it. + +.TP +.B u +Normally, \c +.B ar r\c +\&.\|.\|. inserts all files +listed into the archive. If you would like to insert \c +.I only\c +\& those +of the files you list that are newer than existing members of the same +names, use this modifier. The `\|\c +.B u\c +\|' modifier is allowed only for the +operation `\|\c +.B r\c +\|' (replace). In particular, the combination `\|\c +.B qu\c +\|' is +not allowed, since checking the timestamps would lose any speed +advantage from the operation `\|\c +.B q\c +\|'. + +.TP +.B v +This modifier requests the \c +.I verbose\c +\& version of an operation. Many +operations display additional information, such as filenames processed, +when the modifier `\|\c +.B v\c +\|' is appended. + +.TP +.B V +This modifier shows the version number of +.BR ar . + +.PP + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +, Roland H. Pesch (October 1991). +.BR nm ( 1 )\c +\&, +.BR ranlib ( 1 )\c +\&. + +.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/gnu/usr.bin/binutils/binutils/ar.c b/gnu/usr.bin/binutils/binutils/ar.c new file mode 100644 index 00000000000..abb5b24809f --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/ar.c @@ -0,0 +1,1229 @@ +/* ar.c - Archive modify and extract. + Copyright 1991, 92, 93, 94 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* + Bugs: should use getopt the way tar does (complete w/optional -) and + should have long options too. GNU ar used to check file against filesystem + in quick_update and replace operations (would check mtime). Doesn't warn + when name truncated. No way to specify pos_end. Error messages should be + more consistant. +*/ +#include "bfd.h" +#include "libiberty.h" +#include "progress.h" +#include "bucomm.h" +#include "aout/ar.h" +#include "libbfd.h" +#include "arsup.h" +#include + +#ifdef HAVE_GOOD_UTIME_H +#include +#else /* ! HAVE_GOOD_UTIME_H */ +#ifdef HAVE_UTIMES +#include +#endif /* HAVE_UTIMES */ +#endif /* ! HAVE_GOOD_UTIME_H */ + +#ifdef __GO32___ +#define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */ +#else +#define EXT_NAME_LEN 6 /* ditto for *NIX */ +#endif + +#define BUFSIZE 8192 + +/* Kludge declaration from BFD! This is ugly! FIXME! XXX */ + +struct ar_hdr * + bfd_special_undocumented_glue PARAMS ((bfd * abfd, char *filename)); + +/* Forward declarations */ + +static const char * +normalize PARAMS ((const char *, bfd *)); + +static void +remove_output PARAMS ((void)); + +static void +map_over_members PARAMS ((bfd *, void (*)(bfd *), char **, int)); + +static void +print_contents PARAMS ((bfd * member)); + +static void +delete_members PARAMS ((bfd *, char **files_to_delete)); + +#if 0 +static void +do_quick_append PARAMS ((const char *archive_filename, + char **files_to_append)); +#endif + +static void +move_members PARAMS ((bfd *, char **files_to_move)); + +static void +replace_members PARAMS ((bfd *, char **files_to_replace, boolean quick)); + +static void +print_descr PARAMS ((bfd * abfd)); + +static void +write_archive PARAMS ((bfd *)); + +static void +ranlib_only PARAMS ((const char *archname)); + +static void +ranlib_touch PARAMS ((const char *archname)); + +/** Globals and flags */ + +int mri_mode; + +/* This flag distinguishes between ar and ranlib: + 1 means this is 'ranlib'; 0 means this is 'ar'. + -1 means if we should use argv[0] to decide. */ +extern int is_ranlib; + +/* Nonzero means don't warn about creating the archive file if necessary. */ +int silent_create = 0; + +/* Nonzero means describe each action performed. */ +int verbose = 0; + +/* Nonzero means preserve dates of members when extracting them. */ +int preserve_dates = 0; + +/* Nonzero means don't replace existing members whose dates are more recent + than the corresponding files. */ +int newer_only = 0; + +/* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF + member). -1 means we've been explicitly asked to not write a symbol table; + +1 means we've been explictly asked to write it; + 0 is the default. + Traditionally, the default in BSD has been to not write the table. + However, for POSIX.2 compliance the default is now to write a symbol table + if any of the members are object files. */ +int write_armap = 0; + +/* Nonzero means it's the name of an existing member; position new or moved + files with respect to this one. */ +char *posname = NULL; + +/* Sez how to use `posname': pos_before means position before that member. + pos_after means position after that member. pos_end means always at end. + pos_default means default appropriately. For the latter two, `posname' + should also be zero. */ +enum pos + { + pos_default, pos_before, pos_after, pos_end + } postype = pos_default; + +/* Whether to truncate names of files stored in the archive. */ +static boolean ar_truncate = false; + +int interactive = 0; + +void +mri_emul () +{ + interactive = isatty (fileno (stdin)); + yyparse (); +} + +/* If COUNT is 0, then FUNCTION is called once on each entry. If nonzero, + COUNT is the length of the FILES chain; FUNCTION is called on each entry + whose name matches one in FILES. */ + +static void +map_over_members (arch, function, files, count) + bfd *arch; + void (*function) PARAMS ((bfd *)); + char **files; + int count; +{ + bfd *head; + + if (count == 0) + { + for (head = arch->next; head; head = head->next) + { + PROGRESS (1); + function (head); + } + return; + } + /* This may appear to be a baroque way of accomplishing what we want. + However we have to iterate over the filenames in order to notice where + a filename is requested but does not exist in the archive. Ditto + mapping over each file each time -- we want to hack multiple + references. */ + + for (; count > 0; files++, count--) + { + boolean found = false; + + for (head = arch->next; head; head = head->next) + { + PROGRESS (1); + if (head->filename == NULL) + { + /* Some archive formats don't get the filenames filled in + until the elements are opened. */ + struct stat buf; + bfd_stat_arch_elt (head, &buf); + } + if ((head->filename != NULL) && + (!strcmp (*files, head->filename))) + { + found = true; + function (head); + } + } + if (!found) + fprintf (stderr, "no entry %s in archive\n", *files); + } +} + +boolean operation_alters_arch = false; + +extern char *program_version; + +void +do_show_version () +{ + printf ("GNU %s version %s\n", program_name, program_version); + xexit (0); +} + +void +usage () +{ + if (is_ranlib == 0) + fprintf (stderr, "\ +Usage: %s [-]{dmpqrtx}[abcilosuvV] [member-name] archive-file file...\n\ + %s -M [ abfd->xvec->ar_max_namelen) + { + char *s; + + /* Space leak. */ + s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1); + memcpy (s, filename, abfd->xvec->ar_max_namelen); + s[abfd->xvec->ar_max_namelen] = '\0'; + filename = s; + } + + return filename; +} + +/* Remove any output file. This is only called via xatexit. */ + +static char *output_filename = NULL; +static FILE *output_file = NULL; +static bfd *output_bfd = NULL; + +static void +remove_output () +{ + if (output_filename != NULL) + { + if (output_bfd != NULL && output_bfd->iostream != NULL) + fclose ((FILE *) (output_bfd->iostream)); + if (output_file != NULL) + fclose (output_file); + unlink (output_filename); + } +} + +/* The option parsing should be in its own function. + It will be when I have getopt working. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + char *arg_ptr; + char c; + enum + { + none = 0, delete, replace, print_table, + print_files, extract, move, quick_append + } operation = none; + int arg_index; + char **files; + char *inarch_filename; + char *temp; + int show_version; + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + + START_PROGRESS (program_name, 0); + + bfd_init (); + show_version = 0; + + xatexit (remove_output); + + temp = strrchr (program_name, '/'); + if (temp == (char *) NULL) + temp = program_name; /* shouldn't happen, but... */ + else + ++temp; + if (is_ranlib > 0 || (is_ranlib < 0 && strcmp (temp, "ranlib") == 0)) + { + boolean touch = false; + + is_ranlib = 1; + if (argc < 2) + usage (); + if (strcmp (argv[1], "-V") == 0 + || strcmp (argv[1], "-v") == 0 + || strncmp (argv[1], "--v", 3) == 0) + do_show_version (); + arg_index = 1; + if (strcmp (argv[1], "-t") == 0) + { + ++arg_index; + touch = true; + } + while (arg_index < argc) + { + if (! touch) + ranlib_only (argv[arg_index]); + else + ranlib_touch (argv[arg_index]); + ++arg_index; + } + xexit (0); + } + else + is_ranlib = 0; + + if (argc == 2 && strcmp (argv[1], "-M") == 0) + { + mri_emul (); + xexit (0); + } + + if (argc < 2) + usage (); + + arg_ptr = argv[1]; + + if (*arg_ptr == '-') + ++arg_ptr; /* compatibility */ + + while ((c = *arg_ptr++) != '\0') + { + switch (c) + { + case 'd': + case 'm': + case 'p': + case 'q': + case 'r': + case 't': + case 'x': + if (operation != none) + fatal ("two different operation options specified"); + switch (c) + { + case 'd': + operation = delete; + operation_alters_arch = true; + break; + case 'm': + operation = move; + operation_alters_arch = true; + break; + case 'p': + operation = print_files; + break; + case 'q': + operation = quick_append; + operation_alters_arch = true; + break; + case 'r': + operation = replace; + operation_alters_arch = true; + break; + case 't': + operation = print_table; + break; + case 'x': + operation = extract; + break; + } + case 'l': + break; + case 'c': + silent_create = 1; + break; + case 'o': + preserve_dates = 1; + break; + case 'V': + show_version = true; + break; + case 's': + write_armap = 1; + break; + case 'u': + newer_only = 1; + break; + case 'v': + verbose = 1; + break; + case 'a': + postype = pos_after; + break; + case 'b': + postype = pos_before; + break; + case 'i': + postype = pos_before; + break; + case 'M': + mri_mode = 1; + break; + case 'f': + ar_truncate = true; + break; + default: + fprintf (stderr, "%s: illegal option -- %c\n", program_name, c); + usage (); + } + } + + if (show_version) + do_show_version (); + + if (argc < 3) + usage (); + + if (mri_mode) + { + mri_emul (); + } + else + { + bfd *arch; + + /* We can't write an armap when using ar q, so just do ar r + instead. */ + if (operation == quick_append && write_armap) + operation = replace; + + if ((operation == none || operation == print_table) + && write_armap == 1) + { + ranlib_only (argv[2]); + xexit (0); + } + + if (operation == none) + fatal ("no operation specified"); + + if (newer_only && operation != replace) + fatal ("`u' is only meaningful with the `r' option."); + + arg_index = 2; + + if (postype != pos_default) + posname = argv[arg_index++]; + + inarch_filename = argv[arg_index++]; + + files = arg_index < argc ? argv + arg_index : NULL; + +#if 0 + /* We don't use do_quick_append any more. Too many systems + expect ar to always rebuild the symbol table even when q is + used. */ + + /* We can't do a quick append if we need to construct an + extended name table, because do_quick_append won't be able to + rebuild the name table. Unfortunately, at this point we + don't actually know the maximum name length permitted by this + object file format. So, we guess. FIXME. */ + if (operation == quick_append && ! ar_truncate) + { + char **chk; + + for (chk = files; chk != NULL && *chk != '\0'; chk++) + { + if (strlen (normalize (*chk, (bfd *) NULL)) > 14) + { + operation = replace; + break; + } + } + } + + if (operation == quick_append) + { + /* Note that quick appending to a non-existent archive creates it, + even if there are no files to append. */ + do_quick_append (inarch_filename, files); + xexit (0); + } +#endif + + arch = open_inarch (inarch_filename); + + switch (operation) + { + case print_table: + map_over_members (arch, print_descr, files, argc - 3); + break; + + case print_files: + map_over_members (arch, print_contents, files, argc - 3); + break; + + case extract: + map_over_members (arch, extract_file, files, argc - 3); + break; + + case delete: + if (files != NULL) + delete_members (arch, files); + break; + + case move: + if (files != NULL) + move_members (arch, files); + break; + + case replace: + case quick_append: + if (files != NULL || write_armap > 0) + replace_members (arch, files, operation == quick_append); + break; + + /* Shouldn't happen! */ + default: + fprintf (stderr, "%s: internal error -- this option not implemented\n", + program_name); + xexit (1); + } + } + + END_PROGRESS (program_name); + + xexit (0); + return 0; +} + +bfd * +open_inarch (archive_filename) + const char *archive_filename; +{ + bfd **last_one; + bfd *next_one; + struct stat sbuf; + bfd *arch; + + bfd_set_error (bfd_error_no_error); + + if (stat (archive_filename, &sbuf) != 0) + { + +#ifndef __GO32__ + +/* KLUDGE ALERT! Temporary fix until I figger why + * stat() is wrong ... think it's buried in GO32's IDT + * - Jax + */ + if (errno != ENOENT) + bfd_fatal (archive_filename); +#endif + + if (!operation_alters_arch) + { + fprintf (stderr, "%s: ", program_name); + perror (archive_filename); + maybequit (); + return NULL; + } + + /* Create an empty archive. */ + arch = bfd_openw (archive_filename, NULL); + if (arch == NULL + || ! bfd_set_format (arch, bfd_archive) + || ! bfd_close (arch)) + bfd_fatal (archive_filename); + } + + arch = bfd_openr (archive_filename, NULL); + if (arch == NULL) + { + bloser: + bfd_fatal (archive_filename); + } + + if (bfd_check_format (arch, bfd_archive) != true) + fatal ("%s is not an archive", archive_filename); + last_one = &(arch->next); + /* Read all the contents right away, regardless. */ + for (next_one = bfd_openr_next_archived_file (arch, NULL); + next_one; + next_one = bfd_openr_next_archived_file (arch, next_one)) + { + PROGRESS (1); + *last_one = next_one; + last_one = &next_one->next; + } + *last_one = (bfd *) NULL; + if (bfd_get_error () != bfd_error_no_more_archived_files) + goto bloser; + return arch; +} + +static void +print_contents (abfd) + bfd *abfd; +{ + int ncopied = 0; + char *cbuf = xmalloc (BUFSIZE); + struct stat buf; + long size; + if (bfd_stat_arch_elt (abfd, &buf) != 0) + fatal ("internal stat error on %s", bfd_get_filename (abfd)); + + if (verbose) + printf ("\n\n\n", bfd_get_filename (abfd)); + + bfd_seek (abfd, 0, SEEK_SET); + + size = buf.st_size; + while (ncopied < size) + { + + int nread; + int tocopy = size - ncopied; + if (tocopy > BUFSIZE) + tocopy = BUFSIZE; + + nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke + abstraction! */ + if (nread != tocopy) + fatal ("%s is not a valid archive", + bfd_get_filename (bfd_my_archive (abfd))); + fwrite (cbuf, 1, nread, stdout); + ncopied += tocopy; + } + free (cbuf); +} + +/* Extract a member of the archive into its own file. + + We defer opening the new file until after we have read a BUFSIZ chunk of the + old one, since we know we have just read the archive header for the old + one. Since most members are shorter than BUFSIZ, this means we will read + the old header, read the old data, write a new inode for the new file, and + write the new data, and be done. This 'optimization' is what comes from + sitting next to a bare disk and hearing it every time it seeks. -- Gnu + Gilmore */ + +void +extract_file (abfd) + bfd *abfd; +{ + FILE *ostream; + char *cbuf = xmalloc (BUFSIZE); + int nread, tocopy; + int ncopied = 0; + long size; + struct stat buf; + if (bfd_stat_arch_elt (abfd, &buf) != 0) + fatal ("internal stat error on %s", bfd_get_filename (abfd)); + size = buf.st_size; + + if (verbose) + printf ("x - %s\n", bfd_get_filename (abfd)); + + bfd_seek (abfd, 0, SEEK_SET); + + ostream = 0; + if (size == 0) + { + /* Seems like an abstraction violation, eh? Well it's OK! */ + output_filename = bfd_get_filename (abfd); + + ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); + if (!ostream) + { + perror (bfd_get_filename (abfd)); + xexit (1); + } + + output_file = ostream; + } + else + while (ncopied < size) + { + tocopy = size - ncopied; + if (tocopy > BUFSIZE) + tocopy = BUFSIZE; + + nread = bfd_read (cbuf, 1, tocopy, abfd); + if (nread != tocopy) + fatal ("%s is not a valid archive", + bfd_get_filename (bfd_my_archive (abfd))); + + /* See comment above; this saves disk arm motion */ + if (!ostream) + { + /* Seems like an abstraction violation, eh? Well it's OK! */ + output_filename = bfd_get_filename (abfd); + + ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); + if (!ostream) + { + perror (bfd_get_filename (abfd)); + xexit (1); + } + + output_file = ostream; + } + fwrite (cbuf, 1, nread, ostream); + ncopied += tocopy; + } + + fclose (ostream); + + output_file = NULL; + output_filename = NULL; + + chmod (bfd_get_filename (abfd), buf.st_mode); + + if (preserve_dates) + { +#ifdef HAVE_GOOD_UTIME_H + struct utimbuf tb; + tb.actime = buf.st_mtime; + tb.modtime = buf.st_mtime; + utime (bfd_get_filename (abfd), &tb); /* FIXME check result */ +#else /* ! HAVE_GOOD_UTIME_H */ +#ifndef HAVE_UTIMES + long tb[2]; + tb[0] = buf.st_mtime; + tb[1] = buf.st_mtime; + utime (bfd_get_filename (abfd), tb); /* FIXME check result */ +#else /* HAVE_UTIMES */ + struct timeval tv[2]; + tv[0].tv_sec = buf.st_mtime; + tv[0].tv_usec = 0; + tv[1].tv_sec = buf.st_mtime; + tv[1].tv_usec = 0; + utimes (bfd_get_filename (abfd), tv); /* FIXME check result */ +#endif /* HAVE_UTIMES */ +#endif /* ! HAVE_GOOD_UTIME_H */ + } +free (cbuf); +} + +#if 0 + +/* We don't use this anymore. Too many systems expect ar to rebuild + the symbol table even when q is used. */ + +/* Just do it quickly; don't worry about dups, armap, or anything like that */ + +static void +do_quick_append (archive_filename, files_to_append) + const char *archive_filename; + char **files_to_append; +{ + FILE *ofile, *ifile; + char *buf = xmalloc (BUFSIZE); + long tocopy, thistime; + bfd *temp; + struct stat sbuf; + boolean newfile = false; + bfd_set_error (bfd_error_no_error); + + if (stat (archive_filename, &sbuf) != 0) + { + +#ifndef __GO32__ + +/* KLUDGE ALERT! Temporary fix until I figger why + * stat() is wrong ... think it's buried in GO32's IDT + * - Jax + */ + + if (errno != ENOENT) + bfd_fatal (archive_filename); +#endif + + newfile = true; + } + + ofile = fopen (archive_filename, FOPEN_AUB); + if (ofile == NULL) + { + perror (program_name); + xexit (1); + } + + temp = bfd_openr (archive_filename, NULL); + if (temp == NULL) + { + bfd_fatal (archive_filename); + } + if (newfile == false) + { + if (bfd_check_format (temp, bfd_archive) != true) + fatal ("%s is not an archive", archive_filename); + } + else + { + fwrite (ARMAG, 1, SARMAG, ofile); + if (!silent_create) + fprintf (stderr, "%s: creating %s\n", + program_name, archive_filename); + } + + if (ar_truncate) + temp->flags |= BFD_TRADITIONAL_FORMAT; + + /* assume it's an achive, go straight to the end, sans $200 */ + fseek (ofile, 0, 2); + + for (; files_to_append && *files_to_append; ++files_to_append) + { + struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append); + if (hdr == NULL) + { + bfd_fatal (*files_to_append); + } + + BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr)); + + ifile = fopen (*files_to_append, FOPEN_RB); + if (ifile == NULL) + { + bfd_nonfatal (*files_to_append); + } + + if (stat (*files_to_append, &sbuf) != 0) + { + bfd_nonfatal (*files_to_append); + } + + tocopy = sbuf.st_size; + + /* XXX should do error-checking! */ + fwrite (hdr, 1, sizeof (struct ar_hdr), ofile); + + while (tocopy > 0) + { + thistime = tocopy; + if (thistime > BUFSIZE) + thistime = BUFSIZE; + fread (buf, 1, thistime, ifile); + fwrite (buf, 1, thistime, ofile); + tocopy -= thistime; + } + fclose (ifile); + if ((sbuf.st_size % 2) == 1) + putc ('\012', ofile); + } + fclose (ofile); + bfd_close (temp); + free (buf); +} + +#endif /* 0 */ + +static void +write_archive (iarch) + bfd *iarch; +{ + bfd *obfd; + char *old_name, *new_name; + bfd *contents_head = iarch->next; + + old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1); + strcpy (old_name, bfd_get_filename (iarch)); + new_name = make_tempname (old_name); + + output_filename = new_name; + + obfd = bfd_openw (new_name, bfd_get_target (iarch)); + + if (obfd == NULL) + bfd_fatal (old_name); + + output_bfd = obfd; + + bfd_set_format (obfd, bfd_archive); + + /* Request writing the archive symbol table unless we've + been explicitly requested not to. */ + obfd->has_armap = write_armap >= 0; + + if (ar_truncate) + { + /* This should really use bfd_set_file_flags, but that rejects + archives. */ + obfd->flags |= BFD_TRADITIONAL_FORMAT; + } + + if (bfd_set_archive_head (obfd, contents_head) != true) + bfd_fatal (old_name); + + if (!bfd_close (obfd)) + bfd_fatal (old_name); + + output_bfd = NULL; + output_filename = NULL; + + /* We don't care if this fails; we might be creating the archive. */ + bfd_close (iarch); + unlink (old_name); + + if (rename (new_name, old_name) != 0) + bfd_fatal (old_name); +} + +/* Return a pointer to the pointer to the entry which should be rplacd'd + into when altering. DEFAULT_POS should be how to interpret pos_default, + and should be a pos value. */ + +bfd ** +get_pos_bfd (contents, default_pos) + bfd **contents; + enum pos default_pos; +{ + bfd **after_bfd = contents; + enum pos realpos = (postype == pos_default ? default_pos : postype); + + if (realpos == pos_end) + { + while (*after_bfd) + after_bfd = &((*after_bfd)->next); + } + else + { + for (; *after_bfd; after_bfd = &(*after_bfd)->next) + if (!strcmp ((*after_bfd)->filename, posname)) + { + if (realpos == pos_after) + after_bfd = &(*after_bfd)->next; + break; + } + } + return after_bfd; +} + +static void +delete_members (arch, files_to_delete) + bfd *arch; + char **files_to_delete; +{ + bfd **current_ptr_ptr; + boolean found; + boolean something_changed = false; + for (; *files_to_delete != NULL; ++files_to_delete) + { + /* In a.out systems, the armap is optional. It's also called + __.SYMDEF. So if the user asked to delete it, we should remember + that fact. This isn't quite right for COFF systems (where + __.SYMDEF might be regular member), but it's very unlikely + to be a problem. FIXME */ + + if (!strcmp (*files_to_delete, "__.SYMDEF")) + { + arch->has_armap = false; + write_armap = -1; + continue; + } + + found = false; + current_ptr_ptr = &(arch->next); + while (*current_ptr_ptr) + { + if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0) + { + found = true; + something_changed = true; + if (verbose) + printf ("d - %s\n", + *files_to_delete); + *current_ptr_ptr = ((*current_ptr_ptr)->next); + goto next_file; + } + else + { + current_ptr_ptr = &((*current_ptr_ptr)->next); + } + } + + if (verbose && found == false) + { + printf ("No member named `%s'\n", *files_to_delete); + } + next_file: + ; + } + + if (something_changed == true) + { + write_archive (arch); + } +} + + +/* Reposition existing members within an archive */ + +static void +move_members (arch, files_to_move) + bfd *arch; + char **files_to_move; +{ + bfd **after_bfd; /* New entries go after this one */ + bfd **current_ptr_ptr; /* cdr pointer into contents */ + + for (; *files_to_move; ++files_to_move) + { + current_ptr_ptr = &(arch->next); + while (*current_ptr_ptr) + { + bfd *current_ptr = *current_ptr_ptr; + if (strcmp (normalize (*files_to_move, arch), + current_ptr->filename) == 0) + { + /* Move this file to the end of the list - first cut from + where it is. */ + bfd *link; + *current_ptr_ptr = current_ptr->next; + + /* Now glue to end */ + after_bfd = get_pos_bfd (&arch->next, pos_end); + link = *after_bfd; + *after_bfd = current_ptr; + current_ptr->next = link; + + if (verbose) + printf ("m - %s\n", *files_to_move); + + goto next_file; + } + + current_ptr_ptr = &((*current_ptr_ptr)->next); + } + fprintf (stderr, "%s: no entry %s in archive %s!\n", + program_name, *files_to_move, arch->filename); + xexit (1); + next_file:; + } + + write_archive (arch); +} + +/* Ought to default to replacing in place, but this is existing practice! */ + +static void +replace_members (arch, files_to_move, quick) + bfd *arch; + char **files_to_move; + boolean quick; +{ + boolean changed = false; + bfd **after_bfd; /* New entries go after this one */ + bfd *current; + bfd **current_ptr; + bfd *temp; + + while (files_to_move && *files_to_move) + { + if (! quick) + { + current_ptr = &arch->next; + while (*current_ptr) + { + current = *current_ptr; + + /* For compatibility with existing ar programs, we + permit the same file to be added multiple times. */ + if (strcmp (normalize (*files_to_move, arch), + normalize (current->filename, arch)) == 0 + && current->arelt_data != NULL) + { + if (newer_only) + { + struct stat fsbuf, asbuf; + + if (stat (*files_to_move, &fsbuf) != 0) + { + if (errno != ENOENT) + bfd_fatal (*files_to_move); + goto next_file; + } + if (bfd_stat_arch_elt (current, &asbuf) != 0) + fatal ("internal stat error on %s", current->filename); + + if (fsbuf.st_mtime <= asbuf.st_mtime) + goto next_file; + } + + /* snip out this entry from the chain */ + *current_ptr = current->next; + + after_bfd = get_pos_bfd (&arch->next, pos_end); + temp = *after_bfd; + *after_bfd = bfd_openr (*files_to_move, NULL); + if (*after_bfd == (bfd *) NULL) + { + bfd_fatal (*files_to_move); + } + (*after_bfd)->next = temp; + + if (verbose) + { + printf ("r - %s\n", *files_to_move); + } + + changed = true; + + goto next_file; + } + current_ptr = &(current->next); + } + } + + /* Add to the end of the archive. */ + + after_bfd = get_pos_bfd (&arch->next, pos_end); + temp = *after_bfd; + *after_bfd = bfd_openr (*files_to_move, NULL); + if (*after_bfd == (bfd *) NULL) + { + bfd_fatal (*files_to_move); + } + if (verbose) + { + printf ("a - %s\n", *files_to_move); + } + + (*after_bfd)->next = temp; + + changed = true; + + next_file:; + + files_to_move++; + } + + if (changed) + write_archive (arch); +} + +static void +ranlib_only (archname) + const char *archname; +{ + bfd *arch; + + write_armap = 1; + arch = open_inarch (archname); + if (arch == NULL) + xexit (1); + write_archive (arch); +} + +/* Update the timestamp of the symbol map of an archive. */ + +static void +ranlib_touch (archname) + const char *archname; +{ +#ifdef __GO32__ + /* I don't think updating works on go32. */ + ranlib_only (archname); +#else + int f; + bfd *arch; + + f = open (archname, O_RDWR, 0); + if (f < 0) + { + bfd_set_error (bfd_error_system_call); + bfd_fatal (archname); + } + + arch = bfd_fdopenr (archname, (const char *) NULL, f); + if (arch == NULL + || ! bfd_check_format (arch, bfd_archive)) + bfd_fatal (archname); + + if (! bfd_has_map (arch)) + fatal ("%s: no archive map to update", archname); + + bfd_update_armap_timestamp (arch); + + if (! bfd_close (arch)) + bfd_fatal (archname); +#endif +} + +/* Things which are interesting to map over all or some of the files: */ + +static void +print_descr (abfd) + bfd *abfd; +{ + print_arelt_descr (stdout, abfd, verbose); +} diff --git a/gnu/usr.bin/binutils/binutils/arlex.c b/gnu/usr.bin/binutils/binutils/arlex.c new file mode 100644 index 00000000000..d3f5d0ab483 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/arlex.c @@ -0,0 +1,1802 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/cvs/src/gnu/usr.bin/binutils/binutils/Attic/arlex.c,v 1.1.1.1 1996/01/08 11:03:56 niklas Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 40 +#define YY_END_OF_BUFFER 41 +static yyconst short int yy_accept[177] = + { 0, + 0, 0, 41, 40, 39, 38, 35, 32, 33, 36, + 40, 34, 37, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 36, 31, 37, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 7, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 22, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + + 35, 35, 35, 10, 11, 12, 35, 15, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 25, 26, 27, + 35, 30, 35, 35, 35, 3, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 18, 35, 35, 35, 35, + 35, 35, 35, 1, 2, 4, 5, 35, 35, 35, + 35, 35, 16, 17, 19, 20, 35, 35, 35, 35, + 35, 35, 8, 9, 13, 14, 35, 23, 24, 28, + 29, 35, 35, 6, 21, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 1, 1, 4, 1, 1, 1, 5, + 6, 7, 8, 9, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 10, 1, + 1, 1, 1, 1, 11, 12, 13, 14, 15, 16, + 4, 17, 18, 4, 4, 19, 20, 21, 22, 23, + 4, 24, 25, 26, 27, 28, 4, 29, 30, 4, + 1, 1, 1, 1, 4, 1, 31, 32, 33, 34, + + 35, 36, 4, 37, 38, 4, 4, 39, 40, 41, + 42, 43, 4, 44, 45, 46, 47, 48, 4, 49, + 50, 4, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[51] = + { 0, + 1, 2, 1, 3, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 + } ; + +static yyconst short int yy_base[180] = + { 0, + 0, 0, 193, 194, 194, 194, 0, 194, 194, 0, + 190, 194, 0, 177, 32, 37, 32, 163, 174, 170, + 164, 171, 174, 169, 149, 15, 22, 17, 135, 146, + 142, 136, 143, 146, 141, 0, 0, 194, 0, 161, + 159, 158, 153, 147, 156, 143, 149, 148, 141, 150, + 141, 135, 138, 127, 125, 124, 119, 113, 122, 109, + 115, 114, 107, 116, 107, 101, 104, 43, 136, 135, + 130, 129, 0, 119, 123, 118, 114, 118, 119, 122, + 124, 25, 104, 103, 98, 97, 0, 87, 91, 86, + 82, 86, 87, 90, 92, 105, 100, 97, 94, 93, + + 105, 106, 102, 0, 0, 0, 104, 0, 92, 75, + 70, 67, 64, 63, 75, 76, 72, 0, 0, 0, + 74, 0, 62, 91, 88, 0, 86, 85, 73, 85, + 79, 83, 70, 62, 59, 0, 57, 56, 44, 56, + 50, 54, 41, 0, 0, 0, 0, 63, 58, 59, + 67, 66, 0, 0, 0, 0, 38, 33, 34, 42, + 41, 51, 0, 0, 0, 0, 30, 0, 0, 0, + 0, 43, 21, 0, 0, 194, 65, 66, 69 + } ; + +static yyconst short int yy_def[180] = + { 0, + 176, 1, 176, 176, 176, 176, 177, 176, 176, 178, + 176, 176, 179, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 178, 176, 179, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 0, 176, 176, 176 + } ; + +static yyconst short int yy_nxt[245] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 7, 15, 16, 17, 18, 19, 7, 20, 7, + 7, 21, 7, 22, 23, 7, 7, 24, 7, 7, + 25, 7, 26, 27, 28, 29, 30, 7, 31, 7, + 7, 32, 7, 33, 34, 7, 7, 35, 7, 7, + 41, 43, 45, 55, 44, 42, 57, 59, 56, 58, + 46, 96, 97, 110, 111, 60, 37, 36, 37, 39, + 175, 39, 174, 173, 172, 171, 170, 169, 168, 167, + 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, + 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, + + 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, + 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, + 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, + 116, 115, 114, 113, 112, 109, 108, 107, 106, 105, + 104, 103, 102, 101, 100, 99, 98, 95, 94, 93, + 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, + 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, + 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, + 62, 61, 54, 53, 52, 51, 50, 49, 48, 47, + 40, 38, 176, 3, 176, 176, 176, 176, 176, 176, + + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176 + } ; + +static yyconst short int yy_chk[245] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 15, 16, 17, 26, 16, 15, 27, 28, 26, 27, + 17, 68, 68, 82, 82, 28, 178, 177, 178, 179, + 173, 179, 172, 167, 162, 161, 160, 159, 158, 157, + 152, 151, 150, 149, 148, 143, 142, 141, 140, 139, + 138, 137, 135, 134, 133, 132, 131, 130, 129, 128, + + 127, 125, 124, 123, 121, 117, 116, 115, 114, 113, + 112, 111, 110, 109, 107, 103, 102, 101, 100, 99, + 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, + 88, 86, 85, 84, 83, 81, 80, 79, 78, 77, + 76, 75, 74, 72, 71, 70, 69, 67, 66, 65, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, + 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, + 44, 43, 42, 41, 40, 35, 34, 33, 32, 31, + 30, 29, 25, 24, 23, 22, 21, 20, 19, 18, + 14, 11, 3, 176, 176, 176, 176, 176, 176, 176, + + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "./arlex.l" +#define INITIAL 0 +#line 2 "./arlex.l" +/* arlex.l - Strange script language lexer */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +*/ +#define DONTDECLARE_MALLOC +#include +#include "arparse.h" +extern char *strdup(); +int linenumber; +#line 502 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 33 "./arlex.l" + + +#line 652 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 177 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 194 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 35 "./arlex.l" +{ return ADDLIB; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 36 "./arlex.l" +{ return ADDMOD; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 37 "./arlex.l" +{ return CLEAR; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 38 "./arlex.l" +{ return CREATE; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 39 "./arlex.l" +{ return DELETE; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 40 "./arlex.l" +{ return DIRECTORY; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 41 "./arlex.l" +{ return END; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 42 "./arlex.l" +{ return EXTRACT; } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 43 "./arlex.l" +{ return FULLDIR; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 44 "./arlex.l" +{ return HELP; } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 45 "./arlex.l" +{ return LIST; } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 46 "./arlex.l" +{ return OPEN; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 47 "./arlex.l" +{ return REPLACE; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 48 "./arlex.l" +{ return VERBOSE; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 49 "./arlex.l" +{ return SAVE; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 50 "./arlex.l" +{ return ADDLIB; } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 51 "./arlex.l" +{ return ADDMOD; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 52 "./arlex.l" +{ return CLEAR; } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 53 "./arlex.l" +{ return CREATE; } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 54 "./arlex.l" +{ return DELETE; } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 55 "./arlex.l" +{ return DIRECTORY; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 56 "./arlex.l" +{ return END; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 57 "./arlex.l" +{ return EXTRACT; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 58 "./arlex.l" +{ return FULLDIR; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 59 "./arlex.l" +{ return HELP; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 60 "./arlex.l" +{ return LIST; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 61 "./arlex.l" +{ return OPEN; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 62 "./arlex.l" +{ return REPLACE; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 63 "./arlex.l" +{ return VERBOSE; } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 64 "./arlex.l" +{ return SAVE; } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 65 "./arlex.l" +{ linenumber ++; } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 66 "./arlex.l" +{ return '('; } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 67 "./arlex.l" +{ return ')'; } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 68 "./arlex.l" +{ return ','; } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 69 "./arlex.l" +{ + yylval.name = strdup(yytext); + return FILENAME; + } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 73 "./arlex.l" +{ } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 74 "./arlex.l" +{ } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 75 "./arlex.l" +{ } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 76 "./arlex.l" +{ linenumber ++; return NEWLINE; } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 78 "./arlex.l" +ECHO; + YY_BREAK +#line 938 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 177 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 177 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 176); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 78 "./arlex.l" + +#ifndef yywrap +/* Needed for lex, though not flex. */ +int yywrap() { return 1; } +#endif diff --git a/gnu/usr.bin/binutils/binutils/arlex.l b/gnu/usr.bin/binutils/binutils/arlex.l new file mode 100644 index 00000000000..313b69bf198 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/arlex.l @@ -0,0 +1,82 @@ +%{ +/* arlex.l - Strange script language lexer */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +*/ +#define DONTDECLARE_MALLOC +#include +#include "arparse.h" +extern char *strdup(); +int linenumber; +%} +%% + +"ADDLIB" { return ADDLIB; } +"ADDMOD" { return ADDMOD; } +"CLEAR" { return CLEAR; } +"CREATE" { return CREATE; } +"DELETE" { return DELETE; } +"DIRECTORY" { return DIRECTORY; } +"END" { return END; } +"EXTRACT" { return EXTRACT; } +"FULLDIR" { return FULLDIR; } +"HELP" { return HELP; } +"LIST" { return LIST; } +"OPEN" { return OPEN; } +"REPLACE" { return REPLACE; } +"VERBOSE" { return VERBOSE; } +"SAVE" { return SAVE; } +"addlib" { return ADDLIB; } +"addmod" { return ADDMOD; } +"clear" { return CLEAR; } +"create" { return CREATE; } +"delete" { return DELETE; } +"directory" { return DIRECTORY; } +"end" { return END; } +"extract" { return EXTRACT; } +"fulldir" { return FULLDIR; } +"help" { return HELP; } +"list" { return LIST; } +"open" { return OPEN; } +"replace" { return REPLACE; } +"verbose" { return VERBOSE; } +"save" { return SAVE; } +"+\n" { linenumber ++; } +"(" { return '('; } +")" { return ')'; } +"," { return ','; } +[A-Za-z0-9/$:.\-\_]+ { + yylval.name = strdup(yytext); + return FILENAME; + } +"*".* { } +";".* { } +" " { } +"\n" { linenumber ++; return NEWLINE; } + +%% +#ifndef yywrap +/* Needed for lex, though not flex. */ +int yywrap() { return 1; } +#endif diff --git a/gnu/usr.bin/binutils/binutils/arparse.c b/gnu/usr.bin/binutils/binutils/arparse.c new file mode 100644 index 00000000000..13ca9c4c894 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/arparse.c @@ -0,0 +1,1026 @@ + +/* A Bison parser, made from ./arparse.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define NEWLINE 258 +#define VERBOSE 259 +#define FILENAME 260 +#define ADDLIB 261 +#define LIST 262 +#define ADDMOD 263 +#define CLEAR 264 +#define CREATE 265 +#define DELETE 266 +#define DIRECTORY 267 +#define END 268 +#define EXTRACT 269 +#define FULLDIR 270 +#define HELP 271 +#define QUIT 272 +#define REPLACE 273 +#define SAVE 274 +#define OPEN 275 + +#line 1 "./arparse.y" + +/* arparse.y - Stange script language parser */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +*/ +#define DONTDECLARE_MALLOC +#include "bfd.h" +#include +#include "arsup.h" +extern int verbose; + +#line 34 "./arparse.y" +typedef union { + char *name; +struct list *list ; + +} 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 + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 53 +#define YYFLAG -32768 +#define YYNTBASE 24 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 275 ? yytranslate[x] : 45) + +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, 2, 2, 2, 21, + 22, 2, 2, 23, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 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 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 4, 7, 8, 11, 13, 15, 17, 19, + 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, + 41, 42, 45, 48, 50, 53, 56, 58, 60, 63, + 66, 70, 75, 77, 78, 82, 83, 87, 88, 90, + 91 +}; + +static const short yyrhs[] = { -1, + 25, 26, 0, 26, 27, 0, 0, 28, 3, 0, + 36, 0, 37, 0, 44, 0, 39, 0, 38, 0, + 31, 0, 33, 0, 35, 0, 29, 0, 30, 0, + 32, 0, 34, 0, 13, 0, 1, 0, 5, 0, + 0, 14, 42, 0, 18, 42, 0, 9, 0, 11, + 42, 0, 8, 42, 0, 7, 0, 19, 0, 20, + 5, 0, 10, 5, 0, 6, 5, 41, 0, 12, + 5, 41, 40, 0, 5, 0, 0, 21, 42, 22, + 0, 0, 42, 43, 5, 0, 0, 23, 0, 0, + 4, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 64, 66, 68, 70, 73, 76, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 96, 101, 106, 111, 115, 120, 125, 132, 137, + 143, 147, 154, 157, 160, 163, 167, 174, 178, 180, + 184 +}; + +static const char * const yytname[] = { "$","error","$undefined.","NEWLINE", +"VERBOSE","FILENAME","ADDLIB","LIST","ADDMOD","CLEAR","CREATE","DELETE","DIRECTORY", +"END","EXTRACT","FULLDIR","HELP","QUIT","REPLACE","SAVE","OPEN","'('","')'", +"','","start","@1","session","command_line","command","extract_command","replace_command", +"clear_command","delete_command","addmod_command","list_command","save_command", +"open_command","create_command","addlib_command","directory_command","optional_filename", +"modulelist","modulename","optcomma","verbose_command","" +}; +#endif + +static const short yyr1[] = { 0, + 25, 24, 26, 26, 27, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 40, 41, 41, 42, 42, 43, 43, + 44 +}; + +static const short yyr2[] = { 0, + 0, 2, 2, 0, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 2, 2, 1, 2, 2, 1, 1, 2, 2, + 3, 4, 1, 0, 3, 0, 3, 0, 1, 0, + 1 +}; + +static const short yydefact[] = { 1, + 4, 0, 19, 41, 20, 0, 27, 38, 24, 0, + 38, 0, 18, 38, 38, 28, 0, 3, 0, 14, + 15, 11, 16, 12, 17, 13, 6, 7, 10, 9, + 8, 36, 26, 30, 25, 36, 22, 23, 29, 5, + 38, 31, 39, 0, 34, 40, 37, 33, 32, 35, + 0, 0, 0 +}; + +static const short yydefgoto[] = { 51, + 1, 2, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 49, 42, 33, 44, 31 +}; + +static const short yypact[] = {-32768, +-32768, 5,-32768,-32768,-32768, -4,-32768,-32768,-32768, 2, +-32768, 21,-32768,-32768,-32768,-32768, 22,-32768, 25,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768, 8, -3,-32768, -3, 8, -3, -3,-32768,-32768, +-32768,-32768,-32768, 26, 27, -1,-32768,-32768,-32768,-32768, + 33, 34,-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768, 0, -11,-32768,-32768 +}; + + +#define YYLAST 36 + + +static const short yytable[] = { 35, + 32, -40, 37, 38, -2, 3, 34, -21, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 43, + 50, 43, 15, 16, 17, 36, 39, 40, 41, 46, + 47, 48, 52, 53, 0, 45 +}; + +static const short yycheck[] = { 11, + 5, 5, 14, 15, 0, 1, 5, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 23, + 22, 23, 18, 19, 20, 5, 5, 3, 21, 41, + 5, 5, 0, 0, -1, 36 +}; +/* -*-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 +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #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 reallocate 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 reallocate 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 1: +#line 65 "./arparse.y" +{ prompt(); ; + break;} +case 5: +#line 74 "./arparse.y" +{ prompt(); ; + break;} +case 18: +#line 89 "./arparse.y" +{ ar_end(); return 0; ; + break;} +case 20: +#line 91 "./arparse.y" +{ yyerror("foo"); ; + break;} +case 22: +#line 98 "./arparse.y" +{ ar_extract(yyvsp[0].list); ; + break;} +case 23: +#line 103 "./arparse.y" +{ ar_replace(yyvsp[0].list); ; + break;} +case 24: +#line 108 "./arparse.y" +{ ar_clear(); ; + break;} +case 25: +#line 113 "./arparse.y" +{ ar_delete(yyvsp[0].list); ; + break;} +case 26: +#line 117 "./arparse.y" +{ ar_addmod(yyvsp[0].list); ; + break;} +case 27: +#line 122 "./arparse.y" +{ ar_list(); ; + break;} +case 28: +#line 127 "./arparse.y" +{ ar_save(); ; + break;} +case 29: +#line 134 "./arparse.y" +{ ar_open(yyvsp[0].name,0); ; + break;} +case 30: +#line 139 "./arparse.y" +{ ar_open(yyvsp[0].name,1); ; + break;} +case 31: +#line 145 "./arparse.y" +{ ar_addlib(yyvsp[-1].name,yyvsp[0].list); ; + break;} +case 32: +#line 149 "./arparse.y" +{ ar_directory(yyvsp[-2].name, yyvsp[-1].list, yyvsp[0].name); ; + break;} +case 33: +#line 156 "./arparse.y" +{ yyval.name = yyvsp[0].name; ; + break;} +case 34: +#line 157 "./arparse.y" +{ yyval.name = 0; ; + break;} +case 35: +#line 162 "./arparse.y" +{ yyval.list = yyvsp[-1].list; ; + break;} +case 36: +#line 164 "./arparse.y" +{ yyval.list = 0; ; + break;} +case 37: +#line 169 "./arparse.y" +{ struct list *n = (struct list *) malloc(sizeof(struct list)); + n->next = yyvsp[-2].list; + n->name = yyvsp[0].name; + yyval.list = n; + ; + break;} +case 38: +#line 174 "./arparse.y" +{ yyval.list = 0; ; + break;} +case 41: +#line 186 "./arparse.y" +{ verbose = !verbose; ; + 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 *) malloc(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 190 "./arparse.y" + + + +int +yyerror(x) +char *x; +{ + extern int linenumber; + printf("Synax error in archive script, line %d\n", linenumber + 1); + return 0; +} diff --git a/gnu/usr.bin/binutils/binutils/arparse.h b/gnu/usr.bin/binutils/binutils/arparse.h new file mode 100644 index 00000000000..3212fe3af24 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/arparse.h @@ -0,0 +1,26 @@ +typedef union { + char *name; +struct list *list ; + +} YYSTYPE; +#define NEWLINE 258 +#define VERBOSE 259 +#define FILENAME 260 +#define ADDLIB 261 +#define LIST 262 +#define ADDMOD 263 +#define CLEAR 264 +#define CREATE 265 +#define DELETE 266 +#define DIRECTORY 267 +#define END 268 +#define EXTRACT 269 +#define FULLDIR 270 +#define HELP 271 +#define QUIT 272 +#define REPLACE 273 +#define SAVE 274 +#define OPEN 275 + + +extern YYSTYPE yylval; diff --git a/gnu/usr.bin/binutils/binutils/arparse.y b/gnu/usr.bin/binutils/binutils/arparse.y new file mode 100644 index 00000000000..b7c54d78b9b --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/arparse.y @@ -0,0 +1,200 @@ +%{ +/* arparse.y - Stange script language parser */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +*/ +#define DONTDECLARE_MALLOC +#include "bfd.h" +#include +#include "arsup.h" +extern int verbose; +%} + +%union { + char *name; +struct list *list ; + +}; + +%token NEWLINE +%token VERBOSE +%token FILENAME +%token ADDLIB +%token LIST +%token ADDMOD +%token CLEAR +%token CREATE +%token DELETE +%token DIRECTORY +%token END +%token EXTRACT +%token FULLDIR +%token HELP +%token QUIT +%token REPLACE +%token SAVE +%token OPEN + +%type modulelist +%type modulename +%type optional_filename +%% + +start: + { prompt(); } session + ; + +session: + session command_line + | + ; + +command_line: + command NEWLINE { prompt(); } + +command: + open_command + | create_command + | verbose_command + | directory_command + | addlib_command + | clear_command + | addmod_command + | save_command + | extract_command + | replace_command + | delete_command + | list_command + | END { ar_end(); return 0; } + | error + | FILENAME { yyerror("foo"); } + | + ; + + +extract_command: + EXTRACT modulename + { ar_extract($2); } + ; + +replace_command: + REPLACE modulename + { ar_replace($2); } + ; + +clear_command: + CLEAR + { ar_clear(); } + ; + +delete_command: + DELETE modulename + { ar_delete($2); } + ; +addmod_command: + ADDMOD modulename + { ar_addmod($2); } + ; + +list_command: + LIST + { ar_list(); } + ; + +save_command: + SAVE + { ar_save(); } + ; + + + +open_command: + OPEN FILENAME + { ar_open($2,0); } + ; + +create_command: + CREATE FILENAME + { ar_open($2,1); } + ; + + +addlib_command: + ADDLIB FILENAME modulelist + { ar_addlib($2,$3); } + ; +directory_command: + DIRECTORY FILENAME modulelist optional_filename + { ar_directory($2, $3, $4); } + ; + + + +optional_filename: + FILENAME + { $$ = $1; } + | { $$ = 0; } + ; + +modulelist: + '(' modulename ')' + { $$ = $2; } + | + { $$ = 0; } + ; + +modulename: + modulename optcomma FILENAME + { struct list *n = (struct list *) malloc(sizeof(struct list)); + n->next = $1; + n->name = $3; + $$ = n; + } + | { $$ = 0; } + ; + + +optcomma: + ',' + | + ; + + +verbose_command: + VERBOSE + { verbose = !verbose; } + ; + + +%% + + +int +yyerror(x) +char *x; +{ + extern int linenumber; + printf("Synax error in archive script, line %d\n", linenumber + 1); + return 0; +} diff --git a/gnu/usr.bin/binutils/binutils/arsup.c b/gnu/usr.bin/binutils/binutils/arsup.c new file mode 100644 index 00000000000..5887a9ec628 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/arsup.c @@ -0,0 +1,452 @@ +/* arsup.c - Archive support for MRI compatibility + Copyright (C) 1992 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +This file looks after requests from arparse.y, to provide the MRI +style librarian command syntax + 1 word LIST + +*/ + +#include "bfd.h" +#include "arsup.h" +#include "libiberty.h" +#include "bucomm.h" + +static void map_over_list + PARAMS ((bfd *, void (*function) (bfd *, bfd *), struct list *)); +static void ar_directory_doer PARAMS ((bfd *, bfd *)); +static void ar_addlib_doer PARAMS ((bfd *, bfd *)); + +extern int verbose; + +extern char *strdup(); + +static void +map_over_list (arch, function, list) + bfd *arch; + void (*function) PARAMS ((bfd *, bfd *)); + struct list *list; +{ + bfd *head; + + if (list == 0) { + for (head = arch->next; head; head = head->next){ + function (head, (bfd *) NULL); + } + } + else { + /* + This may appear to be a baroque way of accomplishing what we want. + however we have to iterate over the filenames in order to notice where + a filename is requested but does not exist in the archive. Ditto + mapping over each file each time -- we want to hack multiple + references. + */ + struct list *ptr = list; + + for (ptr = list; ptr; ptr=ptr->next) + { + boolean found = false; + bfd *prev = arch; + for (head = arch->next; head; head = head->next) + { + if ((head->filename != NULL) && + (!strcmp(ptr->name, head->filename))) + { + found = true; + function(head, prev); + + } + prev = head; + } + if (!found) + fprintf(stderr, "No entry %s in archive.\n", ptr->name); + } + } +} + + +FILE *outfile; + +/*ARGSUSED*/ +static void +ar_directory_doer (abfd, ignore) + bfd *abfd; + bfd *ignore; +{ + print_arelt_descr(outfile, abfd, verbose); +} + +void +ar_directory (ar_name, list, output) + char *ar_name; + struct list *list; + char *output; +{ + bfd *arch; + + arch = open_inarch (ar_name); + if (output) + { + outfile = fopen(output,"w"); + if (outfile == 0) + { + outfile = stdout; + fprintf (stderr,"Can't open file %s\n", output); + output = 0; + } + } + else + outfile = stdout; + + map_over_list (arch, ar_directory_doer, list); + + bfd_close (arch); + + if (output) + fclose (outfile); +} + +void +DEFUN_VOID(prompt) +{ + extern int interactive; + if (interactive) + { + printf("AR >"); + fflush(stdout); + } +} + +void +maybequit () +{ + if (! interactive) + xexit (9); +} + + +bfd *obfd; +char *real_name ; +void +DEFUN(ar_open,(name, t), + char *name AND + int t) + +{ + char *tname = (char *) malloc(strlen(name)+10); + real_name = name; + sprintf(tname, "%s-tmp", name); + obfd = bfd_openw(tname, NULL); + + if (!obfd) { + fprintf(stderr,"%s: Can't open output archive %s\n", program_name, + tname); + + maybequit(); + } + else { + if (!t) { + bfd **ptr; + bfd *element; + bfd *ibfd; + ibfd = bfd_openr(name, NULL); + if (!ibfd) { + fprintf(stderr,"%s: Can't open input archive %s\n", + program_name, name); + maybequit(); + return; + } + if (bfd_check_format(ibfd, bfd_archive) != true) { + fprintf(stderr,"%s: file %s is not an archive\n", program_name, + name); + maybequit(); + return; + } + ptr = &(obfd->archive_head); + element = bfd_openr_next_archived_file(ibfd, NULL); + + while (element) { + *ptr = element; + ptr = &element->next; + element = bfd_openr_next_archived_file(ibfd, element); + } + } + + bfd_set_format(obfd, bfd_archive); + + obfd->has_armap = 1; + } +} + + +static void +ar_addlib_doer (abfd, prev) + bfd *abfd; + bfd *prev; +{ + /* Add this module to the output bfd */ + + prev->next = abfd->next; + abfd->next = obfd->archive_head; + obfd->archive_head = abfd; +} + +void +ar_addlib (name, list) + char *name; + struct list *list; +{ + if (obfd == NULL) + { + fprintf (stderr, "%s: no output archive specified yet\n", program_name); + maybequit (); + } + else + { + bfd *arch; + + arch = open_inarch (name); + if (arch != NULL) + map_over_list (arch, ar_addlib_doer, list); + + /* Don't close the bfd, since it will make the elements disasppear */ + } +} + +void +DEFUN(ar_addmod, (list), + struct list *list) +{ + if (!obfd) { + fprintf(stderr, "%s: no open output archive\n", program_name); + maybequit(); + } + else + { + while (list) { + bfd *abfd = bfd_openr(list->name, NULL); + if (!abfd) { + fprintf(stderr,"%s: can't open file %s\n", program_name, + list->name); + maybequit(); + } + else { + abfd->next = obfd->archive_head; + obfd->archive_head = abfd; + } + list = list->next; + } + } +} + + + +void +DEFUN_VOID(ar_clear) +{ +if (obfd) + obfd->archive_head = 0; +} + +void +DEFUN(ar_delete, (list), + struct list *list) +{ + if (!obfd) { + fprintf(stderr, "%s: no open output archive\n", program_name); + maybequit(); + } + else + { + while (list) { + /* Find this name in the archive */ + bfd *member = obfd->archive_head; + bfd **prev = &(obfd->archive_head); + int found = 0; + while (member) { + if (strcmp(member->filename, list->name) == 0) { + *prev = member->next; + found = 1; + } + else { + prev = &(member->next); + } + member = member->next; + } + if (!found) { + fprintf(stderr,"%s: can't find module file %s\n", program_name, + list->name); + maybequit(); + } + list = list->next; + } + } +} + + +void +DEFUN_VOID(ar_save) +{ + + if (!obfd) { + fprintf(stderr, "%s: no open output archive\n", program_name); + maybequit(); + } + else { + char *ofilename = strdup(bfd_get_filename (obfd)); + bfd_close(obfd); + + rename (ofilename, real_name); + obfd = 0; + free(ofilename); + } +} + + + +void +DEFUN(ar_replace, (list), + struct list *list) +{ + if (!obfd) { + fprintf(stderr, "%s: no open output archive\n", program_name); + maybequit(); + } + else + { + while (list) { + /* Find this name in the archive */ + bfd *member = obfd->archive_head; + bfd **prev = &(obfd->archive_head); + int found = 0; + while (member) + { + if (strcmp(member->filename, list->name) == 0) + { + /* Found the one to replace */ + bfd *abfd = bfd_openr(list->name, 0); + if (!abfd) + { + fprintf(stderr, "%s: can't open file %s\n", program_name, list->name); + maybequit(); + } + else { + *prev = abfd; + abfd->next = member->next; + found = 1; + } + } + else { + prev = &(member->next); + } + member = member->next; + } + if (!found) { + bfd *abfd = bfd_openr(list->name, 0); + fprintf(stderr,"%s: can't find module file %s\n", program_name, + list->name); + if (!abfd) + { + fprintf(stderr, "%s: can't open file %s\n", program_name, list->name); + maybequit(); + } + else + { + *prev = abfd; + } + } + + list = list->next; + } + } +} + +/* And I added this one */ +void +DEFUN_VOID(ar_list) +{ + if (!obfd) + { + fprintf(stderr, "%s: no open output archive\n", program_name); + maybequit(); + } + else { + bfd *abfd; + outfile = stdout; + verbose =1 ; + printf("Current open archive is %s\n", bfd_get_filename (obfd)); + for (abfd = obfd->archive_head; + abfd != (bfd *)NULL; + abfd = abfd->next) + { + ar_directory_doer (abfd, (bfd *) NULL); + } + } +} + + +void +DEFUN_VOID(ar_end) +{ + if (obfd) + { + fclose((FILE *)(obfd->iostream)); + unlink(bfd_get_filename (obfd)); + } +} +void +DEFUN(ar_extract,(list), + struct list *list) +{ + if (!obfd) + { + + fprintf(stderr, "%s: no open archive\n", program_name); + maybequit(); + } + else + { + while (list) { + /* Find this name in the archive */ + bfd *member = obfd->archive_head; + int found = 0; + while (member && !found) + { + if (strcmp(member->filename, list->name) == 0) + { + extract_file(member); + found = 1; + } + + member = member->next; + } + if (!found) { + bfd_openr(list->name, 0); + fprintf(stderr,"%s: can't find module file %s\n", program_name, + list->name); + + } + list = list->next; + } + } +} diff --git a/gnu/usr.bin/binutils/binutils/arsup.h b/gnu/usr.bin/binutils/binutils/arsup.h new file mode 100644 index 00000000000..f94909e6ccb --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/arsup.h @@ -0,0 +1,75 @@ +/* arsup.h - archive support header file + Copyright 1992 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 list { + char *name; + struct list *next; +}; + +void +maybequit PARAMS ((void)); + +void +prompt PARAMS ((void)); + +void +ar_clear PARAMS ((void)); + +void +ar_replace PARAMS ((struct list *)); + +void +ar_delete PARAMS ((struct list *)); + +void +ar_save PARAMS ((void)); + +void +ar_list PARAMS ((void)); + +void +ar_open PARAMS ((char *, int)); + +void +ar_directory PARAMS ((char *, struct list *, char *)); + +void +ar_addmod PARAMS ((struct list *)); + +void +ar_addlib PARAMS ((char *, struct list *)); + +void +ar_end PARAMS ((void)); + +void +ar_extract PARAMS ((struct list *)); + +bfd * +open_inarch PARAMS ((const char *archive_filename)); + +int +yyparse PARAMS ((void)); + +/* Functions from ar.c */ + +void +extract_file PARAMS ((bfd * abfd)); + +extern int interactive; diff --git a/gnu/usr.bin/binutils/binutils/binutils.info b/gnu/usr.bin/binutils/binutils/binutils.info new file mode 100644 index 00000000000..43a8f0bab65 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/binutils.info @@ -0,0 +1,1668 @@ +This is Info file binutils.info, produced by Makeinfo-1.55 from the +input file ./binutils.texi. + +START-INFO-DIR-ENTRY +* Binutils: (binutils). The GNU binary utilities "ar", "objcopy", + "objdump", "nm", "nlmconv", "size", + "strings", "strip", and "ranlib". +END-INFO-DIR-ENTRY + + Copyright (C) 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. + + 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. + + +File: binutils.info, Node: Top, Next: ar, Prev: (DIR), Up: (DIR) + +Introduction +************ + + This brief manual contains preliminary documentation for the GNU +binary utilities (collectively version 2.6): + +* Menu: + +* ar:: Create, modify, and extract from archives +* nm:: List symbols from object files +* objcopy:: Copy and translate object files +* objdump:: Display information from object files +* ranlib:: Generate index to archive contents +* size:: List section sizes and total size +* strings:: List printable strings from files +* strip:: Discard symbols +* c++filt:: Filter to demangle encoded C++ symbols +* nlmconv:: Converts object code into an NLM +* Selecting The Target System:: How these utilities determine the target. +* Index:: + + +File: binutils.info, Node: ar, Next: nm, Prev: Top, Up: Top + +ar +** + + ar [-]P[MOD [RELPOS]] ARCHIVE [MEMBER...] + ar -M [ '), and continues executing even after errors. If you +redirect standard input to a script file, no prompts are issued, and +`ar' abandons execution (with a nonzero exit code) on any error. + + The `ar' command language is *not* designed to be equivalent to the +command-line options; in fact, it provides somewhat less control over +archives. The only purpose of the command language is to ease the +transition to GNU `ar' for developers who already have scripts written +for the MRI "librarian" program. + + The syntax for the `ar' command language is straightforward: + * commands are recognized in upper or lower case; for example, `LIST' + is the same as `list'. In the following descriptions, commands are + shown in upper case for clarity. + + * a single command may appear on each line; it is the first word on + the line. + + * empty lines are allowed, and have no effect. + + * comments are allowed; text after either of the characters `*' or + `;' is ignored. + + * Whenever you use a list of names as part of the argument to an `ar' + command, you can separate the individual names with either commas + or blanks. Commas are shown in the explanations below, for + clarity. + + * `+' is used as a line continuation character; if `+' appears at + the end of a line, the text on the following line is considered + part of the current command. + + Here are the commands you can use in `ar' scripts, or when using +`ar' interactively. Three of them have special significance: + + `OPEN' or `CREATE' specify a "current archive", which is a temporary +file required for most of the other commands. + + `SAVE' commits the changes so far specified by the script. Prior to +`SAVE', commands affect only the temporary copy of the current archive. + +`ADDLIB ARCHIVE' +`ADDLIB ARCHIVE (MODULE, MODULE, ... MODULE)' + Add all the contents of ARCHIVE (or, if specified, each named + MODULE from ARCHIVE) to the current archive. + + Requires prior use of `OPEN' or `CREATE'. + +`ADDMOD MEMBER, MEMBER, ... MEMBER' + Add each named MEMBER as a module in the current archive. + + Requires prior use of `OPEN' or `CREATE'. + +`CLEAR' + Discard the contents of the current archive, cancelling the effect + of any operations since the last `SAVE'. May be executed (with no + effect) even if no current archive is specified. + +`CREATE ARCHIVE' + Creates an archive, and makes it the current archive (required for + many other commands). The new archive is created with a temporary + name; it is not actually saved as ARCHIVE until you use `SAVE'. + You can overwrite existing archives; similarly, the contents of any + existing file named ARCHIVE will not be destroyed until `SAVE'. + +`DELETE MODULE, MODULE, ... MODULE' + Delete each listed MODULE from the current archive; equivalent to + `ar -d ARCHIVE MODULE ... MODULE'. + + Requires prior use of `OPEN' or `CREATE'. + +`DIRECTORY ARCHIVE (MODULE, ... MODULE)' +`DIRECTORY ARCHIVE (MODULE, ... MODULE) OUTPUTFILE' + List each named MODULE present in ARCHIVE. The separate command + `VERBOSE' specifies the form of the output: when verbose output is + off, output is like that of `ar -t ARCHIVE MODULE...'. When + verbose output is on, the listing is like `ar -tv ARCHIVE + MODULE...'. + + Output normally goes to the standard output stream; however, if you + specify OUTPUTFILE as a final argument, `ar' directs the output to + that file. + +`END' + Exit from `ar', with a `0' exit code to indicate successful + completion. This command does not save the output file; if you + have changed the current archive since the last `SAVE' command, + those changes are lost. + +`EXTRACT MODULE, MODULE, ... MODULE' + Extract each named MODULE from the current archive, writing them + into the current directory as separate files. Equivalent to `ar -x + ARCHIVE MODULE...'. + + Requires prior use of `OPEN' or `CREATE'. + +`LIST' + Display full contents of the current archive, in "verbose" style + regardless of the state of `VERBOSE'. The effect is like `ar tv + ARCHIVE'). (This single command is a GNU `ld' enhancement, rather + than present for MRI compatibility.) + + Requires prior use of `OPEN' or `CREATE'. + +`OPEN ARCHIVE' + Opens an existing archive for use as the current archive (required + for many other commands). Any changes as the result of subsequent + commands will not actually affect ARCHIVE until you next use + `SAVE'. + +`REPLACE MODULE, MODULE, ... MODULE' + In the current archive, replace each existing MODULE (named in the + `REPLACE' arguments) from files in the current working directory. + To execute this command without errors, both the file, and the + module in the current archive, must exist. + + Requires prior use of `OPEN' or `CREATE'. + +`VERBOSE' + Toggle an internal flag governing the output from `DIRECTORY'. + When the flag is on, `DIRECTORY' output matches output from `ar + -tv '.... + +`SAVE' + Commit your changes to the current archive, and actually save it + as a file with the name specified in the last `CREATE' or `OPEN' + command. + + Requires prior use of `OPEN' or `CREATE'. + + +File: binutils.info, Node: nm, Next: objcopy, Prev: ar, Up: Top + +nm +** + + nm [ -a | --debug-syms ] [ -g | --extern-only ] + [ -B ] [ -C | --demangle ] [ -D | --dynamic ] + [ -s | --print-armap ] [ -A | -o | --print-file-name ] + [ -n | -v | --numeric-sort ] [ -p | --no-sort ] + [ -r | --reverse-sort ] [ --size-sort ] [ -u | --undefined-only ] + [ -t RADIX | --radix=RADIX ] [ -P | --portability ] + [ --target=BFDNAME ] [ -f FORMAT | --format=FORMAT ] + [ --no-demangle ] [ -V | --version ] [ --help ] [ OBJFILE... ] + + GNU `nm' lists the symbols from object files OBJFILE.... If no +object files are listed as arguments, `nm' assumes `a.out'. + + For each symbol, `nm' shows: + + * The symbol value, in the radix selected by options (see below), or + hexadecimal by default. + + * The symbol type. At least the following types are used; others + are, as well, depending on the object file format. If lowercase, + the symbol is local; if uppercase, the symbol is global (external). + + `A' + Absolute. + + `B' + BSS (uninitialized data). + + `C' + Common. + + `D' + Initialized data. + + `I' + Indirect reference. + + `T' + Text (program code). + + `U' + Undefined. + + * The symbol name. + + The long and short forms of options, shown here as alternatives, are +equivalent. + +`-A' +`-o' +`--print-file-name' + Precede each symbol by the name of the input file (or archive + element) in which it was found, rather than identifying the input + file once only, before all of its symbols. + +`-a' +`--debug-syms' + Display all symbols, even debugger-only symbols; normally these + are not listed. + +`-B' + The same as `--format=bsd' (for compatibility with the MIPS `nm'). + +`-C' +`--demangle' + Decode ("demangle") low-level symbol names into user-level names. + Besides removing any initial underscore prepended by the system, + this makes C++ function names readable. *Note c++filt::, for more + information on demangling. + +`--no-demangle' + Do not demangle low-level symbol names. This is the default. + +`-D' +`--dynamic' + Display the dynamic symbols rather than the normal symbols. This + is only meaningful for dynamic objects, such as certain types of + shared libraries. + +`-f FORMAT' +`--format=FORMAT' + Use the output format FORMAT, which can be `bsd', `sysv', or + `posix'. The default is `bsd'. Only the first character of + FORMAT is significant; it can be either upper or lower case. + +`-g' +`--extern-only' + Display only external symbols. + +`-n' +`-v' +`--numeric-sort' + Sort symbols numerically by their addresses, rather than + alphabetically by their names. + +`-p' +`--no-sort' + Do not bother to sort the symbols in any order; print them in the + order encountered. + +`-P' +`--portability' + Use the POSIX.2 standard output format instead of the default + format. Equivalent to `-f posix'. + +`-s' +`--print-armap' + When listing symbols from archive members, include the index: a + mapping (stored in the archive by `ar' or `ranlib') of which + modules contain definitions for which names. + +`-r' +`--reverse-sort' + Reverse the order of the sort (whether numeric or alphabetic); let + the last come first. + +`--size-sort' + Sort symbols by size. The size is computed as the difference + between the value of the symbol and the value of the symbol with + the next higher value. The size of the symbol is printed, rather + than the value. + +`-t RADIX' +`--radix=RADIX' + Use RADIX as the radix for printing the symbol values. It must be + `d' for decimal, `o' for octal, or `x' for hexadecimal. + +`--target=BFDNAME' + Specify an object code format other than your system's default + format. *Note Target Selection::, for more information. + +`-u' +`--undefined-only' + Display only undefined symbols (those external to each object + file). + +`-V' +`--version' + Show the version number of `nm' and exit. + +`--help' + Show a summary of the options to `nm' and exit. + + +File: binutils.info, Node: objcopy, Next: objdump, Prev: nm, Up: Top + +objcopy +******* + + objcopy [ -F BFDNAME | --target=BFDNAME ] + [ -I BFDNAME | --input-target=BFDNAME ] + [ -O BFDNAME | --output-target=BFDNAME ] + [ -S | --strip-all ] [ -g | --strip-debug ] + [ -K SYMBOLNAME | --keep-symbol=SYMBOLNAME ] + [ -N SYMBOLNAME | --strip-symbol=SYMBOLNAME ] + [ -x | --discard-all ] [ -X | --discard-locals ] + [ -b BYTE | --byte=BYTE ] + [ -i INTERLEAVE | --interleave=INTERLEAVE ] + [ -R SECTIONNAME | --remove-section=SECTIONNAME ] + [ --gap-fill=VAL ] [ --pad-to=ADDRESS ] + [ --set-start=VAL ] [ --adjust-start=INCR ] + [ --adjust-vma=INCR ] + [ --adjust-section-vma=SECTION{=,+,-}VAL ] + [ --adjust-warnings ] [ --no-adjust-warnings ] + [ --set-section-flags=SECTION=FLAGS ] + [ --add-section=SECTIONNAME=FILENAME ] + [ -v | --verbose ] [ -V | --version ] [ --help ] + INFILE [OUTFILE] + + The GNU `objcopy' utility copies the contents of an object file to +another. `objcopy' uses the GNU BFD Library to read and write the +object files. It can write the destination object file in a format +different from that of the source object file. The exact behavior of +`objcopy' is controlled by command-line options. + + `objcopy' creates temporary files to do its translations and deletes +them afterward. `objcopy' uses BFD to do all its translation work; it +has access to all the formats described in BFD and thus is able to +recognize most formats without being told explicitly. *Note BFD: +(ld.info)BFD. + + `objcopy' can be used to generate S-records by using an output +target of `srec' (e.g., use `-O srec'). + + `objcopy' can be used to generate a raw binary file by using an +output target of `binary' (e.g., use `-O binary'). When `objcopy' +generates a raw binary file, it will essentially produce a memory dump +of the contents of the input object file. All symbols and relocation +information will be discarded. The memory dump will start at the +virtual address of the lowest section copied into the output file. + + When generating an S-record or a raw binary file, it may be helpful +to use `-S' to remove sections containing debugging information. In +some cases `-R' will be useful to remove sections which contain +information which is not needed by the binary file. + +`INFILE' +`OUTFILE' + The source and output files, respectively. If you do not specify + OUTFILE, `objcopy' creates a temporary file and destructively + renames the result with the name of INFILE. + +`-I BFDNAME' +`--input-target=BFDNAME' + Consider the source file's object format to be BFDNAME, rather than + attempting to deduce it. *Note Target Selection::, for more + information. + +`-O BFDNAME' +`--output-target=BFDNAME' + Write the output file using the object format BFDNAME. *Note + Target Selection::, for more information. + +`-F BFDNAME' +`--target=BFDNAME' + Use BFDNAME as the object format for both the input and the output + file; i.e., simply transfer data from source to destination with no + translation. *Note Target Selection::, for more information. + +`-R SECTIONNAME' +`--remove-section=SECTIONNAME' + Remove any section named SECTIONNAME from the output file. This + option may be given more than once. Note that using this option + inappropriately may make the output file unusable. + +`-S' +`--strip-all' + Do not copy relocation and symbol information from the source file. + +`-g' +`--strip-debug' + Do not copy debugging symbols from the source file. + +`--strip-unneeded' + Strip all symbols that are not needed for relocation processing. + +`-K SYMBOLNAME' +`--keep-symbol=SYMBOLNAME' + Copy only symbol SYMBOLNAME from the source file. This option may + be given more than once. + +`-N SYMBOLNAME' +`--strip-symbol=SYMBOLNAME' + Do not copy symbol SYMBOLNAME from the source file. This option + may be given more than once, and may be combined with strip options + other than `-K'. + +`-x' +`--discard-all' + Do not copy non-global symbols from the source file. + +`-X' +`--discard-locals' + Do not copy compiler-generated local symbols. (These usually + start with `L' or `.'.) + +`-b BYTE' +`--byte=BYTE' + Keep only every BYTEth byte of the input file (header data is not + affected). BYTE can be in the range from 0 to INTERLEAVE-1, where + INTERLEAVE is given by the `-i' or `--interleave' option, or the + default of 4. This option is useful for creating files to program + ROM. It is typically used with an `srec' output target. + +`-i INTERLEAVE' +`--interleave=INTERLEAVE' + Only copy one out of every INTERLEAVE bytes. Select which byte to + copy with the -B or `--byte' option. The default is 4. `objcopy' + ignores this option if you do not specify either `-b' or `--byte'. + +`--gap-fill VAL' + Fill gaps between sections with VAL. This is done by increasing + the size of the section with the lower address, and filling in the + extra space created with VAL. + +`--pad-to ADDRESS' + Pad the output file up to the virtual address ADDRESS. This is + done by increasing the size of the last section. The extra space + is filled in with the value specified by `--gap-fill' (default + zero). + +`--set-start VAL' + Set the address of the new file to VAL. Not all object file + formats support setting the start address. + +`--adjust-start INCR' + Adjust the start address by adding INCR. Not all object file + formats support setting the start address. + +`--adjust-vma INCR' + Adjust the address of all sections, as well as the start address, + by adding INCR. Some object file formats do not permit section + addresses to be changed arbitrarily. Note that this does not + relocate the sections; if the program expects sections to be + loaded at a certain address, and this option is used to change the + sections such that they are loaded at a different address, the + program may fail. + +`--adjust-section-vma SECTION{=,+,-}VAL' + Set or adjust the address of the named SECTION. If `=' is used, + the section address is set to VAL. Otherwise, VAL is added to or + subtracted from the section address. See the comments under + `--adjust-vma', above. If SECTION does not exist in the input + file, a warning will be issued, unless `--no-adjust-warnings' is + used. + +`--adjust-warnings' + If `--adjust-section-vma' is used, and the named section does not + exist, issue a warning. This is the default. + +`--no-adjust-warnings' + Do not issue a warning if `--adjust-section-vma' is used, even if + the named section does not exist. + +`--set-section-flags SECTION=FLAGS' + Set the flags for the named section. The FLAGS argument is a + comma separated string of flag names. The recognized names are + `alloc', `load', `readonly', `code', `data', and `rom'. Not all + flags are meaningful for all object file formats. + +`--add-section SECTIONNAME=FILENAME' + Add a new section named SECTIONNAME while copying the file. The + contents of the new section are taken from the file FILENAME. The + size of the section will be the size of the file. This option only + works on file formats which can support sections with arbitrary + names. + +`-V' +`--version' + Show the version number of `objcopy'. + +`-v' +`--verbose' + Verbose output: list all object files modified. In the case of + archives, `objcopy -V' lists all members of the archive. + +`--help' + Show a summary of the options to `objcopy'. + + +File: binutils.info, Node: objdump, Next: ranlib, Prev: objcopy, Up: Top + +objdump +******* + + objdump [ -a | --archive-headers ] + [ -b BFDNAME | --target=BFDNAME ] + [ -d | --disassemble ] [ -D | --disassemble-all ] + [ -f | --file-headers ] + [ -h | --section-headers | --headers ] [ -i | --info ] + [ -j SECTION | --section=SECTION ] + [ -l | --line-numbers ] [ -S | --source ] + [ -m MACHINE | --architecture=MACHINE ] + [ -r | --reloc ] [ -R | --dynamic-reloc ] + [ -s | --full-contents ] [ --stabs ] + [ -t | --syms ] [ -T | --dynamic-syms ] [ -x | --all-headers ] + [ -w | --wide ] [ --start-address=ADDRESS ] + [ --stop-address=ADDRESS ] [ --version ] [ --help ] + OBJFILE... + + `objdump' displays information about one or more object files. The +options control what particular information to display. This +information is mostly useful to programmers who are working on the +compilation tools, as opposed to programmers who just want their +program to compile and work. + + OBJFILE... are the object files to be examined. When you specify +archives, `objdump' shows information on each of the member object +files. + + The long and short forms of options, shown here as alternatives, are +equivalent. At least one option besides `-l' must be given. + +`-a' +`--archive-header' + If any of the OBJFILE files are archives, display the archive + header information (in a format similar to `ls -l'). Besides the + information you could list with `ar tv', `objdump -a' shows the + object file format of each archive member. + +`-b BFDNAME' +`--target=BFDNAME' + Specify that the object-code format for the object files is + BFDNAME. This option may not be necessary; OBJDUMP can + automatically recognize many formats. + + For example, + objdump -b oasys -m vax -h fu.o + + displays summary information from the section headers (`-h') of + `fu.o', which is explicitly identified (`-m') as a VAX object file + in the format produced by Oasys compilers. You can list the + formats available with the `-i' option. *Note Target Selection::, + for more information. + +`-d' +`--disassemble' + Display the assembler mnemonics for the machine instructions from + OBJFILE. This option only disassembles those sections which are + expected to contain instructions. + +`-D' +`--disassemble-all' + Like `-d', but disassemble the contents of all sections, not just + those expected to contain instructions. + +`-f' +`--file-header' + Display summary information from the overall header of each of the + OBJFILE files. + +`-h' +`--section-header' +`--header' + Display summary information from the section headers of the object + file. + + File segments may be relocated to nonstandard addresses, for + example by using the `-Ttext', `-Tdata', or `-Tbss' options to + `ld'. However, some object file formats, such as a.out, do not + store the starting address of the file segments. In those + situations, although `ld' relocates the sections correctly, using + `objdump -h' to list the file section headers cannot show the + correct addresses. Instead, it shows the usual addresses, which + are implicit for the target. + +`--help' + Print a summary of the options to `objdump' and exit. + +`-i' +`--info' + Display a list showing all architectures and object formats + available for specification with `-b' or `-m'. + +`-j NAME' +`--section=NAME' + Display information only for section NAME. + +`-l' +`--line-numbers' + Label the display (using debugging information) with the filename + and source line numbers corresponding to the object code shown. + Only useful with `-d' or `-D'. + +`-m MACHINE' +`--architecture=MACHINE' + Specify that the object files OBJFILE are for architecture + MACHINE. You can list available architectures using the `-i' + option. + +`-r' +`--reloc' + Print the relocation entries of the file. If used with `-d' or + `-D', the relocations are printed interspersed with the + disassembly. + +`-R' +`--dynamic-reloc' + Print the dynamic relocation entries of the file. This is only + meaningful for dynamic objects, such as certain types of shared + libraries. + +`-s' +`--full-contents' + Display the full contents of any sections requested. + +`-S' +`--source' + Display source code intermixed with disassembly, if possible. + Implies `-d'. + +`--stabs' + Display the full contents of any sections requested. Display the + contents of the .stab and .stab.index and .stab.excl sections from + an ELF file. This is only useful on systems (such as Solaris 2.0) + in which `.stab' debugging symbol-table entries are carried in an + ELF section. In most other file formats, debugging symbol-table + entries are interleaved with linkage symbols, and are visible in + the `--syms' output. + +`--start-address=ADDRESS' + Start displaying data at the specified address. This affects the + output of the `-d', `-r' and `-s' options. + +`--stop-address=ADDRESS' + Stop displaying data at the specified address. This affects the + output of the `-d', `-r' and `-s' options. + +`-t' +`--syms' + Print the symbol table entries of the file. This is similar to + the information provided by the `nm' program. + +`-T' +`--dynamic-syms' + Print the dynamic symbol table entries of the file. This is only + meaningful for dynamic objects, such as certain types of shared + libraries. This is similar to the information provided by the `nm' + program when given the `-D' (`--dynamic') option. + +`--version' + Print the version number of `objdump' and exit. + +`-x' +`--all-header' + Display all available header information, including the symbol + table and relocation entries. Using `-x' is equivalent to + specifying all of `-a -f -h -r -t'. + +`-w' +`--wide' + Format some lines for output devices that have more than 80 + columns. + + +File: binutils.info, Node: ranlib, Next: size, Prev: objdump, Up: Top + +ranlib +****** + + ranlib [-vV] ARCHIVE + + `ranlib' generates an index to the contents of an archive and stores +it in the archive. The index lists each symbol defined by a member of +an archive that is a relocatable object file. + + You may use `nm -s' or `nm --print-armap' to list this index. + + An archive with such an index speeds up linking to the library and +allows routines in the library to call each other without regard to +their placement in the archive. + + The GNU `ranlib' program is another form of GNU `ar'; running +`ranlib' is completely equivalent to executing `ar -s'. *Note ar::. + +`-v' +`-V' + Show the version number of `ranlib'. + + +File: binutils.info, Node: size, Next: strings, Prev: ranlib, Up: Top + +size +**** + + size [ -A | -B | --format=COMPATIBILITY ] + [ --help ] [ -d | -o | -x | --radix=NUMBER ] + [ --target=BFDNAME ] [ -V | --version ] + OBJFILE... + + The GNU `size' utility lists the section sizes--and the total +size--for each of the object or archive files OBJFILE in its argument +list. By default, one line of output is generated for each object file +or each module in an archive. + + OBJFILE... are the object files to be examined. + + The command line options have the following meanings: + +`-A' +`-B' +`--format=COMPATIBILITY' + Using one of these options, you can choose whether the output from + GNU `size' resembles output from System V `size' (using `-A', or + `--format=sysv'), or Berkeley `size' (using `-B', or + `--format=berkeley'). The default is the one-line format similar + to Berkeley's. + + Here is an example of the Berkeley (default) format of output from + `size': + size --format=Berkeley ranlib size + text data bss dec hex filename + 294880 81920 11592 388392 5ed28 ranlib + 294880 81920 11888 388688 5ee50 size + + This is the same data, but displayed closer to System V + conventions: + + size --format=SysV ranlib size + ranlib : + section size addr + .text 294880 8192 + .data 81920 303104 + .bss 11592 385024 + Total 388392 + + + size : + section size addr + .text 294880 8192 + .data 81920 303104 + .bss 11888 385024 + Total 388688 + +`--help' + Show a summary of acceptable arguments and options. + +`-d' +`-o' +`-x' +`--radix=NUMBER' + Using one of these options, you can control whether the size of + each section is given in decimal (`-d', or `--radix=10'); octal + (`-o', or `--radix=8'); or hexadecimal (`-x', or `--radix=16'). + In `--radix=NUMBER', only the three values (8, 10, 16) are + supported. The total size is always given in two radices; decimal + and hexadecimal for `-d' or `-x' output, or octal and hexadecimal + if you're using `-o'. + +`--target=BFDNAME' + Specify that the object-code format for OBJFILE is BFDNAME. This + option may not be necessary; `size' can automatically recognize + many formats. *Note Target Selection::, for more information. + +`-V' +`--version' + Display the version number of `size'. + + +File: binutils.info, Node: strings, Next: strip, Prev: size, Up: Top + +strings +******* + + strings [-afov] [-MIN-LEN] [-n MIN-LEN] [-t RADIX] [-] + [--all] [--print-file-name] [--bytes=MIN-LEN] + [--radix=RADIX] [--target=BFDNAME] + [--help] [--version] FILE... + + For each FILE given, GNU `strings' prints the printable character +sequences that are at least 4 characters long (or the number given with +the options below) and are followed by an unprintable character. By +default, it only prints the strings from the initialized and loaded +sections of object files; for other types of files, it prints the +strings from the whole file. + + `strings' is mainly useful for determining the contents of non-text +files. + +`-a' +`--all' +`-' + Do not scan only the initialized and loaded sections of object + files; scan the whole files. + +`-f' +`--print-file-name' + Print the name of the file before each string. + +`--help' + Print a summary of the program usage on the standard output and + exit. + +`-MIN-LEN' +`-n MIN-LEN' +`--bytes=MIN-LEN' + Print sequences of characters that are at least MIN-LEN characters + long, instead of the default 4. + +`-o' + Like `-t o'. Some other versions of `strings' have `-o' act like + `-t d' instead. Since we can not be compatible with both ways, we + simply chose one. + +`-t RADIX' +`--radix=RADIX' + Print the offset within the file before each string. The single + character argument specifies the radix of the offset--`o' for + octal, `x' for hexadecimal, or `d' for decimal. + +`--target=BFDNAME' + Specify an object code format other than your system's default + format. *Note Target Selection::, for more information. + +`-v' +`--version' + Print the program version number on the standard output and exit. + + +File: binutils.info, Node: strip, Next: c++filt, Prev: strings, Up: Top + +strip +***** + + strip [ -F BFDNAME | --target=BFDNAME | --target=BFDNAME ] + [ -I BFDNAME | --input-target=BFDNAME ] + [ -O BFDNAME | --output-target=BFDNAME ] + [ -s | --strip-all ] [ -S | -g | --strip-debug ] + [ -K SYMBOLNAME | --keep-symbol=SYMBOLNAME ] + [ -N SYMBOLNAME | --strip-symbol=SYMBOLNAME ] + [ -x | --discard-all ] [ -X | --discard-locals ] + [ -R SECTIONNAME | --remove-section=SECTIONNAME ] + [ -v | --verbose ] [ -V | --version ] [ --help ] + OBJFILE... + + GNU `strip' discards all symbols from object files OBJFILE. The +list of object files may include archives. At least one object file +must be given. + + `strip' modifies the files named in its argument, rather than +writing modified copies under different names. + +`-F BFDNAME' +`--target=BFDNAME' + Treat the original OBJFILE as a file with the object code format + BFDNAME, and rewrite it in the same format. *Note Target + Selection::, for more information. + +`--help' + Show a summary of the options to `strip' and exit. + +`-I BFDNAME' +`--input-target=BFDNAME' + Treat the original OBJFILE as a file with the object code format + BFDNAME. *Note Target Selection::, for more information. + +`-O BFDNAME' +`--output-target=BFDNAME' + Replace OBJFILE with a file in the output format BFDNAME. *Note + Target Selection::, for more information. + +`-R SECTIONNAME' +`--remove-section=SECTIONNAME' + Remove any section named SECTIONNAME from the output file. This + option may be given more than once. Note that using this option + inappropriately may make the output file unusable. + +`-s' +`--strip-all' + Remove all symbols. + +`-g' +`-S' +`--strip-debug' + Remove debugging symbols only. + +`--strip-unneeded' + Remove all symbols that are not needed for relocation processing. + +`-K SYMBOLNAME' +`--keep-symbol=SYMBOLNAME' + Keep only symbol SYMBOLNAME from the source file. This option may + be given more than once. + +`-N SYMBOLNAME' +`--strip-symbol=SYMBOLNAME' + Remove symbol SYMBOLNAME from the source file. This option may be + given more than once, and may be combined with strip options other + than `-K'. + +`-x' +`--discard-all' + Remove non-global symbols. + +`-X' +`--discard-locals' + Remove compiler-generated local symbols. (These usually start + with `L' or `.'.) + +`-V' +`--version' + Show the version number for `strip'. + +`-v' +`--verbose' + Verbose output: list all object files modified. In the case of + archives, `strip -v' lists all members of the archive. + + +File: binutils.info, Node: c++filt, Next: nlmconv, Prev: strip, Up: Top + +c++filt +******* + + c++filt [ -_ | --strip-underscores ] + [ -n | --no-strip-underscores ] + [ -s FORMAT | --format=FORMAT ] + [ --help ] [ --version ] [ SYMBOL... ] + + The C++ language provides function overloading, which means that you +can write many functions with the same name (providing each takes +parameters of different types). All C++ function names are encoded +into a low-level assembly label (this process is known as "mangling"). +The `c++filt' program does the inverse mapping: it decodes +("demangles") low-level names into user-level names so that the linker +can keep these overloaded functions from clashing. + + Every alphanumeric word (consisting of letters, digits, underscores, +dollars, or periods) seen in the input is a potential label. If the +label decodes into a C++ name, the C++ name replaces the low-level name +in the output. + + You can use `c++filt' to decipher individual symbols: + + c++filt SYMBOL + + If no SYMBOL arguments are given, `c++filt' reads symbol names from +the standard input and writes the demangled names to the standard +output. All results are printed on the standard output. + +`-_' +`--strip-underscores' + On some systems, both the C and C++ compilers put an underscore in + front of every name. For example, the C name `foo' gets the + low-level name `_foo'. This option removes the initial + underscore. Whether `c++filt' removes the underscore by default + is target dependent. + +`-n' +`--no-strip-underscores' + Do not remove the initial underscore. + +`-s FORMAT' +`--format=FORMAT' + GNU `nm' can decode three different methods of mangling, used by + different C++ compilers. The argument to this option selects which + method it uses: + + `gnu' + the one used by the GNU compiler (the default method) + + `lucid' + the one used by the Lucid compiler + + `arm' + the one specified by the C++ Annotated Reference Manual + +`--help' + Print a summary of the options to `c++filt' and exit. + +`--version' + Print the version number of `c++filt' and exit. + + *Warning:* `c++filt' is a new utility, and the details of its user + interface are subject to change in future releases. In particular, + a command-line option may be required in the the future to decode + a name passed as an argument on the command line; in other words, + + c++filt SYMBOL + + may in a future release become + + c++filt OPTION SYMBOL + + +File: binutils.info, Node: nlmconv, Next: Selecting The Target System, Prev: c++filt, Up: Top + +nlmconv +******* + + `nlmconv' converts a relocatable object file into a NetWare Loadable +Module. + + *Warning:* `nlmconv' is not always built as part of the binary + utilities, since it is only useful for NLM targets. + + nlmconv [ -I BFDNAME | --input-target=BFDNAME ] + [ -O BFDNAME | --output-target=BFDNAME ] + [ -T HEADERFILE | --header-file=HEADERFILE ] + [ -d | --debug] [ -l LINKER | --linker=LINKER ] + [ -h | --help ] [ -V | --version ] + INFILE OUTFILE + + `nlmconv' converts the relocatable `i386' object file INFILE into +the NetWare Loadable Module OUTFILE, optionally reading HEADERFILE for +NLM header information. For instructions on writing the NLM command +file language used in header files, see the `linkers' section, +`NLMLINK' in particular, of the `NLM Development and Tools Overview', +which is part of the NLM Software Developer's Kit ("NLM SDK"), +available from Novell, Inc. `nlmconv' uses the GNU Binary File +Descriptor library to read INFILE; see *Note BFD: (ld.info)BFD, for +more information. + + `nlmconv' can perform a link step. In other words, you can list +more than one object file for input if you list them in the definitions +file (rather than simply specifying one input file on the command line). +In this case, `nlmconv' calls the linker for you. + +`-I BFDNAME' +`--input-target=BFDNAME' + Object format of the input file. `nlmconv' can usually determine + the format of a given file (so no default is necessary). *Note + Target Selection::, for more information. + +`-O BFDNAME' +`--output-target=BFDNAME' + Object format of the output file. `nlmconv' infers the output + format based on the input format, e.g. for a `i386' input file the + output format is `nlm32-i386'. *Note Target Selection::, for more + information. + +`-T HEADERFILE' +`--header-file=HEADERFILE' + Reads HEADERFILE for NLM header information. For instructions on + writing the NLM command file language used in header files, see + see the `linkers' section, of the `NLM Development and Tools + Overview', which is part of the NLM Software Developer's Kit, + available from Novell, Inc. + +`-d' +`--debug' + Displays (on standard error) the linker command line used by + `nlmconv'. + +`-l LINKER' +`--linker=LINKER' + Use LINKER for any linking. LINKER can be an abosolute or a + relative pathname. + +`-h' +`--help' + Prints a usage summary. + +`-V' +`--version' + Prints the version number for `nlmconv'. + + +File: binutils.info, Node: Selecting The Target System, Next: Index, Prev: nlmconv, Up: Top + +Selecting the target system +*************************** + + You can specify three aspects of the target system to the GNU binary +file utilities, each in several ways: + + * the target + + * the architecture + + * the linker emulation (which applies to the linker only) + + In the following summaries, the lists of ways to specify values are +in order of decreasing precedence. The ways listed first override those +listed later. + + The commands to list valid values only list the values for which the +programs you are running were configured. If they were configured with +`--enable-targets=all', the commands list most of the available values, +but a few are left out; not all targets can be configured in at once +because some of them can only be configured "native" (on hosts with the +same type as the target system). + +* Menu: + +* Target Selection:: +* Architecture Selection:: +* Linker Emulation Selection:: + + +File: binutils.info, Node: Target Selection, Next: Architecture Selection, Up: Selecting The Target System + +Target Selection +================ + + A "target" is an object file format. A given target may be +supported for multiple architectures (*note Architecture Selection::.). +A target selection may also have variations for different operating +systems or architectures. + + The command to list valid target values is `objdump -i' (the first +column of output contains the relevant information). + + Some sample values are: `a.out-hp300bsd', `ecoff-littlemips', +`a.out-sunos-big'. + +`objdump' Target +---------------- + + Ways to specify: + + 1. command line option: `-b' or `--target' + + 2. environment variable `GNUTARGET' + + 3. deduced from the input file + +`objcopy' and `strip' Input Target +---------------------------------- + + Ways to specify: + + 1. command line options: `-I' or `--input-target', or `-F' or + `--target' + + 2. environment variable `GNUTARGET' + + 3. deduced from the input file + +`objcopy' and `strip' Output Target +----------------------------------- + + Ways to specify: + + 1. command line options: `-O' or `--output-target', or `-F' or + `--target' + + 2. the input target (see "`objcopy' and `strip' Input Target" above) + + 3. environment variable `GNUTARGET' + + 4. deduced from the input file + +`nm', `size', and `strings' Target +---------------------------------- + + Ways to specify: + + 1. command line option: `--target' + + 2. environment variable `GNUTARGET' + + 3. deduced from the input file + +Linker Input Target +------------------- + + Ways to specify: + + 1. command line option: `-b' or `--format' (*note Options: + (ld.info)Options.) + + 2. script command `TARGET' (*note Option Commands: (ld.info)Option + Commands.) + + 3. environment variable `GNUTARGET' (*note Environment: + (ld.info)Environment.) + + 4. the default target of the selected linker emulation (*note Linker + Emulation Selection::.) + +Linker Output Target +-------------------- + + Ways to specify: + + 1. command line option: `-oformat' (*note Options: (ld.info)Options.) + + 2. script command `OUTPUT_FORMAT' (*note Option Commands: + (ld.info)Option Commands.) + + 3. the linker input target (see "Linker Input Target" above) + + +File: binutils.info, Node: Architecture Selection, Next: Linker Emulation Selection, Prev: Target Selection, Up: Selecting The Target System + +Architecture selection +====================== + + An "architecture" is a type of CPU on which an object file is to +run. Its name may contain a colon, separating the name of the +processor family from the name of the particular CPU. + + The command to list valid architecture values is `objdump -i' (the +second column contains the relevant information). + + Sample values: `m68k:68020', `mips:3000', `sparc'. + +`objdump' Architecture +---------------------- + + Ways to specify: + + 1. command line option: `-m' or `--architecture' + + 2. deduced from the input file + +`objcopy', `nm', `size', `strings' Architecture +----------------------------------------------- + + Ways to specify: + + 1. deduced from the input file + +Linker Input Architecture +------------------------- + + Ways to specify: + + 1. deduced from the input file + +Linker Output Architecture +-------------------------- + + Ways to specify: + + 1. script command `OUTPUT_ARCH' (*note Option Commands: + (ld.info)Option Commands.) + + 2. the default architecture from the linker output target (*note + Target Selection::.) + + +File: binutils.info, Node: Linker Emulation Selection, Prev: Architecture Selection, Up: Selecting The Target System + +Linker emulation selection +========================== + + A linker "emulation" is a "personality" of the linker, which gives +the linker default values for the other aspects of the target system. +In particular, it consists of + + * the linker script + + * the target + + * several "hook" functions that are run at certain stages of the + linking process to do special things that some targets require + + The command to list valid linker emulation values is `ld -V'. + + Sample values: `hp300bsd', `mipslit', `sun4'. + + Ways to specify: + + 1. command line option: `-m' (*note Options: (ld.info)Options.) + + 2. environment variable `LDEMULATION' + + 3. compiled-in `DEFAULT_EMULATION' from `Makefile', which comes from + `EMUL' in `config/TARGET.mt' + + +File: binutils.info, Node: Index, Prev: Selecting The Target System, Up: Top + +Index +***** + +* Menu: + +* .stab: objdump. +* ar compatibility: ar. +* nm compatibility: nm. +* nm compatibility: nm. +* nm format: nm. +* nm format: nm. +* size display format: size. +* size number format: size. +* all header information, object file: objdump. +* ar: ar. +* architecture: objdump. +* architectures available: objdump. +* archive contents: ranlib. +* archive headers: objdump. +* archives: ar. +* c++filt: c++filt. +* collections of files: ar. +* compatibility, ar: ar. +* contents of archive: ar cmdline. +* creating archives: ar cmdline. +* dates in archive: ar cmdline. +* debug symbols: objdump. +* debugging symbols: nm. +* deleting from archive: ar cmdline. +* demangling C++ symbols: c++filt. +* demangling C++ symbols: nm. +* disassembling object code: objdump. +* disassembly, with source: objdump. +* discarding symbols: strip. +* dynamic relocation entries, in object file: objdump. +* dynamic symbol table entries, printing: objdump. +* dynamic symbols: nm. +* ELF object file format: objdump. +* external symbols: nm. +* external symbols: nm. +* extract from archive: ar cmdline. +* file name: nm. +* header information, all: objdump. +* input file name: nm. +* libraries: ar. +* listings strings: strings. +* machine instructions: objdump. +* moving in archive: ar cmdline. +* MRI compatibility, ar: ar scripts. +* name duplication in archive: ar cmdline. +* name length: ar. +* nm: nm. +* objdump: objdump. +* object code format: size. +* object code format: nm. +* object code format: objdump. +* object code format: strings. +* object file header: objdump. +* object file information: objdump. +* object file sections: objdump. +* object formats available: objdump. +* operations on archive: ar cmdline. +* printing from archive: ar cmdline. +* printing strings: strings. +* quick append to archive: ar cmdline. +* radix for section sizes: size. +* ranlib: ranlib. +* relative placement in archive: ar cmdline. +* relocation entries, in object file: objdump. +* removing symbols: strip. +* repeated names in archive: ar cmdline. +* replacement in archive: ar cmdline. +* scripts, ar: ar scripts. +* section headers: objdump. +* section information: objdump. +* section sizes: size. +* sections, full contents: objdump. +* size: size. +* sorting symbols: nm. +* source disassembly: objdump. +* source file name: nm. +* source filenames for object files: objdump. +* stab: objdump. +* start-address: objdump. +* stop-address: objdump. +* strings: strings. +* strings, printing: strings. +* strip: strip. +* symbol index: ar. +* symbol index: ranlib. +* symbol index, listing: nm. +* symbol table entries, printing: objdump. +* symbols: nm. +* symbols, discarding: strip. +* undefined symbols: nm. +* Unix compatibility, ar: ar cmdline. +* updating an archive: ar cmdline. +* version: Top. +* wide output, printing: objdump. +* writing archive index: ar cmdline. + + + +Tag Table: +Node: Top967 +Node: ar1892 +Node: ar cmdline4058 +Node: ar scripts10818 +Node: nm16499 +Node: objcopy20615 +Node: objdump28342 +Node: ranlib34411 +Node: size35145 +Node: strings37812 +Node: strip39637 +Node: c++filt42313 +Node: nlmconv44872 +Node: Selecting The Target System47495 +Node: Target Selection48503 +Node: Architecture Selection50751 +Node: Linker Emulation Selection51983 +Node: Index52861 + +End Tag Table diff --git a/gnu/usr.bin/binutils/binutils/binutils.texi b/gnu/usr.bin/binutils/binutils/binutils.texi new file mode 100644 index 00000000000..62bc2cc8782 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/binutils.texi @@ -0,0 +1,1863 @@ +\input texinfo @c -*- Texinfo -*- +@setfilename binutils.info +@include config.texi + +@ifinfo +@format +START-INFO-DIR-ENTRY +* Binutils: (binutils). The GNU binary utilities "ar", "objcopy", + "objdump", "nm", "nlmconv", "size", + "strings", "strip", and "ranlib". +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@ifinfo +Copyright @copyright{} 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 a 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 + +@synindex ky cp +@c +@c This file documents the GNU binary utilities "ar", "ld", "objcopy", +@c "objdump", "nm", "size", "strings", "strip", and "ranlib". +@c +@c Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +@c +@c This text may be freely distributed under the terms of the GNU +@c General Public License. +@c + +@setchapternewpage odd +@settitle @sc{gnu} Binary Utilities +@titlepage +@finalout +@title The @sc{gnu} Binary Utilities +@subtitle Version @value{VERSION} +@sp 1 +@subtitle May 1993 +@author Roland H. Pesch +@author Jeffrey M. Osier +@author Cygnus Support +@page + +@tex +{\parskip=0pt \hfill Cygnus Support\par \hfill +\TeX{}info \texinfoversion\par } +@end tex + +@vskip 0pt plus 1filll +Copyright @copyright{} 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. + +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 + +@node Top +@top Introduction + +@cindex version +This brief manual contains preliminary documentation for the @sc{gnu} binary +utilities (collectively version @value{VERSION}): + +@iftex +@table @code +@item ar +Create, modify, and extract from archives + +@item nm +List symbols from object files + +@item objcopy +Copy and translate object files + +@item objdump +Display information from object files + +@item ranlib +Generate index to archive contents + +@item size +List file section sizes and total size + +@item strings +List printable strings from files + +@item strip +Discard symbols + +@item c++filt +Demangle encoded C++ symbols + +@item nlmconv +Convert object code into a Netware Loadable Module +@end table +@end iftex + +@menu +* ar:: Create, modify, and extract from archives +* nm:: List symbols from object files +* objcopy:: Copy and translate object files +* objdump:: Display information from object files +* ranlib:: Generate index to archive contents +* size:: List section sizes and total size +* strings:: List printable strings from files +* strip:: Discard symbols +* c++filt:: Filter to demangle encoded C++ symbols +* nlmconv:: Converts object code into an NLM +* Selecting The Target System:: How these utilities determine the target. +* Index:: +@end menu + +@node ar +@chapter ar + +@kindex ar +@cindex archives +@cindex collections of files +@smallexample +ar [-]@var{p}[@var{mod} [@var{relpos}]] @var{archive} [@var{member}@dots{}] +ar -M [ }), and continues executing even after +errors. If you redirect standard input to a script file, no prompts are +issued, and @code{ar} abandons execution (with a nonzero exit code) +on any error. + +The @code{ar} command language is @emph{not} designed to be equivalent +to the command-line options; in fact, it provides somewhat less control +over archives. The only purpose of the command language is to ease the +transition to @sc{gnu} @code{ar} for developers who already have scripts +written for the MRI ``librarian'' program. + +The syntax for the @code{ar} command language is straightforward: +@itemize @bullet +@item +commands are recognized in upper or lower case; for example, @code{LIST} +is the same as @code{list}. In the following descriptions, commands are +shown in upper case for clarity. + +@item +a single command may appear on each line; it is the first word on the +line. + +@item +empty lines are allowed, and have no effect. + +@item +comments are allowed; text after either of the characters @samp{*} +or @samp{;} is ignored. + +@item +Whenever you use a list of names as part of the argument to an @code{ar} +command, you can separate the individual names with either commas or +blanks. Commas are shown in the explanations below, for clarity. + +@item +@samp{+} is used as a line continuation character; if @samp{+} appears +at the end of a line, the text on the following line is considered part +of the current command. +@end itemize + +Here are the commands you can use in @code{ar} scripts, or when using +@code{ar} interactively. Three of them have special significance: + +@code{OPEN} or @code{CREATE} specify a @dfn{current archive}, which is +a temporary file required for most of the other commands. + +@code{SAVE} commits the changes so far specified by the script. Prior +to @code{SAVE}, commands affect only the temporary copy of the current +archive. + +@table @code +@item ADDLIB @var{archive} +@itemx ADDLIB @var{archive} (@var{module}, @var{module}, @dots{} @var{module}) +Add all the contents of @var{archive} (or, if specified, each named +@var{module} from @var{archive}) to the current archive. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item ADDMOD @var{member}, @var{member}, @dots{} @var{member} +@c FIXME! w/Replacement?? If so, like "ar r @var{archive} @var{names}" +@c else like "ar q..." +Add each named @var{member} as a module in the current archive. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item CLEAR +Discard the contents of the current archive, cancelling the effect of +any operations since the last @code{SAVE}. May be executed (with no +effect) even if no current archive is specified. + +@item CREATE @var{archive} +Creates an archive, and makes it the current archive (required for many +other commands). The new archive is created with a temporary name; it +is not actually saved as @var{archive} until you use @code{SAVE}. +You can overwrite existing archives; similarly, the contents of any +existing file named @var{archive} will not be destroyed until @code{SAVE}. + +@item DELETE @var{module}, @var{module}, @dots{} @var{module} +Delete each listed @var{module} from the current archive; equivalent to +@samp{ar -d @var{archive} @var{module} @dots{} @var{module}}. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item DIRECTORY @var{archive} (@var{module}, @dots{} @var{module}) +@itemx DIRECTORY @var{archive} (@var{module}, @dots{} @var{module}) @var{outputfile} +List each named @var{module} present in @var{archive}. The separate +command @code{VERBOSE} specifies the form of the output: when verbose +output is off, output is like that of @samp{ar -t @var{archive} +@var{module}@dots{}}. When verbose output is on, the listing is like +@samp{ar -tv @var{archive} @var{module}@dots{}}. + +Output normally goes to the standard output stream; however, if you +specify @var{outputfile} as a final argument, @code{ar} directs the +output to that file. + +@item END +Exit from @code{ar}, with a @code{0} exit code to indicate successful +completion. This command does not save the output file; if you have +changed the current archive since the last @code{SAVE} command, those +changes are lost. + +@item EXTRACT @var{module}, @var{module}, @dots{} @var{module} +Extract each named @var{module} from the current archive, writing them +into the current directory as separate files. Equivalent to @samp{ar -x +@var{archive} @var{module}@dots{}}. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@ignore +@c FIXME Tokens but no commands??? +@item FULLDIR + +@item HELP +@end ignore + +@item LIST +Display full contents of the current archive, in ``verbose'' style +regardless of the state of @code{VERBOSE}. The effect is like @samp{ar +tv @var{archive}}). (This single command is a @sc{gnu} @code{ld} +enhancement, rather than present for MRI compatibility.) + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item OPEN @var{archive} +Opens an existing archive for use as the current archive (required for +many other commands). Any changes as the result of subsequent commands +will not actually affect @var{archive} until you next use @code{SAVE}. + +@item REPLACE @var{module}, @var{module}, @dots{} @var{module} +In the current archive, replace each existing @var{module} (named in +the @code{REPLACE} arguments) from files in the current working directory. +To execute this command without errors, both the file, and the module in +the current archive, must exist. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item VERBOSE +Toggle an internal flag governing the output from @code{DIRECTORY}. +When the flag is on, @code{DIRECTORY} output matches output from +@samp{ar -tv }@dots{}. + +@item SAVE +Commit your changes to the current archive, and actually save it as a +file with the name specified in the last @code{CREATE} or @code{OPEN} +command. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@end table + +@iftex +@node ld +@chapter ld +@cindex linker +@kindex ld +The @sc{gnu} linker @code{ld} is now described in a separate manual. +@xref{Top,, Overview,, Using LD: the @sc{gnu} linker}. +@end iftex + +@node nm +@chapter nm +@cindex symbols +@kindex nm + +@smallexample +nm [ -a | --debug-syms ] [ -g | --extern-only ] + [ -B ] [ -C | --demangle ] [ -D | --dynamic ] + [ -s | --print-armap ] [ -A | -o | --print-file-name ] + [ -n | -v | --numeric-sort ] [ -p | --no-sort ] + [ -r | --reverse-sort ] [ --size-sort ] [ -u | --undefined-only ] + [ -t @var{radix} | --radix=@var{radix} ] [ -P | --portability ] + [ --target=@var{bfdname} ] [ -f @var{format} | --format=@var{format} ] + [ --no-demangle ] [ -V | --version ] [ --help ] [ @var{objfile}@dots{} ] +@end smallexample + +@sc{gnu} @code{nm} lists the symbols from object files @var{objfile}@dots{}. +If no object files are listed as arguments, @code{nm} assumes +@file{a.out}. + +For each symbol, @code{nm} shows: + +@itemize @bullet +@item +The symbol value, in the radix selected by options (see below), or +hexadecimal by default. + +@item +The symbol type. At least the following types are used; others are, as +well, depending on the object file format. If lowercase, the symbol is +local; if uppercase, the symbol is global (external). + +@c Some more detail on exactly what these symbol types are used for +@c would be nice. +@table @code +@item A +Absolute. + +@item B +BSS (uninitialized data). + +@item C +Common. + +@item D +Initialized data. + +@item I +Indirect reference. + +@item T +Text (program code). + +@item U +Undefined. +@end table + +@item +The symbol name. +@end itemize + +The long and short forms of options, shown here as alternatives, are +equivalent. + +@table @code +@item -A +@itemx -o +@itemx --print-file-name +@cindex input file name +@cindex file name +@cindex source file name +Precede each symbol by the name of the input file (or archive element) +in which it was found, rather than identifying the input file once only, +before all of its symbols. + +@item -a +@itemx --debug-syms +@cindex debugging symbols +Display all symbols, even debugger-only symbols; normally these are not +listed. + +@item -B +@cindex @code{nm} format +@cindex @code{nm} compatibility +The same as @samp{--format=bsd} (for compatibility with the MIPS @code{nm}). + +@item -C +@itemx --demangle +@cindex demangling C++ symbols +Decode (@dfn{demangle}) low-level symbol names into user-level names. +Besides removing any initial underscore prepended by the system, this +makes C++ function names readable. @xref{c++filt}, for more information +on demangling. + +@item --no-demangle +Do not demangle low-level symbol names. This is the default. + +@item -D +@itemx --dynamic +@cindex dynamic symbols +Display the dynamic symbols rather than the normal symbols. This is +only meaningful for dynamic objects, such as certain types of shared +libraries. + +@item -f @var{format} +@itemx --format=@var{format} +@cindex @code{nm} format +@cindex @code{nm} compatibility +Use the output format @var{format}, which can be @code{bsd}, +@code{sysv}, or @code{posix}. The default is @code{bsd}. +Only the first character of @var{format} is significant; it can be +either upper or lower case. + +@item -g +@itemx --extern-only +@cindex external symbols +Display only external symbols. + +@item -n +@itemx -v +@itemx --numeric-sort +Sort symbols numerically by their addresses, rather than alphabetically +by their names. + +@item -p +@itemx --no-sort +@cindex sorting symbols +Do not bother to sort the symbols in any order; print them in the order +encountered. + +@item -P +@itemx --portability +Use the POSIX.2 standard output format instead of the default format. +Equivalent to @samp{-f posix}. + +@item -s +@itemx --print-armap +@cindex symbol index, listing +When listing symbols from archive members, include the index: a mapping +(stored in the archive by @code{ar} or @code{ranlib}) of which modules +contain definitions for which names. + +@item -r +@itemx --reverse-sort +Reverse the order of the sort (whether numeric or alphabetic); let the +last come first. + +@item --size-sort +Sort symbols by size. The size is computed as the difference between +the value of the symbol and the value of the symbol with the next higher +value. The size of the symbol is printed, rather than the value. + +@item -t @var{radix} +@itemx --radix=@var{radix} +Use @var{radix} as the radix for printing the symbol values. It must be +@samp{d} for decimal, @samp{o} for octal, or @samp{x} for hexadecimal. + +@item --target=@var{bfdname} +@cindex object code format +Specify an object code format other than your system's default format. +@xref{Target Selection}, for more information. + +@item -u +@itemx --undefined-only +@cindex external symbols +@cindex undefined symbols +Display only undefined symbols (those external to each object file). + +@item -V +@itemx --version +Show the version number of @code{nm} and exit. + +@item --help +Show a summary of the options to @code{nm} and exit. +@end table + +@node objcopy +@chapter objcopy + +@smallexample +objcopy [ -F @var{bfdname} | --target=@var{bfdname} ] + [ -I @var{bfdname} | --input-target=@var{bfdname} ] + [ -O @var{bfdname} | --output-target=@var{bfdname} ] + [ -S | --strip-all ] [ -g | --strip-debug ] + [ -K @var{symbolname} | --keep-symbol=@var{symbolname} ] + [ -N @var{symbolname} | --strip-symbol=@var{symbolname} ] + [ -x | --discard-all ] [ -X | --discard-locals ] + [ -b @var{byte} | --byte=@var{byte} ] + [ -i @var{interleave} | --interleave=@var{interleave} ] + [ -R @var{sectionname} | --remove-section=@var{sectionname} ] + [ --gap-fill=@var{val} ] [ --pad-to=@var{address} ] + [ --set-start=@var{val} ] [ --adjust-start=@var{incr} ] + [ --adjust-vma=@var{incr} ] + [ --adjust-section-vma=@var{section}@{=,+,-@}@var{val} ] + [ --adjust-warnings ] [ --no-adjust-warnings ] + [ --set-section-flags=@var{section}=@var{flags} ] + [ --add-section=@var{sectionname}=@var{filename} ] + [ -v | --verbose ] [ -V | --version ] [ --help ] + @var{infile} [@var{outfile}] +@end smallexample + +The @sc{gnu} @code{objcopy} utility copies the contents of an object +file to another. @code{objcopy} uses the @sc{gnu} @sc{bfd} Library to +read and write the object files. It can write the destination object +file in a format different from that of the source object file. The +exact behavior of @code{objcopy} is controlled by command-line options. + +@code{objcopy} creates temporary files to do its translations and +deletes them afterward. @code{objcopy} uses @sc{bfd} to do all its +translation work; it has access to all the formats described in @sc{bfd} +and thus is able to recognize most formats without being told +explicitly. @xref{BFD,,BFD,ld.info,Using LD}. + +@code{objcopy} can be used to generate S-records by using an output +target of @samp{srec} (e.g., use @samp{-O srec}). + +@code{objcopy} can be used to generate a raw binary file by using an +output target of @samp{binary} (e.g., use @samp{-O binary}). When +@code{objcopy} generates a raw binary file, it will essentially produce +a memory dump of the contents of the input object file. All symbols and +relocation information will be discarded. The memory dump will start at +the virtual address of the lowest section copied into the output file. + +When generating an S-record or a raw binary file, it may be helpful to +use @samp{-S} to remove sections containing debugging information. In +some cases @samp{-R} will be useful to remove sections which contain +information which is not needed by the binary file. + +@table @code +@item @var{infile} +@itemx @var{outfile} +The source and output files, respectively. +If you do not specify @var{outfile}, @code{objcopy} creates a +temporary file and destructively renames the result with +the name of @var{infile}. + +@item -I @var{bfdname} +@itemx --input-target=@var{bfdname} +Consider the source file's object format to be @var{bfdname}, rather than +attempting to deduce it. @xref{Target Selection}, for more information. + +@item -O @var{bfdname} +@itemx --output-target=@var{bfdname} +Write the output file using the object format @var{bfdname}. +@xref{Target Selection}, for more information. + +@item -F @var{bfdname} +@itemx --target=@var{bfdname} +Use @var{bfdname} as the object format for both the input and the output +file; i.e., simply transfer data from source to destination with no +translation. @xref{Target Selection}, for more information. + +@item -R @var{sectionname} +@itemx --remove-section=@var{sectionname} +Remove any section named @var{sectionname} from the output file. This +option may be given more than once. Note that using this option +inappropriately may make the output file unusable. + +@item -S +@itemx --strip-all +Do not copy relocation and symbol information from the source file. + +@item -g +@itemx --strip-debug +Do not copy debugging symbols from the source file. + +@item --strip-unneeded +Strip all symbols that are not needed for relocation processing. + +@item -K @var{symbolname} +@itemx --keep-symbol=@var{symbolname} +Copy only symbol @var{symbolname} from the source file. This option may +be given more than once. + +@item -N @var{symbolname} +@itemx --strip-symbol=@var{symbolname} +Do not copy symbol @var{symbolname} from the source file. This option +may be given more than once, and may be combined with strip options +other than @code{-K}. + +@item -x +@itemx --discard-all +Do not copy non-global symbols from the source file. +@c FIXME any reason to prefer "non-global" to "local" here? + +@item -X +@itemx --discard-locals +Do not copy compiler-generated local symbols. +(These usually start with @samp{L} or @samp{.}.) + +@item -b @var{byte} +@itemx --byte=@var{byte} +Keep only every @var{byte}th byte of the input file (header data is not +affected). @var{byte} can be in the range from 0 to @var{interleave}-1, +where @var{interleave} is given by the @samp{-i} or @samp{--interleave} +option, or the default of 4. This option is useful for creating files +to program @sc{rom}. It is typically used with an @code{srec} output +target. + +@item -i @var{interleave} +@itemx --interleave=@var{interleave} +Only copy one out of every @var{interleave} bytes. Select which byte to +copy with the @var{-b} or @samp{--byte} option. The default is 4. +@code{objcopy} ignores this option if you do not specify either @samp{-b} or +@samp{--byte}. + +@item --gap-fill @var{val} +Fill gaps between sections with @var{val}. This is done by increasing +the size of the section with the lower address, and filling in the extra +space created with @var{val}. + +@item --pad-to @var{address} +Pad the output file up to the virtual address @var{address}. This is +done by increasing the size of the last section. The extra space is +filled in with the value specified by @samp{--gap-fill} (default zero). + +@item --set-start @var{val} +Set the address of the new file to @var{val}. Not all object file +formats support setting the start address. + +@item --adjust-start @var{incr} +Adjust the start address by adding @var{incr}. Not all object file +formats support setting the start address. + +@item --adjust-vma @var{incr} +Adjust the address of all sections, as well as the start address, by +adding @var{incr}. Some object file formats do not permit section +addresses to be changed arbitrarily. Note that this does not relocate +the sections; if the program expects sections to be loaded at a certain +address, and this option is used to change the sections such that they +are loaded at a different address, the program may fail. + +@item --adjust-section-vma @var{section}@{=,+,-@}@var{val} +Set or adjust the address of the named @var{section}. If @samp{=} is +used, the section address is set to @var{val}. Otherwise, @var{val} is +added to or subtracted from the section address. See the comments under +@samp{--adjust-vma}, above. If @var{section} does not exist in the +input file, a warning will be issued, unless @samp{--no-adjust-warnings} +is used. + +@item --adjust-warnings +If @samp{--adjust-section-vma} is used, and the named section does not +exist, issue a warning. This is the default. + +@item --no-adjust-warnings +Do not issue a warning if @samp{--adjust-section-vma} is used, even if +the named section does not exist. + +@item --set-section-flags @var{section}=@var{flags} +Set the flags for the named section. The @var{flags} argument is a +comma separated string of flag names. The recognized names are +@samp{alloc}, @samp{load}, @samp{readonly}, @samp{code}, @samp{data}, +and @samp{rom}. Not all flags are meaningful for all object file +formats. + +@item --add-section @var{sectionname}=@var{filename} +Add a new section named @var{sectionname} while copying the file. The +contents of the new section are taken from the file @var{filename}. The +size of the section will be the size of the file. This option only +works on file formats which can support sections with arbitrary names. + +@item -V +@itemx --version +Show the version number of @code{objcopy}. + +@item -v +@itemx --verbose +Verbose output: list all object files modified. In the case of +archives, @samp{objcopy -V} lists all members of the archive. + +@item --help +Show a summary of the options to @code{objcopy}. +@end table + +@node objdump +@chapter objdump + +@cindex object file information +@kindex objdump + +@smallexample +objdump [ -a | --archive-headers ] + [ -b @var{bfdname} | --target=@var{bfdname} ] + [ -d | --disassemble ] [ -D | --disassemble-all ] + [ -f | --file-headers ] + [ -h | --section-headers | --headers ] [ -i | --info ] + [ -j @var{section} | --section=@var{section} ] + [ -l | --line-numbers ] [ -S | --source ] + [ -m @var{machine} | --architecture=@var{machine} ] + [ -r | --reloc ] [ -R | --dynamic-reloc ] + [ -s | --full-contents ] [ --stabs ] + [ -t | --syms ] [ -T | --dynamic-syms ] [ -x | --all-headers ] + [ -w | --wide ] [ --start-address=@var{address} ] + [ --stop-address=@var{address} ] [ --version ] [ --help ] + @var{objfile}@dots{} +@end smallexample + +@code{objdump} displays information about one or more object files. +The options control what particular information to display. This +information is mostly useful to programmers who are working on the +compilation tools, as opposed to programmers who just want their +program to compile and work. + +@var{objfile}@dots{} are the object files to be examined. When you +specify archives, @code{objdump} shows information on each of the member +object files. + +The long and short forms of options, shown here as alternatives, are +equivalent. At least one option besides @samp{-l} must be given. + +@table @code +@item -a +@itemx --archive-header +@cindex archive headers +If any of the @var{objfile} files are archives, display the archive +header information (in a format similar to @samp{ls -l}). Besides the +information you could list with @samp{ar tv}, @samp{objdump -a} shows +the object file format of each archive member. + +@item -b @var{bfdname} +@itemx --target=@var{bfdname} +@cindex object code format +Specify that the object-code format for the object files is +@var{bfdname}. This option may not be necessary; @var{objdump} can +automatically recognize many formats. + +For example, +@example +objdump -b oasys -m vax -h fu.o +@end example +@noindent +displays summary information from the section headers (@samp{-h}) of +@file{fu.o}, which is explicitly identified (@samp{-m}) as a VAX object +file in the format produced by Oasys compilers. You can list the +formats available with the @samp{-i} option. +@xref{Target Selection}, for more information. + +@item -d +@itemx --disassemble +@cindex disassembling object code +@cindex machine instructions +Display the assembler mnemonics for the machine instructions from +@var{objfile}. This option only disassembles those sections which are +expected to contain instructions. + +@item -D +@itemx --disassemble-all +Like @samp{-d}, but disassemble the contents of all sections, not just +those expected to contain instructions. + +@item -f +@itemx --file-header +@cindex object file header +Display summary information from the overall header of +each of the @var{objfile} files. + +@item -h +@itemx --section-header +@itemx --header +@cindex section headers +Display summary information from the section headers of the +object file. + +File segments may be relocated to nonstandard addresses, for example by +using the @samp{-Ttext}, @samp{-Tdata}, or @samp{-Tbss} options to +@code{ld}. However, some object file formats, such as a.out, do not +store the starting address of the file segments. In those situations, +although @code{ld} relocates the sections correctly, using @samp{objdump +-h} to list the file section headers cannot show the correct addresses. +Instead, it shows the usual addresses, which are implicit for the +target. + +@item --help +Print a summary of the options to @code{objdump} and exit. + +@item -i +@itemx --info +@cindex architectures available +@cindex object formats available +Display a list showing all architectures and object formats available +for specification with @samp{-b} or @samp{-m}. + +@item -j @var{name} +@itemx --section=@var{name} +@cindex section information +Display information only for section @var{name}. + +@item -l +@itemx --line-numbers +@cindex source filenames for object files +Label the display (using debugging information) with the filename +and source line numbers corresponding to the object code shown. +Only useful with @samp{-d} or @samp{-D}. + +@item -m @var{machine} +@itemx --architecture=@var{machine} +@cindex architecture +Specify that the object files @var{objfile} are for architecture +@var{machine}. You can list available architectures using the @samp{-i} +option. + +@item -r +@itemx --reloc +@cindex relocation entries, in object file +Print the relocation entries of the file. If used with @samp{-d} or +@samp{-D}, the relocations are printed interspersed with the +disassembly. + +@item -R +@itemx --dynamic-reloc +@cindex dynamic relocation entries, in object file +Print the dynamic relocation entries of the file. This is only +meaningful for dynamic objects, such as certain types of shared +libraries. + +@item -s +@itemx --full-contents +@cindex sections, full contents +@cindex object file sections +Display the full contents of any sections requested. + +@item -S +@itemx --source +@cindex source disassembly +@cindex disassembly, with source +Display source code intermixed with disassembly, if possible. Implies +@samp{-d}. + +@item --stabs +@cindex stab +@cindex .stab +@cindex debug symbols +@cindex ELF object file format +Display the full contents of any sections requested. Display the +contents of the .stab and .stab.index and .stab.excl sections from an +ELF file. This is only useful on systems (such as Solaris 2.0) in which +@code{.stab} debugging symbol-table entries are carried in an ELF +section. In most other file formats, debugging symbol-table entries are +interleaved with linkage symbols, and are visible in the @samp{--syms} +output. + +@item --start-address=@var{address} +@cindex start-address +Start displaying data at the specified address. This affects the output +of the @code{-d}, @code{-r} and @code{-s} options. + +@item --stop-address=@var{address} +@cindex stop-address +Stop displaying data at the specified address. This affects the output +of the @code{-d}, @code{-r} and @code{-s} options. + +@item -t +@itemx --syms +@cindex symbol table entries, printing +Print the symbol table entries of the file. +This is similar to the information provided by the @samp{nm} program. + +@item -T +@itemx --dynamic-syms +@cindex dynamic symbol table entries, printing +Print the dynamic symbol table entries of the file. This is only +meaningful for dynamic objects, such as certain types of shared +libraries. This is similar to the information provided by the @samp{nm} +program when given the @samp{-D} (@samp{--dynamic}) option. + +@item --version +Print the version number of @code{objdump} and exit. + +@item -x +@itemx --all-header +@cindex all header information, object file +@cindex header information, all +Display all available header information, including the symbol table and +relocation entries. Using @samp{-x} is equivalent to specifying all of +@samp{-a -f -h -r -t}. + +@item -w +@item --wide +@cindex wide output, printing +Format some lines for output devices that have more than 80 columns. +@end table + +@node ranlib +@chapter ranlib + +@kindex ranlib +@cindex archive contents +@cindex symbol index + +@smallexample +ranlib [-vV] @var{archive} +@end smallexample + +@code{ranlib} generates an index to the contents of an archive and +stores it in the archive. The index lists each symbol defined by a +member of an archive that is a relocatable object file. + +You may use @samp{nm -s} or @samp{nm --print-armap} to list this index. + +An archive with such an index speeds up linking to the library and +allows routines in the library to call each other without regard to +their placement in the archive. + +The @sc{gnu} @code{ranlib} program is another form of @sc{gnu} @code{ar}; running +@code{ranlib} is completely equivalent to executing @samp{ar -s}. +@xref{ar}. + +@table @code +@item -v +@itemx -V +Show the version number of @code{ranlib}. +@end table + +@node size +@chapter size + +@kindex size +@cindex section sizes + +@smallexample +size [ -A | -B | --format=@var{compatibility} ] + [ --help ] [ -d | -o | -x | --radix=@var{number} ] + [ --target=@var{bfdname} ] [ -V | --version ] + @var{objfile}@dots{} +@end smallexample + +The @sc{gnu} @code{size} utility lists the section sizes---and the total +size---for each of the object or archive files @var{objfile} in its +argument list. By default, one line of output is generated for each +object file or each module in an archive. + +@var{objfile}@dots{} are the object files to be examined. + +The command line options have the following meanings: + +@table @code +@item -A +@itemx -B +@itemx --format=@var{compatibility} +@cindex @code{size} display format +Using one of these options, you can choose whether the output from @sc{gnu} +@code{size} resembles output from System V @code{size} (using @samp{-A}, +or @samp{--format=sysv}), or Berkeley @code{size} (using @samp{-B}, or +@samp{--format=berkeley}). The default is the one-line format similar to +Berkeley's. +@c Bonus for doc-source readers: you can also say --format=strange (or +@c anything else that starts with 's') for sysv, and --format=boring (or +@c anything else that starts with 'b') for Berkeley. + +Here is an example of the Berkeley (default) format of output from +@code{size}: +@smallexample +size --format=Berkeley ranlib size +text data bss dec hex filename +294880 81920 11592 388392 5ed28 ranlib +294880 81920 11888 388688 5ee50 size +@end smallexample + +@noindent +This is the same data, but displayed closer to System V conventions: + +@smallexample +size --format=SysV ranlib size +ranlib : +section size addr +.text 294880 8192 +.data 81920 303104 +.bss 11592 385024 +Total 388392 + + +size : +section size addr +.text 294880 8192 +.data 81920 303104 +.bss 11888 385024 +Total 388688 +@end smallexample + +@item --help +Show a summary of acceptable arguments and options. + +@item -d +@itemx -o +@itemx -x +@itemx --radix=@var{number} +@cindex @code{size} number format +@cindex radix for section sizes +Using one of these options, you can control whether the size of each +section is given in decimal (@samp{-d}, or @samp{--radix=10}); octal +(@samp{-o}, or @samp{--radix=8}); or hexadecimal (@samp{-x}, or +@samp{--radix=16}). In @samp{--radix=@var{number}}, only the three +values (8, 10, 16) are supported. The total size is always given in two +radices; decimal and hexadecimal for @samp{-d} or @samp{-x} output, or +octal and hexadecimal if you're using @samp{-o}. + +@item --target=@var{bfdname} +@cindex object code format +Specify that the object-code format for @var{objfile} is +@var{bfdname}. This option may not be necessary; @code{size} can +automatically recognize many formats. +@xref{Target Selection}, for more information. + +@item -V +@itemx --version +Display the version number of @code{size}. +@end table + +@node strings +@chapter strings +@kindex strings +@cindex listings strings +@cindex printing strings +@cindex strings, printing + +@smallexample +strings [-afov] [-@var{min-len}] [-n @var{min-len}] [-t @var{radix}] [-] + [--all] [--print-file-name] [--bytes=@var{min-len}] + [--radix=@var{radix}] [--target=@var{bfdname}] + [--help] [--version] @var{file}@dots{} +@end smallexample + +For each @var{file} given, @sc{gnu} @code{strings} prints the printable +character sequences that are at least 4 characters long (or the number +given with the options below) and are followed by an unprintable +character. By default, it only prints the strings from the initialized +and loaded sections of object files; for other types of files, it prints +the strings from the whole file. + +@code{strings} is mainly useful for determining the contents of non-text +files. + +@table @code +@item -a +@itemx --all +@itemx - +Do not scan only the initialized and loaded sections of object files; +scan the whole files. + +@item -f +@itemx --print-file-name +Print the name of the file before each string. + +@item --help +Print a summary of the program usage on the standard output and exit. + +@itemx -@var{min-len} +@item -n @var{min-len} +@itemx --bytes=@var{min-len} +Print sequences of characters that are at least @var{min-len} characters +long, instead of the default 4. + +@item -o +Like @samp{-t o}. Some other versions of @code{strings} have @samp{-o} +act like @samp{-t d} instead. Since we can not be compatible with both +ways, we simply chose one. + +@item -t @var{radix} +@itemx --radix=@var{radix} +Print the offset within the file before each string. The single +character argument specifies the radix of the offset---@samp{o} for +octal, @samp{x} for hexadecimal, or @samp{d} for decimal. + +@item --target=@var{bfdname} +@cindex object code format +Specify an object code format other than your system's default format. +@xref{Target Selection}, for more information. + +@item -v +@itemx --version +Print the program version number on the standard output and exit. +@end table + +@node strip +@chapter strip + +@kindex strip +@cindex removing symbols +@cindex discarding symbols +@cindex symbols, discarding + +@smallexample +strip [ -F @var{bfdname} | --target=@var{bfdname} | --target=@var{bfdname} ] + [ -I @var{bfdname} | --input-target=@var{bfdname} ] + [ -O @var{bfdname} | --output-target=@var{bfdname} ] + [ -s | --strip-all ] [ -S | -g | --strip-debug ] + [ -K @var{symbolname} | --keep-symbol=@var{symbolname} ] + [ -N @var{symbolname} | --strip-symbol=@var{symbolname} ] + [ -x | --discard-all ] [ -X | --discard-locals ] + [ -R @var{sectionname} | --remove-section=@var{sectionname} ] + [ -v | --verbose ] [ -V | --version ] [ --help ] + @var{objfile}@dots{} +@end smallexample + +@sc{gnu} @code{strip} discards all symbols from object files +@var{objfile}. The list of object files may include archives. +At least one object file must be given. + +@code{strip} modifies the files named in its argument, +rather than writing modified copies under different names. + +@table @code +@item -F @var{bfdname} +@itemx --target=@var{bfdname} +Treat the original @var{objfile} as a file with the object +code format @var{bfdname}, and rewrite it in the same format. +@xref{Target Selection}, for more information. + +@item --help +Show a summary of the options to @code{strip} and exit. + +@item -I @var{bfdname} +@itemx --input-target=@var{bfdname} +Treat the original @var{objfile} as a file with the object +code format @var{bfdname}. +@xref{Target Selection}, for more information. + +@item -O @var{bfdname} +@itemx --output-target=@var{bfdname} +Replace @var{objfile} with a file in the output format @var{bfdname}. +@xref{Target Selection}, for more information. + +@item -R @var{sectionname} +@itemx --remove-section=@var{sectionname} +Remove any section named @var{sectionname} from the output file. This +option may be given more than once. Note that using this option +inappropriately may make the output file unusable. + +@item -s +@itemx --strip-all +Remove all symbols. + +@item -g +@itemx -S +@itemx --strip-debug +Remove debugging symbols only. + +@item --strip-unneeded +Remove all symbols that are not needed for relocation processing. + +@item -K @var{symbolname} +@itemx --keep-symbol=@var{symbolname} +Keep only symbol @var{symbolname} from the source file. This option may +be given more than once. + +@item -N @var{symbolname} +@itemx --strip-symbol=@var{symbolname} +Remove symbol @var{symbolname} from the source file. This option may be +given more than once, and may be combined with strip options other than +@code{-K}. + +@item -x +@itemx --discard-all +Remove non-global symbols. + +@item -X +@itemx --discard-locals +Remove compiler-generated local symbols. +(These usually start with @samp{L} or @samp{.}.) + +@item -V +@itemx --version +Show the version number for @code{strip}. + +@item -v +@itemx --verbose +Verbose output: list all object files modified. In the case of +archives, @samp{strip -v} lists all members of the archive. +@end table + +@node c++filt +@chapter c++filt + +@kindex c++filt +@cindex demangling C++ symbols + +@smallexample +c++filt [ -_ | --strip-underscores ] + [ -n | --no-strip-underscores ] + [ -s @var{format} | --format=@var{format} ] + [ --help ] [ --version ] [ @var{symbol}@dots{} ] +@end smallexample + +The C++ language provides function overloading, which means that you can +write many functions with the same name (providing each takes parameters +of different types). All C++ function names are encoded into a +low-level assembly label (this process is known as +@dfn{mangling}). The @code{c++filt} program does the inverse mapping: it +decodes (@dfn{demangles}) low-level names into user-level names so that +the linker can keep these overloaded functions from clashing. + +Every alphanumeric word (consisting of letters, digits, underscores, +dollars, or periods) seen in the input is a potential label. If the +label decodes into a C++ name, the C++ name replaces the low-level +name in the output. + +You can use @code{c++filt} to decipher individual symbols: + +@example +c++filt @var{symbol} +@end example + +If no @var{symbol} arguments are given, @code{c++filt} reads symbol +names from the standard input and writes the demangled names to the +standard output. All results are printed on the standard output. + +@table @code +@item -_ +@itemx --strip-underscores +On some systems, both the C and C++ compilers put an underscore in front +of every name. For example, the C name @code{foo} gets the low-level +name @code{_foo}. This option removes the initial underscore. Whether +@code{c++filt} removes the underscore by default is target dependent. + +@item -n +@itemx --no-strip-underscores +Do not remove the initial underscore. + +@item -s @var{format} +@itemx --format=@var{format} +@sc{gnu} @code{nm} can decode three different methods of mangling, used by +different C++ compilers. The argument to this option selects which +method it uses: + +@table @code +@item gnu +the one used by the @sc{gnu} compiler (the default method) +@item lucid +the one used by the Lucid compiler +@item arm +the one specified by the C++ Annotated Reference Manual +@end table + +@item --help +Print a summary of the options to @code{c++filt} and exit. + +@item --version +Print the version number of @code{c++filt} and exit. +@end table + +@quotation +@emph{Warning:} @code{c++filt} is a new utility, and the details of its +user interface are subject to change in future releases. In particular, +a command-line option may be required in the the future to decode a name +passed as an argument on the command line; in other words, + +@example +c++filt @var{symbol} +@end example + +@noindent +may in a future release become + +@example +c++filt @var{option} @var{symbol} +@end example +@end quotation + +@node nlmconv +@chapter nlmconv + +@code{nlmconv} converts a relocatable object file into a NetWare +Loadable Module. + +@ignore +@code{nlmconv} currently works with @samp{i386} object +files in @code{coff}, @sc{elf}, or @code{a.out} format, and @sc{SPARC} +object files in @sc{elf}, or @code{a.out} format@footnote{ +@code{nlmconv} should work with any @samp{i386} or @sc{sparc} object +format in the Binary File Descriptor library. It has only been tested +with the above formats.}. +@end ignore + +@quotation +@emph{Warning:} @code{nlmconv} is not always built as part of the binary +utilities, since it is only useful for NLM targets. +@end quotation + +@smallexample +nlmconv [ -I @var{bfdname} | --input-target=@var{bfdname} ] + [ -O @var{bfdname} | --output-target=@var{bfdname} ] + [ -T @var{headerfile} | --header-file=@var{headerfile} ] + [ -d | --debug] [ -l @var{linker} | --linker=@var{linker} ] + [ -h | --help ] [ -V | --version ] + @var{infile} @var{outfile} +@end smallexample + +@code{nlmconv} converts the relocatable @samp{i386} object file +@var{infile} into the NetWare Loadable Module @var{outfile}, optionally +reading @var{headerfile} for NLM header information. For instructions +on writing the NLM command file language used in header files, see the +@samp{linkers} section, @samp{NLMLINK} in particular, of the @cite{NLM +Development and Tools Overview}, which is part of the NLM Software +Developer's Kit (``NLM SDK''), available from Novell, Inc. +@code{nlmconv} uses the @sc{gnu} Binary File Descriptor library to read +@var{infile}; see @ref{BFD,,BFD,ld.info,Using LD}, for +more information. + +@code{nlmconv} can perform a link step. In other words, you can list +more than one object file for input if you list them in the definitions +file (rather than simply specifying one input file on the command line). +In this case, @code{nlmconv} calls the linker for you. + +@table @code +@item -I @var{bfdname} +@itemx --input-target=@var{bfdname} +Object format of the input file. @code{nlmconv} can usually determine +the format of a given file (so no default is necessary). +@xref{Target Selection}, for more information. + +@item -O @var{bfdname} +@itemx --output-target=@var{bfdname} +Object format of the output file. @code{nlmconv} infers the output +format based on the input format, e.g. for a @samp{i386} input file the +output format is @samp{nlm32-i386}. +@xref{Target Selection}, for more information. + +@item -T @var{headerfile} +@itemx --header-file=@var{headerfile} +Reads @var{headerfile} for NLM header information. For instructions on +writing the NLM command file language used in header files, see@ see the +@samp{linkers} section, of the @cite{NLM Development and Tools +Overview}, which is part of the NLM Software Developer's Kit, available +from Novell, Inc. + +@item -d +@itemx --debug +Displays (on standard error) the linker command line used by @code{nlmconv}. + +@item -l @var{linker} +@itemx --linker=@var{linker} +Use @var{linker} for any linking. @var{linker} can be an abosolute or a +relative pathname. + +@item -h +@itemx --help +Prints a usage summary. + +@item -V +@itemx --version +Prints the version number for @code{nlmconv}. +@end table + +@node Selecting The Target System +@chapter Selecting the target system + +You can specify three aspects of the target system to the @sc{gnu} +binary file utilities, each in several ways: + +@itemize @bullet +@item +the target + +@item +the architecture + +@item +the linker emulation (which applies to the linker only) +@end itemize + +In the following summaries, the lists of ways to specify values are in +order of decreasing precedence. The ways listed first override those +listed later. + +The commands to list valid values only list the values for which the +programs you are running were configured. If they were configured with +@samp{--enable-targets=all}, the commands list most of the available +values, but a few are left out; not all targets can be configured in at +once because some of them can only be configured @dfn{native} (on hosts +with the same type as the target system). + +@menu +* Target Selection:: +* Architecture Selection:: +* Linker Emulation Selection:: +@end menu + +@node Target Selection +@section Target Selection + +A @dfn{target} is an object file format. A given target may be +supported for multiple architectures (@pxref{Architecture Selection}). +A target selection may also have variations for different operating +systems or architectures. + +The command to list valid target values is @samp{objdump -i} +(the first column of output contains the relevant information). + +Some sample values are: @samp{a.out-hp300bsd}, @samp{ecoff-littlemips}, +@samp{a.out-sunos-big}. + +@subheading @code{objdump} Target + +Ways to specify: + +@enumerate +@item +command line option: @samp{-b} or @samp{--target} + +@item +environment variable @code{GNUTARGET} + +@item +deduced from the input file +@end enumerate + +@subheading @code{objcopy} and @code{strip} Input Target + +Ways to specify: + +@enumerate +@item +command line options: @samp{-I} or @samp{--input-target}, or @samp{-F} or @samp{--target} + +@item +environment variable @code{GNUTARGET} + +@item +deduced from the input file +@end enumerate + +@subheading @code{objcopy} and @code{strip} Output Target + +Ways to specify: + +@enumerate +@item +command line options: @samp{-O} or @samp{--output-target}, or @samp{-F} or @samp{--target} + +@item +the input target (see ``@code{objcopy} and @code{strip} Input Target'' above) + +@item +environment variable @code{GNUTARGET} + +@item +deduced from the input file +@end enumerate + +@subheading @code{nm}, @code{size}, and @code{strings} Target + +Ways to specify: + +@enumerate +@item +command line option: @samp{--target} + +@item +environment variable @code{GNUTARGET} + +@item +deduced from the input file +@end enumerate + +@subheading Linker Input Target + +Ways to specify: + +@enumerate +@item +command line option: @samp{-b} or @samp{--format} +(@pxref{Options,,Options,ld.info,Using LD}) + +@item +script command @code{TARGET} +(@pxref{Option Commands,,Option Commands,ld.info,Using LD}) + +@item +environment variable @code{GNUTARGET} +(@pxref{Environment,,Environment,ld.info,Using LD}) + +@item +the default target of the selected linker emulation +(@pxref{Linker Emulation Selection}) +@end enumerate + +@subheading Linker Output Target + +Ways to specify: + +@enumerate +@item +command line option: @samp{-oformat} +(@pxref{Options,,Options,ld.info,Using LD}) + +@item +script command @code{OUTPUT_FORMAT} +(@pxref{Option Commands,,Option Commands,ld.info,Using LD}) + +@item +the linker input target (see ``Linker Input Target'' above) +@end enumerate + +@node Architecture Selection +@section Architecture selection + +An @dfn{architecture} is a type of @sc{cpu} on which an object file is +to run. Its name may contain a colon, separating the name of the +processor family from the name of the particular @sc{cpu}. + +The command to list valid architecture values is @samp{objdump -i} (the +second column contains the relevant information). + +Sample values: @samp{m68k:68020}, @samp{mips:3000}, @samp{sparc}. + +@subheading @code{objdump} Architecture + +Ways to specify: + +@enumerate +@item +command line option: @samp{-m} or @samp{--architecture} + +@item +deduced from the input file +@end enumerate + +@subheading @code{objcopy}, @code{nm}, @code{size}, @code{strings} Architecture + +Ways to specify: + +@enumerate +@item +deduced from the input file +@end enumerate + +@subheading Linker Input Architecture + +Ways to specify: + +@enumerate +@item +deduced from the input file +@end enumerate + +@subheading Linker Output Architecture + +Ways to specify: + +@enumerate +@item +script command @code{OUTPUT_ARCH} +(@pxref{Option Commands,,Option Commands,ld.info,Using LD}) + +@item +the default architecture from the linker output target +(@pxref{Target Selection}) +@end enumerate + +@node Linker Emulation Selection +@section Linker emulation selection + +A linker @dfn{emulation} is a ``personality'' of the linker, which gives +the linker default values for the other aspects of the target system. +In particular, it consists of + +@itemize @bullet +@item +the linker script + +@item +the target + +@item +several ``hook'' functions that are run at certain stages of the linking +process to do special things that some targets require +@end itemize + +The command to list valid linker emulation values is @samp{ld -V}. + +Sample values: @samp{hp300bsd}, @samp{mipslit}, @samp{sun4}. + +Ways to specify: + +@enumerate +@item +command line option: @samp{-m} +(@pxref{Options,,Options,ld.info,Using LD}) + +@item +environment variable @code{LDEMULATION} + +@item +compiled-in @code{DEFAULT_EMULATION} from @file{Makefile}, +which comes from @code{EMUL} in @file{config/@var{target}.mt} +@end enumerate + +@node Index +@unnumbered Index + +@printindex cp + +@contents +@bye diff --git a/gnu/usr.bin/binutils/binutils/bucomm.c b/gnu/usr.bin/binutils/binutils/bucomm.c new file mode 100644 index 00000000000..59b13229ffb --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/bucomm.c @@ -0,0 +1,215 @@ +/* bucomm.c -- Bin Utils COMmon code. + Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public 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 might put this in a library someday so it could be dynamically + loaded, but for now it's not necessary. */ + +#include "bfd.h" +#include "libiberty.h" +#include "bucomm.h" + +#include +#include /* ctime, maybe time_t */ + +#ifndef HAVE_TIME_T_IN_TIME_H +#ifndef HAVE_TIME_T_IN_TYPES_H +typedef long time_t; +#endif +#endif + +#ifdef ANSI_PROTOTYPES +#include +#else +#include +#endif + +char *target = NULL; /* default as late as possible */ + +/* Error reporting */ + +char *program_name; + +void +bfd_nonfatal (string) + CONST char *string; +{ + CONST char *errmsg = bfd_errmsg (bfd_get_error ()); + + if (string) + fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg); + else + fprintf (stderr, "%s: %s\n", program_name, errmsg); +} + +void +bfd_fatal (string) + CONST char *string; +{ + bfd_nonfatal (string); + xexit (1); +} + +#ifdef ANSI_PROTOTYPES +void +fatal (const char *format, ...) +{ + va_list args; + + fprintf (stderr, "%s: ", program_name); + va_start (args, format); + vfprintf (stderr, format, args); + va_end (args); + putc ('\n', stderr); + xexit (1); +} +#else +void +fatal (va_alist) + va_dcl +{ + char *Format; + va_list args; + + fprintf (stderr, "%s: ", program_name); + va_start (args); + Format = va_arg (args, char *); + vfprintf (stderr, Format, args); + va_end (args); + putc ('\n', stderr); + xexit (1); +} +#endif + +/* After a false return from bfd_check_format_matches with + bfd_get_error () == bfd_error_file_ambiguously_recognized, print the possible + matching targets. */ + +void +list_matching_formats (p) + char **p; +{ + fprintf(stderr, "%s: Matching formats:", program_name); + while (*p) + fprintf(stderr, " %s", *p++); + fprintf(stderr, "\n"); +} + +/* List the supported targets. */ + +void +list_supported_targets (name, f) + const char *name; + FILE *f; +{ + extern bfd_target *bfd_target_vector[]; + int t; + + if (name == NULL) + fprintf (f, "Supported targets:"); + else + fprintf (f, "%s: supported targets:", name); + for (t = 0; bfd_target_vector[t] != NULL; t++) + fprintf (f, " %s", bfd_target_vector[t]->name); + fprintf (f, "\n"); +} + +/* Display the archive header for an element as if it were an ls -l listing: + + Mode User\tGroup\tSize\tDate Name */ + +void +print_arelt_descr (file, abfd, verbose) + FILE *file; + bfd *abfd; + boolean verbose; +{ + struct stat buf; + + if (verbose) + { + if (bfd_stat_arch_elt (abfd, &buf) == 0) + { + char modebuf[11]; + char timebuf[40]; + time_t when = buf.st_mtime; + CONST char *ctime_result = (CONST char *) ctime (&when); + + /* POSIX format: skip weekday and seconds from ctime output. */ + sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20); + + mode_string (buf.st_mode, modebuf); + modebuf[10] = '\0'; + /* POSIX 1003.2/D11 says to skip first character (entry type). */ + fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1, + (long) buf.st_uid, (long) buf.st_gid, + (long) buf.st_size, timebuf); + } + } + + fprintf (file, "%s\n", bfd_get_filename (abfd)); +} + +/* Return the name of a temporary file in the same directory as FILENAME. */ + +char * +make_tempname (filename) + char *filename; +{ + static char template[] = "stXXXXXX"; + char *tmpname; + char *slash = strrchr (filename, '/'); + + if (slash != (char *) NULL) + { + *slash = 0; + tmpname = xmalloc (strlen (filename) + sizeof (template) + 1); + strcpy (tmpname, filename); + strcat (tmpname, "/"); + strcat (tmpname, template); + mktemp (tmpname); + *slash = '/'; + } + else + { + tmpname = xmalloc (sizeof (template)); + strcpy (tmpname, template); + mktemp (tmpname); + } + return tmpname; +} + +/* Parse a string into a VMA, with a fatal error if it can't be + parsed. */ + +bfd_vma +parse_vma (s, arg) + const char *s; + const char *arg; +{ + bfd_vma ret; + const char *end; + + ret = bfd_scan_vma (s, &end, 0); + if (*end != '\0') + { + fprintf (stderr, "%s: %s: bad number: %s\n", program_name, arg, s); + exit (1); + } + return ret; +} diff --git a/gnu/usr.bin/binutils/binutils/bucomm.h b/gnu/usr.bin/binutils/binutils/bucomm.h new file mode 100644 index 00000000000..d660ca51db0 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/bucomm.h @@ -0,0 +1,103 @@ +/* bucomm.h -- binutils common include file. + Copyright (C) 1992, 93, 94 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 _BUCOMM_H +#define _BUCOMM_H + +#include "ansidecl.h" +#include +#include + +#include "config.h" + +#ifdef USE_BINARY_FOPEN +#include "fopen-bin.h" +#else +#include "fopen-same.h" +#endif + +#include +#ifndef errno +extern int errno; +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#else +extern char *strchr (); +extern char *strrchr (); +extern char *strstr (); +#endif +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#else +#ifdef HAVE_SYS_FILE_H +#include +#endif +#endif + +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif + +#ifndef O_RDWR +#define O_RDWR 2 +#endif + +/* bucomm.c */ +void bfd_nonfatal PARAMS ((CONST char *)); + +void bfd_fatal PARAMS ((CONST char *)); + +void fatal PARAMS ((CONST char *, ...)); + +void list_matching_formats PARAMS ((char **p)); + +void list_supported_targets PARAMS ((const char *, FILE *)); + +void print_arelt_descr PARAMS ((FILE *file, bfd *abfd, boolean verbose)); + +char *make_tempname PARAMS ((char *)); + +bfd_vma parse_vma PARAMS ((const char *, const char *)); + +extern char *program_name; + +/* filemode.c */ +void mode_string PARAMS ((unsigned long mode, char *buf)); + +/* libiberty */ +PTR xmalloc PARAMS ((size_t)); + +PTR xrealloc PARAMS ((char *, size_t)); + +#endif /* _BUCOMM_H */ diff --git a/gnu/usr.bin/binutils/binutils/coffdump.c b/gnu/usr.bin/binutils/binutils/coffdump.c new file mode 100644 index 00000000000..bae1e138ea7 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/coffdump.c @@ -0,0 +1,544 @@ +/* Coff file dumper. + Copyright (C) 1994 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 Steve Chamberlain + + This module reads a type tree generated by coffgrok and prints + it out so we can test the grokker. +*/ + +#include +#include +#include + +#include "coffgrok.h" +#include "bucomm.h" + +#define PROGRAM_VERSION "1.0" + +char *xcalloc(a,b) +int a; +int b; +{ + char *r = xmalloc(a*b); + memset (r, 0, a * b); + return r; +} + +static int atnl; +static void dump_coff_scope (); + +static void +tab (x) +int x; +{ + static int indent; + int i; + + if (atnl) + { + if (x < 0) + { + printf (")"); + indent += x; + + return; + } + else + { + printf ("\n"); + atnl = 0; + } + } + + if (x == -1) + { + for (i = 0; i < indent; i++) + printf (" "); + + indent += x; + printf (")"); + return; + } + + indent += x; + + for (i = 0; i < indent; i++) + printf (" "); + + if (x) + { + printf ("("); + } +} + +static void nl () +{ + atnl = 1; +} + +static void +dump_coff_lines (p) + struct coff_line *p; +{ + int i; + int online = 0; + tab(1); + printf("#lines %d ",p->nlines); + for (i = 0; i < p->nlines; i++) + { + printf("(%d 0x%x)", p->lines[i], p->addresses[i]); + online++; + if (online > 6) + { + nl(); + tab(0); + online = 0; + } + } + nl(); + tab(-1); +} + +static void +dump_coff_type (p) + struct coff_type *p; +{ + tab (1); + printf ("size %d ", p->size); + switch (p->type) + { + case coff_secdef_type: + printf ("section definition at %x size %x\n", + p->u.asecdef.address, + p->u.asecdef.size); + nl(); + break; + case coff_pointer_type: + printf ("pointer to"); + nl (); + dump_coff_type (p->u.pointer.points_to); + break; + case coff_array_type: + printf ("array [%d] of", p->u.array.dim); + nl (); + dump_coff_type (p->u.array.array_of); + break; + case coff_function_type: + printf ("function returning"); + nl (); + dump_coff_type (p->u.function.function_returns); + dump_coff_lines (p->u.function.lines); + printf ("arguments"); + nl (); + dump_coff_scope (p->u.function.parameters); + tab (0); + printf ("code"); + nl (); + dump_coff_scope (p->u.function.code); + tab(0); + break; + case coff_structdef_type: + printf ("structure definition"); + nl (); + dump_coff_scope (p->u.astructdef.elements); + break; + case coff_structref_type: + if (!p->u.aenumref.ref) + printf ("structure ref to UNKNOWN struct"); + else + printf ("structure ref to %s", p->u.aenumref.ref->name); + break; + case coff_enumref_type: + printf ("enum ref to %s", p->u.astructref.ref->name); + break; + case coff_enumdef_type: + printf ("enum definition"); + nl (); + dump_coff_scope (p->u.aenumdef.elements); + break; + case coff_basic_type: + switch (p->u.basic) + { + case T_NULL: + printf ("NULL"); + break; + case T_VOID: + printf ("VOID"); + break; + case T_CHAR: + printf ("CHAR"); + break; + case T_SHORT: + printf ("SHORT"); + break; + case T_INT: + printf ("INT "); + break; + case T_LONG: + printf ("LONG"); + break; + case T_FLOAT: + printf ("FLOAT"); + break; + case T_DOUBLE: + printf ("DOUBLE"); + break; + case T_STRUCT: + printf ("STRUCT"); + break; + case T_UNION: + printf ("UNION"); + break; + case T_ENUM: + printf ("ENUM"); + break; + case T_MOE: + printf ("MOE "); + break; + case T_UCHAR: + printf ("UCHAR"); + break; + case T_USHORT: + printf ("USHORT"); + break; + case T_UINT: + printf ("UINT"); + break; + case T_ULONG: + printf ("ULONG"); + break; + case T_LNGDBL: + printf ("LNGDBL"); + break; + default: + abort (); + } + } + nl (); + tab (-1); +} + +static void +dump_coff_where (p) + struct coff_where *p; +{ + tab (1); + switch (p->where) + { + case coff_where_stack: + printf ("Stack offset %x", p->offset); + break; + case coff_where_memory: + printf ("Memory section %s+%x", p->section->name, p->offset); + break; + case coff_where_register: + printf ("Register %d", p->offset); + break; + case coff_where_member_of_struct: + printf ("Struct Member offset %x", p->offset); + break; + case coff_where_member_of_enum: + printf ("Enum Member offset %x", p->offset); + break; + case coff_where_unknown: + printf ("Undefined symbol"); + break; + case coff_where_strtag: + printf ("STRTAG"); + case coff_where_entag: + printf ("ENTAG"); + break; + case coff_where_typedef: + printf ("TYPEDEF"); + break; + default: + abort (); + } + nl (); + tab (-1); +} + +static void +dump_coff_visible (p) + struct coff_visible *p; +{ + tab (1); + switch (p->type) + { + case coff_vis_ext_def: + printf ("coff_vis_ext_def"); + break; + case coff_vis_ext_ref: + printf ("coff_vis_ext_ref"); + break; + case coff_vis_int_def: + printf ("coff_vis_int_def"); + break; + case coff_vis_common: + printf ("coff_vis_common"); + break; + case coff_vis_auto: + printf ("coff_vis_auto"); + break; + case coff_vis_autoparam: + printf ("coff_vis_autoparam"); + break; + case coff_vis_regparam: + printf ("coff_vis_regparam"); + break; + case coff_vis_register: + printf ("coff_vis_register"); + break; + case coff_vis_tag: + printf ("coff_vis_tag"); + break; + case coff_vis_member_of_struct: + printf ("coff_vis_member_of_struct"); + break; + case coff_vis_member_of_enum: + printf ("coff_vis_member_of_enum"); + break; + default: + abort (); + } + nl (); + tab (-1); +} + + +void +dump_coff_symbol (p) + struct coff_symbol *p; +{ + tab (1); + printf ("List of symbols"); + nl (); + while (p) + { + tab (1); + tab (1); + printf ("Symbol %s, tag %d, number %d", p->name, p->tag, p->number); + nl (); + tab (-1); + tab (1); + printf ("Type"); + nl (); + dump_coff_type (p->type); + tab (-1); + tab (1); + printf ("Where"); + dump_coff_where (p->where); + tab (-1); + tab (1); + printf ("Visible"); + dump_coff_visible (p->visible); + tab (-1); + p = p->next; + tab (-1); + } + tab (-1); +} + +static void +dump_coff_scope (p) + struct coff_scope *p; +{ +if (p) { + tab (1); + printf ("List of blocks %lx ",(unsigned long) p); + + if (p->sec) { + printf( " %s %x..%x", p->sec->name,p->offset, p->offset + p->size -1); + } + nl (); + tab (0); + printf ("*****************"); + nl (); + while (p) + { + tab (0); + printf ("vars %d", p->nvars); + nl (); + dump_coff_symbol (p->vars_head); + printf ("blocks"); + nl (); + dump_coff_scope (p->list_head); + nl (); + p = p->next; + } + + tab (0); + printf ("*****************"); + nl (); + tab (-1); +} +} + +static void +dump_coff_sfile (p) + struct coff_sfile *p; +{ + tab (1); + printf ("List of source files"); + nl (); + while (p) + { + tab (0); + printf ("Source file %s", p->name); + nl (); + dump_coff_scope (p->scope); + p = p->next; + } + tab (-1); +} + +static void +dump_coff_section(ptr) +struct coff_section *ptr; +{ + int i; + tab(1); + printf("section %s %d %d address %x size %x number %d nrelocs %d", + ptr->name, ptr->code, ptr->data, ptr->address,ptr->size, ptr->number, ptr->nrelocs); + nl(); + + for (i = 0; i < ptr->nrelocs; i++) + { + tab(0); + printf("(%x %s %x)", + ptr->relocs[i].offset, + ptr->relocs[i].symbol->name, + ptr->relocs[i].addend); + nl(); + } + tab(-1); + +} + +void +coff_dump (ptr) + struct coff_ofile *ptr; +{ + int i; + printf ("Coff dump"); + nl (); + printf ("#souces %d", ptr->nsources); + nl (); + dump_coff_sfile (ptr->source_head); + for (i = 0; i < ptr->nsections; i++) + dump_coff_section(ptr->sections + i); +} + + + +char * program_name; + +static void +show_usage (file, status) + FILE *file; + int status; +{ + fprintf (file, "Usage: %s [-hV] in-file\n", program_name); + exit (status); +} + +static void +show_help () +{ + printf ("%s: Print a human readable interpretation of a SYSROFF object file\n", + program_name); + show_usage (stdout, 0); +} + + +int +main (ac, av) + int ac; + char *av[]; +{ + bfd *abfd; + struct coff_ofile *tree; + char **matching; + char *input_file = NULL; + int opt; + static struct option long_options[] = + { + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'V' }, + { NULL, no_argument, 0, 0 } + }; + + program_name = av[0]; + xmalloc_set_program_name (program_name); + + while ((opt = getopt_long (ac, av, "hV", long_options, + (int *) NULL)) + != EOF) + { + switch (opt) + { + case 'h': + show_help (); + /*NOTREACHED*/ + case 'V': + printf ("GNU %s version %s\n", program_name, PROGRAM_VERSION); + exit (0); + /*NOTREACHED*/ + case 0: + break; + default: + show_usage (stderr, 1); + /*NOTREACHED*/ + } + } + + if (optind < ac) + { + input_file = av[optind]; + } + + if (!input_file) + { + fprintf (stderr,"%s: no input file specified\n", + program_name); + exit(1); + } + abfd = bfd_openr (input_file, 0); + + if (!abfd) + bfd_fatal (input_file); + + if (! bfd_check_format_matches (abfd, bfd_object, &matching)) + { + bfd_nonfatal (input_file); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + exit (1); + } + + tree = coff_grok (abfd); + + coff_dump(tree); + printf("\n"); + return 0; +} diff --git a/gnu/usr.bin/binutils/binutils/coffgrok.c b/gnu/usr.bin/binutils/binutils/coffgrok.c new file mode 100644 index 00000000000..14d331e8fe4 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/coffgrok.c @@ -0,0 +1,733 @@ + + +/* coffgrok.c + + Copyright (C) 1994 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 Steve Chamberlain (sac@cygnus.com) + + This module reads a coff file and builds a really simple type tree + which can be read by other programs. The first application is a + coff->sysroff converter. It can be tested with coffdump.c. + +*/ + +#include +#include "bucomm.h" + +#include "coff/internal.h" +#include "../bfd/libcoff.h" +#include "coffgrok.h" +int lofile = 1; +static struct coff_scope *top_scope; +static struct coff_scope *file_scope; +static struct coff_ofile *ofile; + +struct coff_symbol *last_function_symbol; +struct coff_type *last_function_type; +struct coff_type *last_struct; +struct coff_type *last_enum; +struct coff_sfile *cur_sfile; + +static struct coff_symbol **tindex; + + +static asymbol **syms; +static long symcount; + +#define N(x) ((x)->_n._n_nptr[1]) + +static struct coff_ptr_struct *rawsyms; +static int rawcount; +static bfd *abfd; +extern char *xcalloc (); +#define PTR_SIZE 4 +#define SHORT_SIZE 2 +#define INT_SIZE 4 +#define LONG_SIZE 4 +#define FLOAT_SIZE 4 +#define DOUBLE_SIZE 8 + +#define INDEXOF(p) ((struct coff_ptr_struct *)(p)-(rawsyms)) + +static struct coff_scope * +empty_scope () +{ + struct coff_scope *l; + l = (struct coff_scope *) (xcalloc (sizeof (struct coff_scope), 1)); + return l; +} + +static struct coff_symbol * +empty_symbol () +{ + return (struct coff_symbol *) (xcalloc (sizeof (struct coff_symbol), 1)); +} + +/*int l;*/ +static void +push_scope (link) + int link; +{ + struct coff_scope *n = empty_scope (); + if (link) + { + if (top_scope) + { + if (top_scope->list_tail) + { + top_scope->list_tail->next = n; + } + else + { + top_scope->list_head = n; + } + top_scope->list_tail = n; + } + } + n->parent = top_scope; + + top_scope = n; +} + +static void +pop_scope () +{ + top_scope = top_scope->parent; +} + +static void +do_sections_p1 (head) + struct coff_ofile *head; +{ + asection *section; + int idx; + struct coff_section *all = (struct coff_section *) (xcalloc (abfd->section_count + 1, + sizeof (struct coff_section))); + head->nsections = abfd->section_count + 1; + head->sections = all; + + for (idx = 0, section = abfd->sections; section; section = section->next, idx++) + { + long relsize; + int i = section->target_index; + arelent **relpp; + long relcount; + + relsize = bfd_get_reloc_upper_bound (abfd, section); + if (relsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + if (relsize == 0) + continue; + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); + if (relcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + + head->sections[i].name = (char *) (section->name); + head->sections[i].code = section->flags & SEC_CODE; + head->sections[i].data = section->flags & SEC_DATA; + if (strcmp (section->name, ".bss") == 0) + head->sections[i].data = 1; + head->sections[i].address = section->vma; + head->sections[i].size = section->_raw_size; + head->sections[i].number = idx; + head->sections[i].nrelocs = section->reloc_count; + head->sections[i].relocs = + (struct coff_reloc *) (xcalloc (section->reloc_count, + sizeof (struct coff_reloc))); + head->sections[i].bfd_section = section; + } + head->sections[0].name = "ABSOLUTE"; + head->sections[0].code = 0; + head->sections[0].data = 0; + head->sections[0].address = 0; + head->sections[0].size = 0; + head->sections[0].number = 0; +} + +static void +do_sections_p2 (head) + struct coff_ofile *head; +{ + asection *section; + for (section = abfd->sections; section; section = section->next) + { + int j; + for (j = 0; j < section->reloc_count; j++) + { + int idx; + int i = section->target_index; + struct coff_reloc *r = head->sections[i].relocs + j; + arelent *sr = section->relocation + j; + r->offset = sr->address; + r->addend = sr->addend; + idx = ((coff_symbol_type *) (sr->sym_ptr_ptr[0]))->native - rawsyms; + r->symbol = tindex[idx]; + } + } +} + +static struct coff_where * +do_where (i) + int i; +{ + struct internal_syment *sym = &rawsyms[i].u.syment; + struct coff_where *where + = (struct coff_where *) (malloc (sizeof (struct coff_where))); + where->offset = sym->n_value; + + if (sym->n_scnum == -1) + sym->n_scnum = 0; + + switch (sym->n_sclass) + { + case C_FIELD: + where->where = coff_where_member_of_struct; + where->offset = sym->n_value / 8; + where->bitoffset = sym->n_value % 8; + where->bitsize = rawsyms[i + 1].u.auxent.x_sym.x_misc.x_lnsz.x_size; + break; + case C_MOE: + where->where = coff_where_member_of_enum; + break; + case C_MOS: + case C_MOU: + where->where = coff_where_member_of_struct; + break; + case C_AUTO: + case C_ARG: + where->where = coff_where_stack; + break; + case C_EXT: + case C_STAT: + case C_EXTDEF: + case C_LABEL: + where->where = coff_where_memory; + where->section = &ofile->sections[sym->n_scnum]; + break; + case C_REG: + case C_REGPARM: + where->where = coff_where_register; + break; + case C_ENTAG: + where->where = coff_where_entag; + break; + case C_STRTAG: + case C_UNTAG: + where->where = coff_where_strtag; + break; + case C_TPDEF: + where->where = coff_where_typedef; + break; + default: + abort (); + break; + } + return where; +} + +static +struct coff_line * +do_lines (i, name) + int i; + char *name; +{ + struct coff_line *res = (struct coff_line *) xcalloc (sizeof (struct coff_line), 1); + asection *s; + int l; + /* Find out if this function has any line numbers in the table */ + for (s = abfd->sections; s; s = s->next) + { + for (l = 0; l < s->lineno_count; l++) + { + if (s->lineno[l].line_number == 0) + { + if (rawsyms + i == ((coff_symbol_type *) (&(s->lineno[l].u.sym[0])))->native) + { + /* These lines are for this function - so count them and stick them on */ + int c = 0; + /* Find the linenumber of the top of the function, since coff linenumbers + are relative to the start of the function. */ + int start_line = rawsyms[i + 3].u.auxent.x_sym.x_misc.x_lnsz.x_lnno; + + l++; + for (c = 0; s->lineno[l + c + 1].line_number; c++) + ; + + /* Add two extra records, one for the prologue and one for the epilogue */ + c += 1; + res->nlines = c; + res->lines = (int *) (xcalloc (sizeof (int), c)); + res->addresses = (int *) (xcalloc (sizeof (int), c)); + res->lines[0] = start_line; + res->addresses[0] = rawsyms[i].u.syment.n_value - s->vma; + for (c = 0; s->lineno[l + c + 1].line_number; c++) + { + res->lines[c + 1] = s->lineno[l + c].line_number + start_line - 1; + res->addresses[c + 1] = s->lineno[l + c].u.offset; + } + return res; + } + } + } + } + return res; +} + +static +struct coff_type * +do_type (i) + int i; +{ + struct internal_syment *sym = &rawsyms[i].u.syment; + union internal_auxent *aux = &rawsyms[i + 1].u.auxent; + struct coff_type *res = (struct coff_type *) malloc (sizeof (struct coff_type)); + int type = sym->n_type; + int which_dt = 0; + int dimind = 0; + + res->type = coff_basic_type; + res->u.basic = type & 0xf; + + switch (type & 0xf) + { + case T_NULL: + case T_VOID: + if (sym->n_numaux && sym->n_sclass == C_STAT) + { + /* This is probably a section definition */ + res->type = coff_secdef_type; + res->size = aux->x_scn.x_scnlen; + } + else + { + if (type == 0) + { + /* Don't know what this is, let's make it a simple int */ + res->size = INT_SIZE; + res->u.basic = T_UINT; + } + else + { + /* Else it could be a function or pointer to void */ + res->size = 0; + } + } + break; + + + break; + case T_UCHAR: + case T_CHAR: + res->size = 1; + break; + case T_USHORT: + case T_SHORT: + res->size = SHORT_SIZE; + break; + case T_UINT: + case T_INT: + res->size = INT_SIZE; + break; + case T_ULONG: + case T_LONG: + res->size = LONG_SIZE; + break; + case T_FLOAT: + res->size = FLOAT_SIZE; + break; + case T_DOUBLE: + res->size = DOUBLE_SIZE; + break; + case T_STRUCT: + case T_UNION: + if (sym->n_numaux) + { + if (aux->x_sym.x_tagndx.p) + { + /* Refering to a struct defined elsewhere */ + res->type = coff_structref_type; + res->u.astructref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)]; + res->size = res->u.astructref.ref ? + res->u.astructref.ref->type->size : 0; + } + else + { + /* A definition of a struct */ + last_struct = res; + res->type = coff_structdef_type; + res->u.astructdef.elements = empty_scope (); + res->u.astructdef.idx = 0; + res->u.astructdef.isstruct = (type & 0xf) == T_STRUCT; + res->size = aux->x_sym.x_misc.x_lnsz.x_size; + } + } + else + { + /* No auxents - it's anonynmous */ + res->type = coff_structref_type; + res->u.astructref.ref = 0; + res->size = 0; + } + break; + case T_ENUM: + if (aux->x_sym.x_tagndx.p) + { + /* Refering to a enum defined elsewhere */ + res->type = coff_enumref_type; + res->u.aenumref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)]; + res->size = res->u.aenumref.ref->type->size; + } + else + { + /* A definition of an enum */ + last_enum = res; + res->type = coff_enumdef_type; + res->u.aenumdef.elements = empty_scope (); + res->size = aux->x_sym.x_misc.x_lnsz.x_size; + } + break; + case T_MOE: + break; + } + + for (which_dt = 5; which_dt >= 0; which_dt--) + { + switch ((type >> ((which_dt * 2) + 4)) & 0x3) + { + case 0: + break; + case DT_ARY: + { + struct coff_type *ptr = ((struct coff_type *) + malloc (sizeof (struct coff_type))); + int els = (dimind < DIMNUM + ? aux->x_sym.x_fcnary.x_ary.x_dimen[dimind] + : 0); + ++dimind; + ptr->type = coff_array_type; + ptr->size = els * res->size; + ptr->u.array.dim = els; + ptr->u.array.array_of = res; + res = ptr; + break; + } + case DT_PTR: + { + struct coff_type *ptr = (struct coff_type *) malloc (sizeof (struct coff_type)); + ptr->size = PTR_SIZE; + ptr->type = coff_pointer_type; + ptr->u.pointer.points_to = res; + res = ptr; + break; + } + case DT_FCN: + { + struct coff_type *ptr = (struct coff_type *) malloc (sizeof (struct coff_type)); + ptr->size = 0; + ptr->type = coff_function_type; + ptr->u.function.function_returns = res; + ptr->u.function.parameters = empty_scope (); + ptr->u.function.lines = do_lines (i, sym->_n._n_nptr[1]); + ptr->u.function.code = 0; + last_function_type = ptr; + res = ptr; + break; + } + } + } + return res; +} + +static struct coff_visible * +do_visible (i) + int i; +{ + struct internal_syment *sym = &rawsyms[i].u.syment; + struct coff_visible *visible = (struct coff_visible *) (malloc (sizeof (struct coff_visible))); + enum coff_vis_type t; + switch (sym->n_sclass) + { + case C_MOS: + case C_MOU: + case C_FIELD: + t = coff_vis_member_of_struct; + break; + case C_MOE: + t = coff_vis_member_of_enum; + break; + + case C_REGPARM: + t = coff_vis_regparam; + break; + + case C_REG: + t = coff_vis_register; + break; + case C_STRTAG: + case C_UNTAG: + case C_ENTAG: + case C_TPDEF: + t = coff_vis_tag; + break; + case C_AUTOARG: + case C_ARG: + t = coff_vis_autoparam; + break; + case C_AUTO: + + + t = coff_vis_auto; + break; + case C_LABEL: + case C_STAT: + t = coff_vis_int_def; + break; + case C_EXT: + if (sym->n_scnum == N_UNDEF) + { + if (sym->n_value) + t = coff_vis_common; + else + t = coff_vis_ext_ref; + } + else + t = coff_vis_ext_def; + break; + default: + abort (); + break; + + } + visible->type = t; + return visible; +} + +static int +do_define (i, b) + int i; + struct coff_scope *b; +{ + static int symbol_index; + struct internal_syment *sym = &rawsyms[i].u.syment; + + /* Define a symbol and attach to block b */ + struct coff_symbol *s = empty_symbol (); + + s->number = ++symbol_index; + s->name = sym->_n._n_nptr[1]; + s->sfile = cur_sfile; + /* Glue onto the ofile list */ + if (lofile >= 0) + { + if (ofile->symbol_list_tail) + ofile->symbol_list_tail->next_in_ofile_list = s; + else + ofile->symbol_list_head = s; + ofile->symbol_list_tail = s; + /* And the block list */ + } + if (b->vars_tail) + b->vars_tail->next = s; + else + b->vars_head = s; + + b->vars_tail = s; + b->nvars++; + s->type = do_type (i); + s->where = do_where (i); + s->visible = do_visible (i); + + tindex[i] = s; + + /* We remember the lowest address in each section for each source file */ + + if (s->where->where == coff_where_memory + && s->type->type == coff_secdef_type) + { + struct coff_isection *is = cur_sfile->section + s->where->section->number; + + if (!is->init) + { + is->low = s->where->offset; + is->high = s->where->offset + s->type->size; + is->init = 1; + is->parent = s->where->section; + } + + } + + if (s->type->type == coff_function_type) + last_function_symbol = s; + + return i + sym->n_numaux + 1; +} + + +static +struct coff_ofile * +doit () +{ + int i; + int infile = 0; + struct coff_ofile *head = + (struct coff_ofile *) xmalloc (sizeof (struct coff_ofile)); + ofile = head; + head->source_head = 0; + head->source_tail = 0; + head->nsources = 0; + head->symbol_list_tail = 0; + head->symbol_list_head = 0; + do_sections_p1 (head); + push_scope (1); + + for (i = 0; i < rawcount;) + { + struct internal_syment *sym = &rawsyms[i].u.syment; + switch (sym->n_sclass) + { + case C_FILE: + { + /* new source file announced */ + struct coff_sfile *n = (struct coff_sfile *) malloc (sizeof (struct coff_sfile)); + n->section = (struct coff_isection *) xcalloc (sizeof (struct coff_isection), abfd->section_count + 1); + cur_sfile = n; + n->name = sym->_n._n_nptr[1]; + n->next = 0; + + if (infile) + { + pop_scope (); + } + infile = 1; + push_scope (1); + file_scope = n->scope = top_scope; + + if (head->source_tail) + head->source_tail->next = n; + else + head->source_head = n; + head->source_tail = n; + head->nsources++; + i += sym->n_numaux + 1; + } + break; + case C_FCN: + { + char *name = sym->_n._n_nptr[1]; + if (name[1] == 'b') + { + /* Function start */ + push_scope (0); + last_function_type->u.function.code = top_scope; + top_scope->sec = ofile->sections + sym->n_scnum; + top_scope->offset = sym->n_value; + } + else + { + top_scope->size = sym->n_value - top_scope->offset + 1; + pop_scope (); + + } + i += sym->n_numaux + 1; + } + break; + + case C_BLOCK: + { + char *name = sym->_n._n_nptr[1]; + if (name[1] == 'b') + { + /* Block start */ + push_scope (1); + top_scope->sec = ofile->sections + sym->n_scnum; + top_scope->offset = sym->n_value; + + } + else + { + top_scope->size = sym->n_value - top_scope->offset + 1; + pop_scope (); + } + i += sym->n_numaux + 1; + } + break; + case C_REGPARM: + case C_ARG: + i = do_define (i, last_function_symbol->type->u.function.parameters); + break; + case C_MOS: + case C_MOU: + case C_FIELD: + i = do_define (i, last_struct->u.astructdef.elements); + break; + case C_MOE: + i = do_define (i, last_enum->u.aenumdef.elements); + break; + case C_STRTAG: + case C_ENTAG: + case C_UNTAG: + /* Various definition */ + i = do_define (i, top_scope); + break; + case C_EXT: + case C_LABEL: + i = do_define (i, file_scope); + break; + case C_STAT: + case C_TPDEF: + case C_AUTO: + case C_REG: + i = do_define (i, top_scope); + break; + default: + abort (); + case C_EOS: + i += sym->n_numaux + 1; + break; + } + } + do_sections_p2 (head); + return head; +} + +struct coff_ofile * +coff_grok (inabfd) + bfd *inabfd; +{ + long storage; + struct coff_ofile *p; + abfd = inabfd; + storage = bfd_get_symtab_upper_bound (abfd); + + if (storage < 0) + bfd_fatal (abfd->filename); + + syms = (asymbol **) xmalloc (storage); + symcount = bfd_canonicalize_symtab (abfd, syms); + if (symcount < 0) + bfd_fatal (abfd->filename); + rawsyms = obj_raw_syments (abfd); + rawcount = obj_raw_syment_count (abfd);; + tindex = (struct coff_symbol **) (xcalloc (sizeof (struct coff_symbol *), rawcount)); + + p = doit (); + return p; +} diff --git a/gnu/usr.bin/binutils/binutils/coffgrok.h b/gnu/usr.bin/binutils/binutils/coffgrok.h new file mode 100644 index 00000000000..c0ade42a61f --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/coffgrok.h @@ -0,0 +1,206 @@ +#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 */ + + + struct coff_reloc + { + int offset; + struct coff_symbol *symbol; + int addend; + }; + + struct coff_section + { + char *name; + int code; + int data; + int address; + int number; /* 0..n, .text = 0 */ + int nrelocs; + int size; + struct coff_reloc *relocs; + struct sec *bfd_section; + }; + +struct coff_ofile +{ + int nsources; + struct coff_sfile *source_head; + struct coff_sfile *source_tail; + int nsections; + struct coff_section *sections; + struct coff_symbol *symbol_list_head; + struct coff_symbol *symbol_list_tail; +}; + +struct coff_isection { + int low; + int high; + int init; + struct coff_section *parent; +}; + +struct coff_sfile +{ + char *name; + struct coff_scope *scope; + struct coff_sfile *next; + + /* Vector which maps where in each output section + the input file has it's data */ + struct coff_isection *section; + +}; + + + struct coff_type +{ + int size; + enum + { + coff_pointer_type, coff_function_type, coff_array_type, coff_structdef_type, coff_basic_type, + coff_structref_type, coff_enumref_type, coff_enumdef_type, coff_secdef_type + } type; + union + { + struct + { + int address; + int size; + } asecdef; + + struct + { + int isstruct; + struct coff_scope *elements; + int idx; + } + astructdef; + struct + { + struct coff_symbol *ref; + } astructref; + + struct + { + struct coff_scope *elements; + int idx; + } aenumdef; + struct + { + struct coff_symbol *ref; + } aenumref; + + struct + { + struct coff_type *points_to; + } pointer; + struct + { + int dim; + struct coff_type *array_of; + } array; + + struct + { + struct coff_type *function_returns; + struct coff_scope *parameters; + struct coff_scope *code; + struct coff_line *lines; + } function; + int basic; /* One of T_VOID.. T_UINT */ + } u; +}; + + + struct coff_line + { + int nlines; + int *lines; + int *addresses; + }; + + + struct coff_scope + { + struct coff_section *sec; /* What section */ + int offset; /* where */ + int size; /* How big */ + struct coff_scope *parent; /* one up */ + + struct coff_scope *next; /*next along */ + + int nvars; + + struct coff_symbol *vars_head; /* symbols */ + struct coff_symbol *vars_tail; + + struct coff_scope *list_head; /* children */ + struct coff_scope *list_tail; + + }; + + + struct coff_visible + { + enum coff_vis_type + { + coff_vis_ext_def, + coff_vis_ext_ref, + coff_vis_int_def, + coff_vis_common, + coff_vis_auto, + coff_vis_register, + coff_vis_tag, + coff_vis_member_of_struct, + coff_vis_member_of_enum, + coff_vis_autoparam, + coff_vis_regparam, + } type; + }; + + struct coff_where + { + enum + { + coff_where_stack, coff_where_memory, coff_where_register, coff_where_unknown, + coff_where_strtag, coff_where_member_of_struct, + coff_where_member_of_enum, coff_where_entag, coff_where_typedef + + } where; + int offset; + int bitoffset; + int bitsize; + struct coff_section *section; + }; + + struct coff_symbol + { + char *name; + int tag; + struct coff_type *type; + struct coff_where *where; + struct coff_visible *visible; + struct coff_symbol *next; + struct coff_symbol *next_in_ofile_list; /* For the ofile list */ + int number; + int er_number; + struct coff_sfile *sfile; + }; + +struct coff_ofile *coff_grok(); diff --git a/gnu/usr.bin/binutils/binutils/config.in b/gnu/usr.bin/binutils/binutils/config.in new file mode 100644 index 00000000000..a0b59ac9433 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/config.in @@ -0,0 +1,43 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Define if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Is the type time_t defined in ? */ +#undef HAVE_TIME_T_IN_TIME_H + +/* Is the type time_t defined in ? */ +#undef HAVE_TIME_T_IN_TYPES_H + +/* Does define struct utimbuf? */ +#undef HAVE_GOOD_UTIME_H + +/* Whether fprintf must be declared even if is included. */ +#undef NEED_DECLARATION_FPRINTF + +/* Do we need to use the b modifier when opening binary files? */ +#undef USE_BINARY_FOPEN + +/* Define if you have the sbrk function. */ +#undef HAVE_SBRK + +/* Define if you have the utimes function. */ +#undef HAVE_UTIMES + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H diff --git a/gnu/usr.bin/binutils/binutils/config.texi b/gnu/usr.bin/binutils/binutils/config.texi new file mode 100644 index 00000000000..48247dcdffa --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/config.texi @@ -0,0 +1 @@ +@set VERSION 2.6 diff --git a/gnu/usr.bin/binutils/binutils/configure b/gnu/usr.bin/binutils/binutils/configure new file mode 100644 index 00000000000..3562008b59d --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/configure @@ -0,0 +1,1404 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.4 +# 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-targets alternative target configurations" + +# 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.4" + 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=ar.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 + + + +# Check whether --enable-targets or --disable-targets was given. +enableval="$enable_targets" +if test -n "$enableval"; then + 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 + + + +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 -z "$host" ; then + { echo "configure: error: Unrecognized host 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 '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," + + +# host-specific stuff: + +HDEFINES= +LDFLAGS= + +. ${srcdir}/../bfd/configure.host + +echo $ac_n "checking for CC""... $ac_c" 1>&6 +test -z "$CC" && test -r ../Makefile && CC=`egrep '^CC *=' ../Makefile | tail -1 | sed 's/^CC *= *//'` +test -z "$CC" && CC=cc +echo "$ac_t""setting CC to $CC" 1>&6 + +cat > conftest.c <&5 | egrep yes >/dev/null 2>&1; then + GCC=yes + if test "${CFLAGS+set}" != set; then + echo 'void f(){}' > conftest.c + if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + CFLAGS="-g -O" + else + CFLAGS="-O" + fi + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi +rm -f conftest* + + + + +AR=${AR-ar} + +# 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 + +# 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' + + +# 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 </dev/null; then + ac_cv_c_cross=no +else + ac_cv_c_cross=yes +fi +fi +rm -fr conftest* +fi +cross_compiling=$ac_cv_c_cross +echo "$ac_t""$ac_cv_c_cross" 1>&6 + +# 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 < +Syntax Error +EOF +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +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 < +Syntax Error +EOF +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +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 string.h strings.h stdlib.h unistd.h fcntl.h sys/file.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 +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +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 '[a-z]./\055' '[A-Z]___'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif +int main() { return 0; } +int t() { +int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + ac_cv_header_sys_wait_h=yes +else + rm -rf conftest* + ac_cv_header_sys_wait_h=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6 +if test $ac_cv_header_sys_wait_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SYS_WAIT_H 1 +EOF + +fi + +for ac_func in sbrk utimes +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 < +/* 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 $ac_link; 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 '[a-z]' '[A-Z]'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for time_t in time.h""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'bu_cv_decl_time_t_time_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { return 0; } +int t() { +time_t i; +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + bu_cv_decl_time_t_time_h=yes +else + rm -rf conftest* + bu_cv_decl_time_t_time_h=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$bu_cv_decl_time_t_time_h" 1>&6 +if test $bu_cv_decl_time_t_time_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_TIME_T_IN_TIME_H 1 +EOF + +fi + +echo $ac_n "checking for time_t in sys/types.h""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'bu_cv_decl_time_t_types_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { return 0; } +int t() { +time_t i; +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + bu_cv_decl_time_t_types_h=yes +else + rm -rf conftest* + bu_cv_decl_time_t_types_h=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$bu_cv_decl_time_t_types_h" 1>&6 +if test $bu_cv_decl_time_t_types_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_TIME_T_IN_TYPES_H 1 +EOF + +fi + +# Under Next 3.2 apparently does not define struct utimbuf +# by default. +echo $ac_n "checking for utime.h""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'bu_cv_header_utime_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#ifdef HAVE_TIME_H +#include +#endif +#include +int main() { return 0; } +int t() { +struct utimbuf s; +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + bu_cv_header_utime_h=yes +else + rm -rf conftest* + bu_cv_header_utime_h=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$bu_cv_header_utime_h" 1>&6 +if test $bu_cv_header_utime_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_GOOD_UTIME_H 1 +EOF + +fi + +echo $ac_n "checking whether fprintf must be declared""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'bu_cv_decl_needed_fprintf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { return 0; } +int t() { +int (*pfn) = (int (*)) fprintf +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + bu_cv_decl_needed_fprintf=no +else + rm -rf conftest* + bu_cv_decl_needed_fprintf=yes +fi +rm -f conftest* + +fi + +echo "$ac_t""$bu_cv_decl_needed_fprintf" 1>&6 +if test $bu_cv_decl_needed_fprintf = yes; then + cat >> confdefs.h <<\EOF +#define NEED_DECLARATION_FPRINTF 1 +EOF + +fi + +case "${host}" in +i[345]86-*-msdos* | i[345]86-*-go32* | i[345]86-*-win32) + cat >> confdefs.h <<\EOF +#define USE_BINARY_FOPEN 1 +EOF + ;; +esac + +# target-specific 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 +BUILD_NLMCONV= +NLMCONV_DEFS= +BUILD_SRCONV= +BUILD_DLLTOOL= +DLLTOOL_DEFS= + +for targ in $target $canon_targets +do + if test "x$targ" = "xall"; then + all_targets=true + BUILD_NLMCONV='$(NLMCONV_PROG)' + BUILD_SRCONV='$(SRCONV_PROG)' + NLMCONV_DEFS="-DNLMCONV_I386 -DNLMCONV_ALPHA -DNLMCONV_POWERPC -DNLMCONV_SPARC" + else + case $targ in + i[345]86*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_I386" + ;; + alpha*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_ALPHA" + ;; + powerpc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_POWERPC" + ;; + sparc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_SPARC" + ;; + esac + case $targ in + *-*-hms*) BUILD_SRCONV='$(SRCONV_PROG)' ;; + esac + case $targ in + arm-*pe*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" + ;; + i[3-6]86-*pe* | i[3-6]86-*-win32) + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386" + ;; + powerpc*-*pe*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC" + ;; + esac + fi +done + + + + + + + +targ=$target +. $srcdir/../bfd/config.bfd +if test "x$targ_underscore" = "xyes"; then + UNDERSCORE=1 +else + UNDERSCORE=0 +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 + +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 </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.4" + 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 + +# 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%@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%@CC_FOR_BUILD@%$CC_FOR_BUILD%g +s%@CPP@%$CPP%g +s%@NLMCONV_DEFS@%$NLMCONV_DEFS%g +s%@BUILD_NLMCONV@%$BUILD_NLMCONV%g +s%@BUILD_SRCONV@%$BUILD_SRCONV%g +s%@BUILD_DLLTOOL@%$BUILD_DLLTOOL%g +s%@DLLTOOL_DEFS@%$DLLTOOL_DEFS%g +s%@UNDERSCORE@%$UNDERSCORE%g + +CEOF +EOF +cat >> $CONFIG_STATUS <> $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 <> $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/gnu/usr.bin/binutils/binutils/configure.bat b/gnu/usr.bin/binutils/binutils/configure.bat new file mode 100644 index 00000000000..f7d70f1150b --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/configure.bat @@ -0,0 +1,63 @@ +@echo off +if "%1" == "h8/300" goto h8300 + +echo Configuring binutils for go32 +update ../bfd/hosts/go32.h sysdep.h +goto common + +:h8300 +echo Configuring binutils for H8/300 +update ..\bfd\hosts\h-go32.h sysdep.h + +:common + +echo # Makefile generated by "configure.bat"> Makefile + +if exist config.sed del config.sed + +sed -n "/^VERSION=/ p" Makefile.in | sed -e "s/^/s^/" -e "s/=/^\"/" -e "s/$/\"^/" > config.sed +sed -f config.sed version.c > version2.c + +if exist config.sed del config.sed + +echo "s/version\./version2\./g ">> config.sed +echo "s/-DVERSION=[^ ]* // ">> config.sed + +echo "s/^ \$(srcdir)\/move-if-change/ update/ ">> config.sed +echo "/^###$/ i\ ">> config.sed +echo "CC = gcc ">> config.sed +echo "s/:\([^ ]\)/: \1/g ">> config.sed +echo "s/^ \ *\.\// go32 / ">> config.sed +echo "s/`echo \$(srcdir)\///g ">> config.sed +echo "s/ | sed 's,\^\\\.\/,,'`//g ">> config.sed +echo "s/^ cd \$(srcdir)[ ]*;// ">> config.sed + +echo "/^arparse\.c/ i\ ">> config.sed +echo "arparse.o: arparse.c\ ">> config.sed +echo " $(CC) -c $(CFLAGS) $(INCLUDES) $(HDEFINES) $(TDEFINES) arparse.c ">> config.sed +echo "/\$(BISON)/ c\ ">> config.sed +echo " bison $(BISONFLAGS) -o $@ arparse.y ">> config.sed +echo "/y\.tab\./ d ">> config.sed + +echo "/^arlex.c/ { ">> config.sed +echo " i\ ">> config.sed +echo "arlex.o: arlex.c ">> config.sed +echo " i\ ">> config.sed +echo " $(CC) -c $(CFLAGS) $(INCLUDES) $(HDEFINES) $(TDEFINES) arlex.c ">> config.sed +echo "} ">> config.sed +echo "/\$(LEX)/ c\ ">> config.sed +echo " flex $(LEX_OPTIONS) arlex.l ">> config.sed +echo "s/lex\.yy\./lexyy./g ">> config.sed + +echo "s/'"/\\"/g ">> config.sed +echo "s/"'/\\"/g ">> config.sed + +echo "s/c++filt/cxxfilt/g ">> config.sed + +sed -e "s/^\"//" -e "s/\"$//" -e "s/[ ]*$//" config.sed > config2.sed +sed -f config2.sed Makefile.in >> Makefile +del config.sed +del config2.sed + +echo int prepends_underscore = 1; > underscore.c + diff --git a/gnu/usr.bin/binutils/binutils/configure.in b/gnu/usr.bin/binutils/binutils/configure.in new file mode 100644 index 00000000000..ff50d824dba --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/configure.in @@ -0,0 +1,184 @@ +dnl Process this file with autoconf to produce a configure script. +dnl +AC_PREREQ(2.0) +AC_INIT(ar.c) + +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_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 +if test -z "$host" ; then + AC_MSG_ERROR(Unrecognized host system type; please check config.sub.) +fi +AC_ARG_PROGRAM + +# host-specific stuff: + +HDEFINES= +LDFLAGS= + +. ${srcdir}/../bfd/configure.host + +AC_PROG_CC +AC_SUBST(CFLAGS) +AC_SUBST(HDEFINES) +AC_SUBST(LDFLAGS) +AR=${AR-ar} +AC_SUBST(AR) +AC_PROG_RANLIB +AC_PROG_INSTALL + +BFD_CC_FOR_BUILD + +AC_CHECK_HEADERS(string.h strings.h stdlib.h unistd.h fcntl.h sys/file.h) +AC_HEADER_SYS_WAIT +AC_CHECK_FUNCS(sbrk utimes) + +AC_MSG_CHECKING(for time_t in time.h) +AC_CACHE_VAL(bu_cv_decl_time_t_time_h, +[AC_TRY_COMPILE([#include ], [time_t i;], +bu_cv_decl_time_t_time_h=yes, bu_cv_decl_time_t_time_h=no)]) +AC_MSG_RESULT($bu_cv_decl_time_t_time_h) +if test $bu_cv_decl_time_t_time_h = yes; then + AC_DEFINE([HAVE_TIME_T_IN_TIME_H]) +fi + +AC_MSG_CHECKING(for time_t in sys/types.h) +AC_CACHE_VAL(bu_cv_decl_time_t_types_h, +[AC_TRY_COMPILE([#include ], [time_t i;], +bu_cv_decl_time_t_types_h=yes, bu_cv_decl_time_t_types_h=no)]) +AC_MSG_RESULT($bu_cv_decl_time_t_types_h) +if test $bu_cv_decl_time_t_types_h = yes; then + AC_DEFINE([HAVE_TIME_T_IN_TYPES_H]) +fi + +# Under Next 3.2 apparently does not define struct utimbuf +# by default. +AC_MSG_CHECKING([for utime.h]) +AC_CACHE_VAL(bu_cv_header_utime_h, +[AC_TRY_COMPILE([#include +#ifdef HAVE_TIME_H +#include +#endif +#include ], +[struct utimbuf s;], +bu_cv_header_utime_h=yes, bu_cv_header_utime_h=no)]) +AC_MSG_RESULT($bu_cv_header_utime_h) +if test $bu_cv_header_utime_h = yes; then + AC_DEFINE(HAVE_GOOD_UTIME_H) +fi + +AC_MSG_CHECKING([whether fprintf must be declared]) +AC_CACHE_VAL(bu_cv_decl_needed_fprintf, +[AC_TRY_COMPILE([#include ], +[int (*pfn) = (int (*)) fprintf], +bu_cv_decl_needed_fprintf=no, bu_cv_decl_needed_fprintf=yes)]) +AC_MSG_RESULT($bu_cv_decl_needed_fprintf) +if test $bu_cv_decl_needed_fprintf = yes; then + AC_DEFINE(NEED_DECLARATION_FPRINTF) +fi + +BFD_BINARY_FOPEN + +# target-specific 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 +BUILD_NLMCONV= +NLMCONV_DEFS= +BUILD_SRCONV= +BUILD_DLLTOOL= +DLLTOOL_DEFS= + +for targ in $target $canon_targets +do + if test "x$targ" = "xall"; then + all_targets=true + BUILD_NLMCONV='$(NLMCONV_PROG)' + BUILD_SRCONV='$(SRCONV_PROG)' + NLMCONV_DEFS="-DNLMCONV_I386 -DNLMCONV_ALPHA -DNLMCONV_POWERPC -DNLMCONV_SPARC" + else + case $targ in +changequote(,)dnl + i[345]86*-*-netware*) +changequote([,])dnl + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_I386" + ;; + alpha*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_ALPHA" + ;; + powerpc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_POWERPC" + ;; + sparc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_SPARC" + ;; + esac + case $targ in + *-*-hms*) BUILD_SRCONV='$(SRCONV_PROG)' ;; + esac + case $targ in + arm-*pe*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" + ;; +changequote(,)dnl + i[3-6]86-*pe* | i[3-6]86-*-win32) +changequote([,])dnl + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386" + ;; + powerpc*-*pe*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC" + ;; + esac + fi +done + +AC_SUBST(NLMCONV_DEFS) +AC_SUBST(BUILD_NLMCONV) +AC_SUBST(BUILD_SRCONV) +AC_SUBST(BUILD_DLLTOOL) +AC_SUBST(DLLTOOL_DEFS) + +targ=$target +. $srcdir/../bfd/config.bfd +if test "x$targ_underscore" = "xyes"; then + UNDERSCORE=1 +else + UNDERSCORE=0 +fi +AC_SUBST(UNDERSCORE) + +AC_OUTPUT(Makefile, +[case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac]) diff --git a/gnu/usr.bin/binutils/binutils/cxxfilt.man b/gnu/usr.bin/binutils/binutils/cxxfilt.man new file mode 100644 index 00000000000..a4d5d45106b --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/cxxfilt.man @@ -0,0 +1,114 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH @PROGRAM@ 1 "June 1993" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +@PROGRAM@ \- demangle C++ symbols + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B @PROGRAM@ +.RB "[\|" \-_ | \-\-strip-underscores "\|]" +.RB "[\|" "\-s {gnu,lucid,arm} " | " \-\-format={gnu,lucid,arm}" "\|]" +.RB "[\|" \-\-help "\|]" +.RB "[\|" \-\-version "\|]" +.RB "[\|" symbol "...\|]" +.SH DESCRIPTION +The C++ language provides function overloading, which means that you can +write many functions with the same name (providing each takes parameters +of different types). All C++ function names are encoded into a +low-level assembly label (this process is known as +.I mangling\c +). The +.B @PROGRAM@ +program does the inverse mapping: it decodes (\fIdemangles\fR) +low-level names into user-level names so that the linker can keep +these overloaded functions from clashing. +.PP +Every alphanumeric word (consisting of letters, digits, underscores, +dollars, or periods) seen in the input is a potential label. If the +label decodes into a C++ name, the C++ name replaces the low-level +name in the output. +.PP +You can use +.B @PROGRAM@ +to decipher individual symbols by specifying these symbols on the +command line. +.PP +If no +.B symbol +arguments are given, +.B @PROGRAM@ +reads symbol names from the standard input and writes the demangled +names to the standard output. All results are printed on the standard +output. +.SH OPTIONS +.TP +.B \-_ +.TP +.B \-\-strip\-underscores +On some systems, both the C and C++ compilers put an +underscore in front of every name. For example, the C name +.B foo +gets the low-level name +.BR _foo . +This option removes the leading underscore. + +.TP +.B "\-s {gnu,lucid,arm}" +.TP +.B \-\-format={gnu,lucid,arm} +GNU +.B nm +can decode three different methods of mangling, used by different C++ +compilers. This option selects which method it uses: the one used by +the GNU compiler, the one used by the Lucid compiler, or the one +specified by the C++ Annotated Reference Manual. The default is the +GNU style. + +.TP +.B \-\-help +Print a summary of the options to +.B @PROGRAM@ +and exit. + +.TP +.B \-\-version +Print the version number of +.B @PROGRAM@ +and exit. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (June 1993). + +.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/gnu/usr.bin/binutils/binutils/deflex.l b/gnu/usr.bin/binutils/binutils/deflex.l new file mode 100644 index 00000000000..6ce50adb260 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/deflex.l @@ -0,0 +1,85 @@ +%{ +/* deflex.l - Lexer for .def files */ + +/* Copyright (C) 1995 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +*/ +#define DONTDECLARE_MALLOC +#include "defparse.h" +extern char *strdup(); +int linenumber; + +%} +%% +"NAME" { return NAME;} +"LIBRARY" { return LIBRARY;} +"DESCRIPTION" { return DESCRIPTION;} +"STACKSIZE" { return STACKSIZE;} +"HEAPSIZE" { return HEAPSIZE;} +"CODE" { return CODE;} +"DATA" { return DATA;} +"SECTIONS" { return SECTIONS;} +"EXPORTS" { return EXPORTS;} +"IMPORTS" { return IMPORTS;} +"VERSION" { return VERSION;} +"BASE" { return BASE;} +"CONSTANT" { return CONSTANT; } +"NONAME" { return NONAME; } +"READ" { return READ;} +"WRITE" { return WRITE;} +"EXECUTE" { return EXECUTE;} +"SHARED" { return SHARED;} + +[0-9][x0-9A-Fa-f]* { yylval.number = strtol (yytext,0,0); + return NUMBER; } + +[A-Za-z$:\-\_][A-Za-z0-9/$:\-\_@]+ { + yylval.id = strdup(yytext); + return ID; + } + +"\""[^\"]*"\"" { + yylval.id = strdup (yytext+1); + yylval.id[yyleng-2] = 0; + return ID; + } + +"\'"[^\']*"\'" { + yylval.id = strdup (yytext+1); + yylval.id[yyleng-2] = 0; + return ID; + } +"*".* { } +";".* { } +" " { } +"\t" { } +"\n" { linenumber ++ ;} +"=" { return '=';} +"." { return '.';} +"@" { return '@';} +"," { return ',';} +%% +#ifndef yywrap +/* Needed for lex, though not flex. */ +int yywrap() { return 1; } +#endif diff --git a/gnu/usr.bin/binutils/binutils/defparse.y b/gnu/usr.bin/binutils/binutils/defparse.y new file mode 100644 index 00000000000..8a0f844458e --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/defparse.y @@ -0,0 +1,132 @@ +/* defparse.y - parser for .def files */ + +/* Copyright (C) 1995 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +%union { + char *id; + int number; +}; + +%token NAME, LIBRARY, DESCRIPTION, STACKSIZE, HEAPSIZE, CODE, DATA +%token SECTIONS, EXPORTS, IMPORTS, VERSION, BASE, CONSTANT +%token READ WRITE EXECUTE SHARED NONAME +%token ID +%token NUMBER +%type opt_base opt_ordinal opt_NONAME opt_CONSTANT attr attr_list opt_number +%type opt_name opt_equal_name + +%% + +start: start command + | command + ; + +command: + NAME opt_name opt_base { def_name ($2, $3); } + | LIBRARY opt_name opt_base { def_library ($2, $3); } + | EXPORTS explist + | DESCRIPTION ID { def_description ($2);} + | STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);} + | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);} + | CODE attr_list { def_code ($2);} + | DATA attr_list { def_data ($2);} + | SECTIONS seclist + | IMPORTS implist + | VERSION NUMBER { def_version ($2,0);} + | VERSION NUMBER '.' NUMBER { def_version ($2,$4);} + ; + + +explist: + explist expline + | expline + ; + +expline: + ID opt_equal_name opt_ordinal opt_NONAME opt_CONSTANT + { def_exports ($1, $2, $3, $4, $5);} + ; +implist: + implist impline + | impline + ; + +impline: + ID '=' ID '.' ID { def_import ($1,$3,$5);} + | ID '.' ID { def_import (0, $1,$3);} + ; +seclist: + seclist secline + | secline + ; + +secline: + ID attr_list { def_section ($1,$2);} + ; + +attr_list: + attr_list opt_comma attr + | attr + ; + +opt_comma: + ',' + | + ; +opt_number: ',' NUMBER { $$=$2;} + | { $$=-1;} + ; + +attr: + READ { $$ = 1;} + | WRITE { $$ = 2;} + | EXECUTE { $$=4;} + | SHARED { $$=8;} + ; + +opt_CONSTANT: + CONSTANT {$$=1;} + | {$$=0;} + ; +opt_NONAME: + NONAME {$$=1;} + | {$$=0;} + ; + +opt_name: ID { $$ =$1; } + | { $$=""; } + ; + +opt_ordinal: + '@' NUMBER { $$=$2;} + | { $$=-1;} + ; + +opt_equal_name: + '=' ID { $$ = $2; } + | { $$ = 0; } + ; + +opt_base: BASE '=' NUMBER { $$= $3;} + | { $$=-1;} + ; + + + diff --git a/gnu/usr.bin/binutils/binutils/dlltool.c b/gnu/usr.bin/binutils/binutils/dlltool.c new file mode 100644 index 00000000000..95abe2bf154 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/dlltool.c @@ -0,0 +1,2030 @@ +#define show_allnames 0 + +/* dlltool.c -- tool to generate stuff for PE style DLLs + Copyright (C) 1995 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public 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 program allows you to build the files necessary to create + DLLs to run on a system which understands PE format image files. + (eg, Windows NT) + + A DLL contains an export table which contains the information + which the runtime loader needs to tie up references from a + referencing program. + + The export table is generated by this program by reading + in a .DEF file or scanning the .a and .o files which will be in the + DLL. A .o file can contain information in special ".drectve" sections + with export information. + + A DEF file contains any number of the following commands: + + + NAME [ , ] + The result is going to be .EXE + + LIBRARY [ , ] + The result is going to be .DLL + + EXPORTS ( [ = ] [ @ ] [ NONAME ] [CONSTANT] ) * + Declares name1 as an exported symbol from the + DLL, with optional ordinal number + + IMPORTS ( [ = ] . ) * + Ignored for compatibility + + DESCRIPTION + Puts into output .exp file in the .rdata section + + [STACKSIZE|HEAPSIZE] [ , ] + Generates --stack|--heap , + in the output .drectve section. The linker will + see this and act upon it. + + [CODE|DATA] + + SECTIONS ( + )* + = READ | WRITE | EXECUTE | SHARED + Generates --attr in the output + .drectve section. The linker will see this and act + upon it. + + + A -export: in a .drectve section in an input .o or .a + file to this program is equivalent to a EXPORTS + in a .DEF file. + + + + The program generates output files with the prefix supplied + on the command line, or in the def file, or taken from the first + supplied argument. + + The .exp.s file contains the information necessary to export + the routines in the DLL. The .lib.s file contains the information + necessary to use the DLL's routines from a referencing program. + + + + Example: + + file1.c: + asm (".section .drectve"); + asm (".ascii \"-export:adef\""); + + adef(char *s) + { + printf("hello from the dll %s\n",s); + } + + bdef(char *s) + { + printf("hello from the dll and the other entry point %s\n",s); + } + + file2.c: + asm (".section .drectve"); + asm (".ascii \"-export:cdef\""); + asm (".ascii \"-export:ddef\""); + cdef(char *s) + { + printf("hello from the dll %s\n",s); + } + + ddef(char *s) + { + printf("hello from the dll and the other entry point %s\n",s); + } + + printf() + { + return 9; + } + + main.c + + main() + { + cdef(); + } + + thedll.def + + LIBRARY thedll + HEAPSIZE 0x40000, 0x2000 + EXPORTS bdef @ 20 + cdef @ 30 NONAME + + SECTIONS donkey READ WRITE + aardvark EXECUTE + + + # compile up the parts of the dll + + gcc -c file1.c + gcc -c file2.c + + # put them in a library (you don't have to, you + # could name all the .os on the dlltool line) + + ar qcv thedll.in file1.o file2.o + ranlib thedll.in + + # run this tool over the library and the def file + ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a + + # build the dll with the library with file1.o, file2.o and the export table + ld -o thedll.dll thedll.o thedll.in + + # build the mainline + gcc -c themain.c + + # link the executable with the import library + ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a + + */ + +#define PAGE_SIZE 4096 +#define PAGE_MASK (-PAGE_SIZE) +#include "bfd.h" +#include "libiberty.h" +#include "bucomm.h" +#include "getopt.h" +#include "demangle.h" +#include +#ifdef HAVE_SYS_WAIT_H +#include +#else +#ifndef WIFEXITED +#define WIFEXITED(w) (((w)&0377) == 0) +#endif +#ifndef WIFSIGNALED +#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0) +#endif +#ifndef WTERMSIG +#define WTERMSIG(w) ((w) & 0177) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(w) (((w) >> 8) & 0377) +#endif +#endif + + + +char *as_name = "as"; + +static int no_idata4; +static int no_idata5; +static char *exp_name; +static char *imp_name; +static char *head_label; +static char *imp_name_lab; +static char *dll_name; + +static int add_indirect = 0; +static int add_underscore = 0; +static int dontdeltemps = 0; + +int yyparse(); +int yydebug; +static char *def_file; + +static char *program_name; +char *strrchr (); +char *strdup (); + +static int machine; +int killat; +static int verbose; +FILE *output_def; +FILE *base_file; + +#ifdef DLLTOOL_ARM +static char *mname = "arm"; +#endif + +#ifdef DLLTOOL_I386 +static char *mname = "i386"; +#endif + +#ifdef DLLTOOL_PPC +static char *mname = "ppc"; +#endif + +#define PATHMAX 250 /* What's the right name for this ? */ + +/* This bit of assemly does jmp * .... +s set how_jtab_roff to mark where the 32bit abs branch should go */ +unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90}; + + +unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5, + 0x00, 0xf0, 0x9c, 0xe5, + 0, 0, 0, 0}; +/* If I understand what is going on here, this will need more for ppc + support, but this lets the program start. Kim Knuttila (krk@cygnus.com) */ + +unsigned char ppc_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90}; + +char outfile[PATHMAX]; +struct mac + { + char *type; + char *how_byte; + char *how_short; + char *how_long; + char *how_asciz; + char *how_comment; + char *how_jump; + char *how_global; + char *how_space; + char *how_align_short; + char *how_align_long; + char *how_bfd_target; + enum bfd_architecture how_bfd_arch; + unsigned char *how_jtab; + int how_jtab_size; /* size of the jtab entry */ + int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */ + } +mtable[] += +{ + { +#define MARM 0 + "arm", ".byte", ".short", ".long", ".asciz", "@", + "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", + ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm, + arm_jtab, sizeof(arm_jtab),8 + } + , + { +#define M386 1 + "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386, + i386_jtab,sizeof(i386_jtab),2, + } + , + { +#define MPPC 2 + "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc, + ppc_jtab,sizeof(ppc_jtab),2, + } + , +{ 0} +}; + + +char * +rvaafter (machine) + int machine; +{ + switch (machine) + { + case MARM: + return ""; + case M386: + return ""; + case MPPC: + return ""; + } +return ""; +} + +char * +rvabefore (machine) + int machine; +{ + switch (machine) + { + case MARM: + return ".rva\t"; + case M386: + return ".rva\t"; + case MPPC: + return ".rva\t"; + } +return ""; +} + +char * +asm_prefix (machine) +int machine; +{ + switch (machine) + { + case MARM: + return ""; + case M386: + return "_"; + case MPPC: + return ""; + } +return ""; +} +#define ASM_BYTE mtable[machine].how_byte +#define ASM_SHORT mtable[machine].how_short +#define ASM_LONG mtable[machine].how_long +#define ASM_TEXT mtable[machine].how_asciz +#define ASM_C mtable[machine].how_comment +#define ASM_JUMP mtable[machine].how_jump +#define ASM_GLOBAL mtable[machine].how_global +#define ASM_SPACE mtable[machine].how_space +#define ASM_ALIGN_SHORT mtable[machine].how_align_short +#define ASM_RVA_BEFORE rvabefore(machine) +#define ASM_RVA_AFTER rvaafter(machine) +#define ASM_PREFIX asm_prefix(machine) +#define ASM_ALIGN_LONG mtable[machine].how_align_long +#define HOW_BFD_TARGET 0 /* always default*/ +#define HOW_BFD_ARCH mtable[machine].how_bfd_arch +#define HOW_JTAB mtable[machine].how_jtab +#define HOW_JTAB_SIZE mtable[machine].how_jtab_size +#define HOW_JTAB_ROFF mtable[machine].how_jtab_roff +static char **oav; + + +FILE *yyin; /* communications with flex */ +extern int linenumber; +void +process_def_file (name) + char *name; +{ + FILE *f = fopen (name, FOPEN_RT); + if (!f) + { + fprintf (stderr, "%s: Can't open def file %s\n", program_name, name); + exit (1); + } + + yyin = f; + + yyparse (); +} + +/**********************************************************************/ + +/* Communications with the parser */ + + +typedef struct dlist +{ + char *text; + struct dlist *next; +} +dlist_type; + +typedef struct export + { + char *name; + char *internal_name; + int ordinal; + int constant; + int noname; + int hint; + struct export *next; + } +export_type; + +static char *d_name; /* Arg to NAME or LIBRARY */ +static int d_nfuncs; /* Number of functions exported */ +static int d_named_nfuncs; /* Number of named functions exported */ +static int d_low_ord; /* Lowest ordinal index */ +static int d_high_ord; /* Highest ordinal index */ +static export_type *d_exports; /*list of exported functions */ +static export_type **d_exports_lexically; /* vector of exported functions in alpha order */ +static dlist_type *d_list; /* Descriptions */ +static dlist_type *a_list; /* Stuff to go in directives */ + +static int d_is_dll; +static int d_is_exe; + +int +yyerror () +{ + fprintf (stderr, "%s: Syntax error in def file %s:%d\n", + program_name, def_file, linenumber); + return 0; +} + +void +def_exports (name, internal_name, ordinal, noname, constant) + char *name; + char *internal_name; + int ordinal; + int noname; + int constant; +{ + struct export *p = (struct export *) xmalloc (sizeof (*p)); + + p->name = name; + p->internal_name = internal_name ? internal_name : name; + p->ordinal = ordinal; + p->constant = constant; + p->noname = noname; + p->next = d_exports; + d_exports = p; + d_nfuncs++; +} + + +void +def_name (name, base) + char *name; + int base; +{ + if (verbose) + fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base); + if (d_is_dll) + { + fprintf (stderr, "Can't have LIBRARY and NAME\n"); + } + d_name = name; + d_is_exe = 1; +} + +void +def_library (name, base) + char *name; + int base; +{ + if (verbose) + printf ("%s: LIBRARY %s base %x\n", program_name, name, base); + if (d_is_exe) + { + fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name); + } + d_name = name; + d_is_dll = 1; +} + +void +def_description (desc) + char *desc; +{ + dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); + d->text = strdup (desc); + d->next = d_list; + d_list = d; +} + +void +new_directive (dir) + char *dir; +{ + dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); + d->text = strdup (dir); + d->next = a_list; + a_list = d; +} + +void +def_stacksize (reserve, commit) + int reserve; + int commit; +{ + char b[200]; + if (commit > 0) + sprintf (b, "-stack 0x%x,0x%x ", reserve, commit); + else + sprintf (b, "-stack 0x%x ", reserve); + new_directive (strdup (b)); +} + +void +def_heapsize (reserve, commit) + int reserve; + int commit; +{ + char b[200]; + if (commit > 0) + sprintf (b, "-heap 0x%x,0x%x ", reserve, commit); + else + sprintf (b, "-heap 0x%x ", reserve); + new_directive (strdup (b)); +} + + +void +def_import (internal, module, entry) + char *internal; + char *module; + char *entry; +{ + if (verbose) + fprintf (stderr, "%s: IMPORTS are ignored", program_name); +} + +void +def_version (major, minor) +int major; +int minor; +{ + printf ("VERSION %d.%d\n", major, minor); +} + + +void +def_section (name, attr) + char *name; + int attr; +{ + char buf[200]; + char atts[5]; + char *d = atts; + if (attr & 1) + *d++ = 'R'; + + if (attr & 2) + *d++ = 'W'; + if (attr & 4) + *d++ = 'X'; + if (attr & 8) + *d++ = 'S'; + *d++ = 0; + sprintf (buf, "-attr %s %s", name, atts); + new_directive (strdup (buf)); +} +void +def_code (attr) + int attr; +{ + + def_section ("CODE", attr); +} + +void +def_data (attr) + int attr; +{ + def_section ("DATA", attr); +} + + +/**********************************************************************/ + +void +run (what, args) + char *what; + char *args; +{ + char *s; + int pid; + int i; + char **argv; + extern char **environ; + if (verbose) + fprintf (stderr, "%s %s\n", what, args); + + /* Count the args */ + i = 0; + for (s = args; *s; s++) + if (*s == ' ') + i++; + i++; + argv = alloca (sizeof (char *) * (i + 3)); + i = 0; + argv[i++] = what; + s = args; + while (1) + { + argv[i++] = s; + while (*s != ' ' && *s != 0) + s++; + if (*s == 0) + break; + *s++ = 0; + } + argv[i++] = 0; + + + pid = vfork (); + + if (pid == 0) + { + execvp (what, argv); + fprintf (stderr, "%s: can't exec %s\n", program_name, what); + exit (1); + } + else if (pid == -1) + { + extern int errno; + fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno); + exit (1); + } + else + { + int status; + waitpid (pid, &status, 0); + if (status) + { + if (WIFSIGNALED (status)) + { + fprintf (stderr, "%s: %s %s terminated with signal %d\n", + program_name, what, args, WTERMSIG (status)); + exit (1); + } + + if (WIFEXITED (status)) + { + fprintf (stderr, "%s: %s %s terminated with exit status %d\n", + program_name, what, args, WEXITSTATUS (status)); + exit (1); + } + } + } +} + +/* read in and block out the base relocations */ +static void +basenames (abfd) + bfd *abfd; +{ + + + + +} + +void +scan_open_obj_file (abfd) + bfd *abfd; +{ + /* Look for .drectve's */ + asection *s = bfd_get_section_by_name (abfd, ".drectve"); + if (s) + { + int size = bfd_get_section_size_before_reloc (s); + char *buf = xmalloc (size); + char *p; + char *e; + bfd_get_section_contents (abfd, s, buf, 0, size); + if (verbose) + fprintf (stderr, "%s: Sucking in info from %s\n", + program_name, + bfd_get_filename (abfd)); + + /* Search for -export: strings */ + p = buf; + e = buf + size; + while (p < e) + { + if (p[0] == '-' + && strncmp (p, "-export:", 8) == 0) + { + char *name; + char *c; + p += 8; + name = p; + while (*p != ' ' && *p != '-' && p < e) + p++; + c = xmalloc (p - name + 1); + memcpy (c, name, p - name); + c[p - name] = 0; + def_exports (c, 0, -1, 0); + } + else + p++; + } + free (buf); + } + + basenames (abfd); + + if (verbose) + fprintf (stderr, "%s: Done readin\n", + program_name); + +} + + +void +scan_obj_file (filename) + char *filename; +{ + bfd *f = bfd_openr (filename, 0); + + if (!f) + { + fprintf (stderr, "%s: Unable to open object file %s\n", + program_name, + filename); + exit (1); + } + if (bfd_check_format (f, bfd_archive)) + { + bfd *arfile = bfd_openr_next_archived_file (f, 0); + while (arfile) + { + if (bfd_check_format (arfile, bfd_object)) + scan_open_obj_file (arfile); + bfd_close (arfile); + arfile = bfd_openr_next_archived_file (f, arfile); + } + } + else if (bfd_check_format (f, bfd_object)) + { + scan_open_obj_file (f); + } + + bfd_close (f); +} + +/**********************************************************************/ + + + +void +dump_def_info (f) + FILE *f; +{ + int i; + export_type *exp; + fprintf (f, "%s ", ASM_C); + for (i = 0; oav[i]; i++) + fprintf (f, "%s ", oav[i]); + fprintf (f, "\n"); + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + fprintf (f, "%s %d = %s %s @ %d %s%s\n", + ASM_C, + i, + exp->name, + exp->internal_name, + exp->ordinal, + exp->noname ? "NONAME " : "", + exp->constant ? "CONSTANT" : ""); + } +} +/* Generate the .exp file */ + +int +sfunc (a, b) + long *a; + long *b; +{ + return *a - *b; +} + + + +static void +flush_page (f, need, page_addr, on_page) + FILE *f; + int *need; + int page_addr; + int on_page; +{ + int i; + + /* Flush this page */ + fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n", + ASM_LONG, + page_addr, + ASM_C); + fprintf (f, "\t%s\t0x%x\t%s Size of block\n", + ASM_LONG, + (on_page * 2) + (on_page & 1) * 2 + 8, + ASM_C); + for (i = 0; i < on_page; i++) + { + fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, (need[i] - page_addr) | 0x3000); + } + /* And padding */ + if (on_page & 1) + fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000); + +} + + +void +gen_def_file () +{ + int i; + export_type *exp; + + fprintf (output_def, ";"); + for (i = 0; oav[i]; i++) + fprintf (output_def, " %s", oav[i]); + + fprintf (output_def, "\nEXPORTS\n"); + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + char *quote = strchr (exp->name, '.') ? "\"" : ""; + fprintf (output_def, "\t%s%s%s @ %d%s ; %s\n", + quote, + exp->name, + quote, + exp->ordinal, + exp->noname ? " NONAME" : "", + cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS)); + } +} +void +gen_exp_file () +{ + FILE *f; + int i; + export_type *exp; + dlist_type *dl; + + + sprintf (outfile, "t%s", exp_name); + + if (verbose) + fprintf (stderr, "%s: Generate exp file %s\n", + program_name, exp_name); + + f = fopen (outfile, FOPEN_WT); + if (!f) + { + fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile); + exit (1); + } + if (verbose) + { + fprintf (stderr, "%s: Opened file %s\n", + program_name, outfile); + } + + dump_def_info (f); + if (d_exports) + { + fprintf (f, "\t.section .edata\n\n"); + fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s 0x%x %s Time and date\n", ASM_LONG, time(0),ASM_C); + fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C); + fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C); + + + fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C); + fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n", + ASM_C, + d_named_nfuncs, d_low_ord, d_high_ord); + fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, + show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C); + fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + + fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n", + ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + + fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + + fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name); + + + fprintf(f,"%s Export address Table\n", ASM_C); + fprintf(f,"\t%s\n", ASM_ALIGN_LONG); + fprintf (f, "afuncs:\n"); + i = d_low_ord; + + for (exp = d_exports; exp; exp = exp->next) + { + if (exp->ordinal != i) + { +#if 0 + fprintf (f, "\t%s\t%d\t%s %d..%d missing\n", + ASM_SPACE, + (exp->ordinal - i) * 4, + ASM_C, + i, exp->ordinal - 1); + i = exp->ordinal; +#endif + while (i < exp->ordinal) + { + fprintf(f,"\t%s\t0\n", ASM_LONG); + i++; + } + } + fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE, + ASM_PREFIX, + exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); + i++; + } + + fprintf (f,"%s Export Name Pointer Table\n", ASM_C); + fprintf (f, "anames:\n"); + + for (i = 0; (exp = d_exports_lexically[i]); i++) + { + if (!exp->noname || show_allnames) + fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER); + } + + fprintf (f,"%s Export Oridinal Table\n", ASM_C); + fprintf (f, "anords:\n"); + for (i = 0; (exp = d_exports_lexically[i]); i++) + { + if (!exp->noname || show_allnames) + fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord); + } + + fprintf(f,"%s Export Name Table\n", ASM_C); + for (i = 0; (exp = d_exports_lexically[i]); i++) + if (!exp->noname || show_allnames) + fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name); + + if (a_list) + { + fprintf (f, "\t.section .drectve\n"); + for (dl = a_list; dl; dl = dl->next) + { + fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text); + } + } + if (d_list) + { + fprintf (f, "\t.section .rdata\n"); + for (dl = d_list; dl; dl = dl->next) + { + char *p; + int l; + /* We dont output as ascii 'cause there can + be quote characters in the string */ + + l = 0; + for (p = dl->text; *p; p++) + { + if (l == 0) + fprintf (f, "\t%s\t", ASM_BYTE); + else + fprintf (f, ","); + fprintf (f, "%d", *p); + if (p[1] == 0) + { + fprintf (f, ",0\n"); + break; + } + if (++l == 10) + { + fprintf (f, "\n"); + l = 0; + } + } + } + } + } + + + /* Add to the output file a way of getting to the exported names + without using the import library. */ + if (add_indirect) + { + fprintf (f, "\t.section\t.rdata\n"); + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + if (!exp->noname || show_allnames) + { + fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name); + fprintf (f, "__imp_%s:\n", exp->name); + fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name); + } + } + + /* Dump the reloc section if a base file is provided */ + if (base_file) + { + int addr; + long need[PAGE_SIZE]; + long page_addr; + int numbytes; + int num_entries; + long *copy; + int j; + int on_page; + fprintf (f, "\t.section\t.init\n"); + fprintf (f, "lab:\n"); + + fseek (base_file, 0, SEEK_END); + numbytes = ftell (base_file); + fseek (base_file, 0, SEEK_SET); + copy = malloc (numbytes); + fread (copy, 1, numbytes, base_file); + num_entries = numbytes / sizeof (long); + + + fprintf (f, "\t.section\t.reloc\n"); + if (num_entries) + { + + int src; + int dst = 0; + int last = -1; + qsort (copy, num_entries, sizeof (long), sfunc); + /* Delete duplcates */ + for (src = 0; src < num_entries; src++) + { + if (last != copy[src]) + last = copy[dst++] = copy[src]; + } + num_entries = dst; + addr = copy[0]; + page_addr = addr & PAGE_MASK; /* work out the page addr */ + on_page = 0; + for (j = 0; j < num_entries; j++) + { + addr = copy[j]; + if ((addr & PAGE_MASK) != page_addr) + { + flush_page (f, need, page_addr, on_page); + on_page = 0; + page_addr = addr & PAGE_MASK; + } + need[on_page++] = addr; + } + flush_page (f, need, page_addr, on_page); + +/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/ + } + } + + fclose (f); + + /* assemble the file */ + sprintf (outfile, "-o %s t%s", exp_name, exp_name); + run (as_name, outfile); + if (dontdeltemps == 0) + { + sprintf (outfile, "t%s", exp_name); + unlink (outfile); + } +} + +static char * +xlate (char *name) +{ + if (add_underscore) + { + char *copy = malloc (strlen (name) + 2); + copy[0] = '_'; + strcpy (copy + 1, name); + name = copy; + } + + if (killat) + { + char *p; + p = strchr (name, '@'); + if (p) + *p = 0; + } + return name; +} + +/**********************************************************************/ + +static void dump_iat (f, exp) +FILE *f; +export_type *exp; +{ + if (exp->noname && !show_allnames ) + { + fprintf (f, "\t%s\t0x%08x\n", + ASM_LONG, + exp->ordinal | 0x80000000); /* hint or orindal ?? */ + } + else + { + fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE, + exp->ordinal, + ASM_RVA_AFTER); + } +} + + + +typedef struct +{ + int id; + const char *name; + int flags; + asection *sec; + asymbol *sym; + asymbol **sympp; + int size; + unsigned char *data; +} sinfo; + + +#define TEXT 0 +#define DATA 1 +#define BSS 2 +#define IDATA7 3 +#define IDATA5 4 +#define IDATA4 5 +#define IDATA6 6 +#define NSECS 7 + +static sinfo secdata[NSECS] = +{ + { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS}, + { DATA, ".data", SEC_DATA}, + { BSS,".bss" }, + { IDATA7, ".idata$7",SEC_HAS_CONTENTS}, + { IDATA5, ".idata$5", SEC_HAS_CONTENTS}, + { IDATA4, ".idata$4", SEC_HAS_CONTENTS}, + { IDATA6,".idata$6", SEC_HAS_CONTENTS} + + +}; +/* +This is what we're trying to make + + .text + .global _GetFileVersionInfoSizeW@8 + .global __imp_GetFileVersionInfoSizeW@8 +_GetFileVersionInfoSizeW@8: + jmp * __imp_GetFileVersionInfoSizeW@8 + .section .idata$7 # To force loading of head + .long __version_a_head +# Import Address Table + .section .idata$5 +__imp_GetFileVersionInfoSizeW@8: + .rva ID2 + +# Import Lookup Table + .section .idata$4 + .rva ID2 +# Hint/Name table + .section .idata$6 +ID2: .short 2 + .asciz "GetFileVersionInfoSizeW" + +*/ + +static char *make_label (prefix, name) +const char *prefix; +const char *name; +{ + int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name); + char *copy = xmalloc (len +1 ); + strcpy (copy, ASM_PREFIX); + strcat (copy, prefix); + strcat (copy, name); + return copy; +} +static bfd * +make_one_lib_file (exp, i) +export_type *exp; +int i; +{ + if (0) + { + FILE *f; + char *prefix="d"; + sprintf (outfile, "%ss%d.s", prefix, i); + f = fopen (outfile, FOPEN_WT); + fprintf (f, "\t.text\n"); + fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name); + fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name); + fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX, + exp->name, ASM_JUMP, exp->name); + + fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C); + fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label); + + + fprintf (f,"%s Import Address Table\n", ASM_C); + + fprintf (f, "\t.section .idata$5\n"); + fprintf (f, "__imp_%s:\n", exp->name); + + dump_iat (f, exp); + + fprintf (f, "\n%s Import Lookup Table\n", ASM_C); + fprintf (f, "\t.section .idata$4\n"); + + dump_iat (f, exp); + + if(!exp->noname || show_allnames) + { + fprintf (f, "%s Hint/Name table\n", ASM_C); + fprintf (f, "\t.section .idata$6\n"); + fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint); + fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name)); + } + + fclose (f); + + + sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i); + + run (as_name, outfile); + + } + else + { + + bfd *abfd; + + asymbol *exp_label; + asymbol *iname; + asymbol *iname_lab; + asymbol **iname_lab_pp; + asymbol *ptrs[NSECS+3+1]; /* one symbol for each section, 2 extra + a null */ + + char *outname = xmalloc (10); + int oidx = 0; + sprintf (outname, "ds%d.o", i); + abfd = bfd_openw (outname, HOW_BFD_TARGET); + if (!abfd) + { + fprintf (stderr, "%s: bfd_open failed open output file %s\n", program_name, outname); + exit (1); + } + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0); + + + for (i = 0; i < NSECS; i++) + { + sinfo *si = secdata + i; + if (si->id != i) + abort(); + si->sec = bfd_make_section_old_way (abfd, si->name); + bfd_set_section_flags (abfd, + si->sec, + si->flags); + si->sec->output_section = si->sec; + si->sym = bfd_make_empty_symbol(abfd); + si->sym->name = si->sec->name; + si->sym->section = si->sec; + si->sym->flags = BSF_LOCAL; + si->sym->value = 0; + ptrs[oidx] = si->sym; + si->sympp = ptrs + oidx; + + oidx++; + } + + exp_label = bfd_make_empty_symbol(abfd); + exp_label->name = make_label ("",exp->name); + exp_label->section = secdata[TEXT].sec; + exp_label->flags = BSF_GLOBAL; + exp_label->value = 0; + + ptrs[oidx++] = exp_label; + + iname = bfd_make_empty_symbol(abfd); + + iname->name = make_label ("__imp_", exp->name); + + iname->section = secdata[IDATA5].sec; + iname->flags = BSF_GLOBAL; + iname->value = 0; + + + iname_lab = bfd_make_empty_symbol(abfd); + + iname_lab->name = head_label; + iname_lab->section = (asection *)&bfd_und_section; + iname_lab->flags = 0; + iname_lab->value = 0; + + + ptrs[oidx++] = iname; + iname_lab_pp = ptrs + oidx; + ptrs[oidx++] = iname_lab; + ptrs[oidx] = 0; + + for (i = 0; i < NSECS; i++) + { + sinfo *si = secdata + i; + asection *sec = si->sec; + arelent *rel; + arelent **rpp; + + switch (i) + { + case TEXT: + si->size = HOW_JTAB_SIZE; + si->data = xmalloc (HOW_JTAB_SIZE); + memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE); + + /* add the reloc into idata$5 */ + rel = xmalloc (sizeof (arelent)); + rpp = xmalloc (sizeof (arelent *) * 2); + rpp[0] = rel; + rpp[1] = 0; + rel->address = HOW_JTAB_ROFF; + rel->addend = 0; + rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); + rel->sym_ptr_ptr = secdata[IDATA5].sympp; + sec->orelocation = rpp; + sec->reloc_count = 1; + break; + case IDATA4: + case IDATA5: + /* An idata$4 or idata$5 is one word long, and has an + rva to idata$6 */ + + + si->data = xmalloc (4); + si->size = 4; + + if (exp->noname) + { + si->data[0] = exp->ordinal ; + si->data[1] = exp->ordinal >> 8; + si->data[2] = exp->ordinal >> 16; + si->data[3] = 0x80; + } + else + { + sec->reloc_count = 1; + memset (si->data, 0, si->size); + rel = xmalloc (sizeof (arelent)); + rpp = xmalloc (sizeof (arelent *) * 2); + rpp[0] = rel; + rpp[1] = 0; + rel->address = 0; + rel->addend = 0; + rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); + rel->sym_ptr_ptr = secdata[IDATA6].sympp; + sec->orelocation = rpp; + } + + break; + + case IDATA6: + if (!exp->noname) + { + int idx = exp->hint + 1; + si->size = strlen (xlate (exp->name)) + 3; + si->data = xmalloc (si->size); + si->data[0] = idx & 0xff; + si->data[1] = idx >> 8; + strcpy (si->data + 2, xlate (exp->name)); + } + break; + case IDATA7: + si->size = 4; + si->data =xmalloc(4); + memset (si->data, 0, si->size); + rel = xmalloc (sizeof (arelent)); + rpp = xmalloc (sizeof (arelent *) * 2); + rpp[0] = rel; + rel->address = 0; + rel->addend = 0; + rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); + rel->sym_ptr_ptr = iname_lab_pp; + sec->orelocation = rpp; + sec->reloc_count = 1; + break; + } + } + + { + bfd_vma vma = 0; + /* Size up all the sections */ + for (i = 0; i < NSECS; i++) + { + sinfo *si = secdata + i; + bfd_set_section_size (abfd, si->sec, si->size); + bfd_set_section_vma (abfd, si->sec, vma); +/* vma += si->size;*/ + } + } + /* Write them out */ + for (i = 0; i < NSECS; i++) + { + sinfo *si = secdata + i; + if (i == IDATA5 && no_idata5) + continue; + + if (i == IDATA4 && no_idata4) + continue; + + bfd_set_section_contents (abfd, si->sec, + si->data, 0, + si->size); + } + + bfd_set_symtab (abfd, ptrs, oidx); + bfd_close (abfd); + abfd = bfd_openr (outname, HOW_BFD_TARGET); + return abfd; + } + +} + + +static +bfd * +make_head() +{ + FILE * f = fopen ("dh.s", FOPEN_WT); + + fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C); + fprintf (f, "\t.section .idata$2\n"); + + fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label); + + fprintf (f, "%s:\n", head_label); + + fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n", + ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + + fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C); + fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C); + fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n", + ASM_RVA_BEFORE, + imp_name_lab, + ASM_RVA_AFTER, + ASM_C); + fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n", + ASM_RVA_BEFORE, + ASM_RVA_AFTER, ASM_C); + + fprintf (f, "%sStuff for compatibility\n", ASM_C); + + if (!no_idata5) + { + fprintf (f, "\t.section\t.idata$5\n"); + fprintf (f, "\t%s\t0\n", ASM_LONG); + fprintf (f, "fthunk:\n"); + } + if (!no_idata4) + { + fprintf (f, "\t.section\t.idata$4\n"); + + fprintf (f, "\t%s\t0\n", ASM_LONG); + fprintf (f, "\t.section .idata$4\n"); + fprintf (f, "hname:\n"); + } + fclose (f); + + sprintf (outfile, "-o dh.o dh.s"); + run (as_name, outfile); + + return bfd_openr ("dh.o", HOW_BFD_TARGET); +} + +static +bfd * make_tail() +{ + FILE * f = fopen ("dt.s", FOPEN_WT); + fprintf (f, "\t.section .idata$7\n"); + fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab); + fprintf (f, "__%s_iname:\t%s\t\"%s\"\n", + imp_name_lab, ASM_TEXT, dll_name); + + if (!no_idata4) + { + fprintf (f, "\t.section .idata$4\n"); + fprintf (f, "\t%s\t0\n", ASM_LONG); + } + if (!no_idata5) + { + fprintf (f, "\t.section .idata$5\n"); + fprintf (f, "\t%s\t0\n", ASM_LONG); + } + fclose (f); + + sprintf (outfile, "-o dt.o dt.s"); + run (as_name, outfile); + return bfd_openr ("dt.o", HOW_BFD_TARGET); +} + +static void +gen_lib_file () +{ + int i; + export_type *exp; + bfd *ar_head; + bfd *ar_tail; + bfd *outarch; + bfd * head = 0; + + unlink (imp_name); + + outarch = bfd_openw (imp_name, HOW_BFD_TARGET); + + if (!outarch) + { + fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name); + exit (1); + } + bfd_set_format (outarch, bfd_archive); + outarch->has_armap = 1; + + /* Work out a reasonable size of things to put onto one line. */ + + + + ar_head = make_head (); + ar_tail = make_tail(); + + for (i = 0; (exp = d_exports_lexically[i]); i++) + { + bfd *n = make_one_lib_file (exp, i); + n->next = head; + head = n; + } + + + /* Now stick them all into the archive */ + + ar_head->next = head; + ar_tail->next = ar_head; + head = ar_tail; + + bfd_set_archive_head (outarch, head); + bfd_close (outarch); + + /* Delete all the temp files */ + + if (dontdeltemps == 0) + { + sprintf (outfile, "dh.o"); + unlink (outfile); + sprintf (outfile, "dh.s"); + unlink (outfile); + sprintf (outfile, "dt.o"); + unlink (outfile); + sprintf (outfile, "dt.s"); + unlink (outfile); + } + + if (dontdeltemps < 2) + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + sprintf (outfile, "ds%d.o",i); + unlink (outfile); + } + +} +/**********************************************************************/ + +/* Run through the information gathered from the .o files and the + .def file and work out the best stuff */ +int +pfunc (a, b) + void *a; + void *b; +{ + export_type *ap = *(export_type **) a; + export_type *bp = *(export_type **) b; + if (ap->ordinal == bp->ordinal) + return 0; + + /* unset ordinals go to the bottom */ + if (ap->ordinal == -1) + return 1; + if (bp->ordinal == -1) + return -1; + return (ap->ordinal - bp->ordinal); +} + + +int +nfunc (a, b) + void *a; + void *b; +{ + export_type *ap = *(export_type **) a; + export_type *bp = *(export_type **) b; + + return (strcmp (ap->name, bp->name)); +} + +static +void +remove_null_names (ptr) + export_type **ptr; +{ + int src; + int dst; + for (dst = src = 0; src < d_nfuncs; src++) + { + if (ptr[src]) + { + ptr[dst] = ptr[src]; + dst++; + } + } + d_nfuncs = dst; +} + +static void +dtab (ptr) + export_type **ptr; +{ +#ifdef SACDEBUG + int i; + for (i = 0; i < d_nfuncs; i++) + { + if (ptr[i]) + { + printf ("%d %s @ %d %s%s\n", + i, ptr[i]->name, ptr[i]->ordinal, + ptr[i]->noname ? "NONAME " : "", + ptr[i]->constant ? "CONSTANT" : ""); + } + else + printf ("empty\n"); + } +#endif +} + +static void +process_duplicates (d_export_vec) + export_type **d_export_vec; +{ + int more = 1; + int i; + while (more) + { + + more = 0; + /* Remove duplicates */ + qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc); + + dtab (d_export_vec); + for (i = 0; i < d_nfuncs - 1; i++) + { + if (strcmp (d_export_vec[i]->name, + d_export_vec[i + 1]->name) == 0) + { + + export_type *a = d_export_vec[i]; + export_type *b = d_export_vec[i + 1]; + + more = 1; + if (verbose) + fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n", + a->name, + a->ordinal, + b->ordinal); + if (a->ordinal != -1 + && b->ordinal != -1) + { + + fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n", + a->name); + exit (1); + } + /* Merge attributes */ + b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal; + b->constant |= a->constant; + b->noname |= a->noname; + d_export_vec[i] = 0; + } + + dtab (d_export_vec); + remove_null_names (d_export_vec); + dtab (d_export_vec); + } + } + + + /* Count the names */ + for (i = 0; i < d_nfuncs; i++) + { + if (!d_export_vec[i]->noname) + d_named_nfuncs++; + } +} + +static void +fill_ordinals (d_export_vec) + export_type **d_export_vec; +{ + int lowest = 0; + + int i; + char *ptr; + qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); + + /* fill in the unset ordinals with ones from our range */ + + ptr = (char *) malloc (65536); + + memset (ptr, 0, 65536); + + /* Mark in our large vector all the numbers that are taken */ + for (i = 0; i < d_nfuncs; i++) + { + if (d_export_vec[i]->ordinal != -1) + { + ptr[d_export_vec[i]->ordinal] = 1; + if (lowest == 0) + lowest = d_export_vec[i]->ordinal; + } + } + + for (i = 0; i < d_nfuncs; i++) + { + if (d_export_vec[i]->ordinal == -1) + { + int j; + for (j = lowest; j < 65536; j++) + if (ptr[j] == 0) + { + ptr[j] = 1; + d_export_vec[i]->ordinal = j; + goto done; + } + + for (j = 1; j < lowest; j++) + if (ptr[j] == 0) + { + ptr[j] = 1; + d_export_vec[i]->ordinal = j; + goto done; + } + done:; + + } + } + + free (ptr); + + /* And resort */ + + qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); + + + /* Work out the lowest ordinal number */ + if (d_export_vec[0]) + d_low_ord = d_export_vec[0]->ordinal; + if (d_nfuncs) + { + if (d_export_vec[d_nfuncs-1]) + d_high_ord = d_export_vec[d_nfuncs-1]->ordinal; + } +} + +int alphafunc(av,bv) +void *av; +void *bv; +{ + export_type **a = av; + export_type **b = bv; + + return strcmp ((*a)->name, (*b)->name); +} + +void +mangle_defs () +{ + /* First work out the minimum ordinal chosen */ + + export_type *exp; + + int i; + int hint = 0; + export_type **d_export_vec + = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs); + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + d_export_vec[i] = exp; + } + + process_duplicates (d_export_vec); + fill_ordinals (d_export_vec); + + /* Put back the list in the new order */ + d_exports = 0; + for (i = d_nfuncs - 1; i >= 0; i--) + { + d_export_vec[i]->next = d_exports; + d_exports = d_export_vec[i]; + } + + /* Build list in alpha order */ + d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1)); + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + d_exports_lexically[i] = exp; + } + d_exports_lexically[i] = 0; + + qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc); + + /* Fill exp entries with their hint values */ + + for (i = 0; i < d_nfuncs; i++) + { + if (!d_exports_lexically[i]->noname || show_allnames) + d_exports_lexically[i]->hint = hint++; + } + +} + + + + + + +/**********************************************************************/ + +void +usage (file, status) + FILE *file; + int status; +{ + fprintf (file, "Usage %s \n", program_name); + fprintf (file, " --machine \n"); + fprintf (file, " --output-exp Generate export file.\n"); + fprintf (file, " --output-lib Generate input library.\n"); + fprintf (file, " --add-indirect Add dll indirects to export file.\n"); + fprintf (file, " --dllname Name of input dll to put into output lib.\n"); + fprintf (file, " --def Name input .def file\n"); + fprintf (file, " --output-def Name output .def file\n"); + fprintf (file, " --base-file Read linker generated base file\n"); + fprintf (file, " --no-idata4 Don't generate idata$4 section\n"); + fprintf (file, " --no-idata5 Don't generate idata$5 section\n"); + fprintf (file, " -v Verbose\n"); + fprintf (file, " -U Add underscores to .lib\n"); + fprintf (file, " -k Kill @ from exported names\n"); + fprintf (file, " --as Use for assembler\n"); + fprintf (file, " --nodelete Keep temp files.\n"); + exit (status); +} + +#define OPTION_NO_IDATA4 'x' +#define OPTION_NO_IDATA5 'c' +static struct option long_options[] = +{ + {"nodelete", no_argument, NULL, 'n'}, + {"dllname", required_argument, NULL, 'D'}, + {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4}, + {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5}, + {"output-exp", required_argument, NULL, 'e'}, + {"output-def", required_argument, NULL, 'z'}, + {"output-lib", required_argument, NULL, 'l'}, + {"def", required_argument, NULL, 'd'}, + {"add-underscore", no_argument, NULL, 'U'}, + {"killat", no_argument, NULL, 'k'}, + {"help", no_argument, NULL, 'h'}, + {"machine", required_argument, NULL, 'm'}, + {"add-indirect", no_argument, NULL, 'a'}, + {"base-file", required_argument, NULL, 'b'}, + {"as", required_argument, NULL, 'S'}, + {0} +}; + + + +int +main (ac, av) + int ac; + char **av; +{ + int c; + int i; + char *firstarg = 0; + program_name = av[0]; + oav = av; + + while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0)) + != EOF) + { + switch (c) + { + case OPTION_NO_IDATA4: + no_idata4 = 1; + break; + case OPTION_NO_IDATA5: + no_idata5 = 1; + break; + case 'S': + as_name = optarg; + break; + + /* ignored for compatibility */ + case 'u': + break; + case 'a': + add_indirect = 1; + break; + case 'z': + output_def = fopen (optarg, FOPEN_WT); + break; + case 'D': + dll_name = optarg; + break; + case 'l': + imp_name = optarg; + break; + case 'e': + exp_name = optarg; + break; + case 'h': + case '?': + usage (stderr, 0); + break; + case 'm': + mname = optarg; + break; + case 'v': + verbose = 1; + break; + case 'y': + yydebug = 1; + break; + case 'U': + add_underscore = 1; + break; + case 'k': + killat = 1; + break; + case 'd': + def_file = optarg; + break; + case 'n': + dontdeltemps++; + break; + case 'b': + base_file = fopen (optarg, FOPEN_RB); + if (!base_file) + { + fprintf (stderr, "%s: Unable to open base-file %s\n", + av[0], + optarg); + exit (1); + } + break; + default: + usage (stderr, 1); + } + } + + + for (i = 0; mtable[i].type; i++) + { + if (strcmp (mtable[i].type, mname) == 0) + break; + } + + if (!mtable[i].type) + { + fprintf (stderr, "Machine not supported\n"); + exit (1); + } + machine = i; + + + if (!dll_name && exp_name) + { + char len = strlen (exp_name) + 5; + dll_name = xmalloc (len); + strcpy (dll_name, exp_name); + strcat (dll_name, ".dll"); + } + + if (def_file) + { + process_def_file (def_file); + } + while (optind < ac) + { + if (!firstarg) + firstarg = av[optind]; + scan_obj_file (av[optind]); + optind++; + } + + + mangle_defs (); + + if (exp_name) + gen_exp_file (); + if (imp_name) + { + /* Make imp_name safe for use as a label. */ + char *p; + imp_name_lab = strdup (imp_name); + for (p = imp_name_lab; *p; *p++) + { + if (!isalpha (*p) && !isdigit (*p)) + *p = '_'; + } + head_label = make_label("_head_", imp_name_lab); + gen_lib_file (); + } + if (output_def) + gen_def_file (); + + return 0; +} diff --git a/gnu/usr.bin/binutils/binutils/filemode.c b/gnu/usr.bin/binutils/binutils/filemode.c new file mode 100644 index 00000000000..a8b00cd58cf --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/filemode.c @@ -0,0 +1,264 @@ +/* filemode.c -- make a string describing file modes + Copyright (C) 1985, 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public 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" + +static char ftypelet PARAMS ((unsigned long)); +static void setst PARAMS ((unsigned long, char *)); + +/* 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. */ + +#if 0 + +/* This is not used; only mode_string is used. */ + +void +filemodestring (statp, str) + struct stat *statp; + char *str; +{ + mode_string ((unsigned long) statp->st_mode, str); +} + +#endif + +/* Get definitions for the file permission bits. */ + +#ifndef S_IRWXU +#define S_IRWXU 0700 +#endif +#ifndef S_IRUSR +#define S_IRUSR 0400 +#endif +#ifndef S_IWUSR +#define S_IWUSR 0200 +#endif +#ifndef S_IXUSR +#define S_IXUSR 0100 +#endif + +#ifndef S_IRWXG +#define S_IRWXG 0070 +#endif +#ifndef S_IRGRP +#define S_IRGRP 0040 +#endif +#ifndef S_IWGRP +#define S_IWGRP 0020 +#endif +#ifndef S_IXGRP +#define S_IXGRP 0010 +#endif + +#ifndef S_IRWXO +#define S_IRWXO 0007 +#endif +#ifndef S_IROTH +#define S_IROTH 0004 +#endif +#ifndef S_IWOTH +#define S_IWOTH 0002 +#endif +#ifndef S_IXOTH +#define S_IXOTH 0001 +#endif + +/* Like filemodestring, but only the relevant part of the `struct stat' + is given as an argument. */ + +void +mode_string (mode, str) + unsigned long mode; + char *str; +{ + str[0] = ftypelet ((unsigned long) mode); + str[1] = (mode & S_IRUSR) != 0 ? 'r' : '-'; + str[2] = (mode & S_IWUSR) != 0 ? 'w' : '-'; + str[3] = (mode & S_IXUSR) != 0 ? 'x' : '-'; + str[4] = (mode & S_IRGRP) != 0 ? 'r' : '-'; + str[5] = (mode & S_IWGRP) != 0 ? 'w' : '-'; + str[6] = (mode & S_IXGRP) != 0 ? 'x' : '-'; + str[7] = (mode & S_IROTH) != 0 ? 'r' : '-'; + str[8] = (mode & S_IWOTH) != 0 ? 'w' : '-'; + str[9] = (mode & S_IXOTH) != 0 ? 'x' : '-'; + setst ((unsigned long) 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. */ + +#ifndef S_ISDIR +#ifdef S_IFDIR +#define S_ISDIR(i) (((i) & S_IFMT) == S_IFDIR) +#else /* ! defined (S_IFDIR) */ +#define S_ISDIR(i) (((i) & 0170000) == 040000) +#endif /* ! defined (S_IFDIR) */ +#endif /* ! defined (S_ISDIR) */ + +#ifndef S_ISBLK +#ifdef S_IFBLK +#define S_ISBLK(i) (((i) & S_IFMT) == S_IFBLK) +#else /* ! defined (S_IFBLK) */ +#define S_ISBLK(i) 0 +#endif /* ! defined (S_IFBLK) */ +#endif /* ! defined (S_ISBLK) */ + +#ifndef S_ISCHR +#ifdef S_IFCHR +#define S_ISCHR(i) (((i) & S_IFMT) == S_IFCHR) +#else /* ! defined (S_IFCHR) */ +#define S_ISCHR(i) 0 +#endif /* ! defined (S_IFCHR) */ +#endif /* ! defined (S_ISCHR) */ + +#ifndef S_ISFIFO +#ifdef S_IFIFO +#define S_ISFIFO(i) (((i) & S_IFMT) == S_IFIFO) +#else /* ! defined (S_IFIFO) */ +#define S_ISFIFO(i) 0 +#endif /* ! defined (S_IFIFO) */ +#endif /* ! defined (S_ISFIFO) */ + +#ifndef S_ISSOCK +#ifdef S_IFSOCK +#define S_ISSOCK(i) (((i) & S_IFMT) == S_IFSOCK) +#else /* ! defined (S_IFSOCK) */ +#define S_ISSOCK(i) 0 +#endif /* ! defined (S_IFSOCK) */ +#endif /* ! defined (S_ISSOCK) */ + +#ifndef S_ISLNK +#ifdef S_IFLNK +#define S_ISLNK(i) (((i) & S_IFMT) == S_IFLNK) +#else /* ! defined (S_IFLNK) */ +#define S_ISLNK(i) 0 +#endif /* ! defined (S_IFLNK) */ +#endif /* ! defined (S_ISLNK) */ + +static char +ftypelet (bits) + unsigned long bits; +{ + if (S_ISDIR (bits)) + return 'd'; + if (S_ISLNK (bits)) + return 'l'; + if (S_ISBLK (bits)) + return 'b'; + if (S_ISCHR (bits)) + return 'c'; + if (S_ISSOCK (bits)) + return 's'; + if (S_ISFIFO (bits)) + return 'p'; + +#ifdef S_IFMT +#ifdef S_IFMPC + if ((bits & S_IFMT) == S_IFMPC + || (bits & S_IFMT) == S_IFMPB) + return 'm'; +#endif +#ifdef S_IFNWK + if ((bits & S_IFMT) == S_IFNWK) + return 'n'; +#endif +#endif + + return '-'; +} + +/* Set the 's' and 't' flags in file attributes string CHARS, + according to the file mode BITS. */ + +static void +setst (bits, chars) + unsigned long 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/gnu/usr.bin/binutils/binutils/gmalloc.c b/gnu/usr.bin/binutils/binutils/gmalloc.c new file mode 100644 index 00000000000..c259a5f1441 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/gmalloc.c @@ -0,0 +1,1116 @@ + +/* gmalloc.c - THIS FILE IS AUTOMAGICALLY GENERATED SO DON'T EDIT IT. */ + +/* Single-file skeleton for GNU malloc. + Copyright 1989 Free Software Foundation + Written May 1989 by Mike Haertel. + + This program is free software; you can 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 should have received a copy of the GNU General Public 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 author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#define __ONEFILE + +/* DO NOT DELETE THIS LINE -- ansidecl.h INSERTED HERE. */ +/* Copyright (C) 1989 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C 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 1, or (at your option) +any later version. + +The GNU C 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 the GNU C Library; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* ANSI and traditional C compatibility macros + + ANSI C is assumed if __STDC__ is #defined. + + Macros + PTR - Generic pointer type + LONG_DOUBLE - `long double' type + CONST - `const' keyword + VOLATILE - `volatile' keyword + SIGNED - `signed' keyword + PTRCONST - Generic const pointer (void *const) + + EXFUN(name, prototype) - declare external function NAME + with prototype PROTOTYPE + DEFUN(name, arglist, args) - define function NAME with + args ARGLIST of types in ARGS + DEFUN_VOID(name) - define function NAME with no args + AND - argument separator for ARGS + NOARGS - null arglist + DOTS - `...' in args + + For example: + extern int EXFUN(printf, (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 */ + + +#ifdef __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(NOARGS) + +#else /* Not ANSI C. */ + +#define PTR char * +#define PTRCONST PTR +#define LONG_DOUBLE double + +#define AND ; +#define NOARGS +#define CONST +#define VOLATILE +#define SIGNED +#define DOTS + +#define EXFUN(name, proto) name() +#define DEFUN(name, arglist, args) name arglist args; +#define DEFUN_VOID(name) name() + +#endif /* ANSI C. */ + + +#endif /* ansidecl.h */ + +#ifdef __STDC__ +#include +#else +/* DO NOT DELETE THIS LINE -- limits.h INSERTED HERE. */ +/* Number of bits in a `char'. */ +#define CHAR_BIT 8 + +/* No multibyte characters supported yet. */ +#define MB_LEN_MAX 1 + +/* Minimum and maximum values a `signed char' can hold. */ +#define SCHAR_MIN -128 +#define SCHAR_MAX 127 + +/* Maximum value an `unsigned char' can hold. (Minimum is 0). */ +#define UCHAR_MAX 255U + +/* Minimum and maximum values a `char' can hold. */ +#ifdef __CHAR_UNSIGNED__ +#define CHAR_MIN 0 +#define CHAR_MAX 255U +#else +#define CHAR_MIN -128 +#define CHAR_MAX 127 +#endif + +/* Minimum and maximum values a `signed short int' can hold. */ +#define SHRT_MIN -32768 +#define SHRT_MAX 32767 + +/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */ +#define USHRT_MAX 65535U + +/* Minimum and maximum values a `signed int' can hold. */ +#define INT_MIN -2147483648 +#define INT_MAX 2147483647 + +/* Maximum value an `unsigned int' can hold. (Minimum is 0). */ +#define UINT_MAX 4294967295U + +/* Minimum and maximum values a `signed long int' can hold. + (Same as `int'). */ +#define LONG_MIN (-LONG_MAX-1) +#define LONG_MAX 2147483647 + +/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */ +#define ULONG_MAX 4294967295U +#endif + +#ifdef __STDC__ +#include +#else +/* DO NOT DELETE THIS LINE -- stddef.h INSERTED HERE. */ +#ifndef _STDDEF_H +#define _STDDEF_H + +/* Signed type of difference of two pointers. */ + +typedef long ptrdiff_t; + +/* Unsigned type of `sizeof' something. */ + +#ifndef _SIZE_T /* in case has defined it. */ +#define _SIZE_T +typedef unsigned long size_t; +#endif /* _SIZE_T */ + +/* A null pointer constant. */ + +#undef NULL /* in case has defined it. */ +#define NULL 0 + +/* Offset of member MEMBER in a struct of type TYPE. */ + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +#endif /* _STDDEF_H */ +#endif + +/* DO NOT DELETE THIS LINE -- stdlib.h INSERTED HERE. */ +/* Fake stdlib.h supplying the stuff needed by malloc. */ + +#ifndef __ONEFILE +#include +#endif + +extern void EXFUN(abort, (void)); +extern void EXFUN(free, (PTR)); +extern PTR EXFUN(malloc, (size_t)); +extern PTR EXFUN(realloc, (PTR, size_t)); + +/* DO NOT DELETE THIS LINE -- string.h INSERTED HERE. */ +/* Fake string.h supplying stuff used by malloc. */ +#ifndef __ONEFILE +#include +#endif + +extern PTR EXFUN(memcpy, (PTR, PTR, size_t)); +extern PTR EXFUN(memset, (PTR, int, size_t)); +#define memmove memcpy + +#define _MALLOC_INTERNAL +/* DO NOT DELETE THIS LINE -- malloc.h INSERTED HERE. */ +/* Declarations for `malloc' and friends. + Copyright 1990 Free Software Foundation + Written May 1989 by Mike Haertel. + + This program is free software; you can 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 should have received a copy of the GNU General Public 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 author may be reached (Email) at the address mike@@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_H + +#define _MALLOC_H 1 + +#ifndef __ONEFILE +#define __need_NULL +#define __need_size_t +#define __need_ptrdiff_t +#include +#endif + +#ifdef _MALLOC_INTERNAL + +#ifndef __ONEFILE +#include +#endif + +/* The allocator divides the heap into blocks of fixed size; large + requests receive one or more whole blocks, and small requests + receive a fragment of a block. Fragment sizes are powers of two, + and all fragments of a block are the same size. When all the + fragments in a block have been freed, the block itself is freed. */ +#define INT_BIT (CHAR_BIT * sizeof(int)) +#define BLOCKLOG (INT_BIT > 16 ? 12 : 9) +#define BLOCKSIZE (1 << BLOCKLOG) +#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) + +/* Determine the amount of memory spanned by the initial heap table + (not an absolute limit). */ +#define HEAP (INT_BIT > 16 ? 4194304 : 65536) + +/* Number of contiguous free blocks allowed to build up at the end of + memory before they will be returned to the system. */ +#define FINAL_FREE_BLOCKS 8 + +/* Where to start searching the free list when looking for new memory. + The two possible values are 0 and _heapindex. Starting at 0 seems + to reduce total memory usage, while starting at _heapindex seems to + run faster. */ +#define MALLOC_SEARCH_START _heapindex + +/* Data structure giving per-block information. */ +typedef union + { + /* Heap information for a busy block. */ + struct + { + /* Zero for a large block, or positive giving the + logarithm to the base two of the fragment size. */ + int type; + union + { + struct + { + size_t nfree; /* Free fragments in a fragmented block. */ + size_t first; /* First free fragment of the block. */ + } frag; + /* Size (in blocks) of a large cluster. */ + size_t size; + } info; + } busy; + /* Heap information for a free block (that may be the first of + a free cluster). */ + struct + { + size_t size; /* Size (in blocks) of a free cluster. */ + size_t next; /* Index of next free cluster. */ + size_t prev; /* Index of previous free cluster. */ + } free; + } malloc_info; + +/* Pointer to first block of the heap. */ +extern char *_heapbase; + +/* Table indexed by block number giving per-block information. */ +extern malloc_info *_heapinfo; + +/* Address to block number and vice versa. */ +#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) +#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + _heapbase)) + +/* Current search index for the heap table. */ +extern size_t _heapindex; + +/* Limit of valid info table indices. */ +extern size_t _heaplimit; + +/* Doubly linked lists of free fragments. */ +struct list + { + struct list *next; + struct list *prev; + }; + +/* Free list headers for each fragment size. */ +extern struct list _fraghead[]; + +/* Instrumentation. */ +extern size_t _chunks_used; +extern size_t _bytes_used; +extern size_t _chunks_free; +extern size_t _bytes_free; + +/* Internal version of free() used in morecore(). */ +extern void EXFUN(__free, (PTR __ptr)); + +#endif /* _MALLOC_INTERNAL. */ + +/* Underlying allocation function; successive calls should + return contiguous pieces of memory. */ +extern PTR EXFUN((*__morecore), (ptrdiff_t __size)); + +/* Default value of previous. */ +extern PTR EXFUN(__default_morecore, (ptrdiff_t __size)); + +/* Flag whether malloc has been called. */ +extern int __malloc_initialized; + +/* Hooks for debugging versions. */ +extern void EXFUN((*__free_hook), (PTR __ptr)); +extern PTR EXFUN((*__malloc_hook), (size_t __size)); +extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size)); + +/* Activate a standard collection of debugging hooks. */ +extern void EXFUN(mcheck, (void EXFUN((*func), (void)))); + +/* Statistics available to the user. */ +struct mstats + { + size_t bytes_total; /* Total size of the heap. */ + size_t chunks_used; /* Chunks allocated by the user. */ + size_t bytes_used; /* Byte total of user-allocated chunks. */ + size_t chunks_free; /* Chunks in the free list. */ + size_t bytes_free; /* Byte total of chunks in the free list. */ + }; + +/* Pick up the current statistics. */ +extern struct mstats EXFUN(mstats, (NOARGS)); + +#endif /* malloc.h */ + +/* DO NOT DELETE THIS LINE -- free.c INSERTED HERE. */ +/* Free a block of memory allocated by `malloc'. + Copyright 1990 Free Software Foundation + Written May 1989 by Mike Haertel. + + This program is free software; you can 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 should have received a copy of the GNU General Public 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 author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef __ONEFILE +#include "ansidecl.h" +#include +#include + +#define _MALLOC_INTERNAL +#include "malloc.h" +#endif /* __ONEFILE */ + +/* Debugging hook for free. */ +void EXFUN((*__free_hook), (PTR __ptr)); + +/* Return memory to the heap. Like free() but don't call a __free_hook + if there is one. */ +void +DEFUN(__free, (ptr), PTR ptr) +{ + int type; + size_t block, blocks; + register size_t i; + struct list *prev, *next; + + block = BLOCK(ptr); + + type = _heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Get as many statistics as early as we can. */ + --_chunks_used; + _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; + _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; + + /* Find the free cluster previous to this one in the free list. + Start searching at the last block referenced; this may benefit + programs with locality of allocation. */ + i = _heapindex; + if (i > block) + while (i > block) + i = _heapinfo[i].free.prev; + else + { + do + i = _heapinfo[i].free.next; + while (i > 0 && i < block); + i = _heapinfo[i].free.prev; + } + + /* Determine how to link this block into the free list. */ + if (block == i + _heapinfo[i].free.size) + { + /* Coalesce this block with its predecessor. */ + _heapinfo[i].free.size += _heapinfo[block].busy.info.size; + block = i; + } + else + { + /* Really link this block back into the free list. */ + _heapinfo[block].free.size = _heapinfo[block].busy.info.size; + _heapinfo[block].free.next = _heapinfo[i].free.next; + _heapinfo[block].free.prev = i; + _heapinfo[i].free.next = block; + _heapinfo[_heapinfo[block].free.next].free.prev = block; + ++_chunks_free; + } + + /* Now that the block is linked in, see if we can coalesce it + with its successor (by deleting its successor from the list + and adding in its size). */ + if (block + _heapinfo[block].free.size == _heapinfo[block].free.next) + { + _heapinfo[block].free.size + += _heapinfo[_heapinfo[block].free.next].free.size; + _heapinfo[block].free.next + = _heapinfo[_heapinfo[block].free.next].free.next; + _heapinfo[_heapinfo[block].free.next].free.prev = block; + --_chunks_free; + } + + /* Now see if we can return stuff to the system. */ + blocks = _heapinfo[block].free.size; + if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit + && (*__morecore)(0) == ADDRESS(block + blocks)) + { + register size_t bytes = blocks * BLOCKSIZE; + _heaplimit -= blocks; + (*__morecore)(- bytes); + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapinfo[block].free.next; + _heapinfo[_heapinfo[block].free.next].free.prev + = _heapinfo[block].free.prev; + block = _heapinfo[block].free.prev; + --_chunks_free; + _bytes_free -= bytes; + } + + /* Set the next search to begin at this block. */ + _heapindex = block; + break; + + default: + /* Do some of the statistics. */ + --_chunks_used; + _bytes_used -= 1 << type; + ++_chunks_free; + _bytes_free += 1 << type; + + /* Get the address of the first free fragment in this block. */ + prev = (struct list *) ((char *) ADDRESS(block) + + (_heapinfo[block].busy.info.frag.first << type)); + + if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1) + { + /* If all fragments of this block are free, remove them + from the fragment list and free the whole block. */ + next = prev; + for (i = 1; i < BLOCKSIZE >> type; ++i) + next = next->next; + prev->prev->next = next; + if (next != NULL) + next->prev = prev->prev; + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = 1; + + /* Keep the statistics accurate. */ + ++_chunks_used; + _bytes_used += BLOCKSIZE; + _chunks_free -= BLOCKSIZE >> type; + _bytes_free -= BLOCKSIZE; + + free(ADDRESS(block)); + } + else if (_heapinfo[block].busy.info.frag.nfree != 0) + { + /* If some fragments of this block are free, link this + fragment into the fragment list after the first free + fragment of this block. */ + next = (struct list *) ptr; + next->next = prev->next; + next->prev = prev; + prev->next = next; + if (next->next != NULL) + next->next->prev = next; + ++_heapinfo[block].busy.info.frag.nfree; + } + else + { + /* No fragments of this block are free, so link this + fragment into the fragment list and announce that + it is the first free fragment of this block. */ + prev = (struct list *) ptr; + _heapinfo[block].busy.info.frag.nfree = 1; + _heapinfo[block].busy.info.frag.first = (unsigned int) + (((char *) ptr - (char *) NULL) % BLOCKSIZE >> type); + prev->next = _fraghead[type].next; + prev->prev = &_fraghead[type]; + prev->prev->next = prev; + if (prev->next != NULL) + prev->next->prev = prev; + } + break; + } +} + +/* Return memory to the heap. */ +void +DEFUN(free, (ptr), PTR ptr) +{ + if (ptr == NULL) + return; + + if (__free_hook != NULL) + (*__free_hook)(ptr); + else + __free (ptr); +} + +/* DO NOT DELETE THIS LINE -- malloc.c INSERTED HERE. */ +/* Memory allocator `malloc'. + Copyright 1990 Free Software Foundation + Written May 1989 by Mike Haertel. + + This program is free software; you can 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 should have received a copy of the GNU General Public 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 author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef __ONEFILE +#include "ansidecl.h" +#include +#include +#include + +#define _MALLOC_INTERNAL +#include "malloc.h" +#endif /* __ONEFILE */ + +/* How to really get more memory. */ +PTR EXFUN((*__morecore), (ptrdiff_t __size)) = __default_morecore; + +/* Debugging hook for `malloc'. */ +PTR EXFUN((*__malloc_hook), (size_t __size)); + +/* Pointer to the base of the first block. */ +char *_heapbase; + +/* Block information table. Allocated with align/__free (not malloc/free). */ +malloc_info *_heapinfo; + +/* Number of info entries. */ +static size_t heapsize; + +/* Search index in the info table. */ +size_t _heapindex; + +/* Limit of valid info table indices. */ +size_t _heaplimit; + +/* Free lists for each fragment size. */ +struct list _fraghead[BLOCKLOG]; + +/* Instrumentation. */ +size_t _chunks_used; +size_t _bytes_used; +size_t _chunks_free; +size_t _bytes_free; + +/* Are you experienced? */ +int __malloc_initialized; + +/* Aligned allocation. */ +static PTR +DEFUN(align, (size), size_t size) +{ + PTR result; + unsigned int adj; + + result = (*__morecore)(size); + adj = (unsigned int) ((char *) result - (char *) NULL) % BLOCKSIZE; + if (adj != 0) + { + adj = BLOCKSIZE - adj; + (void) (*__morecore)(adj); + result = (char *) result + adj; + } + return result; +} + +/* Set everything up and remember that we have. */ +static int +DEFUN_VOID(initialize) +{ + heapsize = HEAP / BLOCKSIZE; + _heapinfo = (malloc_info *) align(heapsize * sizeof(malloc_info)); + if (_heapinfo == NULL) + return 0; + memset(_heapinfo, 0, heapsize * sizeof(malloc_info)); + _heapinfo[0].free.size = 0; + _heapinfo[0].free.next = _heapinfo[0].free.prev = 0; + _heapindex = 0; + _heapbase = (char *) _heapinfo; + __malloc_initialized = 1; + return 1; +} + +/* Get neatly aligned memory, initializing or + growing the heap info table as necessary. */ +static PTR +DEFUN(morecore, (size), size_t size) +{ + PTR result; + malloc_info *newinfo, *oldinfo; + size_t newsize; + + result = align(size); + if (result == NULL) + return NULL; + + /* Check if we need to grow the info table. */ + if (BLOCK((char *) result + size) > heapsize) + { + newsize = heapsize; + while (BLOCK((char *) result + size) > newsize) + newsize *= 2; + newinfo = (malloc_info *) align(newsize * sizeof(malloc_info)); + if (newinfo == NULL) + { + (*__morecore)(- size); + return NULL; + } + memset(newinfo, 0, newsize * sizeof(malloc_info)); + memcpy(newinfo, _heapinfo, heapsize * sizeof(malloc_info)); + oldinfo = _heapinfo; + newinfo[BLOCK(oldinfo)].busy.type = 0; + newinfo[BLOCK(oldinfo)].busy.info.size + = BLOCKIFY(heapsize * sizeof(malloc_info)); + _heapinfo = newinfo; + __free(oldinfo); + heapsize = newsize; + } + + _heaplimit = BLOCK((char *) result + size); + return result; +} + +/* Allocate memory from the heap. */ +PTR +DEFUN(malloc, (size), size_t size) +{ + PTR result; + size_t block, blocks, lastblocks, start; + register size_t i; + struct list *next; + + if (size == 0) + return NULL; + + if (__malloc_hook != NULL) + return (*__malloc_hook)(size); + + if (!__malloc_initialized) + if (!initialize()) + return NULL; + + if (size < sizeof(struct list)) + size = sizeof(struct list); + + /* Determine the allocation policy based on the request size. */ + if (size <= BLOCKSIZE / 2) + { + /* Small allocation to receive a fragment of a block. + Determine the logarithm to base two of the fragment size. */ + register size_t log = 1; + --size; + while ((size /= 2) != 0) + ++log; + + /* Look in the fragment lists for a + free fragment of the desired size. */ + next = _fraghead[log].next; + if (next != NULL) + { + /* There are free fragments of this size. + Pop a fragment out of the fragment list and return it. + Update the block's nfree and first counters. */ + result = (PTR) next; + next->prev->next = next->next; + if (next->next != NULL) + next->next->prev = next->prev; + block = BLOCK(result); + if (--_heapinfo[block].busy.info.frag.nfree != 0) + _heapinfo[block].busy.info.frag.first = (unsigned int) + (((char *) next->next - (char *) NULL) % BLOCKSIZE) >> log; + + /* Update the statistics. */ + ++_chunks_used; + _bytes_used += 1 << log; + --_chunks_free; + _bytes_free -= 1 << log; + } + else + { + /* No free fragments of the desired size, so get a new block + and break it into fragments, returning the first. */ + result = malloc(BLOCKSIZE); + if (result == NULL) + return NULL; + + /* Link all fragments but the first into the free list. */ + for (i = 1; i < BLOCKSIZE >> log; ++i) + { + next = (struct list *) ((char *) result + (i << log)); + next->next = _fraghead[log].next; + next->prev = &_fraghead[log]; + next->prev->next = next; + if (next->next != NULL) + next->next->prev = next; + } + + /* Initialize the nfree and first counters for this block. */ + block = BLOCK(result); + _heapinfo[block].busy.type = log; + _heapinfo[block].busy.info.frag.nfree = i - 1; + _heapinfo[block].busy.info.frag.first = i - 1; + + _chunks_free += (BLOCKSIZE >> log) - 1; + _bytes_free += BLOCKSIZE - (1 << log); + } + } + else + { + /* Large allocation to receive one or more blocks. + Search the free list in a circle starting at the last place visited. + If we loop completely around without finding a large enough + space we will have to get more memory from the system. */ + blocks = BLOCKIFY(size); + start = block = MALLOC_SEARCH_START; + while (_heapinfo[block].free.size < blocks) + { + block = _heapinfo[block].free.next; + if (block == start) + { + /* Need to get more from the system. Check to see if + the new core will be contiguous with the final free + block; if so we don't need to get as much. */ + block = _heapinfo[0].free.prev; + lastblocks = _heapinfo[block].free.size; + if (_heaplimit != 0 && block + lastblocks == _heaplimit && + (*__morecore)(0) == ADDRESS(block + lastblocks) && + (morecore((blocks - lastblocks) * BLOCKSIZE)) != NULL) + { + _heapinfo[block].free.size = blocks; + _bytes_free += (blocks - lastblocks) * BLOCKSIZE; + continue; + } + result = morecore(blocks * BLOCKSIZE); + if (result == NULL) + return NULL; + block = BLOCK(result); + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = blocks; + ++_chunks_used; + _bytes_used += blocks * BLOCKSIZE; + return result; + } + } + + /* At this point we have found a suitable free list entry. + Figure out how to remove what we need from the list. */ + result = ADDRESS(block); + if (_heapinfo[block].free.size > blocks) + { + /* The block we found has a bit left over, + so relink the tail end back into the free list. */ + _heapinfo[block + blocks].free.size + = _heapinfo[block].free.size - blocks; + _heapinfo[block + blocks].free.next + = _heapinfo[block].free.next; + _heapinfo[block + blocks].free.prev + = _heapinfo[block].free.prev; + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapinfo[_heapinfo[block].free.next].free.prev + = _heapindex = block + blocks; + } + else + { + /* The block exactly matches our requirements, + so just remove it from the list. */ + _heapinfo[_heapinfo[block].free.next].free.prev + = _heapinfo[block].free.prev; + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapindex = _heapinfo[block].free.next; + --_chunks_free; + } + + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = blocks; + ++_chunks_used; + _bytes_used += blocks * BLOCKSIZE; + _bytes_free -= blocks * BLOCKSIZE; + } + + return result; +} + +/* DO NOT DELETE THIS LINE -- realloc.c INSERTED HERE. */ +/* Change the size of a block allocated by `malloc'. + Copyright 1990 Free Software Foundation + Written May 1989 by Mike Haertel. + + This program is free software; you can 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 should have received a copy of the GNU General Public 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 author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef __ONEFILE +#include "ansidecl.h" +#include +#include + +#define _MALLOC_INTERNAL +#include "malloc.h" +#endif /* __ONEFILE */ + +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +/* Debugging hook for realloc. */ +PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size)); + +/* Resize the given region to the new size, returning a pointer + to the (possibly moved) region. This is optimized for speed; + some benchmarks seem to indicate that greater compactness is + achieved by unconditionally allocating and copying to a + new region. This module has incestuous knowledge of the + internals of both free and malloc. */ +PTR +DEFUN(realloc, (ptr, size), PTR ptr AND size_t size) +{ + PTR result; + int type; + size_t block, blocks, oldlimit; + + if (size == 0) + { + free(ptr); + return NULL; + } + else if (ptr == NULL) + return malloc(size); + + if (__realloc_hook != NULL) + return (*__realloc_hook)(ptr, size); + + block = BLOCK(ptr); + + type = _heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Maybe reallocate a large block to a small fragment. */ + if (size <= BLOCKSIZE / 2) + { + result = malloc(size); + if (result != NULL) + { + memcpy(result, ptr, size); + free(ptr); + return result; + } + } + + /* The new size is a large allocation as well; + see if we can hold it in place. */ + blocks = BLOCKIFY(size); + if (blocks < _heapinfo[block].busy.info.size) + { + /* The new size is smaller; return + excess memory to the free list. */ + _heapinfo[block + blocks].busy.type = 0; + _heapinfo[block + blocks].busy.info.size + = _heapinfo[block].busy.info.size - blocks; + _heapinfo[block].busy.info.size = blocks; + free(ADDRESS(block + blocks)); + result = ptr; + } + else if (blocks == _heapinfo[block].busy.info.size) + /* No size change necessary. */ + result = ptr; + else + { + /* Won't fit, so allocate a new region that will. + Free the old region first in case there is sufficient + adjacent free space to grow without moving. */ + blocks = _heapinfo[block].busy.info.size; + /* Prevent free from actually returning memory to the system. */ + oldlimit = _heaplimit; + _heaplimit = 0; + free(ptr); + _heaplimit = oldlimit; + result = malloc(size); + if (result == NULL) + { + (void) malloc(blocks * BLOCKSIZE); + return NULL; + } + if (ptr != result) + memmove(result, ptr, blocks * BLOCKSIZE); + } + break; + + default: + /* Old size is a fragment; type is logarithm + to base two of the fragment size. */ + if (size > 1 << (type - 1) && size <= 1 << type) + /* The new size is the same kind of fragment. */ + result = ptr; + else + { + /* The new size is different; allocate a new space, + and copy the lesser of the new size and the old. */ + result = malloc(size); + if (result == NULL) + return NULL; + memcpy(result, ptr, MIN(size, 1 << type)); + free(ptr); + } + break; + } + + return result; +} + +/* DO NOT DELETE THIS LINE -- unix.c INSERTED HERE. */ +/* unix.c - get more memory with a UNIX system call. + Copyright 1990 Free Software Foundation + Written May 1989 by Mike Haertel. + + This program is free software; you can 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 should have received a copy of the GNU General Public 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 author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef __ONEFILE +#include "ansidecl.h" +#include + +#define _MALLOC_INTERNAL +#include "malloc.h" +#endif /* __ONEFILE */ + +extern PTR EXFUN(sbrk, (ptrdiff_t size)); + +PTR +DEFUN(__default_morecore, (size), ptrdiff_t size) +{ + PTR result; + + result = sbrk(size); + if (result == (PTR) -1) + return NULL; + return result; +} + +#define __getpagesize getpagesize +/* DO NOT DELETE THIS LINE -- valloc.c INSERTED HERE. */ +/* Allocate memory on a page boundary. + Copyright 1990 Free Software Foundation + Written May 1989 by Mike Haertel. + + This program is free software; you can 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 should have received a copy of the GNU General Public 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 author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef __ONEFILE +#include "ansidecl.h" +#include +#endif /* __ONEFILE */ + +extern size_t EXFUN(__getpagesize, (NOARGS)); + +static size_t pagesize; + +PTR +DEFUN(valloc, (size), size_t size) +{ + PTR result; + unsigned int adj; + + if (pagesize == 0) + pagesize = __getpagesize(); + + result = malloc(size + pagesize); + if (result == NULL) + return NULL; + adj = (unsigned int) ((char *) result - (char *) NULL) % pagesize; + if (adj != 0) + result = (char *) result + pagesize - adj; + return result; +} diff --git a/gnu/usr.bin/binutils/binutils/is-ranlib.c b/gnu/usr.bin/binutils/binutils/is-ranlib.c new file mode 100644 index 00000000000..fde72a43da5 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/is-ranlib.c @@ -0,0 +1,3 @@ +/* Linked with ar.o to flag that this program is 'ranlib' (not 'ar'). */ + +int is_ranlib = 1; diff --git a/gnu/usr.bin/binutils/binutils/is-strip.c b/gnu/usr.bin/binutils/binutils/is-strip.c new file mode 100644 index 00000000000..215341a325c --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/is-strip.c @@ -0,0 +1,4 @@ +/* Linked with objcopy.o to flag that this program is 'strip' (not + 'objcopy'). */ + +int is_strip = 1; diff --git a/gnu/usr.bin/binutils/binutils/mac-binutils.r b/gnu/usr.bin/binutils/binutils/mac-binutils.r new file mode 100644 index 00000000000..8516237b5ea --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/mac-binutils.r @@ -0,0 +1,42 @@ +/* Resources for GNU binutils. */ + +#include "SysTypes.r" + +/* Version resources. */ + +resource 'vers' (1) { + 0, + 0, + 0, + 0, + verUs, + VERSION_STRING, + VERSION_STRING " (c) 1986-95 FSF, Inc. " +}; + +resource 'vers' (2, purgeable) { + 0, + 0, + 0, + 0, + verUs, + VERSION_STRING, + "binutils " /* fill in major/minor versions */ "for MPW" +}; + +#ifdef WANT_CFRG + +#include "CodeFragmentTypes.r" + +resource 'cfrg' (0) { + { + kPowerPC, + kFullLib, + kNoVersionNum, kNoVersionNum, + 0,0, + kIsApp, kOnDiskFlat, kZeroOffset, kWholeFork, + PROG_NAME + } +}; + +#endif /* WANT_CFRG */ diff --git a/gnu/usr.bin/binutils/binutils/maybe-ranlib.c b/gnu/usr.bin/binutils/binutils/maybe-ranlib.c new file mode 100644 index 00000000000..f37bc0ff216 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/maybe-ranlib.c @@ -0,0 +1,4 @@ +/* Linked with ar.o to flag that this program decides at runtime + (using argv[0] if it is is 'ar' or 'ranlib'. */ + +int is_ranlib = -1; diff --git a/gnu/usr.bin/binutils/binutils/maybe-strip.c b/gnu/usr.bin/binutils/binutils/maybe-strip.c new file mode 100644 index 00000000000..6467c99e935 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/maybe-strip.c @@ -0,0 +1,4 @@ +/* Linked with objcopy.o to flag that this program decides at runtime + (using argv[0] if it is is 'strip' or 'objcopy'. */ + +int is_strip = -1; diff --git a/gnu/usr.bin/binutils/binutils/mpw-config.in b/gnu/usr.bin/binutils/binutils/mpw-config.in new file mode 100644 index 00000000000..90ea628fb23 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/mpw-config.in @@ -0,0 +1,23 @@ +# Configuration fragment for binutils. + +Set target_arch `echo {target_canonical} | sed -e 's/-.*-.*//'` + +# (should canonicalize arch name) */ + +Set archname ARCH_{target_arch} + +Set underscore 0 + +If "{target_canonical}" =~ /sh-hitachi-hms/ + Set underscore 1 +End If + +Echo '# From mpw-config.in' > "{o}"mk.tmp +Echo "ARCHDEFS = -d" {archname} >> "{o}"mk.tmp +Echo "UNDERSCORE = " {underscore} >> "{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/gnu/usr.bin/binutils/binutils/mpw-make.sed b/gnu/usr.bin/binutils/binutils/mpw-make.sed new file mode 100644 index 00000000000..6984d2fd471 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/mpw-make.sed @@ -0,0 +1,78 @@ +# Sed commands to finish translating the binutils Unix makefile into MPW syntax. + +# Define undefined makefile variables. +/^#### .*/a\ +\ +BUILD_NLMCONV = \ +BUILD_SRCONV = \ +SYSINFO_PROG = \ +BUILD_DLLTOOL = \ +\ +"{o}"underscore.c.o \\Option-f "{o}"underscore.c\ + +# Whack out unused host define bits. +/HDEFINES/s/@HDEFINES@// + +/BUILD_NLMCONV/s/@BUILD_NLMCONV@// +/BUILD_SRCONV/s/@BUILD_SRCONV@// +/BUILD_DLLTOOL/s/@BUILD_DLLTOOL@// + +/UNDERSCORE/s/@UNDERSCORE@/{UNDERSCORE}/ + +# Whack out target makefile fragment. +/target_makefile_fragment/s/target_makefile_fragment@// + +# Fix and add to the include paths. +/^INCLUDES = .*$/s/$/ -i "{INCDIR}":mpw: -i ::extra-include:/ +/BFDDIR/s/-i {BFDDIR} /-i "{BFDDIR}": / +/INCDIR/s/-i {INCDIR} /-i "{INCDIR}": / + +# Use byacc instead of bison (for now anyway). +/BISON/s/^BISON =.*$/BISON = byacc/ +#/BISONFLAGS/s/^BISONFLAGS =.*$/BISONFLAGS = / + +# '+' is a special char to MPW, don't use it ever. +/c++filt/s/c++filt/cplusfilt/ + +/^{[A-Z]*_PROG}/s/$/ "{s}"mac-binutils.r/ +/{[A-Z]*_PROG}\.r/s/{[A-Z]*_PROG}\.r/mac-binutils.r/ + +# Fix the locations of generated files. +/config/s/"{s}"config\.h/"{o}"config.h/g +/config/s/^config\.h/"{o}"config\.h/ +/underscore/s/"{s}"underscore\.c/"{o}"underscore.c/g +/underscore/s/^underscore\.c/"{o}"underscore\.c/ + +# Fix paths to generated source files. +/lex.yy.c/s/"{s}"lex\.yy\.c/"{o}"lex.yy.c/g +/lex.yy.c/s/^lex\.yy\.c/"{o}"lex.yy.c/ +/arlex.c/s/"{s}"arlex\.c/"{o}"arlex.c/g +/arlex.c/s/^arlex\.c/"{o}"arlex.c/ +/y.tab.c/s/"{s}"y\.tab\.c/"{o}"y.tab.c/g +/y.tab.c/s/^y\.tab\.c/"{o}"y.tab.c/ +/arparse.c/s/"{s}"arparse\.c/"{o}"arparse.c/g +/arparse.c/s/^arparse\.c/"{o}"arparse.c/ +/y.tab.h/s/"{s}"y\.tab\.h/"{o}"y.tab.h/g +/y.tab.h/s/^y\.tab\.h/"{o}"y.tab.h/ +/arparse.h/s/"{s}"arparse\.h/"{o}"arparse.h/g +/arparse.h/s/^arparse\.h/"{o}"arparse.h/ + +/"{s}"{INCDIR}/s/"{s}"{INCDIR}/"{INCDIR}"/g + +# The generated lexer may include an ifdef for older Mac compilers that +# needs to work with newer compilers also. +/lex.yy.c/s/Rename -y \([^ ]*\) \([^ ]*\)$/sed -e 's,ifdef macintosh,if defined(macintosh) || defined(__MWERKS__),' \1 > \2/ + +# Fix an over-eagerness. +/echo.*WARNING.*This file/s/'.*'/' '/ + +# Remove un-useful targets. +/^Makefile \\Option-f/,/^$/d +/^"{o}"config.h \\Option-f/,/^$/d +/^config.status \\Option-f/,/^$/d + +# Don't try to make the demangler's man page, it's useless. +/^{DEMANGLER_PROG}\.1 \\Option-f/,/^$/d +# Don't depend on it either. +/{DEMANGLER_PROG}/s/ {DEMANGLER_PROG}\.1// + diff --git a/gnu/usr.bin/binutils/binutils/nlmconv.1 b/gnu/usr.bin/binutils/binutils/nlmconv.1 new file mode 100644 index 00000000000..e38d80525e9 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/nlmconv.1 @@ -0,0 +1,110 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH nlmconv 1 "June 1993" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +nlmconv\(em\&converts object code into an NLM + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B nlmconv +.RB "[\|" \-I\ \fIbfdname\fB\ |\ \-\-input\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-O\ \fIbfdname\fB\ |\ \-\-output\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-T\ \fIheaderfile\fB\ |\ \-\-header\-file=\fIheaderfile\fR "\|]" +.RB "[\|" \-V\ |\ \-\-version\fR "\|]" +.RB "[\|" \-\-help\fR "\|]" +.B infile +.B outfile +.SH DESCRIPTION +.B nlmconv +converts the relocatable object file +.B infile +into the NetWare Loadable Module +.BR outfile , +optionally reading +.I headerfile +for NLM header information. For instructions on writing the NLM +command file language used in header files, see +.IR "The NetWare Tool Maker Specification Manual" , +available from Novell, Inc. +.B nlmconv +currently works with i386 object files in +.BR COFF , +.BR ELF , +or +.B a.out +format, and with SPARC object files in +.B ELF +or +.B a.out +format. +.br +.B nlmconv +uses the GNU Binary File Descriptor library to read +.IR infile . +.SH OPTIONS +.TP +.B \-I \fIbfdname\fR, \fB\-\-input\-target=\fIbfdname +Consider the source file's object format to be +.IR bfdname , +rather than attempting to deduce it. +.TP +.B \-O \fIbfdname\fR, \fB\-\-output\-target=\fIbfdname +Write the output file using the object format +.IR bfdname . +.B nlmconv +infers the output format based on the input format, e.g. for an i386 +input file the output format is +.IR nlm32\-i386 . +.TP +.B \-T \fIheaderfile\fR, \fB\-\-header\-file=\fIheaderfile +Reads +.I headerfile +for NLM header information. For instructions on writing the NLM +command file language used in header files, see +.IR "The NetWare Tool Maker Specification Manual" , +available from Novell, Inc. +.TP +.B \-V\fR, \fB\-\-version +Show the version number of +.B nlmconv +and exit. +.TP +.B \-h\fR, \fB\-\-help +Show a summary of the options to +.B nlmconv +and exit. +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (June 1993). + +.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/gnu/usr.bin/binutils/binutils/nlmconv.c b/gnu/usr.bin/binutils/binutils/nlmconv.c new file mode 100644 index 00000000000..f7f72f6cd66 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/nlmconv.c @@ -0,0 +1,2346 @@ +/* nlmconv.c -- NLM conversion program + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 Lance Taylor . + + This program can be used to convert any appropriate object file + into a NetWare Loadable Module (an NLM). It will accept a linker + specification file which is identical to that accepted by the + NetWare linker, NLMLINK, except that the INPUT command, normally + used to give a list of object files to link together, is not used. + This program will convert only a single object file. */ + +#include "bfd.h" +#include "libiberty.h" +#include "bucomm.h" + +#include +#include +#include +#include +#include +#include +#include + +/* Internal BFD NLM header. */ +#include "libnlm.h" +#include "nlmconv.h" + +#ifdef NLMCONV_ALPHA +#include "coff/sym.h" +#include "coff/ecoff.h" +#endif + +/* If strerror is just a macro, we want to use the one from libiberty + since it will handle undefined values. */ +#undef strerror +extern char *strerror (); + +#ifndef localtime +extern struct tm *localtime (); +#endif + +#ifndef getenv +extern char *getenv (); +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef R_OK +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 +#endif + +/* Global variables. */ + +/* The name used to invoke the program. */ +char *program_name; + +/* The version number. */ +extern char *program_version; + +/* Local variables. */ + +/* Whether to print out debugging information (currently just controls + whether it prints the linker command if there is one). */ +static int debug; + +/* The symbol table. */ +static asymbol **symbols; + +/* A section we create in the output file to hold pointers to where + the sections of the input file end up. We will put a pointer to + this section in the NLM header. These is an entry for each input + section. The format is + null terminated section name + zeroes to adjust to 4 byte boundary + 4 byte section data file pointer + 4 byte section size + We don't need a version number. The way we find this information + is by finding a stamp in the NLM header information. If we need to + change the format of this information, we can simply change the + stamp. */ +static asection *secsec; + +/* A temporary file name to be unlinked on exit. Actually, for most + errors, we leave it around. It's not clear whether that is helpful + or not. */ +static char *unlink_on_exit; + +/* The list of long options. */ +static struct option long_options[] = +{ + { "debug", no_argument, 0, 'd' }, + { "header-file", required_argument, 0, 'T' }, + { "help", no_argument, 0, 'h' }, + { "input-target", required_argument, 0, 'I' }, + { "input-format", required_argument, 0, 'I' }, /* Obsolete */ + { "linker", required_argument, 0, 'l' }, + { "output-target", required_argument, 0, 'O' }, + { "output-format", required_argument, 0, 'O' }, /* Obsolete */ + { "version", no_argument, 0, 'V' }, + { NULL, no_argument, 0, 0 } +}; + +/* Local routines. */ + +static void show_help PARAMS ((void)); +static void show_usage PARAMS ((FILE *, int)); +static const char *select_output_format PARAMS ((enum bfd_architecture, + unsigned long, boolean)); +static void setup_sections PARAMS ((bfd *, asection *, PTR)); +static void copy_sections PARAMS ((bfd *, asection *, PTR)); +static void mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +static void default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +static char *link_inputs PARAMS ((struct string_list *, char *)); +static const char *choose_temp_base_try PARAMS ((const char *, + const char *)); +static void choose_temp_base PARAMS ((void)); +static int pexecute PARAMS ((char *, char *[])); + +#ifdef NLMCONV_I386 +static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +#endif + +#ifdef NLMCONV_ALPHA +static void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +#endif + +#ifdef NLMCONV_POWERPC +static void powerpc_build_stubs PARAMS ((bfd *, bfd *, asymbol ***, long *)); +static void powerpc_resolve_stubs PARAMS ((bfd *, bfd *)); +static void powerpc_mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +#endif + +/* The main routine. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int opt; + char *input_file = NULL; + const char *input_format = NULL; + const char *output_format = NULL; + const char *header_file = NULL; + char *ld_arg = NULL; + Nlm_Internal_Fixed_Header fixed_hdr_struct; + Nlm_Internal_Variable_Header var_hdr_struct; + Nlm_Internal_Version_Header version_hdr_struct; + Nlm_Internal_Copyright_Header copyright_hdr_struct; + Nlm_Internal_Extended_Header extended_hdr_struct; + bfd *inbfd; + bfd *outbfd; + asymbol **newsyms, **outsyms; + long symcount, newsymalloc, newsymcount; + long symsize; + asection *text_sec, *bss_sec, *data_sec; + bfd_vma vma; + bfd_size_type align; + asymbol *endsym; + long i; + char inlead, outlead; + boolean gotstart, gotexit, gotcheck; + struct stat st; + FILE *custom_data, *help_data, *message_data, *rpc_data, *shared_data; + size_t custom_size, help_size, message_size, module_size, rpc_size; + asection *custom_section, *help_section, *message_section, *module_section; + asection *rpc_section, *shared_section; + bfd *sharedbfd; + size_t shared_offset, shared_size; + Nlm_Internal_Fixed_Header sharedhdr; + int len; + char *modname; + char **matching; + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + + bfd_init (); + + while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options, + (int *) NULL)) + != EOF) + { + switch (opt) + { + case 'd': + debug = 1; + break; + case 'h': + show_help (); + /*NOTREACHED*/ + case 'I': + input_format = optarg; + break; + case 'l': + ld_arg = optarg; + break; + case 'O': + output_format = optarg; + break; + case 'T': + header_file = optarg; + break; + case 'V': + printf ("GNU %s version %s\n", program_name, program_version); + exit (0); + /*NOTREACHED*/ + case 0: + break; + default: + show_usage (stderr, 1); + /*NOTREACHED*/ + } + } + + /* The input and output files may be named on the command line. */ + output_file = NULL; + if (optind < argc) + { + input_file = argv[optind]; + ++optind; + if (optind < argc) + { + output_file = argv[optind]; + ++optind; + if (optind < argc) + show_usage (stderr, 1); + if (strcmp (input_file, output_file) == 0) + { + fprintf (stderr, + "%s: input and output files must be different\n", + program_name); + exit (1); + } + } + } + + /* Initialize the header information to default values. */ + fixed_hdr = &fixed_hdr_struct; + memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct); + var_hdr = &var_hdr_struct; + memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct); + version_hdr = &version_hdr_struct; + memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct); + copyright_hdr = ©right_hdr_struct; + memset ((PTR) ©right_hdr_struct, 0, sizeof copyright_hdr_struct); + extended_hdr = &extended_hdr_struct; + memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct); + check_procedure = NULL; + custom_file = NULL; + debug_info = false; + exit_procedure = "_Stop"; + export_symbols = NULL; + map_file = NULL; + full_map = false; + help_file = NULL; + import_symbols = NULL; + message_file = NULL; + modules = NULL; + sharelib_file = NULL; + start_procedure = "_Prelude"; + verbose = false; + rpc_file = NULL; + + parse_errors = 0; + + /* Parse the header file (if there is one). */ + if (header_file != NULL) + { + if (! nlmlex_file (header_file) + || yyparse () != 0 + || parse_errors != 0) + exit (1); + } + + if (input_files != NULL) + { + if (input_file != NULL) + { + fprintf (stderr, + "%s: input file named both on command line and with INPUT\n", + program_name); + exit (1); + } + if (input_files->next == NULL) + input_file = input_files->string; + else + input_file = link_inputs (input_files, ld_arg); + } + else if (input_file == NULL) + { + fprintf (stderr, "%s: no input file\n", program_name); + show_usage (stderr, 1); + } + + inbfd = bfd_openr (input_file, input_format); + if (inbfd == NULL) + bfd_fatal (input_file); + + if (! bfd_check_format_matches (inbfd, bfd_object, &matching)) + { + bfd_nonfatal (input_file); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + exit (1); + } + + if (output_format == NULL) + output_format = select_output_format (bfd_get_arch (inbfd), + bfd_get_mach (inbfd), + inbfd->xvec->byteorder_big_p); + + assert (output_format != NULL); + + /* Use the output file named on the command line if it exists. + Otherwise use the file named in the OUTPUT statement. */ + if (output_file == NULL) + { + fprintf (stderr, "%s: no name for output file\n", + program_name); + show_usage (stderr, 1); + } + + outbfd = bfd_openw (output_file, output_format); + if (outbfd == NULL) + bfd_fatal (output_file); + if (! bfd_set_format (outbfd, bfd_object)) + bfd_fatal (output_file); + + assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour); + + if (bfd_arch_get_compatible (inbfd, outbfd) == NULL) + fprintf (stderr, + "%s: warning:input and output formats are not compatible\n", + program_name); + + /* Move the values read from the command file into outbfd. */ + *nlm_fixed_header (outbfd) = fixed_hdr_struct; + *nlm_variable_header (outbfd) = var_hdr_struct; + *nlm_version_header (outbfd) = version_hdr_struct; + *nlm_copyright_header (outbfd) = copyright_hdr_struct; + *nlm_extended_header (outbfd) = extended_hdr_struct; + + /* Start copying the input BFD to the output BFD. */ + if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd))) + bfd_fatal (bfd_get_filename (outbfd)); + + symsize = bfd_get_symtab_upper_bound (inbfd); + if (symsize < 0) + bfd_fatal (input_file); + symbols = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (inbfd, symbols); + if (symcount < 0) + bfd_fatal (input_file); + + /* Make sure we have a .bss section. */ + bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME); + if (bss_sec == NULL) + { + bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME); + if (bss_sec == NULL + || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC) + || ! bfd_set_section_alignment (outbfd, bss_sec, 1)) + bfd_fatal ("make .bss section"); + } + + /* We store the original section names in the .nlmsections section, + so that programs which understand it can resurrect the original + sections from the NLM. We will put a pointer to .nlmsections in + the NLM header area. */ + secsec = bfd_make_section (outbfd, ".nlmsections"); + if (secsec == NULL) + bfd_fatal ("make .nlmsections section"); + if (! bfd_set_section_flags (outbfd, secsec, SEC_HAS_CONTENTS)) + bfd_fatal ("set .nlmsections flags"); + +#ifdef NLMCONV_POWERPC + /* For PowerPC NetWare we need to build stubs for calls to undefined + symbols. Because each stub requires an entry in the TOC section + which must be at the same location as other entries in the TOC + section, we must do this before determining where the TOC section + goes in setup_sections. */ + if (bfd_get_arch (inbfd) == bfd_arch_powerpc) + powerpc_build_stubs (inbfd, outbfd, &symbols, &symcount); +#endif + + /* Set up the sections. */ + bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd); + + text_sec = bfd_get_section_by_name (outbfd, NLM_CODE_NAME); + + /* The .bss section immediately follows the .data section. */ + data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME); + if (data_sec != NULL) + { + bfd_size_type add; + + vma = bfd_get_section_size_before_reloc (data_sec); + align = 1 << bss_sec->alignment_power; + add = ((vma + align - 1) &~ (align - 1)) - vma; + vma += add; + if (! bfd_set_section_vma (outbfd, bss_sec, vma)) + bfd_fatal ("set .bss vma"); + if (add != 0) + { + bfd_size_type data_size; + + data_size = bfd_get_section_size_before_reloc (data_sec); + if (! bfd_set_section_size (outbfd, data_sec, data_size + add)) + bfd_fatal ("set .data size"); + } + } + + /* Adjust symbol information. */ + inlead = bfd_get_symbol_leading_char (inbfd); + outlead = bfd_get_symbol_leading_char (outbfd); + gotstart = false; + gotexit = false; + gotcheck = false; + newsymalloc = 10; + newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *)); + newsymcount = 0; + endsym = NULL; + for (i = 0; i < symcount; i++) + { + register asymbol *sym; + + sym = symbols[i]; + + /* Add or remove a leading underscore. */ + if (inlead != outlead) + { + if (inlead != '\0') + { + if (bfd_asymbol_name (sym)[0] == inlead) + { + if (outlead == '\0') + ++sym->name; + else + { + char *new; + + new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1); + new[0] = outlead; + strcpy (new + 1, bfd_asymbol_name (sym) + 1); + sym->name = new; + } + } + } + else + { + char *new; + + new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2); + new[0] = outlead; + strcpy (new + 1, bfd_asymbol_name (sym)); + sym->name = new; + } + } + + /* NLM's have an uninitialized data section, but they do not + have a common section in the Unix sense. Move all common + symbols into the .bss section, and mark them as exported. */ + if (bfd_is_com_section (bfd_get_section (sym))) + { + bfd_vma size; + + sym->section = bss_sec; + size = sym->value; + sym->value = bss_sec->_raw_size; + bss_sec->_raw_size += size; + align = 1 << bss_sec->alignment_power; + bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1); + sym->flags |= BSF_EXPORT | BSF_GLOBAL; + } + else if (bfd_get_section (sym)->output_section != NULL) + { + /* Move the symbol into the output section. */ + sym->value += bfd_get_section (sym)->output_offset; + sym->section = bfd_get_section (sym)->output_section; + /* This is no longer a section symbol. */ + sym->flags &=~ BSF_SECTION_SYM; + } + + /* Force _edata and _end to be defined. This would normally be + done by the linker, but the manipulation of the common + symbols will confuse it. */ + if ((sym->flags & BSF_DEBUGGING) == 0 + && bfd_asymbol_name (sym)[0] == '_' + && bfd_is_und_section (bfd_get_section (sym))) + { + if (strcmp (bfd_asymbol_name (sym), "_edata") == 0) + { + sym->section = bss_sec; + sym->value = 0; + } + if (strcmp (bfd_asymbol_name (sym), "_end") == 0) + { + sym->section = bss_sec; + endsym = sym; + } + +#ifdef NLMCONV_POWERPC + /* For PowerPC NetWare, we define __GOT0. This is the start + of the .got section. */ + if (bfd_get_arch (inbfd) == bfd_arch_powerpc + && strcmp (bfd_asymbol_name (sym), "__GOT0") == 0) + { + asection *got_sec; + + got_sec = bfd_get_section_by_name (inbfd, ".got"); + assert (got_sec != (asection *) NULL); + sym->value = got_sec->output_offset; + sym->section = got_sec->output_section; + } +#endif + } + + /* If this is a global symbol, check the export list. */ + if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0) + { + register struct string_list *l; + int found_simple; + + /* Unfortunately, a symbol can appear multiple times on the + export list, with and without prefixes. */ + found_simple = 0; + for (l = export_symbols; l != NULL; l = l->next) + { + if (strcmp (l->string, bfd_asymbol_name (sym)) == 0) + found_simple = 1; + else + { + char *zbase; + + zbase = strchr (l->string, '@'); + if (zbase != NULL + && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0) + { + /* We must add a symbol with this prefix. */ + if (newsymcount >= newsymalloc) + { + newsymalloc += 10; + newsyms = ((asymbol **) + xrealloc ((PTR) newsyms, + (newsymalloc + * sizeof (asymbol *)))); + } + newsyms[newsymcount] = + (asymbol *) xmalloc (sizeof (asymbol)); + *newsyms[newsymcount] = *sym; + newsyms[newsymcount]->name = l->string; + ++newsymcount; + } + } + } + if (! found_simple) + { + /* The unmodified symbol is actually not exported at + all. */ + sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT); + sym->flags |= BSF_LOCAL; + } + } + + /* If it's an undefined symbol, see if it's on the import list. + Change the prefix if necessary. */ + if (bfd_is_und_section (bfd_get_section (sym))) + { + register struct string_list *l; + + for (l = import_symbols; l != NULL; l = l->next) + { + if (strcmp (l->string, bfd_asymbol_name (sym)) == 0) + break; + else + { + char *zbase; + + zbase = strchr (l->string, '@'); + if (zbase != NULL + && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0) + { + sym->name = l->string; + break; + } + } + } + if (l == NULL) + fprintf (stderr, + "%s: warning: symbol %s imported but not in import list\n", + program_name, bfd_asymbol_name (sym)); + } + + /* See if it's one of the special named symbols. */ + if ((sym->flags & BSF_DEBUGGING) == 0) + { + bfd_vma val; + + /* FIXME: If these symbols are not in the .text section, we + add the .text section size to the value. This may not be + correct for all targets. I'm not sure how this should + really be handled. */ + if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0) + { + val = bfd_asymbol_value (sym); + if (bfd_get_section (sym) == data_sec + && text_sec != (asection *) NULL) + val += bfd_section_size (outbfd, text_sec); + if (! bfd_set_start_address (outbfd, val)) + bfd_fatal ("set start address"); + gotstart = true; + } + if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0) + { + val = bfd_asymbol_value (sym); + if (bfd_get_section (sym) == data_sec + && text_sec != (asection *) NULL) + val += bfd_section_size (outbfd, text_sec); + nlm_fixed_header (outbfd)->exitProcedureOffset = val; + gotexit = true; + } + if (check_procedure != NULL + && strcmp (bfd_asymbol_name (sym), check_procedure) == 0) + { + val = bfd_asymbol_value (sym); + if (bfd_get_section (sym) == data_sec + && text_sec != (asection *) NULL) + val += bfd_section_size (outbfd, text_sec); + nlm_fixed_header (outbfd)->checkUnloadProcedureOffset = val; + gotcheck = true; + } + } + } + + if (endsym != NULL) + { + endsym->value = bfd_get_section_size_before_reloc (bss_sec); + + /* FIXME: If any relocs referring to _end use inplace addends, + then I think they need to be updated. This is handled by + i386_mangle_relocs. Is it needed for any other object + formats? */ + } + + if (newsymcount == 0) + outsyms = symbols; + else + { + outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1) + * sizeof (asymbol *)); + memcpy (outsyms, symbols, symcount * sizeof (asymbol *)); + memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *)); + outsyms[symcount + newsymcount] = NULL; + } + + bfd_set_symtab (outbfd, outsyms, symcount + newsymcount); + + if (! gotstart) + fprintf (stderr, "%s: warning: START procedure %s not defined\n", + program_name, start_procedure); + if (! gotexit) + fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n", + program_name, exit_procedure); + if (check_procedure != NULL + && ! gotcheck) + fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n", + program_name, check_procedure); + + /* Add additional sections required for the header information. */ + if (custom_file != NULL) + { + custom_data = fopen (custom_file, "r"); + if (custom_data == NULL + || fstat (fileno (custom_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, custom_file, + strerror (errno)); + custom_file = NULL; + } + else + { + custom_size = st.st_size; + custom_section = bfd_make_section (outbfd, ".nlmcustom"); + if (custom_section == NULL + || ! bfd_set_section_size (outbfd, custom_section, custom_size) + || ! bfd_set_section_flags (outbfd, custom_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("custom section"); + } + } + if (help_file != NULL) + { + help_data = fopen (help_file, "r"); + if (help_data == NULL + || fstat (fileno (help_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, help_file, + strerror (errno)); + help_file = NULL; + } + else + { + help_size = st.st_size; + help_section = bfd_make_section (outbfd, ".nlmhelp"); + if (help_section == NULL + || ! bfd_set_section_size (outbfd, help_section, help_size) + || ! bfd_set_section_flags (outbfd, help_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("help section"); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + if (message_file != NULL) + { + message_data = fopen (message_file, "r"); + if (message_data == NULL + || fstat (fileno (message_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, message_file, + strerror (errno)); + message_file = NULL; + } + else + { + message_size = st.st_size; + message_section = bfd_make_section (outbfd, ".nlmmessages"); + if (message_section == NULL + || ! bfd_set_section_size (outbfd, message_section, message_size) + || ! bfd_set_section_flags (outbfd, message_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("message section"); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + if (modules != NULL) + { + struct string_list *l; + + module_size = 0; + for (l = modules; l != NULL; l = l->next) + module_size += strlen (l->string) + 1; + module_section = bfd_make_section (outbfd, ".nlmmodules"); + if (module_section == NULL + || ! bfd_set_section_size (outbfd, module_section, module_size) + || ! bfd_set_section_flags (outbfd, module_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("module section"); + } + if (rpc_file != NULL) + { + rpc_data = fopen (rpc_file, "r"); + if (rpc_data == NULL + || fstat (fileno (rpc_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file, + strerror (errno)); + rpc_file = NULL; + } + else + { + rpc_size = st.st_size; + rpc_section = bfd_make_section (outbfd, ".nlmrpc"); + if (rpc_section == NULL + || ! bfd_set_section_size (outbfd, rpc_section, rpc_size) + || ! bfd_set_section_flags (outbfd, rpc_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("rpc section"); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + if (sharelib_file != NULL) + { + sharedbfd = bfd_openr (sharelib_file, output_format); + if (sharedbfd == NULL + || ! bfd_check_format (sharedbfd, bfd_object)) + { + fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file, + bfd_errmsg (bfd_get_error ())); + sharelib_file = NULL; + } + else + { + sharedhdr = *nlm_fixed_header (sharedbfd); + bfd_close (sharedbfd); + shared_data = fopen (sharelib_file, "r"); + if (shared_data == NULL + || (fstat (fileno (shared_data), &st) < 0)) + { + fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file, + strerror (errno)); + sharelib_file = NULL; + } + else + { + /* If we were clever, we could just copy out the + sections of the shared library which we actually + need. However, we would have to figure out the sizes + of the external and public information, and that can + not be done without reading through them. */ + if (sharedhdr.uninitializedDataSize > 0) + { + /* There is no place to record this information. */ + fprintf (stderr, + "%s:%s: warning: shared libraries can not have uninitialized data\n", + program_name, sharelib_file); + } + shared_offset = st.st_size; + if (shared_offset > sharedhdr.codeImageOffset) + shared_offset = sharedhdr.codeImageOffset; + if (shared_offset > sharedhdr.dataImageOffset) + shared_offset = sharedhdr.dataImageOffset; + if (shared_offset > sharedhdr.relocationFixupOffset) + shared_offset = sharedhdr.relocationFixupOffset; + if (shared_offset > sharedhdr.externalReferencesOffset) + shared_offset = sharedhdr.externalReferencesOffset; + if (shared_offset > sharedhdr.publicsOffset) + shared_offset = sharedhdr.publicsOffset; + shared_size = st.st_size - shared_offset; + shared_section = bfd_make_section (outbfd, ".nlmshared"); + if (shared_section == NULL + || ! bfd_set_section_size (outbfd, shared_section, + shared_size) + || ! bfd_set_section_flags (outbfd, shared_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("shared section"); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + } + + /* Check whether a version was given. */ + if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0) + fprintf (stderr, "%s: warning: No version number given\n", + program_name); + + /* At least for now, always create an extended header, because that + is what NLMLINK does. */ + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + + strncpy (nlm_cygnus_ext_header (outbfd)->stamp, "CyGnUsEx", 8); + + /* If the date was not given, force it in. */ + if (nlm_version_header (outbfd)->month == 0 + && nlm_version_header (outbfd)->day == 0 + && nlm_version_header (outbfd)->year == 0) + { + time_t now; + struct tm *ptm; + + time (&now); + ptm = localtime (&now); + nlm_version_header (outbfd)->month = ptm->tm_mon + 1; + nlm_version_header (outbfd)->day = ptm->tm_mday; + nlm_version_header (outbfd)->year = ptm->tm_year + 1900; + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + } + +#ifdef NLMCONV_POWERPC + /* Resolve the stubs we build for PowerPC NetWare. */ + if (bfd_get_arch (inbfd) == bfd_arch_powerpc) + powerpc_resolve_stubs (inbfd, outbfd); +#endif + + /* Copy over the sections. */ + bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd); + + /* Finish up the header information. */ + if (custom_file != NULL) + { + PTR data; + + data = xmalloc (custom_size); + if (fread (data, 1, custom_size, custom_data) != custom_size) + fprintf (stderr, "%s:%s: read: %s\n", program_name, custom_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, custom_section, data, + (file_ptr) 0, custom_size)) + bfd_fatal ("custom section"); + nlm_fixed_header (outbfd)->customDataOffset = + custom_section->filepos; + nlm_fixed_header (outbfd)->customDataSize = custom_size; + } + free (data); + } + if (! debug_info) + { + /* As a special hack, the backend recognizes a debugInfoOffset + of -1 to mean that it should not output any debugging + information. This can not be handling by fiddling with the + symbol table because exported symbols appear in both the + export information and the debugging information. */ + nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1; + } + if (map_file != NULL) + fprintf (stderr, + "%s: warning: MAP and FULLMAP are not supported; try ld -M\n", + program_name); + if (help_file != NULL) + { + PTR data; + + data = xmalloc (help_size); + if (fread (data, 1, help_size, help_data) != help_size) + fprintf (stderr, "%s:%s: read: %s\n", program_name, help_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, help_section, data, + (file_ptr) 0, help_size)) + bfd_fatal ("help section"); + nlm_extended_header (outbfd)->helpFileOffset = + help_section->filepos; + nlm_extended_header (outbfd)->helpFileLength = help_size; + } + free (data); + } + if (message_file != NULL) + { + PTR data; + + data = xmalloc (message_size); + if (fread (data, 1, message_size, message_data) != message_size) + fprintf (stderr, "%s:%s: read: %s\n", program_name, message_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, message_section, data, + (file_ptr) 0, message_size)) + bfd_fatal ("message section"); + nlm_extended_header (outbfd)->messageFileOffset = + message_section->filepos; + nlm_extended_header (outbfd)->messageFileLength = message_size; + + /* FIXME: Are these offsets correct on all platforms? Are + they 32 bits on all platforms? What endianness? */ + nlm_extended_header (outbfd)->languageID = + bfd_h_get_32 (outbfd, (bfd_byte *) data + 106); + nlm_extended_header (outbfd)->messageCount = + bfd_h_get_32 (outbfd, (bfd_byte *) data + 110); + } + free (data); + } + if (modules != NULL) + { + PTR data; + unsigned char *set; + struct string_list *l; + bfd_size_type c; + + data = xmalloc (module_size); + c = 0; + set = (unsigned char *) data; + for (l = modules; l != NULL; l = l->next) + { + *set = strlen (l->string); + strncpy (set + 1, l->string, *set); + set += *set + 1; + ++c; + } + if (! bfd_set_section_contents (outbfd, module_section, data, + (file_ptr) 0, module_size)) + bfd_fatal ("module section"); + nlm_fixed_header (outbfd)->moduleDependencyOffset = + module_section->filepos; + nlm_fixed_header (outbfd)->numberOfModuleDependencies = c; + } + if (rpc_file != NULL) + { + PTR data; + + data = xmalloc (rpc_size); + if (fread (data, 1, rpc_size, rpc_data) != rpc_size) + fprintf (stderr, "%s:%s: read: %s\n", program_name, rpc_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, rpc_section, data, + (file_ptr) 0, rpc_size)) + bfd_fatal ("rpc section"); + nlm_extended_header (outbfd)->RPCDataOffset = + rpc_section->filepos; + nlm_extended_header (outbfd)->RPCDataLength = rpc_size; + } + free (data); + } + if (sharelib_file != NULL) + { + PTR data; + + data = xmalloc (shared_size); + if (fseek (shared_data, shared_offset, SEEK_SET) != 0 + || fread (data, 1, shared_size, shared_data) != shared_size) + fprintf (stderr, "%s:%s: read: %s\n", program_name, sharelib_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, shared_section, data, + (file_ptr) 0, shared_size)) + bfd_fatal ("shared section"); + } + nlm_extended_header (outbfd)->sharedCodeOffset = + sharedhdr.codeImageOffset - shared_offset + shared_section->filepos; + nlm_extended_header (outbfd)->sharedCodeLength = + sharedhdr.codeImageSize; + nlm_extended_header (outbfd)->sharedDataOffset = + sharedhdr.dataImageOffset - shared_offset + shared_section->filepos; + nlm_extended_header (outbfd)->sharedDataLength = + sharedhdr.dataImageSize; + nlm_extended_header (outbfd)->sharedRelocationFixupOffset = + (sharedhdr.relocationFixupOffset + - shared_offset + + shared_section->filepos); + nlm_extended_header (outbfd)->sharedRelocationFixupCount = + sharedhdr.numberOfRelocationFixups; + nlm_extended_header (outbfd)->sharedExternalReferenceOffset = + (sharedhdr.externalReferencesOffset + - shared_offset + + shared_section->filepos); + nlm_extended_header (outbfd)->sharedExternalReferenceCount = + sharedhdr.numberOfExternalReferences; + nlm_extended_header (outbfd)->sharedPublicsOffset = + sharedhdr.publicsOffset - shared_offset + shared_section->filepos; + nlm_extended_header (outbfd)->sharedPublicsCount = + sharedhdr.numberOfPublics; + nlm_extended_header (outbfd)->sharedDebugRecordOffset = + sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos; + nlm_extended_header (outbfd)->sharedDebugRecordCount = + sharedhdr.numberOfDebugRecords; + nlm_extended_header (outbfd)->SharedInitializationOffset = + sharedhdr.codeStartOffset; + nlm_extended_header (outbfd)->SharedExitProcedureOffset = + sharedhdr.exitProcedureOffset; + free (data); + } + len = strlen (output_file); + if (len > NLM_MODULE_NAME_SIZE - 2) + len = NLM_MODULE_NAME_SIZE - 2; + nlm_fixed_header (outbfd)->moduleName[0] = len; + + strncpy (nlm_fixed_header (outbfd)->moduleName + 1, output_file, + NLM_MODULE_NAME_SIZE - 2); + nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0'; + for (modname = nlm_fixed_header (outbfd)->moduleName; + *modname != '\0'; + modname++) + if (islower (*modname)) + *modname = toupper (*modname); + + strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG", + NLM_OLD_THREAD_NAME_LENGTH); + + nlm_cygnus_ext_header (outbfd)->offset = secsec->filepos; + nlm_cygnus_ext_header (outbfd)->length = bfd_section_size (outbfd, secsec); + + if (! bfd_close (outbfd)) + bfd_fatal (output_file); + if (! bfd_close (inbfd)) + bfd_fatal (input_file); + + if (unlink_on_exit != NULL) + unlink (unlink_on_exit); + + return 0; +} + +/* Display a help message and exit. */ + +static void +show_help () +{ + printf ("%s: Convert an object file into a NetWare Loadable Module\n", + program_name); + show_usage (stdout, 0); +} + +/* Show a usage message and exit. */ + +static void +show_usage (file, status) + FILE *file; + int status; +{ + fprintf (file, "\ +Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n\ + [--input-target=bfdname] [--output-target=bfdname]\n\ + [--header-file=file] [--linker=linker] [--debug]\n\ + [--help] [--version]\n\ + [in-file [out-file]]\n", + program_name); + exit (status); +} + +/* Select the output format based on the input architecture, machine, + and endianness. This chooses the appropriate NLM target. */ + +static const char * +select_output_format (arch, mach, bigendian) + enum bfd_architecture arch; + unsigned long mach; + boolean bigendian; +{ + switch (arch) + { +#ifdef NLMCONV_I386 + case bfd_arch_i386: + return "nlm32-i386"; +#endif +#ifdef NLMCONV_SPARC + case bfd_arch_sparc: + return "nlm32-sparc"; +#endif +#ifdef NLMCONV_ALPHA + case bfd_arch_alpha: + return "nlm32-alpha"; +#endif +#ifdef NLMCONV_POWERPC + case bfd_arch_powerpc: + return "nlm32-powerpc"; +#endif + default: + fprintf (stderr, "%s: support not compiled in for %s\n", + program_name, bfd_printable_arch_mach (arch, mach)); + exit (1); + /* Avoid warning. */ + return NULL; + } + /*NOTREACHED*/ +} + +/* The BFD sections are copied in two passes. This function selects + the output section for each input section, and sets up the section + name, size, etc. */ + +static void +setup_sections (inbfd, insec, data_ptr) + bfd *inbfd; + asection *insec; + PTR data_ptr; +{ + bfd *outbfd = (bfd *) data_ptr; + flagword f; + const char *outname; + asection *outsec; + bfd_vma offset; + bfd_size_type align; + bfd_size_type add; + bfd_size_type secsecsize; + + f = bfd_get_section_flags (inbfd, insec); + if (f & SEC_CODE) + outname = NLM_CODE_NAME; + else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS)) + outname = NLM_INITIALIZED_DATA_NAME; + else if (f & SEC_ALLOC) + outname = NLM_UNINITIALIZED_DATA_NAME; + else + outname = bfd_section_name (inbfd, insec); + + outsec = bfd_get_section_by_name (outbfd, outname); + if (outsec == NULL) + { + outsec = bfd_make_section (outbfd, outname); + if (outsec == NULL) + bfd_fatal ("make section"); + } + + insec->output_section = outsec; + + offset = bfd_section_size (outbfd, outsec); + align = 1 << bfd_section_alignment (inbfd, insec); + add = ((offset + align - 1) &~ (align - 1)) - offset; + insec->output_offset = offset + add; + + if (! bfd_set_section_size (outbfd, outsec, + (bfd_section_size (outbfd, outsec) + + bfd_section_size (inbfd, insec) + + add))) + bfd_fatal ("set section size"); + + if ((bfd_section_alignment (inbfd, insec) + > bfd_section_alignment (outbfd, outsec)) + && ! bfd_set_section_alignment (outbfd, outsec, + bfd_section_alignment (inbfd, insec))) + bfd_fatal ("set section alignment"); + + if (! bfd_set_section_flags (outbfd, outsec, + f | bfd_get_section_flags (outbfd, outsec))) + bfd_fatal ("set section flags"); + + bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0); + + /* For each input section we allocate space for an entry in + .nlmsections. */ + secsecsize = bfd_section_size (outbfd, secsec); + secsecsize += strlen (bfd_section_name (inbfd, insec)) + 1; + secsecsize = (secsecsize + 3) &~ 3; + secsecsize += 8; + if (! bfd_set_section_size (outbfd, secsec, secsecsize)) + bfd_fatal ("set .nlmsections size"); +} + +/* Copy the section contents. */ + +static void +copy_sections (inbfd, insec, data_ptr) + bfd *inbfd; + asection *insec; + PTR data_ptr; +{ + static bfd_size_type secsecoff = 0; + bfd *outbfd = (bfd *) data_ptr; + const char *inname; + asection *outsec; + bfd_size_type size; + PTR contents; + long reloc_size; + bfd_byte buf[4]; + bfd_size_type add; + + inname = bfd_section_name (inbfd, insec); + + outsec = insec->output_section; + assert (outsec != NULL); + + size = bfd_get_section_size_before_reloc (insec); + + /* FIXME: Why are these necessary? */ + insec->_cooked_size = insec->_raw_size; + insec->reloc_done = true; + + if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0) + contents = NULL; + else + { + contents = xmalloc (size); + if (! bfd_get_section_contents (inbfd, insec, contents, + (file_ptr) 0, size)) + bfd_fatal (bfd_get_filename (inbfd)); + } + + reloc_size = bfd_get_reloc_upper_bound (inbfd, insec); + if (reloc_size < 0) + bfd_fatal (bfd_get_filename (inbfd)); + if (reloc_size != 0) + { + arelent **relocs; + long reloc_count; + + relocs = (arelent **) xmalloc (reloc_size); + reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols); + if (reloc_count < 0) + bfd_fatal (bfd_get_filename (inbfd)); + mangle_relocs (outbfd, insec, &relocs, &reloc_count, (char *) contents, + size); + + /* FIXME: refers to internal BFD fields. */ + if (outsec->orelocation != (arelent **) NULL) + { + bfd_size_type total_count; + arelent **combined; + + total_count = reloc_count + outsec->reloc_count; + combined = (arelent **) xmalloc (total_count * sizeof (arelent *)); + memcpy (combined, outsec->orelocation, + outsec->reloc_count * sizeof (arelent *)); + memcpy (combined + outsec->reloc_count, relocs, + (size_t) (reloc_count * sizeof (arelent *))); + free (outsec->orelocation); + reloc_count = total_count; + relocs = combined; + } + + bfd_set_reloc (outbfd, outsec, relocs, reloc_count); + } + + if (contents != NULL) + { + if (! bfd_set_section_contents (outbfd, outsec, contents, + insec->output_offset, size)) + bfd_fatal (bfd_get_filename (outbfd)); + free (contents); + } + + /* Add this section to .nlmsections. */ + if (! bfd_set_section_contents (outbfd, secsec, (PTR) inname, secsecoff, + strlen (inname) + 1)) + bfd_fatal ("set .nlmsection contents"); + secsecoff += strlen (inname) + 1; + + add = ((secsecoff + 3) &~ 3) - secsecoff; + if (add != 0) + { + bfd_h_put_32 (outbfd, (bfd_vma) 0, buf); + if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, add)) + bfd_fatal ("set .nlmsection contents"); + secsecoff += add; + } + + if (contents != NULL) + bfd_h_put_32 (outbfd, (bfd_vma) outsec->filepos, buf); + else + bfd_h_put_32 (outbfd, (bfd_vma) 0, buf); + if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4)) + bfd_fatal ("set .nlmsection contents"); + secsecoff += 4; + + bfd_h_put_32 (outbfd, (bfd_vma) size, buf); + if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4)) + bfd_fatal ("set .nlmsection contents"); + secsecoff += 4; +} + +/* Some, perhaps all, NetWare targets require changing the relocs used + by the input formats. */ + +static void +mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + switch (bfd_get_arch (outbfd)) + { +#ifdef NLMCONV_I386 + case bfd_arch_i386: + i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, + contents, contents_size); + break; +#endif +#ifdef NLMCONV_ALPHA + case bfd_arch_alpha: + alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, + contents, contents_size); + break; +#endif +#ifdef NLMCONV_POWERPC + case bfd_arch_powerpc: + powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, + contents, contents_size); + break; +#endif + default: + default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, + contents, contents_size); + break; + } +} + +/* By default all we need to do for relocs is change the address by + the output_offset. */ + +/*ARGSUSED*/ +static void +default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + if (insec->output_offset != 0) + { + long reloc_count; + register arelent **relocs; + register long i; + + reloc_count = *reloc_count_ptr; + relocs = *relocs_ptr; + for (i = 0; i < reloc_count; i++, relocs++) + (*relocs)->address += insec->output_offset; + } +} + +#ifdef NLMCONV_I386 + +/* NetWare on the i386 supports a restricted set of relocs, which are + different from those used on other i386 targets. This routine + converts the relocs. It is, obviously, very target dependent. At + the moment, the nlm32-i386 backend performs similar translations; + however, it is more reliable and efficient to do them here. */ + +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 */ + +static void +i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + long reloc_count, i; + arelent **relocs; + + reloc_count = *reloc_count_ptr; + relocs = *relocs_ptr; + for (i = 0; i < reloc_count; i++) + { + arelent *rel; + asymbol *sym; + bfd_size_type address; + bfd_vma addend; + + rel = *relocs++; + sym = *rel->sym_ptr_ptr; + + /* We're moving the relocs from the input section to the output + section, so we must adjust the address accordingly. */ + address = rel->address; + rel->address += insec->output_offset; + + /* Note that no serious harm will ensue if we fail to change a + reloc. The backend will fail when writing out the reloc. */ + + /* Make sure this reloc is within the data we have. We use only + 4 byte relocs here, so we insist on having 4 bytes. */ + if (address + 4 > contents_size) + continue; + + /* A PC relative reloc entirely within a single section is + completely unnecessary. This can be generated by ld -r. */ + if (sym == insec->symbol + && rel->howto != NULL + && rel->howto->pc_relative + && ! rel->howto->pcrel_offset) + { + --*reloc_count_ptr; + --relocs; + memmove (relocs, relocs + 1, + (size_t) ((reloc_count - i) * sizeof (arelent *))); + continue; + } + + /* Get the amount the relocation will add in. */ + addend = rel->addend + sym->value; + + /* NetWare doesn't support PC relative relocs against defined + symbols, so we have to eliminate them by doing the relocation + now. We can only do this if the reloc is within a single + section. */ + if (rel->howto != NULL + && rel->howto->pc_relative + && bfd_get_section (sym) == insec->output_section) + { + bfd_vma val; + + if (rel->howto->pcrel_offset) + addend -= address; + + val = bfd_get_32 (outbfd, (bfd_byte *) contents + address); + val += addend; + bfd_put_32 (outbfd, val, (bfd_byte *) contents + address); + + --*reloc_count_ptr; + --relocs; + memmove (relocs, relocs + 1, + (size_t) ((reloc_count - i) * sizeof (arelent *))); + 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. */ + 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 (outbfd, (bfd_byte *) contents + address); + val += addend; + bfd_put_32 (outbfd, val, (bfd_byte *) contents + address); + + /* Adjust the reloc for the changes we just made. */ + rel->addend = 0; + if (! bfd_is_und_section (bfd_get_section (sym))) + rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr; + } + + /* 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 that special_function is NULL + 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 (outbfd, (bfd_byte *) contents + address); + val += address; + bfd_put_32 (outbfd, val, (bfd_byte *) contents + address); + + /* We must change to a new howto. */ + rel->howto = &nlm_i386_pcrel_howto; + } + } +} + +#endif /* NLMCONV_I386 */ + +#ifdef NLMCONV_ALPHA + +/* On the Alpha the first reloc for every section must be a special + relocs which hold the GP address. Also, the first reloc in the + file must be a special reloc which holds the address of the .lita + section. */ + +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 */ + +/*ARGSUSED*/ +static void +alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + register arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + long old_reloc_count; + arelent **old_relocs; + register arelent **relocs; + + old_reloc_count = *reloc_count_ptr; + old_relocs = *relocs_ptr; + relocs = (arelent **) xmalloc ((old_reloc_count + 3) * sizeof (arelent *)); + *relocs_ptr = relocs; + + if (nlm_alpha_backend_data (outbfd)->lita_address == 0) + { + bfd *inbfd; + asection *lita_section; + + inbfd = insec->owner; + lita_section = bfd_get_section_by_name (inbfd, _LITA); + if (lita_section != (asection *) NULL) + { + nlm_alpha_backend_data (outbfd)->lita_address = + bfd_get_section_vma (inbfd, lita_section); + nlm_alpha_backend_data (outbfd)->lita_size = + bfd_section_size (inbfd, lita_section); + } + else + { + /* Avoid outputting this reloc again. */ + nlm_alpha_backend_data (outbfd)->lita_address = 4; + } + + *relocs = (arelent *) xmalloc (sizeof (arelent)); + (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + (*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address; + (*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1; + (*relocs)->howto = &nlm32_alpha_nw_howto; + ++relocs; + ++(*reloc_count_ptr); + } + + /* Get the GP value from bfd. */ + if (nlm_alpha_backend_data (outbfd)->gp == 0) + nlm_alpha_backend_data (outbfd)->gp = + bfd_ecoff_get_gp_value (insec->owner); + + *relocs = (arelent *) xmalloc (sizeof (arelent)); + (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + (*relocs)->address = nlm_alpha_backend_data (outbfd)->gp; + (*relocs)->addend = 0; + (*relocs)->howto = &nlm32_alpha_nw_howto; + ++relocs; + ++(*reloc_count_ptr); + + memcpy ((PTR) relocs, (PTR) old_relocs, + (size_t) old_reloc_count * sizeof (arelent *)); + relocs[old_reloc_count] = (arelent *) NULL; + + free (old_relocs); + + if (insec->output_offset != 0) + { + register bfd_size_type i; + + for (i = 0; i < old_reloc_count; i++, relocs++) + (*relocs)->address += insec->output_offset; + } +} + +#endif /* NLMCONV_ALPHA */ + +#ifdef NLMCONV_POWERPC + +/* We keep a linked list of stubs which we must build. Because BFD + requires us to know the sizes of all sections before we can set the + contents of any, we must figure out which stubs we want to build + before we can actually build any of them. */ + +struct powerpc_stub +{ + /* Next stub in linked list. */ + struct powerpc_stub *next; + + /* Symbol whose value is the start of the stub. This is a symbol + whose name begins with `.'. */ + asymbol *start; + + /* Symbol we are going to create a reloc against. This is a symbol + with the same name as START but without the leading `.'. */ + asymbol *reloc; + + /* The TOC index for this stub. This is the index into the TOC + section at which the reloc is created. */ + unsigned int toc_index; +}; + +/* The linked list of stubs. */ + +static struct powerpc_stub *powerpc_stubs; + +/* This is what a stub looks like. The first instruction will get + adjusted with the correct TOC index. */ + +static unsigned long powerpc_stub_insns[] = +{ + 0x81820000, /* lwz r12,0(r2) */ + 0x90410014, /* stw r2,20(r1) */ + 0x800c0000, /* lwz r0,0(r12) */ + 0x804c0004, /* lwz r2,r(r12) */ + 0x7c0903a6, /* mtctr r0 */ + 0x4e800420, /* bctr */ + 0, /* Traceback table. */ + 0xc8000, + 0 +}; + +#define POWERPC_STUB_INSN_COUNT \ + (sizeof powerpc_stub_insns / sizeof powerpc_stub_insns[0]) + +#define POWERPC_STUB_SIZE (4 * POWERPC_STUB_INSN_COUNT) + +/* Each stub uses a four byte TOC entry. */ +#define POWERPC_STUB_TOC_ENTRY_SIZE (4) + +/* The original size of the .got section. */ +static bfd_size_type powerpc_initial_got_size; + +/* Look for all undefined symbols beginning with `.', and prepare to + build a stub for each one. */ + +static void +powerpc_build_stubs (inbfd, outbfd, symbols_ptr, symcount_ptr) + bfd *inbfd; + bfd *outbfd; + asymbol ***symbols_ptr; + long *symcount_ptr; +{ + asection *stub_sec; + asection *got_sec; + unsigned int got_base; + long i; + long symcount; + long stubcount; + + /* Make a section to hold stubs. We don't set SEC_HAS_CONTENTS for + the section to prevent copy_sections from reading from it. */ + stub_sec = bfd_make_section (inbfd, ".stubs"); + if (stub_sec == (asection *) NULL + || ! bfd_set_section_flags (inbfd, stub_sec, + (SEC_CODE + | SEC_RELOC + | SEC_ALLOC + | SEC_LOAD)) + || ! bfd_set_section_alignment (inbfd, stub_sec, 2)) + bfd_fatal (".stubs"); + + /* Get the TOC section, which is named .got. */ + got_sec = bfd_get_section_by_name (inbfd, ".got"); + if (got_sec == (asection *) NULL) + { + got_sec = bfd_make_section (inbfd, ".got"); + if (got_sec == (asection *) NULL + || ! bfd_set_section_flags (inbfd, got_sec, + (SEC_DATA + | SEC_RELOC + | SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS)) + || ! bfd_set_section_alignment (inbfd, got_sec, 2)) + bfd_fatal (".got"); + } + + powerpc_initial_got_size = bfd_section_size (inbfd, got_sec); + got_base = powerpc_initial_got_size; + got_base = (got_base + 3) &~ 3; + + stubcount = 0; + + symcount = *symcount_ptr; + for (i = 0; i < symcount; i++) + { + asymbol *sym; + asymbol *newsym; + char *newname; + struct powerpc_stub *item; + + sym = (*symbols_ptr)[i]; + + /* We must make a stub for every undefined symbol whose name + starts with '.'. */ + if (bfd_asymbol_name (sym)[0] != '.' + || ! bfd_is_und_section (bfd_get_section (sym))) + continue; + + /* Make a new undefined symbol with the same name but without + the leading `.'. */ + newsym = (asymbol *) xmalloc (sizeof (asymbol)); + *newsym = *sym; + newname = (char *) xmalloc (strlen (bfd_asymbol_name (sym))); + strcpy (newname, bfd_asymbol_name (sym) + 1); + newsym->name = newname; + + /* Define the `.' symbol to be in the stub section. */ + sym->section = stub_sec; + sym->value = stubcount * POWERPC_STUB_SIZE; + /* We set the BSF_DYNAMIC flag here so that we can check it when + we are mangling relocs. FIXME: This is a hack. */ + sym->flags = BSF_LOCAL | BSF_DYNAMIC; + + /* Add this stub to the linked list. */ + item = (struct powerpc_stub *) xmalloc (sizeof (struct powerpc_stub)); + item->start = sym; + item->reloc = newsym; + item->toc_index = got_base + stubcount * POWERPC_STUB_TOC_ENTRY_SIZE; + + item->next = powerpc_stubs; + powerpc_stubs = item; + + ++stubcount; + } + + if (stubcount > 0) + { + asymbol **s; + struct powerpc_stub *l; + + /* Add the new symbols we just created to the symbol table. */ + *symbols_ptr = (asymbol **) xrealloc ((char *) *symbols_ptr, + ((symcount + stubcount) + * sizeof (asymbol))); + *symcount_ptr += stubcount; + s = &(*symbols_ptr)[symcount]; + for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next) + *s++ = l->reloc; + + /* Set the size of the .stubs section and increase the size of + the .got section. */ + if (! bfd_set_section_size (inbfd, stub_sec, + stubcount * POWERPC_STUB_SIZE) + || ! bfd_set_section_size (inbfd, got_sec, + (got_base + + (stubcount + * POWERPC_STUB_TOC_ENTRY_SIZE)))) + bfd_fatal ("stub section sizes"); + } +} + +/* Resolve all the stubs for PowerPC NetWare. We fill in the contents + of the output section, and create new relocs in the TOC. */ + +static void +powerpc_resolve_stubs (inbfd, outbfd) + bfd *inbfd; + bfd *outbfd; +{ + bfd_byte buf[POWERPC_STUB_SIZE]; + unsigned int i; + unsigned int stubcount; + arelent **relocs; + asection *got_sec; + arelent **r; + struct powerpc_stub *l; + + if (powerpc_stubs == (struct powerpc_stub *) NULL) + return; + + for (i = 0; i < POWERPC_STUB_INSN_COUNT; i++) + bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[i], buf + i * 4); + + got_sec = bfd_get_section_by_name (inbfd, ".got"); + assert (got_sec != (asection *) NULL); + assert (got_sec->output_section->orelocation == (arelent **) NULL); + + stubcount = 0; + for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next) + ++stubcount; + relocs = (arelent **) xmalloc (stubcount * sizeof (arelent *)); + + r = relocs; + for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next) + { + arelent *reloc; + + /* Adjust the first instruction to use the right TOC index. */ + bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[0] + l->toc_index, buf); + + /* Write this stub out. */ + if (! bfd_set_section_contents (outbfd, + bfd_get_section (l->start), + buf, + l->start->value, + POWERPC_STUB_SIZE)) + bfd_fatal ("writing stub"); + + /* Create a new reloc for the TOC entry. */ + reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = &l->reloc; + reloc->address = l->toc_index + got_sec->output_offset; + reloc->addend = 0; + reloc->howto = bfd_reloc_type_lookup (inbfd, BFD_RELOC_32); + + *r++ = reloc; + } + + bfd_set_reloc (outbfd, got_sec->output_section, relocs, stubcount); +} + +/* Adjust relocation entries for PowerPC NetWare. We do not output + TOC relocations. The object code already contains the offset from + the TOC pointer. When the function is called, the TOC register, + r2, will be set to the correct TOC value, so there is no need for + any further reloc. */ + +/*ARGSUSED*/ +static void +powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + register arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + reloc_howto_type *toc_howto; + long reloc_count; + register arelent **relocs; + register long i; + + toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16); + if (toc_howto == (reloc_howto_type *) NULL) + abort (); + + /* If this is the .got section, clear out all the contents beyond + the initial size. We must do this here because copy_sections is + going to write out whatever we return in the contents field. */ + if (strcmp (bfd_get_section_name (insec->owner, insec), ".got") == 0) + memset (contents + powerpc_initial_got_size, 0, + (size_t) (bfd_get_section_size_after_reloc (insec) + - powerpc_initial_got_size)); + + reloc_count = *reloc_count_ptr; + relocs = *relocs_ptr; + for (i = 0; i < reloc_count; i++) + { + arelent *rel; + asymbol *sym; + bfd_vma sym_value; + + rel = *relocs++; + sym = *rel->sym_ptr_ptr; + + /* Convert any relocs against the .bss section into relocs + against the .data section. */ + if (strcmp (bfd_get_section_name (outbfd, bfd_get_section (sym)), + NLM_UNINITIALIZED_DATA_NAME) == 0) + { + asection *datasec; + + datasec = bfd_get_section_by_name (outbfd, + NLM_INITIALIZED_DATA_NAME); + if (datasec != NULL) + { + rel->addend += (bfd_get_section_vma (outbfd, + bfd_get_section (sym)) + + sym->value); + rel->sym_ptr_ptr = datasec->symbol_ptr_ptr; + sym = *rel->sym_ptr_ptr; + } + } + + /* We must be able to resolve all PC relative relocs at this + point. If we get a branch to an undefined symbol we build a + stub, since NetWare will resolve undefined symbols into a + pointer to a function descriptor. */ + if (rel->howto->pc_relative) + { + /* This check for whether a symbol is in the same section as + the reloc will be wrong if there is a PC relative reloc + between two sections both of which were placed in the + same output section. This should not happen. */ + if (bfd_get_section (sym) != insec->output_section) + fprintf (stderr, "%s: unresolved PC relative reloc against %s\n", + program_name, bfd_asymbol_name (sym)); + else + { + bfd_vma val; + + assert (rel->howto->size == 2 && rel->howto->pcrel_offset); + val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address); + val = ((val &~ rel->howto->dst_mask) + | (((val & rel->howto->src_mask) + + (sym->value - rel->address) + + rel->addend) + & rel->howto->dst_mask)); + bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address); + + /* If this reloc is against an stubbed symbol and the + next instruction is + cror 31,31,31 + then we replace the next instruction with + lwz r2,20(r1) + This reloads the TOC pointer after a stub call. */ + if (bfd_asymbol_name (sym)[0] == '.' + && (sym->flags & BSF_DYNAMIC) != 0 + && (bfd_get_32 (outbfd, + (bfd_byte *) contents + rel->address + 4) + == 0x4ffffb82)) /* cror 31,31,31 */ + bfd_put_32 (outbfd, (bfd_vma) 0x80410014, /* lwz r2,20(r1) */ + (bfd_byte *) contents + rel->address + 4); + + --*reloc_count_ptr; + --relocs; + memmove (relocs, relocs + 1, + (size_t) ((reloc_count - 1) * sizeof (arelent *))); + continue; + } + } + + /* When considering a TOC reloc, we do not want to include the + symbol value. The symbol will be start of the TOC section + (which is named .got). We do want to include the addend. */ + if (rel->howto == toc_howto) + sym_value = 0; + else + sym_value = sym->value; + + /* If this is a relocation against a symbol with a value, or + there is a reloc addend, we need to update the addend in the + object file. */ + if (sym_value + rel->addend != 0) + { + bfd_vma val; + + switch (rel->howto->size) + { + case 1: + val = bfd_get_16 (outbfd, + (bfd_byte *) contents + rel->address); + val = ((val &~ rel->howto->dst_mask) + | (((val & rel->howto->src_mask) + + sym_value + + rel->addend) + & rel->howto->dst_mask)); + if ((bfd_signed_vma) val < - 0x8000 + || (bfd_signed_vma) val >= 0x8000) + fprintf (stderr, + "%s: overflow when adjusting relocation against %s\n", + program_name, bfd_asymbol_name (sym)); + bfd_put_16 (outbfd, val, (bfd_byte *) contents + rel->address); + break; + + case 2: + val = bfd_get_32 (outbfd, + (bfd_byte *) contents + rel->address); + val = ((val &~ rel->howto->dst_mask) + | (((val & rel->howto->src_mask) + + sym_value + + rel->addend) + & rel->howto->dst_mask)); + bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address); + break; + + default: + abort (); + } + + if (! bfd_is_und_section (bfd_get_section (sym))) + rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr; + rel->addend = 0; + } + + /* Now that we have incorporated the addend, remove any TOC + relocs. */ + if (rel->howto == toc_howto) + { + --*reloc_count_ptr; + --relocs; + memmove (relocs, relocs + 1, + (size_t) ((reloc_count - i) * sizeof (arelent *))); + continue; + } + + rel->address += insec->output_offset; + } +} + +#endif /* NLMCONV_POWERPC */ + +/* Name of linker. */ +#ifndef LD_NAME +#define LD_NAME "ld" +#endif + +/* Temporary file name base. */ +static char *temp_filename; + +/* The user has specified several input files. Invoke the linker to + link them all together, and convert and delete the resulting output + file. */ + +static char * +link_inputs (inputs, ld) + struct string_list *inputs; + char *ld; +{ + size_t c; + struct string_list *q; + char **argv; + size_t i; + int pid; + int status; + + c = 0; + for (q = inputs; q != NULL; q = q->next) + ++c; + + argv = (char **) alloca ((c + 5) * sizeof(char *)); + +#ifndef __MSDOS__ + if (ld == NULL) + { + char *p; + + /* Find the linker to invoke based on how nlmconv was run. */ + p = program_name + strlen (program_name); + while (p != program_name) + { + if (p[-1] == '/') + { + ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1); + memcpy (ld, program_name, p - program_name); + strcpy (ld + (p - program_name), LD_NAME); + break; + } + --p; + } + } +#endif + + if (ld == NULL) + ld = (char *) LD_NAME; + + choose_temp_base (); + + unlink_on_exit = xmalloc (strlen (temp_filename) + 3); + sprintf (unlink_on_exit, "%s.O", temp_filename); + + argv[0] = ld; + argv[1] = (char *) "-Ur"; + argv[2] = (char *) "-o"; + argv[3] = unlink_on_exit; + i = 4; + for (q = inputs; q != NULL; q = q->next, i++) + argv[i] = q->string; + argv[i] = NULL; + + if (debug) + { + for (i = 0; argv[i] != NULL; i++) + fprintf (stderr, " %s", argv[i]); + fprintf (stderr, "\n"); + } + + pid = pexecute (ld, argv); + + if (waitpid (pid, &status, 0) < 0) + { + perror ("waitpid"); + unlink (unlink_on_exit); + exit (1); + } + + if (status != 0) + { + fprintf (stderr, "%s: Execution of %s failed\n", program_name, ld); + unlink (unlink_on_exit); + exit (1); + } + + return unlink_on_exit; +} + +/* Choose a temporary file name. Stolen from gcc.c. */ + +static const char * +choose_temp_base_try (try, base) + const char *try; + const char *base; +{ + const char *rv; + + if (base) + rv = base; + else if (try == NULL) + rv = NULL; + else if (access (try, R_OK | W_OK) != 0) + rv = NULL; + else + rv = try; + return rv; +} + +static void +choose_temp_base () +{ + const char *base = NULL; + int len; + + base = choose_temp_base_try (getenv ("TMPDIR"), base); + base = choose_temp_base_try (getenv ("TMP"), base); + base = choose_temp_base_try (getenv ("TEMP"), base); + +#ifdef P_tmpdir + base = choose_temp_base_try (P_tmpdir, base); +#endif + + base = choose_temp_base_try ("/usr/tmp", base); + base = choose_temp_base_try ("/tmp", base); + + /* If all else fails, use the current directory! */ + if (base == NULL) + base = "./"; + + len = strlen (base); + temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1); + strcpy (temp_filename, base); + if (len > 0 && temp_filename[len-1] != '/') + temp_filename[len++] = '/'; + strcpy (temp_filename + len, "ccXXXXXX"); + + mktemp (temp_filename); + if (*temp_filename == '\0') + abort (); +} + +/* Execute a job. Stolen from gcc.c. */ + +#ifndef OS2 +#ifdef __MSDOS__ + +static int +pexecute (program, argv) + char *program; + char *argv[]; +{ + char *scmd, *rf; + FILE *argfile; + int i; + + scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 10); + rf = scmd + strlen(program) + 2 + el; + sprintf (scmd, "%s.exe @%s.gp", program, temp_filename); + argfile = fopen (rf, "w"); + if (argfile == 0) + pfatal_with_name (rf); + + for (i=1; argv[i]; i++) + { + char *cp; + for (cp = argv[i]; *cp; cp++) + { + if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp)) + fputc ('\\', argfile); + fputc (*cp, argfile); + } + fputc ('\n', argfile); + } + fclose (argfile); + + i = system (scmd); + + remove (rf); + + if (i == -1) + { + perror (program); + return MIN_FATAL_STATUS << 8; + } + + return i << 8; +} + +#else /* not __MSDOS__ */ + +static int +pexecute (program, argv) + char *program; + char *argv[]; +{ + int pid; + int retries, sleep_interval; + + /* Fork a subprocess; wait and retry if it fails. */ + sleep_interval = 1; + for (retries = 0; retries < 4; retries++) + { + pid = vfork (); + if (pid >= 0) + break; + sleep (sleep_interval); + sleep_interval *= 2; + } + + switch (pid) + { + case -1: +#ifdef vfork + perror ("fork"); +#else + perror ("vfork"); +#endif + exit (1); + /* NOTREACHED */ + return 0; + + case 0: /* child */ + /* Exec the program. */ + execvp (program, argv); + perror (program); + exit (1); + /* NOTREACHED */ + return 0; + + default: + /* Return child's process number. */ + return pid; + } +} + +#endif /* not __MSDOS__ */ +#else /* not OS2 */ + +static int +pexecute (program, argv) + char *program; + char *argv[]; +{ + return spawnvp (1, program, argv); +} +#endif /* not OS2 */ diff --git a/gnu/usr.bin/binutils/binutils/nlmconv.h b/gnu/usr.bin/binutils/binutils/nlmconv.h new file mode 100644 index 00000000000..c92a557bb7f --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/nlmconv.h @@ -0,0 +1,84 @@ +/* nlmconv.h -- header file for NLM conversion program + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 Lance Taylor . + + bfd.h, nlm/common.h and nlm/internal.h must be included before this + file. */ + +/* A linked list of strings. */ + +struct string_list +{ + struct string_list *next; + char *string; +}; + +/* The NLM header parser in nlmheader.y stores information in the + following variables. */ + +extern Nlm_Internal_Fixed_Header *fixed_hdr; +extern Nlm_Internal_Variable_Header *var_hdr; +extern Nlm_Internal_Version_Header *version_hdr; +extern Nlm_Internal_Copyright_Header *copyright_hdr; +extern Nlm_Internal_Extended_Header *extended_hdr; + +/* Procedure named by CHECK. */ +extern char *check_procedure; +/* File named by CUSTOM. */ +extern char *custom_file; +/* Whether to generate debugging information (DEBUG). */ +extern boolean debug_info; +/* Procedure named by EXIT. */ +extern char *exit_procedure; +/* Exported symbols (EXPORT). */ +extern struct string_list *export_symbols; +/* List of files from INPUT. */ +extern struct string_list *input_files; +/* Map file name (MAP, FULLMAP). */ +extern char *map_file; +/* Whether a full map has been requested (FULLMAP). */ +extern boolean full_map; +/* File named by HELP. */ +extern char *help_file; +/* Imported symbols (IMPORT). */ +extern struct string_list *import_symbols; +/* File named by MESSAGES. */ +extern char *message_file; +/* Autoload module list (MODULE). */ +extern struct string_list *modules; +/* File named by OUTPUT. */ +extern char *output_file; +/* File named by SHARELIB. */ +extern char *sharelib_file; +/* Start procedure name (START). */ +extern char *start_procedure; +/* VERBOSE. */ +extern boolean verbose; +/* RPC description file (XDCDATA). */ +extern char *rpc_file; + +/* The number of serious parse errors. */ +extern int parse_errors; + +/* The parser. */ +extern int yyparse PARAMS ((void)); + +/* Tell the lexer what file to read. */ +extern boolean nlmlex_file PARAMS ((const char *)); diff --git a/gnu/usr.bin/binutils/binutils/nlmheader.c b/gnu/usr.bin/binutils/binutils/nlmheader.c new file mode 100644 index 00000000000..c27f66292bf --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/nlmheader.c @@ -0,0 +1,1931 @@ + +/* A Bison parser, made from ./nlmheader.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define CHECK 258 +#define CODESTART 259 +#define COPYRIGHT 260 +#define CUSTOM 261 +#define DATE 262 +#define DEBUG 263 +#define DESCRIPTION 264 +#define EXIT 265 +#define EXPORT 266 +#define FLAG_ON 267 +#define FLAG_OFF 268 +#define FULLMAP 269 +#define HELP 270 +#define IMPORT 271 +#define INPUT 272 +#define MAP 273 +#define MESSAGES 274 +#define MODULE 275 +#define MULTIPLE 276 +#define OS_DOMAIN 277 +#define OUTPUT 278 +#define PSEUDOPREEMPTION 279 +#define REENTRANT 280 +#define SCREENNAME 281 +#define SHARELIB 282 +#define STACK 283 +#define START 284 +#define SYNCHRONIZE 285 +#define THREADNAME 286 +#define TYPE 287 +#define VERBOSE 288 +#define VERSION 289 +#define XDCDATA 290 +#define STRING 291 +#define QUOTED_STRING 292 + +#line 1 "./nlmheader.y" +/* nlmheader.y - parse NLM header specification keywords. + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 Lance Taylor . + + This bison file parses the commands recognized by the NetWare NLM + linker, except for lists of object files. It stores the + information in global variables. + + This implementation is based on the description in the NetWare Tool + Maker Specification manual, edition 1.0. */ + +#include +#include +#include +#include "bfd.h" +#include "sysdep.h" +#include "bucomm.h" +#include "nlm/common.h" +#include "nlm/internal.h" +#include "nlmconv.h" + +/* Information is stored in the structures pointed to by these + variables. */ + +Nlm_Internal_Fixed_Header *fixed_hdr; +Nlm_Internal_Variable_Header *var_hdr; +Nlm_Internal_Version_Header *version_hdr; +Nlm_Internal_Copyright_Header *copyright_hdr; +Nlm_Internal_Extended_Header *extended_hdr; + +/* Procedure named by CHECK. */ +char *check_procedure; +/* File named by CUSTOM. */ +char *custom_file; +/* Whether to generate debugging information (DEBUG). */ +boolean debug_info; +/* Procedure named by EXIT. */ +char *exit_procedure; +/* Exported symbols (EXPORT). */ +struct string_list *export_symbols; +/* List of files from INPUT. */ +struct string_list *input_files; +/* Map file name (MAP, FULLMAP). */ +char *map_file; +/* Whether a full map has been requested (FULLMAP). */ +boolean full_map; +/* File named by HELP. */ +char *help_file; +/* Imported symbols (IMPORT). */ +struct string_list *import_symbols; +/* File named by MESSAGES. */ +char *message_file; +/* Autoload module list (MODULE). */ +struct string_list *modules; +/* File named by OUTPUT. */ +char *output_file; +/* File named by SHARELIB. */ +char *sharelib_file; +/* Start procedure name (START). */ +char *start_procedure; +/* VERBOSE. */ +boolean verbose; +/* RPC description file (XDCDATA). */ +char *rpc_file; + +/* The number of serious errors that have occurred. */ +int parse_errors; + +/* The current symbol prefix when reading a list of import or export + symbols. */ +static char *symbol_prefix; + +/* Parser error message handler. */ +#define yyerror(msg) nlmheader_error (msg); + +/* Local functions. */ +static int yylex PARAMS ((void)); +static void nlmlex_file_push PARAMS ((const char *)); +static boolean nlmlex_file_open PARAMS ((const char *)); +static int nlmlex_buf_init PARAMS ((void)); +static char nlmlex_buf_add PARAMS ((int)); +static long nlmlex_get_number PARAMS ((const char *)); +static void nlmheader_identify PARAMS ((void)); +static void nlmheader_warn PARAMS ((const char *, int)); +static void nlmheader_error PARAMS ((const char *)); +static struct string_list * string_list_cons PARAMS ((char *, + struct string_list *)); +static struct string_list * string_list_append PARAMS ((struct string_list *, + struct string_list *)); +static struct string_list * string_list_append1 PARAMS ((struct string_list *, + char *)); +static char *xstrdup PARAMS ((const char *)); + + +#line 113 "./nlmheader.y" +typedef union +{ + char *string; + struct string_list *list; +} 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 + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 82 +#define YYFLAG -32768 +#define YYNTBASE 40 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 292 ? yytranslate[x] : 50) + +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, 2, 2, 2, 38, + 39, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 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, 35, + 36, 37 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 3, 6, 9, 12, 15, 18, 23, 25, + 28, 31, 32, 36, 39, 42, 44, 47, 50, 51, + 55, 58, 60, 63, 66, 69, 71, 73, 76, 78, + 80, 83, 86, 89, 92, 94, 97, 100, 102, 107, + 111, 114, 115, 117, 119, 121, 124, 127, 131, 133, + 134 +}; + +static const short yyrhs[] = { 41, + 0, 0, 42, 41, 0, 3, 36, 0, 4, 36, + 0, 5, 37, 0, 6, 36, 0, 7, 36, 36, + 36, 0, 8, 0, 9, 37, 0, 10, 36, 0, + 0, 11, 43, 45, 0, 12, 36, 0, 13, 36, + 0, 14, 0, 14, 36, 0, 15, 36, 0, 0, + 16, 44, 45, 0, 17, 49, 0, 18, 0, 18, + 36, 0, 19, 36, 0, 20, 49, 0, 21, 0, + 22, 0, 23, 36, 0, 24, 0, 25, 0, 26, + 37, 0, 27, 36, 0, 28, 36, 0, 29, 36, + 0, 30, 0, 31, 37, 0, 32, 36, 0, 33, + 0, 34, 36, 36, 36, 0, 34, 36, 36, 0, + 35, 36, 0, 0, 46, 0, 48, 0, 47, 0, + 46, 48, 0, 46, 47, 0, 38, 36, 39, 0, + 36, 0, 0, 36, 49, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 144, 150, 152, 157, 162, 167, 184, 188, 206, 210, + 226, 230, 235, 238, 243, 248, 253, 258, 262, 267, + 270, 274, 278, 282, 286, 290, 294, 298, 305, 309, + 313, 329, 333, 338, 342, 346, 362, 367, 371, 395, + 411, 419, 424, 434, 439, 443, 447, 455, 466, 482, + 487 +}; + +static const char * const yytname[] = { "$","error","$undefined.","CHECK", +"CODESTART","COPYRIGHT","CUSTOM","DATE","DEBUG","DESCRIPTION","EXIT","EXPORT", +"FLAG_ON","FLAG_OFF","FULLMAP","HELP","IMPORT","INPUT","MAP","MESSAGES","MODULE", +"MULTIPLE","OS_DOMAIN","OUTPUT","PSEUDOPREEMPTION","REENTRANT","SCREENNAME", +"SHARELIB","STACK","START","SYNCHRONIZE","THREADNAME","TYPE","VERBOSE","VERSION", +"XDCDATA","STRING","QUOTED_STRING","'('","')'","file","commands","command","@1", +"@2","symbol_list_opt","symbol_list","symbol_prefix","symbol","string_list", +"" +}; +#endif + +static const short yyr1[] = { 0, + 40, 41, 41, 42, 42, 42, 42, 42, 42, 42, + 42, 43, 42, 42, 42, 42, 42, 42, 44, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 45, 45, 46, 46, 46, 46, 47, 48, 49, + 49 +}; + +static const short yyr2[] = { 0, + 1, 0, 2, 2, 2, 2, 2, 4, 1, 2, + 2, 0, 3, 2, 2, 1, 2, 2, 0, 3, + 2, 1, 2, 2, 2, 1, 1, 2, 1, 1, + 2, 2, 2, 2, 1, 2, 2, 1, 4, 3, + 2, 0, 1, 1, 1, 2, 2, 3, 1, 0, + 2 +}; + +static const short yydefact[] = { 2, + 0, 0, 0, 0, 0, 9, 0, 0, 12, 0, + 0, 16, 0, 19, 50, 22, 0, 50, 26, 27, + 0, 29, 30, 0, 0, 0, 0, 35, 0, 0, + 38, 0, 0, 1, 2, 4, 5, 6, 7, 0, + 10, 11, 42, 14, 15, 17, 18, 42, 50, 21, + 23, 24, 25, 28, 31, 32, 33, 34, 36, 37, + 0, 41, 3, 0, 49, 0, 13, 43, 45, 44, + 20, 51, 40, 8, 0, 47, 46, 39, 48, 0, + 0, 0 +}; + +static const short yydefgoto[] = { 80, + 34, 35, 43, 48, 67, 68, 69, 70, 50 +}; + +static const short yypact[] = { -3, + -1, 1, 2, 4, 5,-32768, 6, 8,-32768, 9, + 10, 11, 12,-32768, 13, 14, 16, 13,-32768,-32768, + 17,-32768,-32768, 18, 20, 21, 22,-32768, 23, 25, +-32768, 26, 27,-32768, -3,-32768,-32768,-32768,-32768, 29, +-32768,-32768, -2,-32768,-32768,-32768,-32768, -2, 13,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + 30,-32768,-32768, 31,-32768, 32,-32768, -2,-32768,-32768, +-32768,-32768, 33,-32768, 3,-32768,-32768,-32768,-32768, 38, + 51,-32768 +}; + +static const short yypgoto[] = {-32768, + 19,-32768,-32768,-32768, 24,-32768, -9, 7, 15 +}; + + +#define YYLAST 75 + + +static const short yytable[] = { 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, 53, 65, 36, 66, 37, 81, 38, 39, + 40, 79, 41, 42, 44, 45, 46, 47, 49, 51, + 82, 52, 54, 63, 55, 56, 57, 58, 76, 59, + 60, 61, 62, 72, 64, 73, 74, 75, 78, 0, + 0, 71, 0, 0, 77 +}; + +static const short yycheck[] = { 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, 35, 18, 36, 36, 38, 36, 0, 37, 36, + 36, 39, 37, 36, 36, 36, 36, 36, 36, 36, + 0, 36, 36, 35, 37, 36, 36, 36, 68, 37, + 36, 36, 36, 49, 36, 36, 36, 36, 36, -1, + -1, 48, -1, -1, 68 +}; +/* -*-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 +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #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 reallocate 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 reallocate 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 4: +#line 159 "./nlmheader.y" +{ + check_procedure = yyvsp[0].string; + ; + break;} +case 5: +#line 163 "./nlmheader.y" +{ + nlmheader_warn ("CODESTART is not implemented; sorry", -1); + free (yyvsp[0].string); + ; + break;} +case 6: +#line 168 "./nlmheader.y" +{ + int len; + + strncpy (copyright_hdr->stamp, "CoPyRiGhT=", 10); + len = strlen (yyvsp[0].string); + if (len >= NLM_MAX_COPYRIGHT_MESSAGE_LENGTH) + { + nlmheader_warn ("copyright string is too long", + NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1); + len = NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1; + } + copyright_hdr->copyrightMessageLength = len; + strncpy (copyright_hdr->copyrightMessage, yyvsp[0].string, len); + copyright_hdr->copyrightMessage[len] = '\0'; + free (yyvsp[0].string); + ; + break;} +case 7: +#line 185 "./nlmheader.y" +{ + custom_file = yyvsp[0].string; + ; + break;} +case 8: +#line 189 "./nlmheader.y" +{ + /* We don't set the version stamp here, because we use the + version stamp to detect whether the required VERSION + keyword was given. */ + version_hdr->month = nlmlex_get_number (yyvsp[-2].string); + version_hdr->day = nlmlex_get_number (yyvsp[-1].string); + version_hdr->year = nlmlex_get_number (yyvsp[0].string); + free (yyvsp[-2].string); + free (yyvsp[-1].string); + free (yyvsp[0].string); + if (version_hdr->month < 1 || version_hdr->month > 12) + nlmheader_warn ("illegal month", -1); + if (version_hdr->day < 1 || version_hdr->day > 31) + nlmheader_warn ("illegal day", -1); + if (version_hdr->year < 1900 || version_hdr->year > 3000) + nlmheader_warn ("illegal year", -1); + ; + break;} +case 9: +#line 207 "./nlmheader.y" +{ + debug_info = true; + ; + break;} +case 10: +#line 211 "./nlmheader.y" +{ + int len; + + len = strlen (yyvsp[0].string); + if (len > NLM_MAX_DESCRIPTION_LENGTH) + { + nlmheader_warn ("description string is too long", + NLM_MAX_DESCRIPTION_LENGTH); + len = NLM_MAX_DESCRIPTION_LENGTH; + } + var_hdr->descriptionLength = len; + strncpy (var_hdr->descriptionText, yyvsp[0].string, len); + var_hdr->descriptionText[len] = '\0'; + free (yyvsp[0].string); + ; + break;} +case 11: +#line 227 "./nlmheader.y" +{ + exit_procedure = yyvsp[0].string; + ; + break;} +case 12: +#line 231 "./nlmheader.y" +{ + symbol_prefix = NULL; + ; + break;} +case 13: +#line 235 "./nlmheader.y" +{ + export_symbols = string_list_append (export_symbols, yyvsp[0].list); + ; + break;} +case 14: +#line 239 "./nlmheader.y" +{ + fixed_hdr->flags |= nlmlex_get_number (yyvsp[0].string); + free (yyvsp[0].string); + ; + break;} +case 15: +#line 244 "./nlmheader.y" +{ + fixed_hdr->flags &=~ nlmlex_get_number (yyvsp[0].string); + free (yyvsp[0].string); + ; + break;} +case 16: +#line 249 "./nlmheader.y" +{ + map_file = ""; + full_map = true; + ; + break;} +case 17: +#line 254 "./nlmheader.y" +{ + map_file = yyvsp[0].string; + full_map = true; + ; + break;} +case 18: +#line 259 "./nlmheader.y" +{ + help_file = yyvsp[0].string; + ; + break;} +case 19: +#line 263 "./nlmheader.y" +{ + symbol_prefix = NULL; + ; + break;} +case 20: +#line 267 "./nlmheader.y" +{ + import_symbols = string_list_append (import_symbols, yyvsp[0].list); + ; + break;} +case 21: +#line 271 "./nlmheader.y" +{ + input_files = string_list_append (input_files, yyvsp[0].list); + ; + break;} +case 22: +#line 275 "./nlmheader.y" +{ + map_file = ""; + ; + break;} +case 23: +#line 279 "./nlmheader.y" +{ + map_file = yyvsp[0].string; + ; + break;} +case 24: +#line 283 "./nlmheader.y" +{ + message_file = yyvsp[0].string; + ; + break;} +case 25: +#line 287 "./nlmheader.y" +{ + modules = string_list_append (modules, yyvsp[0].list); + ; + break;} +case 26: +#line 291 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x2; + ; + break;} +case 27: +#line 295 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x10; + ; + break;} +case 28: +#line 299 "./nlmheader.y" +{ + if (output_file == NULL) + output_file = yyvsp[0].string; + else + nlmheader_warn ("ignoring duplicate OUTPUT statement", -1); + ; + break;} +case 29: +#line 306 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x8; + ; + break;} +case 30: +#line 310 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x1; + ; + break;} +case 31: +#line 314 "./nlmheader.y" +{ + int len; + + len = strlen (yyvsp[0].string); + if (len >= NLM_MAX_SCREEN_NAME_LENGTH) + { + nlmheader_warn ("screen name is too long", + NLM_MAX_SCREEN_NAME_LENGTH); + len = NLM_MAX_SCREEN_NAME_LENGTH; + } + var_hdr->screenNameLength = len; + strncpy (var_hdr->screenName, yyvsp[0].string, len); + var_hdr->screenName[NLM_MAX_SCREEN_NAME_LENGTH] = '\0'; + free (yyvsp[0].string); + ; + break;} +case 32: +#line 330 "./nlmheader.y" +{ + sharelib_file = yyvsp[0].string; + ; + break;} +case 33: +#line 334 "./nlmheader.y" +{ + var_hdr->stackSize = nlmlex_get_number (yyvsp[0].string); + free (yyvsp[0].string); + ; + break;} +case 34: +#line 339 "./nlmheader.y" +{ + start_procedure = yyvsp[0].string; + ; + break;} +case 35: +#line 343 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x4; + ; + break;} +case 36: +#line 347 "./nlmheader.y" +{ + int len; + + len = strlen (yyvsp[0].string); + if (len >= NLM_MAX_THREAD_NAME_LENGTH) + { + nlmheader_warn ("thread name is too long", + NLM_MAX_THREAD_NAME_LENGTH); + len = NLM_MAX_THREAD_NAME_LENGTH; + } + var_hdr->threadNameLength = len; + strncpy (var_hdr->threadName, yyvsp[0].string, len); + var_hdr->threadName[len] = '\0'; + free (yyvsp[0].string); + ; + break;} +case 37: +#line 363 "./nlmheader.y" +{ + fixed_hdr->moduleType = nlmlex_get_number (yyvsp[0].string); + free (yyvsp[0].string); + ; + break;} +case 38: +#line 368 "./nlmheader.y" +{ + verbose = true; + ; + break;} +case 39: +#line 372 "./nlmheader.y" +{ + long val; + + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + version_hdr->majorVersion = nlmlex_get_number (yyvsp[-2].string); + val = nlmlex_get_number (yyvsp[-1].string); + if (val < 0 || val > 99) + nlmheader_warn ("illegal minor version number (must be between 0 and 99)", + -1); + else + version_hdr->minorVersion = val; + val = nlmlex_get_number (yyvsp[0].string); + if (val < 0) + nlmheader_warn ("illegal revision number (must be between 0 and 26)", + -1); + else if (val > 26) + version_hdr->revision = 0; + else + version_hdr->revision = val; + free (yyvsp[-2].string); + free (yyvsp[-1].string); + free (yyvsp[0].string); + ; + break;} +case 40: +#line 396 "./nlmheader.y" +{ + long val; + + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + version_hdr->majorVersion = nlmlex_get_number (yyvsp[-1].string); + val = nlmlex_get_number (yyvsp[0].string); + if (val < 0 || val > 99) + nlmheader_warn ("illegal minor version number (must be between 0 and 99)", + -1); + else + version_hdr->minorVersion = val; + version_hdr->revision = 0; + free (yyvsp[-1].string); + free (yyvsp[0].string); + ; + break;} +case 41: +#line 412 "./nlmheader.y" +{ + rpc_file = yyvsp[0].string; + ; + break;} +case 42: +#line 421 "./nlmheader.y" +{ + yyval.list = NULL; + ; + break;} +case 43: +#line 425 "./nlmheader.y" +{ + yyval.list = yyvsp[0].list; + ; + break;} +case 44: +#line 436 "./nlmheader.y" +{ + yyval.list = string_list_cons (yyvsp[0].string, NULL); + ; + break;} +case 45: +#line 440 "./nlmheader.y" +{ + yyval.list = NULL; + ; + break;} +case 46: +#line 444 "./nlmheader.y" +{ + yyval.list = string_list_append1 (yyvsp[-1].list, yyvsp[0].string); + ; + break;} +case 47: +#line 448 "./nlmheader.y" +{ + yyval.list = yyvsp[-1].list; + ; + break;} +case 48: +#line 457 "./nlmheader.y" +{ + if (symbol_prefix != NULL) + free (symbol_prefix); + symbol_prefix = yyvsp[-1].string; + ; + break;} +case 49: +#line 468 "./nlmheader.y" +{ + if (symbol_prefix == NULL) + yyval.string = yyvsp[0].string; + else + { + yyval.string = xmalloc (strlen (symbol_prefix) + strlen (yyvsp[0].string) + 2); + sprintf (yyval.string, "%s@%s", symbol_prefix, yyvsp[0].string); + free (yyvsp[0].string); + } + ; + break;} +case 50: +#line 484 "./nlmheader.y" +{ + yyval.list = NULL; + ; + break;} +case 51: +#line 488 "./nlmheader.y" +{ + yyval.list = string_list_cons (yyvsp[-1].string, yyvsp[0].list); + ; + 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 *) malloc(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 493 "./nlmheader.y" + + +/* If strerror is just a macro, we want to use the one from libiberty + since it will handle undefined values. */ +#undef strerror +extern char *strerror (); + +/* The lexer is simple, too simple for flex. Keywords are only + recognized at the start of lines. Everything else must be an + argument. A comma is treated as whitespace. */ + +/* The states the lexer can be in. */ + +enum lex_state +{ + /* At the beginning of a line. */ + BEGINNING_OF_LINE, + /* In the middle of a line. */ + IN_LINE +}; + +/* We need to keep a stack of files to handle file inclusion. */ + +struct input +{ + /* The file to read from. */ + FILE *file; + /* The name of the file. */ + char *name; + /* The current line number. */ + int lineno; + /* The current state. */ + enum lex_state state; + /* The next file on the stack. */ + struct input *next; +}; + +/* The current input file. */ + +static struct input current; + +/* The character which introduces comments. */ +#define COMMENT_CHAR '#' + +/* Start the lexer going on the main input file. */ + +boolean +nlmlex_file (name) + const char *name; +{ + current.next = NULL; + return nlmlex_file_open (name); +} + +/* Start the lexer going on a subsidiary input file. */ + +static void +nlmlex_file_push (name) + const char *name; +{ + struct input *push; + + push = (struct input *) xmalloc (sizeof (struct input)); + *push = current; + if (nlmlex_file_open (name)) + current.next = push; + else + { + current = *push; + free (push); + } +} + +/* Start lexing from a file. */ + +static boolean +nlmlex_file_open (name) + const char *name; +{ + current.file = fopen (name, "r"); + if (current.file == NULL) + { + fprintf (stderr, "%s:%s: %s\n", program_name, name, strerror (errno)); + ++parse_errors; + return false; + } + current.name = xstrdup (name); + current.lineno = 1; + current.state = BEGINNING_OF_LINE; + return true; +} + +/* Table used to turn keywords into tokens. */ + +struct keyword_tokens_struct +{ + const char *keyword; + int token; +}; + +struct keyword_tokens_struct keyword_tokens[] = +{ + { "CHECK", CHECK }, + { "CODESTART", CODESTART }, + { "COPYRIGHT", COPYRIGHT }, + { "CUSTOM", CUSTOM }, + { "DATE", DATE }, + { "DEBUG", DEBUG }, + { "DESCRIPTION", DESCRIPTION }, + { "EXIT", EXIT }, + { "EXPORT", EXPORT }, + { "FLAG_ON", FLAG_ON }, + { "FLAG_OFF", FLAG_OFF }, + { "FULLMAP", FULLMAP }, + { "HELP", HELP }, + { "IMPORT", IMPORT }, + { "INPUT", INPUT }, + { "MAP", MAP }, + { "MESSAGES", MESSAGES }, + { "MODULE", MODULE }, + { "MULTIPLE", MULTIPLE }, + { "OS_DOMAIN", OS_DOMAIN }, + { "OUTPUT", OUTPUT }, + { "PSEUDOPREEMPTION", PSEUDOPREEMPTION }, + { "REENTRANT", REENTRANT }, + { "SCREENNAME", SCREENNAME }, + { "SHARELIB", SHARELIB }, + { "STACK", STACK }, + { "STACKSIZE", STACK }, + { "START", START }, + { "SYNCHRONIZE", SYNCHRONIZE }, + { "THREADNAME", THREADNAME }, + { "TYPE", TYPE }, + { "VERBOSE", VERBOSE }, + { "VERSION", VERSION }, + { "XDCDATA", XDCDATA } +}; + +#define KEYWORD_COUNT (sizeof (keyword_tokens) / sizeof (keyword_tokens[0])) + +/* The lexer accumulates strings in these variables. */ +static char *lex_buf; +static int lex_size; +static int lex_pos; + +/* Start accumulating strings into the buffer. */ +#define BUF_INIT() \ + ((void) (lex_buf != NULL ? lex_pos = 0 : nlmlex_buf_init ())) + +static int +nlmlex_buf_init () +{ + lex_size = 10; + lex_buf = xmalloc (lex_size + 1); + lex_pos = 0; + return 0; +} + +/* Finish a string in the buffer. */ +#define BUF_FINISH() ((void) (lex_buf[lex_pos] = '\0')) + +/* Accumulate a character into the buffer. */ +#define BUF_ADD(c) \ + ((void) (lex_pos < lex_size \ + ? lex_buf[lex_pos++] = (c) \ + : nlmlex_buf_add (c))) + +static char +nlmlex_buf_add (c) + int c; +{ + if (lex_pos >= lex_size) + { + lex_size *= 2; + lex_buf = xrealloc (lex_buf, lex_size + 1); + } + + return lex_buf[lex_pos++] = c; +} + +/* The lexer proper. This is called by the bison generated parsing + code. */ + +static int +yylex () +{ + int c; + +tail_recurse: + + c = getc (current.file); + + /* Commas are treated as whitespace characters. */ + while (isspace ((unsigned char) c) || c == ',') + { + current.state = IN_LINE; + if (c == '\n') + { + ++current.lineno; + current.state = BEGINNING_OF_LINE; + } + c = getc (current.file); + } + + /* At the end of the file we either pop to the previous file or + finish up. */ + if (c == EOF) + { + fclose (current.file); + free (current.name); + if (current.next == NULL) + return 0; + else + { + struct input *next; + + next = current.next; + current = *next; + free (next); + goto tail_recurse; + } + } + + /* A comment character always means to drop everything until the + next newline. */ + if (c == COMMENT_CHAR) + { + do + { + c = getc (current.file); + } + while (c != '\n'); + ++current.lineno; + current.state = BEGINNING_OF_LINE; + goto tail_recurse; + } + + /* An '@' introduces an include file. */ + if (c == '@') + { + do + { + c = getc (current.file); + if (c == '\n') + ++current.lineno; + } + while (isspace ((unsigned char) c)); + BUF_INIT (); + while (! isspace ((unsigned char) c) && c != EOF) + { + BUF_ADD (c); + c = getc (current.file); + } + BUF_FINISH (); + + ungetc (c, current.file); + + nlmlex_file_push (lex_buf); + goto tail_recurse; + } + + /* A non-space character at the start of a line must be the start of + a keyword. */ + if (current.state == BEGINNING_OF_LINE) + { + BUF_INIT (); + while (isalnum ((unsigned char) c) || c == '_') + { + if (islower ((unsigned char) c)) + BUF_ADD (toupper ((unsigned char) c)); + else + BUF_ADD (c); + c = getc (current.file); + } + BUF_FINISH (); + + if (c != EOF && ! isspace ((unsigned char) c) && c != ',') + { + nlmheader_identify (); + fprintf (stderr, "%s:%d: illegal character in keyword: %c\n", + current.name, current.lineno, c); + } + else + { + int i; + + for (i = 0; i < KEYWORD_COUNT; i++) + { + if (lex_buf[0] == keyword_tokens[i].keyword[0] + && strcmp (lex_buf, keyword_tokens[i].keyword) == 0) + { + /* Pushing back the final whitespace avoids worrying + about \n here. */ + ungetc (c, current.file); + current.state = IN_LINE; + return keyword_tokens[i].token; + } + } + + nlmheader_identify (); + fprintf (stderr, "%s:%d: unrecognized keyword: %s\n", + current.name, current.lineno, lex_buf); + } + + ++parse_errors; + /* Treat the rest of this line as a comment. */ + ungetc (COMMENT_CHAR, current.file); + goto tail_recurse; + } + + /* Parentheses just represent themselves. */ + if (c == '(' || c == ')') + return c; + + /* Handle quoted strings. */ + if (c == '"' || c == '\'') + { + int quote; + int start_lineno; + + quote = c; + start_lineno = current.lineno; + + c = getc (current.file); + BUF_INIT (); + while (c != quote && c != EOF) + { + BUF_ADD (c); + if (c == '\n') + ++current.lineno; + c = getc (current.file); + } + BUF_FINISH (); + + if (c == EOF) + { + nlmheader_identify (); + fprintf (stderr, "%s:%d: end of file in quoted string\n", + current.name, start_lineno); + ++parse_errors; + } + + /* FIXME: Possible memory leak. */ + yylval.string = xstrdup (lex_buf); + return QUOTED_STRING; + } + + /* Gather a generic argument. */ + BUF_INIT (); + while (! isspace (c) + && c != ',' + && c != COMMENT_CHAR + && c != '(' + && c != ')') + { + BUF_ADD (c); + c = getc (current.file); + } + BUF_FINISH (); + + ungetc (c, current.file); + + /* FIXME: Possible memory leak. */ + yylval.string = xstrdup (lex_buf); + return STRING; +} + +/* Get a number from a string. */ + +static long +nlmlex_get_number (s) + const char *s; +{ + long ret; + char *send; + + ret = strtol (s, &send, 10); + if (*send != '\0') + nlmheader_warn ("bad number", -1); + return ret; +} + +/* Prefix the nlmconv warnings with a note as to where they come from. + We don't use program_name on every warning, because then some + versions of the emacs next-error function can't recognize the line + number. */ + +static void +nlmheader_identify () +{ + static int done; + + if (! done) + { + fprintf (stderr, "%s: problems in NLM command language input:\n", + program_name); + done = 1; + } +} + +/* Issue a warning. */ + +static void +nlmheader_warn (s, imax) + const char *s; + int imax; +{ + nlmheader_identify (); + fprintf (stderr, "%s:%d: %s", current.name, current.lineno, s); + if (imax != -1) + fprintf (stderr, " (max %d)", imax); + fprintf (stderr, "\n"); +} + +/* Report an error. */ + +static void +nlmheader_error (s) + const char *s; +{ + nlmheader_warn (s, -1); + ++parse_errors; +} + +/* Add a string to a string list. */ + +static struct string_list * +string_list_cons (s, l) + char *s; + struct string_list *l; +{ + struct string_list *ret; + + ret = (struct string_list *) xmalloc (sizeof (struct string_list)); + ret->next = l; + ret->string = s; + return ret; +} + +/* Append a string list to another string list. */ + +static struct string_list * +string_list_append (l1, l2) + struct string_list *l1; + struct string_list *l2; +{ + register struct string_list **pp; + + for (pp = &l1; *pp != NULL; pp = &(*pp)->next) + ; + *pp = l2; + return l1; +} + +/* Append a string to a string list. */ + +static struct string_list * +string_list_append1 (l, s) + struct string_list *l; + char *s; +{ + struct string_list *n; + register struct string_list **pp; + + n = (struct string_list *) xmalloc (sizeof (struct string_list)); + n->next = NULL; + n->string = s; + for (pp = &l; *pp != NULL; pp = &(*pp)->next) + ; + *pp = n; + return l; +} + +/* Duplicate a string in memory. */ + +static char * +xstrdup (s) + const char *s; +{ + unsigned long len; + char *ret; + + len = strlen (s); + ret = xmalloc (len + 1); + strcpy (ret, s); + return ret; +} diff --git a/gnu/usr.bin/binutils/binutils/nlmheader.y b/gnu/usr.bin/binutils/binutils/nlmheader.y new file mode 100644 index 00000000000..eada318490e --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/nlmheader.y @@ -0,0 +1,979 @@ +%{/* nlmheader.y - parse NLM header specification keywords. + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 Lance Taylor . + + This bison file parses the commands recognized by the NetWare NLM + linker, except for lists of object files. It stores the + information in global variables. + + This implementation is based on the description in the NetWare Tool + Maker Specification manual, edition 1.0. */ + +#include +#include +#include +#include "bfd.h" +#include "sysdep.h" +#include "bucomm.h" +#include "nlm/common.h" +#include "nlm/internal.h" +#include "nlmconv.h" + +/* Information is stored in the structures pointed to by these + variables. */ + +Nlm_Internal_Fixed_Header *fixed_hdr; +Nlm_Internal_Variable_Header *var_hdr; +Nlm_Internal_Version_Header *version_hdr; +Nlm_Internal_Copyright_Header *copyright_hdr; +Nlm_Internal_Extended_Header *extended_hdr; + +/* Procedure named by CHECK. */ +char *check_procedure; +/* File named by CUSTOM. */ +char *custom_file; +/* Whether to generate debugging information (DEBUG). */ +boolean debug_info; +/* Procedure named by EXIT. */ +char *exit_procedure; +/* Exported symbols (EXPORT). */ +struct string_list *export_symbols; +/* List of files from INPUT. */ +struct string_list *input_files; +/* Map file name (MAP, FULLMAP). */ +char *map_file; +/* Whether a full map has been requested (FULLMAP). */ +boolean full_map; +/* File named by HELP. */ +char *help_file; +/* Imported symbols (IMPORT). */ +struct string_list *import_symbols; +/* File named by MESSAGES. */ +char *message_file; +/* Autoload module list (MODULE). */ +struct string_list *modules; +/* File named by OUTPUT. */ +char *output_file; +/* File named by SHARELIB. */ +char *sharelib_file; +/* Start procedure name (START). */ +char *start_procedure; +/* VERBOSE. */ +boolean verbose; +/* RPC description file (XDCDATA). */ +char *rpc_file; + +/* The number of serious errors that have occurred. */ +int parse_errors; + +/* The current symbol prefix when reading a list of import or export + symbols. */ +static char *symbol_prefix; + +/* Parser error message handler. */ +#define yyerror(msg) nlmheader_error (msg); + +/* Local functions. */ +static int yylex PARAMS ((void)); +static void nlmlex_file_push PARAMS ((const char *)); +static boolean nlmlex_file_open PARAMS ((const char *)); +static int nlmlex_buf_init PARAMS ((void)); +static char nlmlex_buf_add PARAMS ((int)); +static long nlmlex_get_number PARAMS ((const char *)); +static void nlmheader_identify PARAMS ((void)); +static void nlmheader_warn PARAMS ((const char *, int)); +static void nlmheader_error PARAMS ((const char *)); +static struct string_list * string_list_cons PARAMS ((char *, + struct string_list *)); +static struct string_list * string_list_append PARAMS ((struct string_list *, + struct string_list *)); +static struct string_list * string_list_append1 PARAMS ((struct string_list *, + char *)); +static char *xstrdup PARAMS ((const char *)); + +%} + +%union +{ + char *string; + struct string_list *list; +}; + +/* The reserved words. */ + +%token CHECK CODESTART COPYRIGHT CUSTOM DATE DEBUG DESCRIPTION EXIT +%token EXPORT FLAG_ON FLAG_OFF FULLMAP HELP IMPORT INPUT MAP MESSAGES +%token MODULE MULTIPLE OS_DOMAIN OUTPUT PSEUDOPREEMPTION REENTRANT +%token SCREENNAME SHARELIB STACK START SYNCHRONIZE +%token THREADNAME TYPE VERBOSE VERSION XDCDATA + +/* Arguments. */ + +%token STRING +%token QUOTED_STRING + +/* Typed non-terminals. */ +%type symbol_list_opt symbol_list string_list +%type symbol + +%% + +/* Keywords must start in the leftmost column of the file. Arguments + may appear anywhere else. The lexer uses this to determine what + token to return, so we don't have to worry about it here. */ + +/* The entire file is just a list of commands. */ + +file: + commands + ; + +/* A possibly empty list of commands. */ + +commands: + /* May be empty. */ + | command commands + ; + +/* A single command. There is where most of the work takes place. */ + +command: + CHECK STRING + { + check_procedure = $2; + } + | CODESTART STRING + { + nlmheader_warn ("CODESTART is not implemented; sorry", -1); + free ($2); + } + | COPYRIGHT QUOTED_STRING + { + int len; + + strncpy (copyright_hdr->stamp, "CoPyRiGhT=", 10); + len = strlen ($2); + if (len >= NLM_MAX_COPYRIGHT_MESSAGE_LENGTH) + { + nlmheader_warn ("copyright string is too long", + NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1); + len = NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1; + } + copyright_hdr->copyrightMessageLength = len; + strncpy (copyright_hdr->copyrightMessage, $2, len); + copyright_hdr->copyrightMessage[len] = '\0'; + free ($2); + } + | CUSTOM STRING + { + custom_file = $2; + } + | DATE STRING STRING STRING + { + /* We don't set the version stamp here, because we use the + version stamp to detect whether the required VERSION + keyword was given. */ + version_hdr->month = nlmlex_get_number ($2); + version_hdr->day = nlmlex_get_number ($3); + version_hdr->year = nlmlex_get_number ($4); + free ($2); + free ($3); + free ($4); + if (version_hdr->month < 1 || version_hdr->month > 12) + nlmheader_warn ("illegal month", -1); + if (version_hdr->day < 1 || version_hdr->day > 31) + nlmheader_warn ("illegal day", -1); + if (version_hdr->year < 1900 || version_hdr->year > 3000) + nlmheader_warn ("illegal year", -1); + } + | DEBUG + { + debug_info = true; + } + | DESCRIPTION QUOTED_STRING + { + int len; + + len = strlen ($2); + if (len > NLM_MAX_DESCRIPTION_LENGTH) + { + nlmheader_warn ("description string is too long", + NLM_MAX_DESCRIPTION_LENGTH); + len = NLM_MAX_DESCRIPTION_LENGTH; + } + var_hdr->descriptionLength = len; + strncpy (var_hdr->descriptionText, $2, len); + var_hdr->descriptionText[len] = '\0'; + free ($2); + } + | EXIT STRING + { + exit_procedure = $2; + } + | EXPORT + { + symbol_prefix = NULL; + } + symbol_list_opt + { + export_symbols = string_list_append (export_symbols, $3); + } + | FLAG_ON STRING + { + fixed_hdr->flags |= nlmlex_get_number ($2); + free ($2); + } + | FLAG_OFF STRING + { + fixed_hdr->flags &=~ nlmlex_get_number ($2); + free ($2); + } + | FULLMAP + { + map_file = ""; + full_map = true; + } + | FULLMAP STRING + { + map_file = $2; + full_map = true; + } + | HELP STRING + { + help_file = $2; + } + | IMPORT + { + symbol_prefix = NULL; + } + symbol_list_opt + { + import_symbols = string_list_append (import_symbols, $3); + } + | INPUT string_list + { + input_files = string_list_append (input_files, $2); + } + | MAP + { + map_file = ""; + } + | MAP STRING + { + map_file = $2; + } + | MESSAGES STRING + { + message_file = $2; + } + | MODULE string_list + { + modules = string_list_append (modules, $2); + } + | MULTIPLE + { + fixed_hdr->flags |= 0x2; + } + | OS_DOMAIN + { + fixed_hdr->flags |= 0x10; + } + | OUTPUT STRING + { + if (output_file == NULL) + output_file = $2; + else + nlmheader_warn ("ignoring duplicate OUTPUT statement", -1); + } + | PSEUDOPREEMPTION + { + fixed_hdr->flags |= 0x8; + } + | REENTRANT + { + fixed_hdr->flags |= 0x1; + } + | SCREENNAME QUOTED_STRING + { + int len; + + len = strlen ($2); + if (len >= NLM_MAX_SCREEN_NAME_LENGTH) + { + nlmheader_warn ("screen name is too long", + NLM_MAX_SCREEN_NAME_LENGTH); + len = NLM_MAX_SCREEN_NAME_LENGTH; + } + var_hdr->screenNameLength = len; + strncpy (var_hdr->screenName, $2, len); + var_hdr->screenName[NLM_MAX_SCREEN_NAME_LENGTH] = '\0'; + free ($2); + } + | SHARELIB STRING + { + sharelib_file = $2; + } + | STACK STRING + { + var_hdr->stackSize = nlmlex_get_number ($2); + free ($2); + } + | START STRING + { + start_procedure = $2; + } + | SYNCHRONIZE + { + fixed_hdr->flags |= 0x4; + } + | THREADNAME QUOTED_STRING + { + int len; + + len = strlen ($2); + if (len >= NLM_MAX_THREAD_NAME_LENGTH) + { + nlmheader_warn ("thread name is too long", + NLM_MAX_THREAD_NAME_LENGTH); + len = NLM_MAX_THREAD_NAME_LENGTH; + } + var_hdr->threadNameLength = len; + strncpy (var_hdr->threadName, $2, len); + var_hdr->threadName[len] = '\0'; + free ($2); + } + | TYPE STRING + { + fixed_hdr->moduleType = nlmlex_get_number ($2); + free ($2); + } + | VERBOSE + { + verbose = true; + } + | VERSION STRING STRING STRING + { + long val; + + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + version_hdr->majorVersion = nlmlex_get_number ($2); + val = nlmlex_get_number ($3); + if (val < 0 || val > 99) + nlmheader_warn ("illegal minor version number (must be between 0 and 99)", + -1); + else + version_hdr->minorVersion = val; + val = nlmlex_get_number ($4); + if (val < 0) + nlmheader_warn ("illegal revision number (must be between 0 and 26)", + -1); + else if (val > 26) + version_hdr->revision = 0; + else + version_hdr->revision = val; + free ($2); + free ($3); + free ($4); + } + | VERSION STRING STRING + { + long val; + + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + version_hdr->majorVersion = nlmlex_get_number ($2); + val = nlmlex_get_number ($3); + if (val < 0 || val > 99) + nlmheader_warn ("illegal minor version number (must be between 0 and 99)", + -1); + else + version_hdr->minorVersion = val; + version_hdr->revision = 0; + free ($2); + free ($3); + } + | XDCDATA STRING + { + rpc_file = $2; + } + ; + +/* A possibly empty list of symbols. */ + +symbol_list_opt: + /* Empty. */ + { + $$ = NULL; + } + | symbol_list + { + $$ = $1; + } + ; + +/* A list of symbols in an import or export list. Prefixes may appear + in parentheses. We need to use left recursion here to avoid + building up a large import list on the parser stack. */ + +symbol_list: + symbol + { + $$ = string_list_cons ($1, NULL); + } + | symbol_prefix + { + $$ = NULL; + } + | symbol_list symbol + { + $$ = string_list_append1 ($1, $2); + } + | symbol_list symbol_prefix + { + $$ = $1; + } + ; + +/* A prefix for subsequent symbols. */ + +symbol_prefix: + '(' STRING ')' + { + if (symbol_prefix != NULL) + free (symbol_prefix); + symbol_prefix = $2; + } + ; + +/* A single symbol. */ + +symbol: + STRING + { + if (symbol_prefix == NULL) + $$ = $1; + else + { + $$ = xmalloc (strlen (symbol_prefix) + strlen ($1) + 2); + sprintf ($$, "%s@%s", symbol_prefix, $1); + free ($1); + } + } + ; + +/* A list of strings. */ + +string_list: + /* May be empty. */ + { + $$ = NULL; + } + | STRING string_list + { + $$ = string_list_cons ($1, $2); + } + ; + +%% + +/* If strerror is just a macro, we want to use the one from libiberty + since it will handle undefined values. */ +#undef strerror +extern char *strerror (); + +/* The lexer is simple, too simple for flex. Keywords are only + recognized at the start of lines. Everything else must be an + argument. A comma is treated as whitespace. */ + +/* The states the lexer can be in. */ + +enum lex_state +{ + /* At the beginning of a line. */ + BEGINNING_OF_LINE, + /* In the middle of a line. */ + IN_LINE +}; + +/* We need to keep a stack of files to handle file inclusion. */ + +struct input +{ + /* The file to read from. */ + FILE *file; + /* The name of the file. */ + char *name; + /* The current line number. */ + int lineno; + /* The current state. */ + enum lex_state state; + /* The next file on the stack. */ + struct input *next; +}; + +/* The current input file. */ + +static struct input current; + +/* The character which introduces comments. */ +#define COMMENT_CHAR '#' + +/* Start the lexer going on the main input file. */ + +boolean +nlmlex_file (name) + const char *name; +{ + current.next = NULL; + return nlmlex_file_open (name); +} + +/* Start the lexer going on a subsidiary input file. */ + +static void +nlmlex_file_push (name) + const char *name; +{ + struct input *push; + + push = (struct input *) xmalloc (sizeof (struct input)); + *push = current; + if (nlmlex_file_open (name)) + current.next = push; + else + { + current = *push; + free (push); + } +} + +/* Start lexing from a file. */ + +static boolean +nlmlex_file_open (name) + const char *name; +{ + current.file = fopen (name, "r"); + if (current.file == NULL) + { + fprintf (stderr, "%s:%s: %s\n", program_name, name, strerror (errno)); + ++parse_errors; + return false; + } + current.name = xstrdup (name); + current.lineno = 1; + current.state = BEGINNING_OF_LINE; + return true; +} + +/* Table used to turn keywords into tokens. */ + +struct keyword_tokens_struct +{ + const char *keyword; + int token; +}; + +struct keyword_tokens_struct keyword_tokens[] = +{ + { "CHECK", CHECK }, + { "CODESTART", CODESTART }, + { "COPYRIGHT", COPYRIGHT }, + { "CUSTOM", CUSTOM }, + { "DATE", DATE }, + { "DEBUG", DEBUG }, + { "DESCRIPTION", DESCRIPTION }, + { "EXIT", EXIT }, + { "EXPORT", EXPORT }, + { "FLAG_ON", FLAG_ON }, + { "FLAG_OFF", FLAG_OFF }, + { "FULLMAP", FULLMAP }, + { "HELP", HELP }, + { "IMPORT", IMPORT }, + { "INPUT", INPUT }, + { "MAP", MAP }, + { "MESSAGES", MESSAGES }, + { "MODULE", MODULE }, + { "MULTIPLE", MULTIPLE }, + { "OS_DOMAIN", OS_DOMAIN }, + { "OUTPUT", OUTPUT }, + { "PSEUDOPREEMPTION", PSEUDOPREEMPTION }, + { "REENTRANT", REENTRANT }, + { "SCREENNAME", SCREENNAME }, + { "SHARELIB", SHARELIB }, + { "STACK", STACK }, + { "STACKSIZE", STACK }, + { "START", START }, + { "SYNCHRONIZE", SYNCHRONIZE }, + { "THREADNAME", THREADNAME }, + { "TYPE", TYPE }, + { "VERBOSE", VERBOSE }, + { "VERSION", VERSION }, + { "XDCDATA", XDCDATA } +}; + +#define KEYWORD_COUNT (sizeof (keyword_tokens) / sizeof (keyword_tokens[0])) + +/* The lexer accumulates strings in these variables. */ +static char *lex_buf; +static int lex_size; +static int lex_pos; + +/* Start accumulating strings into the buffer. */ +#define BUF_INIT() \ + ((void) (lex_buf != NULL ? lex_pos = 0 : nlmlex_buf_init ())) + +static int +nlmlex_buf_init () +{ + lex_size = 10; + lex_buf = xmalloc (lex_size + 1); + lex_pos = 0; + return 0; +} + +/* Finish a string in the buffer. */ +#define BUF_FINISH() ((void) (lex_buf[lex_pos] = '\0')) + +/* Accumulate a character into the buffer. */ +#define BUF_ADD(c) \ + ((void) (lex_pos < lex_size \ + ? lex_buf[lex_pos++] = (c) \ + : nlmlex_buf_add (c))) + +static char +nlmlex_buf_add (c) + int c; +{ + if (lex_pos >= lex_size) + { + lex_size *= 2; + lex_buf = xrealloc (lex_buf, lex_size + 1); + } + + return lex_buf[lex_pos++] = c; +} + +/* The lexer proper. This is called by the bison generated parsing + code. */ + +static int +yylex () +{ + int c; + +tail_recurse: + + c = getc (current.file); + + /* Commas are treated as whitespace characters. */ + while (isspace ((unsigned char) c) || c == ',') + { + current.state = IN_LINE; + if (c == '\n') + { + ++current.lineno; + current.state = BEGINNING_OF_LINE; + } + c = getc (current.file); + } + + /* At the end of the file we either pop to the previous file or + finish up. */ + if (c == EOF) + { + fclose (current.file); + free (current.name); + if (current.next == NULL) + return 0; + else + { + struct input *next; + + next = current.next; + current = *next; + free (next); + goto tail_recurse; + } + } + + /* A comment character always means to drop everything until the + next newline. */ + if (c == COMMENT_CHAR) + { + do + { + c = getc (current.file); + } + while (c != '\n'); + ++current.lineno; + current.state = BEGINNING_OF_LINE; + goto tail_recurse; + } + + /* An '@' introduces an include file. */ + if (c == '@') + { + do + { + c = getc (current.file); + if (c == '\n') + ++current.lineno; + } + while (isspace ((unsigned char) c)); + BUF_INIT (); + while (! isspace ((unsigned char) c) && c != EOF) + { + BUF_ADD (c); + c = getc (current.file); + } + BUF_FINISH (); + + ungetc (c, current.file); + + nlmlex_file_push (lex_buf); + goto tail_recurse; + } + + /* A non-space character at the start of a line must be the start of + a keyword. */ + if (current.state == BEGINNING_OF_LINE) + { + BUF_INIT (); + while (isalnum ((unsigned char) c) || c == '_') + { + if (islower ((unsigned char) c)) + BUF_ADD (toupper ((unsigned char) c)); + else + BUF_ADD (c); + c = getc (current.file); + } + BUF_FINISH (); + + if (c != EOF && ! isspace ((unsigned char) c) && c != ',') + { + nlmheader_identify (); + fprintf (stderr, "%s:%d: illegal character in keyword: %c\n", + current.name, current.lineno, c); + } + else + { + int i; + + for (i = 0; i < KEYWORD_COUNT; i++) + { + if (lex_buf[0] == keyword_tokens[i].keyword[0] + && strcmp (lex_buf, keyword_tokens[i].keyword) == 0) + { + /* Pushing back the final whitespace avoids worrying + about \n here. */ + ungetc (c, current.file); + current.state = IN_LINE; + return keyword_tokens[i].token; + } + } + + nlmheader_identify (); + fprintf (stderr, "%s:%d: unrecognized keyword: %s\n", + current.name, current.lineno, lex_buf); + } + + ++parse_errors; + /* Treat the rest of this line as a comment. */ + ungetc (COMMENT_CHAR, current.file); + goto tail_recurse; + } + + /* Parentheses just represent themselves. */ + if (c == '(' || c == ')') + return c; + + /* Handle quoted strings. */ + if (c == '"' || c == '\'') + { + int quote; + int start_lineno; + + quote = c; + start_lineno = current.lineno; + + c = getc (current.file); + BUF_INIT (); + while (c != quote && c != EOF) + { + BUF_ADD (c); + if (c == '\n') + ++current.lineno; + c = getc (current.file); + } + BUF_FINISH (); + + if (c == EOF) + { + nlmheader_identify (); + fprintf (stderr, "%s:%d: end of file in quoted string\n", + current.name, start_lineno); + ++parse_errors; + } + + /* FIXME: Possible memory leak. */ + yylval.string = xstrdup (lex_buf); + return QUOTED_STRING; + } + + /* Gather a generic argument. */ + BUF_INIT (); + while (! isspace (c) + && c != ',' + && c != COMMENT_CHAR + && c != '(' + && c != ')') + { + BUF_ADD (c); + c = getc (current.file); + } + BUF_FINISH (); + + ungetc (c, current.file); + + /* FIXME: Possible memory leak. */ + yylval.string = xstrdup (lex_buf); + return STRING; +} + +/* Get a number from a string. */ + +static long +nlmlex_get_number (s) + const char *s; +{ + long ret; + char *send; + + ret = strtol (s, &send, 10); + if (*send != '\0') + nlmheader_warn ("bad number", -1); + return ret; +} + +/* Prefix the nlmconv warnings with a note as to where they come from. + We don't use program_name on every warning, because then some + versions of the emacs next-error function can't recognize the line + number. */ + +static void +nlmheader_identify () +{ + static int done; + + if (! done) + { + fprintf (stderr, "%s: problems in NLM command language input:\n", + program_name); + done = 1; + } +} + +/* Issue a warning. */ + +static void +nlmheader_warn (s, imax) + const char *s; + int imax; +{ + nlmheader_identify (); + fprintf (stderr, "%s:%d: %s", current.name, current.lineno, s); + if (imax != -1) + fprintf (stderr, " (max %d)", imax); + fprintf (stderr, "\n"); +} + +/* Report an error. */ + +static void +nlmheader_error (s) + const char *s; +{ + nlmheader_warn (s, -1); + ++parse_errors; +} + +/* Add a string to a string list. */ + +static struct string_list * +string_list_cons (s, l) + char *s; + struct string_list *l; +{ + struct string_list *ret; + + ret = (struct string_list *) xmalloc (sizeof (struct string_list)); + ret->next = l; + ret->string = s; + return ret; +} + +/* Append a string list to another string list. */ + +static struct string_list * +string_list_append (l1, l2) + struct string_list *l1; + struct string_list *l2; +{ + register struct string_list **pp; + + for (pp = &l1; *pp != NULL; pp = &(*pp)->next) + ; + *pp = l2; + return l1; +} + +/* Append a string to a string list. */ + +static struct string_list * +string_list_append1 (l, s) + struct string_list *l; + char *s; +{ + struct string_list *n; + register struct string_list **pp; + + n = (struct string_list *) xmalloc (sizeof (struct string_list)); + n->next = NULL; + n->string = s; + for (pp = &l; *pp != NULL; pp = &(*pp)->next) + ; + *pp = n; + return l; +} + +/* Duplicate a string in memory. */ + +static char * +xstrdup (s) + const char *s; +{ + unsigned long len; + char *ret; + + len = strlen (s); + ret = xmalloc (len + 1); + strcpy (ret, s); + return ret; +} diff --git a/gnu/usr.bin/binutils/binutils/nm.1 b/gnu/usr.bin/binutils/binutils/nm.1 new file mode 100644 index 00000000000..13681bea9a7 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/nm.1 @@ -0,0 +1,219 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH nm 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +nm \- list symbols from object files. + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B nm +.RB "[\|" \-a | \-\-debug\-syms "\|]" +.RB "[\|" \-g | \-\-extern\-only "\|]" +.RB "[\|" \-B "\|]" +.RB "[\|" \-C | \-\-demangle "\|]" +.RB "[\|" \-D | \-\-dynamic "\|]" +.RB "[\|" \-s | \-\-print\-armap "\|]" +.RB "[\|" \-o | \-\-print\-file\-name "\|]" +.RB "[\|" \-n | \-\-numeric\-sort "\|]" +.RB "[\|" \-p | \-\-no\-sort "\|]" +.RB "[\|" \-r | \-\-reverse\-sort "\|]" +.RB "[\|" \-\-size\-sort "\|]" +.RB "[\|" \-u | \-\-undefined\-only "\|]" +.RB "[\|" \-\-help "\|]" +.RB "[\|" \-\-version "\|]" +.RB "[\|" "\-t \fIradix" | \-\-radix=\fIradix "\|]" +.RB "[\|" \-P | --portability "\|]" +.RB "[\|" "\-f \fIformat" | \-\-format=\fIformat "\|]" +.RB "[\|" "\-\-target=\fIbfdname" "\|]" +.RB "[\|" \c +.I objfile\c +\&.\|.\|.\|] +.ad b +.hy 1 +.SH DESCRIPTION +GNU \c +.B nm\c +\& lists the symbols from object files \c +.I objfile\c +\&. If no object files are given as arguments, \c +.B nm\c +\& assumes `\|\c +.B a.out\c +\|'. + +.SH OPTIONS +The long and short forms of options, shown here as alternatives, are +equivalent. + +.TP +.B \-A +.TP +.B \-o +.TP +.B \-\-print\-file\-name +Precede each symbol by the name of the input file where it was found, +rather than identifying the input file once only before all of its +symbols. + +.TP +.B \-a +.TP +.B \-\-debug\-syms +Display debugger-only symbols; normally these are not listed. + +.TP +.B \-B +The same as +.B \-\-format=bsd +(for compatibility with the MIPS \fBnm\fP). + +.TP +.B \-C +.TP +.B \-\-demangle +Decode (\fIdemangle\fP) low-level symbol names into user-level names. +Besides removing any initial underscore prepended by the system, this +makes C++ function names readable. + +.TP +.B \-D +.TP +.B \-\-dynamic +Display the dynamic symbols rather than the normal symbols. This is +only meaningful for dynamic objects, such as certain types of shared +libraries. + +.TP +.B "\-f \fIformat" +Use the output format \fIformat\fP, which can be ``bsd'', +``sysv'', or ``posix''. The default is ``bsd''. +Only the first character of \fIformat\fP is significant; it can be +either upper or lower case. + +.TP +.B \-g +.TP +.B \-\-extern\-only +Display only external symbols. + +.TP +.B \-n +.TP +.B \-v +.TP +.B \-\-numeric\-sort +Sort symbols numerically by their addresses, not alphabetically by their +names. + +.TP +.B \-p +.TP +.B \-\-no\-sort +Don't bother to sort the symbols in any order; just print them in the +order encountered. + +.TP +.B \-P +.TP +.B \-\-portability +Use the POSIX.2 standard output format instead of the default format. +Equivalent to ``\-f posix''. + +.TP +.B \-s +.TP +.B \-\-print\-armap +When listing symbols from archive members, include the index: a mapping +(stored in the archive by \c +.B ar\c +\& or \c +.B ranlib\c +\&) of what modules +contain definitions for what names. + +.TP +.B \-r +.TP +.B \-\-reverse\-sort +Reverse the sense of the sort (whether numeric or alphabetic); let the +last come first. + +.TP +.B \-\-size\-sort +Sort symbols by size. The size is computed as the difference between +the value of the symbol and the value of the symbol with the next higher +value. The size of the symbol is printed, rather than the value. + +.TP +.B "\-t \fIradix" +.TP +.B "\-\-radix=\fIradix" +Use \fIradix\fP as the radix for printing the symbol values. It must be +``d'' for decimal, ``o'' for octal, or ``x'' for hexadecimal. + +.TP +.BI "\-\-target=" "bfdname" +Specify an object code format other than your system's default format. +See +.BR objdump ( 1 ), +for information on listing available formats. + +.TP +.B \-u +.TP +.B \-\-undefined\-only +Display only undefined symbols (those external to each object file). + +.TP +.B \-V +.TP +.B \-\-version +Show the version number of +.B nm +and exit. + +.TP +.B \-\-help +Show a summary of the options to +.B nm +and exit. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (October 1991); +.BR ar "(" 1 ")," +.BR objdump ( 1 ), +.BR ranlib "(" 1 ")." + + +.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/gnu/usr.bin/binutils/binutils/nm.c b/gnu/usr.bin/binutils/binutils/nm.c new file mode 100644 index 00000000000..b243055766d --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/nm.c @@ -0,0 +1,1340 @@ +/* nm.c -- Describe symbol table of a rel file. + Copyright 1991, 92, 93, 94 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public 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 "progress.h" +#include "bucomm.h" +#include "getopt.h" +#include "aout/stab_gnu.h" +#include "aout/ranlib.h" +#include "demangle.h" +#include "libiberty.h" + +/* When sorting by size, we use this structure to hold the size and a + pointer to the minisymbol. */ + +struct size_sym +{ + const PTR minisym; + bfd_vma size; +}; + +static boolean +display_file PARAMS ((char *filename)); + +static void +display_rel_file PARAMS ((bfd * file, bfd * archive)); + +static long +filter_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int)); + +static long +sort_symbols_by_size PARAMS ((bfd *, boolean, PTR, long, unsigned int, + struct size_sym **)); + +static void +print_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int, bfd *)); + +static void +print_size_symbols PARAMS ((bfd *, boolean, struct size_sym *, long, bfd *)); + +static void +print_symbol PARAMS ((bfd *, asymbol *, bfd *)); + +static void +print_symdef_entry PARAMS ((bfd * abfd)); + +/* The sorting functions. */ + +static int +numeric_forward PARAMS ((const PTR, const PTR)); + +static int +numeric_reverse PARAMS ((const PTR, const PTR)); + +static int +non_numeric_forward PARAMS ((const PTR, const PTR)); + +static int +non_numeric_reverse PARAMS ((const PTR, const PTR)); + +static int +size_forward1 PARAMS ((const PTR, const PTR)); + +static int +size_forward2 PARAMS ((const PTR, const PTR)); + +/* The output formatting functions. */ + +static void +print_object_filename_bsd PARAMS ((char *filename)); + +static void +print_object_filename_sysv PARAMS ((char *filename)); + +static void +print_object_filename_posix PARAMS ((char *filename)); + + +static void +print_archive_filename_bsd PARAMS ((char *filename)); + +static void +print_archive_filename_sysv PARAMS ((char *filename)); + +static void +print_archive_filename_posix PARAMS ((char *filename)); + + +static void +print_archive_member_bsd PARAMS ((char *archive, CONST char *filename)); + +static void +print_archive_member_sysv PARAMS ((char *archive, CONST char *filename)); + +static void +print_archive_member_posix PARAMS ((char *archive, CONST char *filename)); + + +static void +print_symbol_filename_bsd PARAMS ((bfd * archive_bfd, bfd * abfd)); + +static void +print_symbol_filename_sysv PARAMS ((bfd * archive_bfd, bfd * abfd)); + +static void +print_symbol_filename_posix PARAMS ((bfd * archive_bfd, bfd * abfd)); + + +static void +print_value PARAMS ((bfd_vma)); + +static void +print_symbol_info_bsd PARAMS ((symbol_info * info, bfd * abfd)); + +static void +print_symbol_info_sysv PARAMS ((symbol_info * info, bfd * abfd)); + +static void +print_symbol_info_posix PARAMS ((symbol_info * info, bfd * abfd)); + + +/* Support for different output formats. */ +struct output_fns + { + /* Print the name of an object file given on the command line. */ + void (*print_object_filename) PARAMS ((char *filename)); + + /* Print the name of an archive file given on the command line. */ + void (*print_archive_filename) PARAMS ((char *filename)); + + /* Print the name of an archive member file. */ + void (*print_archive_member) PARAMS ((char *archive, CONST char *filename)); + + /* Print the name of the file (and archive, if there is one) + containing a symbol. */ + void (*print_symbol_filename) PARAMS ((bfd * archive_bfd, bfd * abfd)); + + /* Print a line of information about a symbol. */ + void (*print_symbol_info) PARAMS ((symbol_info * info, bfd * abfd)); + }; +static struct output_fns formats[] = +{ + {print_object_filename_bsd, + print_archive_filename_bsd, + print_archive_member_bsd, + print_symbol_filename_bsd, + print_symbol_info_bsd}, + {print_object_filename_sysv, + print_archive_filename_sysv, + print_archive_member_sysv, + print_symbol_filename_sysv, + print_symbol_info_sysv}, + {print_object_filename_posix, + print_archive_filename_posix, + print_archive_member_posix, + print_symbol_filename_posix, + print_symbol_info_posix} +}; + +/* Indices in `formats'. */ +#define FORMAT_BSD 0 +#define FORMAT_SYSV 1 +#define FORMAT_POSIX 2 +#define FORMAT_DEFAULT FORMAT_BSD + +/* The output format to use. */ +static struct output_fns *format = &formats[FORMAT_DEFAULT]; + + +/* Command options. */ + +static int do_demangle = 0; /* Pretty print C++ symbol names. */ +static int external_only = 0; /* print external symbols only */ +static int no_sort = 0; /* don't sort; print syms in order found */ +static int print_debug_syms = 0; /* print debugger-only symbols too */ +static int print_armap = 0; /* describe __.SYMDEF data in archive files. */ +static int reverse_sort = 0; /* sort in downward(alpha or numeric) order */ +static int sort_numerically = 0; /* sort in numeric rather than alpha order */ +static int sort_by_size = 0; /* sort by size of symbol */ +static int undefined_only = 0; /* print undefined symbols only */ +static int dynamic = 0; /* print dynamic symbols. */ +static int show_version = 0; /* show the version number */ +static int show_stats = 0; /* show statistics */ + +/* When to print the names of files. Not mutually exclusive in SYSV format. */ +static int filename_per_file = 0; /* Once per file, on its own line. */ +static int filename_per_symbol = 0; /* Once per symbol, at start of line. */ + +/* Print formats for printing a symbol value. */ +#ifndef BFD64 +static char value_format[] = "%08lx"; +#else +#if BFD_HOST_64BIT_LONG +static char value_format[] = "%016lx"; +#else +/* We don't use value_format for this case. */ +#endif +#endif +static int print_radix = 16; +/* Print formats for printing stab info. */ +static char other_format[] = "%02x"; +static char desc_format[] = "%04x"; + +/* IMPORT */ +extern char *program_name; +extern char *program_version; +extern char *target; +extern int print_version; + +static struct option long_options[] = +{ + {"debug-syms", no_argument, &print_debug_syms, 1}, + {"demangle", no_argument, &do_demangle, 1}, + {"dynamic", no_argument, &dynamic, 1}, + {"extern-only", no_argument, &external_only, 1}, + {"format", required_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */ + {"no-demangle", no_argument, &do_demangle, 0}, + {"no-sort", no_argument, &no_sort, 1}, + {"numeric-sort", no_argument, &sort_numerically, 1}, + {"portability", no_argument, 0, 'P'}, + {"print-armap", no_argument, &print_armap, 1}, + {"print-file-name", no_argument, 0, 'o'}, + {"radix", required_argument, 0, 't'}, + {"reverse-sort", no_argument, &reverse_sort, 1}, + {"size-sort", no_argument, &sort_by_size, 1}, + {"stats", no_argument, &show_stats, 1}, + {"target", required_argument, 0, 200}, + {"undefined-only", no_argument, &undefined_only, 1}, + {"version", no_argument, &show_version, 1}, + {0, no_argument, 0, 0} +}; + +/* Some error-reporting functions */ + +void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, "\ +Usage: %s [-aABCDgnopPrsuvV] [-t radix] [--radix=radix] [--target=bfdname]\n\ + [--debug-syms] [--extern-only] [--print-armap] [--print-file-name]\n\ + [--numeric-sort] [--no-sort] [--reverse-sort] [--size-sort]\n\ + [--undefined-only] [--portability] [-f {bsd,sysv,posix}]\n\ + [--format={bsd,sysv,posix}] [--demangle] [--no-demangle] [--dynamic]\n\ + [--version] [--help]\n\ + [file...]\n", + program_name); + list_supported_targets (program_name, stream); + exit (status); +} + +/* Set the radix for the symbol value and size according to RADIX. */ + +void +set_print_radix (radix) + char *radix; +{ + switch (*radix) + { + case 'x': + break; + case 'd': + case 'o': + if (*radix == 'd') + print_radix = 10; + else + print_radix = 8; +#ifndef BFD64 + value_format[4] = *radix; +#else +#if BFD_HOST_64BIT_LONG + value_format[5] = *radix; +#else + /* This case requires special handling for octal and decimal + printing. */ +#endif +#endif + other_format[3] = desc_format[3] = *radix; + break; + default: + fprintf (stderr, "%s: %s: invalid radix\n", program_name, radix); + exit (1); + } +} + +void +set_output_format (f) + char *f; +{ + int i; + + switch (*f) + { + case 'b': + case 'B': + i = FORMAT_BSD; + break; + case 'p': + case 'P': + i = FORMAT_POSIX; + break; + case 's': + case 'S': + i = FORMAT_SYSV; + break; + default: + fprintf (stderr, "%s: %s: invalid output format\n", program_name, f); + exit (1); + } + format = &formats[i]; +} + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int retval; + + program_name = *argv; + xmalloc_set_program_name (program_name); + + START_PROGRESS (program_name, 0); + + bfd_init (); + + while ((c = getopt_long (argc, argv, "aABCDef:gnopPrst:uvV", long_options, (int *) 0)) != EOF) + { + switch (c) + { + case 'a': + print_debug_syms = 1; + break; + case 'A': + case 'o': + filename_per_symbol = 1; + break; + case 'B': /* For MIPS compatibility. */ + set_output_format ("bsd"); + break; + case 'C': + do_demangle = 1; + break; + case 'D': + dynamic = 1; + break; + case 'e': + /* Ignored for HP/UX compatibility. */ + break; + case 'f': + set_output_format (optarg); + break; + case 'g': + external_only = 1; + break; + case 'h': + usage (stdout, 0); + case 'n': + case 'v': + sort_numerically = 1; + break; + case 'p': + no_sort = 1; + break; + case 'P': + set_output_format ("posix"); + break; + case 'r': + reverse_sort = 1; + break; + case 's': + print_armap = 1; + break; + case 't': + set_print_radix (optarg); + break; + case 'u': + undefined_only = 1; + break; + case 'V': + show_version = 1; + break; + + case 200: /* --target */ + target = optarg; + break; + + case 0: /* A long option that just sets a flag. */ + break; + + default: + usage (stderr, 1); + } + } + + if (show_version) + { + printf ("GNU %s version %s\n", program_name, program_version); + exit (0); + } + + /* OK, all options now parsed. If no filename specified, do a.out. */ + if (optind == argc) + return !display_file ("a.out"); + + retval = 0; + + if (argc - optind > 1) + filename_per_file = 1; + + /* We were given several filenames to do. */ + while (optind < argc) + { + PROGRESS (1); + if (!display_file (argv[optind++])) + retval++; + } + + END_PROGRESS (program_name); + +#ifdef HAVE_SBRK + if (show_stats) + { + extern char **environ; + char *lim = (char *) sbrk (0); + + fprintf (stderr, "%s: data size %ld\n", program_name, + (long) (lim - (char *) &environ)); + } +#endif + + exit (retval); + return retval; +} + +static void +display_archive (file) + bfd *file; +{ + bfd *arfile = NULL; + bfd *last_arfile = NULL; + char **matching; + + (*format->print_archive_filename) (bfd_get_filename (file)); + + if (print_armap) + print_symdef_entry (file); + + for (;;) + { + PROGRESS (1); + + arfile = bfd_openr_next_archived_file (file, arfile); + + if (arfile == NULL) + { + if (bfd_get_error () != bfd_error_no_more_archived_files) + bfd_fatal (bfd_get_filename (file)); + break; + } + + if (bfd_check_format_matches (arfile, bfd_object, &matching)) + { + (*format->print_archive_member) (bfd_get_filename (file), + bfd_get_filename (arfile)); + display_rel_file (arfile, file); + } + else + { + bfd_nonfatal (bfd_get_filename (arfile)); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + } + + if (last_arfile != NULL) + bfd_close (last_arfile); + last_arfile = arfile; + } + + if (last_arfile != NULL) + bfd_close (last_arfile); +} + +static boolean +display_file (filename) + char *filename; +{ + boolean retval = true; + bfd *file; + char **matching; + + file = bfd_openr (filename, target); + if (file == NULL) + { + bfd_nonfatal (filename); + return false; + } + + if (bfd_check_format (file, bfd_archive)) + { + display_archive (file); + } + else if (bfd_check_format_matches (file, bfd_object, &matching)) + { + (*format->print_object_filename) (filename); + display_rel_file (file, NULL); + } + else + { + bfd_nonfatal (filename); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + retval = false; + } + + if (bfd_close (file) == false) + bfd_fatal (filename); + + return retval; +} + +/* These globals are used to pass information into the sorting + routines. */ +static bfd *sort_bfd; +static boolean sort_dynamic; +static asymbol *sort_x; +static asymbol *sort_y; + +/* Symbol-sorting predicates */ +#define valueof(x) ((x)->section->vma + (x)->value) + +/* Numeric sorts. Undefined symbols are always considered "less than" + defined symbols with zero values. Common symbols are not treated + specially -- i.e., their sizes are used as their "values". */ + +static int +numeric_forward (P_x, P_y) + const PTR P_x; + const PTR P_y; +{ + asymbol *x, *y; + asection *xs, *ys; + + x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x); + y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y); + if (x == NULL || y == NULL) + bfd_fatal (bfd_get_filename (sort_bfd)); + + xs = bfd_get_section (x); + ys = bfd_get_section (y); + + if (bfd_is_und_section (xs)) + { + if (! bfd_is_und_section (ys)) + return -1; + } + else if (bfd_is_und_section (ys)) + return 1; + else if (valueof (x) != valueof (y)) + return valueof (x) < valueof (y) ? -1 : 1; + + return non_numeric_forward (P_x, P_y); +} + +static int +numeric_reverse (x, y) + const PTR x; + const PTR y; +{ + return - numeric_forward (x, y); +} + +static int +non_numeric_forward (P_x, P_y) + const PTR P_x; + const PTR P_y; +{ + asymbol *x, *y; + const char *xn, *yn; + + x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x); + y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y); + if (x == NULL || y == NULL) + bfd_fatal (bfd_get_filename (sort_bfd)); + + xn = bfd_asymbol_name (x); + yn = bfd_asymbol_name (y); + + return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) : + ((yn == NULL) ? 1 : strcmp (xn, yn))); +} + +static int +non_numeric_reverse (x, y) + const PTR x; + const PTR y; +{ + return - non_numeric_forward (x, y); +} + +static int (*(sorters[2][2])) PARAMS ((const PTR, const PTR)) = +{ + { non_numeric_forward, non_numeric_reverse }, + { numeric_forward, numeric_reverse } +}; + +/* This sort routine is used by sort_symbols_by_size. It is similar + to numeric_forward, but when symbols have the same value it sorts + by section VMA. This simplifies the sort_symbols_by_size code + which handles symbols at the end of sections. Also, this routine + tries to sort file names before other symbols with the same value. + That will make the file name have a zero size, which will make + sort_symbols_by_size choose the non file name symbol, leading to + more meaningful output. For similar reasons, this code sorts + gnu_compiled_* and gcc2_compiled before other symbols with the same + value. */ + +static int +size_forward1 (P_x, P_y) + const PTR P_x; + const PTR P_y; +{ + asymbol *x, *y; + asection *xs, *ys; + const char *xn, *yn; + size_t xnl, ynl; + int xf, yf; + + x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x); + y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y); + if (x == NULL || y == NULL) + bfd_fatal (bfd_get_filename (sort_bfd)); + + xs = bfd_get_section (x); + ys = bfd_get_section (y); + + if (bfd_is_und_section (xs)) + abort (); + if (bfd_is_und_section (ys)) + abort (); + + if (valueof (x) != valueof (y)) + return valueof (x) < valueof (y) ? -1 : 1; + + if (xs->vma != ys->vma) + return xs->vma < ys->vma ? -1 : 1; + + xn = bfd_asymbol_name (x); + yn = bfd_asymbol_name (y); + xnl = strlen (xn); + ynl = strlen (yn); + + /* The symbols gnu_compiled and gcc2_compiled convey even less + information than the file name, so sort them out first. */ + + xf = (strstr (xn, "gnu_compiled") != NULL + || strstr (xn, "gcc2_compiled") != NULL); + yf = (strstr (yn, "gnu_compiled") != NULL + || strstr (yn, "gcc2_compiled") != NULL); + + if (xf && ! yf) + return -1; + if (! xf && yf) + return 1; + + /* We use a heuristic for the file name. It may not work on non + Unix systems, but it doesn't really matter; the only difference + is precisely which symbol names get printed. */ + +#define file_symbol(s, sn, snl) \ + (((s)->flags & BSF_FILE) != 0 \ + || ((sn)[(snl) - 2] == '.' \ + && ((sn)[(snl) - 1] == 'o' \ + || (sn)[(snl) - 1] == 'a'))) + + xf = file_symbol (x, xn, xnl); + yf = file_symbol (y, yn, ynl); + + if (xf && ! yf) + return -1; + if (! xf && yf) + return 1; + + return non_numeric_forward (P_x, P_y); +} + +/* This sort routine is used by sort_symbols_by_size. It is sorting + an array of size_sym structures into size order. */ + +static int +size_forward2 (P_x, P_y) + const PTR P_x; + const PTR P_y; +{ + const struct size_sym *x = (const struct size_sym *) P_x; + const struct size_sym *y = (const struct size_sym *) P_y; + + if (x->size < y->size) + return reverse_sort ? 1 : -1; + else if (x->size > y->size) + return reverse_sort ? -1 : 1; + else + return sorters[0][reverse_sort] (x->minisym, y->minisym); +} + +/* Sort the symbols by size. We guess the size by assuming that the + difference between the address of a symbol and the address of the + next higher symbol is the size. FIXME: ELF actually stores a size + with each symbol. We should use it. */ + +static long +sort_symbols_by_size (abfd, dynamic, minisyms, symcount, size, symsizesp) + bfd *abfd; + boolean dynamic; + PTR minisyms; + long symcount; + unsigned int size; + struct size_sym **symsizesp; +{ + struct size_sym *symsizes; + bfd_byte *from, *fromend; + asymbol *sym; + asymbol *store_sym, *store_next; + + qsort (minisyms, symcount, size, size_forward1); + + /* We are going to return a special set of symbols and sizes to + print. */ + symsizes = (struct size_sym *) xmalloc (symcount * sizeof (struct size_sym)); + *symsizesp = symsizes; + + /* Note that filter_symbols has already removed all absolute and + undefined symbols. Here we remove all symbols whose size winds + up as zero. */ + + from = (bfd_byte *) minisyms; + fromend = from + symcount * size; + + store_sym = sort_x; + store_next = sort_y; + + if (from < fromend) + { + sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from, + store_sym); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + } + + for (; from < fromend; from += size) + { + asymbol *next; + asection *sec; + bfd_vma sz; + asymbol *temp; + + if (from + size < fromend) + { + next = bfd_minisymbol_to_symbol (abfd, + dynamic, + (const PTR) (from + size), + store_next); + if (next == NULL) + bfd_fatal (bfd_get_filename (abfd)); + } + + sec = bfd_get_section (sym); + + if (bfd_is_com_section (sec)) + sz = sym->value; + else + { + if (from + size < fromend + && sec == bfd_get_section (next)) + sz = valueof (next) - valueof (sym); + else + sz = (bfd_get_section_vma (abfd, sec) + + bfd_section_size (abfd, sec) + - valueof (sym)); + } + + if (sz != 0) + { + symsizes->minisym = (const PTR) from; + symsizes->size = sz; + ++symsizes; + } + + sym = next; + + temp = store_sym; + store_sym = store_next; + store_next = temp; + } + + symcount = symsizes - *symsizesp; + + /* We must now sort again by size. */ + qsort ((PTR) *symsizesp, symcount, sizeof (struct size_sym), size_forward2); + + return symcount; +} + +/* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */ + +static void +display_rel_file (abfd, archive_bfd) + bfd *abfd; + bfd *archive_bfd; +{ + long symcount; + PTR minisyms; + unsigned int size; + struct size_sym *symsizes; + + if (! dynamic) + { + if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) + { + printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd)); + return; + } + } + + symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size); + if (symcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + + if (symcount == 0) + { + fprintf (stderr, "%s: no symbols\n", bfd_get_filename (abfd)); + return; + } + + /* Discard the symbols we don't want to print. + It's OK to do this in place; we'll free the storage anyway + (after printing). */ + + symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size); + + symsizes = NULL; + if (! no_sort) + { + sort_bfd = abfd; + sort_dynamic = dynamic; + sort_x = bfd_make_empty_symbol (abfd); + sort_y = bfd_make_empty_symbol (abfd); + if (sort_x == NULL || sort_y == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + if (! sort_by_size) + qsort (minisyms, symcount, size, + sorters[sort_numerically][reverse_sort]); + else + symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount, + size, &symsizes); + } + + if (! sort_by_size) + print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd); + else + print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd); + + free (minisyms); +} + +/* Choose which symbol entries to print; + compact them downward to get rid of the rest. + Return the number of symbols to be printed. */ + +static long +filter_symbols (abfd, dynamic, minisyms, symcount, size) + bfd *abfd; + boolean dynamic; + PTR minisyms; + long symcount; + unsigned int size; +{ + bfd_byte *from, *fromend, *to; + asymbol *store; + + store = bfd_make_empty_symbol (abfd); + if (store == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + from = (bfd_byte *) minisyms; + fromend = from + symcount * size; + to = (bfd_byte *) minisyms; + + for (; from < fromend; from += size) + { + int keep = 0; + asymbol *sym; + + PROGRESS (1); + + sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from, store); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + if (undefined_only) + keep = bfd_is_und_section (sym->section); + else if (external_only) + keep = ((sym->flags & BSF_GLOBAL) != 0 + || bfd_is_und_section (sym->section) + || bfd_is_com_section (sym->section)); + else + keep = 1; + + if (keep + && ! print_debug_syms + && (sym->flags & BSF_DEBUGGING) != 0) + keep = 0; + + if (keep + && sort_by_size + && (bfd_is_abs_section (sym->section) + || bfd_is_und_section (sym->section))) + keep = 0; + + if (keep) + { + memcpy (to, from, size); + to += size; + } + } + + return (to - (bfd_byte *) minisyms) / size; +} + +/* Print symbol name NAME, read from ABFD, with printf format FORMAT, + demangling it if requested. */ + +static void +print_symname (format, name, abfd) + char *format, *name; + bfd *abfd; +{ + if (do_demangle && *name) + { + char *res; + + /* In this mode, give a user-level view of the symbol name + even if it's not mangled; strip off any leading + underscore. */ + if (bfd_get_symbol_leading_char (abfd) == name[0]) + name++; + + res = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS); + if (res) + { + printf (format, res); + free (res); + return; + } + } + + printf (format, name); +} + +/* Print the symbols. If ARCHIVE_BFD is non-NULL, it is the archive + containing ABFD. */ + +static void +print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd) + bfd *abfd; + boolean dynamic; + PTR minisyms; + long symcount; + unsigned int size; + bfd *archive_bfd; +{ + asymbol *store; + bfd_byte *from, *fromend; + + store = bfd_make_empty_symbol (abfd); + if (store == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + from = (bfd_byte *) minisyms; + fromend = from + symcount * size; + for (; from < fromend; from += size) + { + asymbol *sym; + + sym = bfd_minisymbol_to_symbol (abfd, dynamic, from, store); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + print_symbol (abfd, sym, archive_bfd); + } +} + +/* Print the symbols when sorting by size. */ + +static void +print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd) + bfd *abfd; + boolean dynamic; + struct size_sym *symsizes; + long symcount; + bfd *archive_bfd; +{ + asymbol *store; + struct size_sym *from, *fromend; + + store = bfd_make_empty_symbol (abfd); + if (store == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + from = symsizes; + fromend = from + symcount; + for (; from < fromend; from++) + { + asymbol *sym; + + sym = bfd_minisymbol_to_symbol (abfd, dynamic, from->minisym, store); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + /* Set the symbol value so that we actually display the symbol + size. */ + sym->value = from->size - bfd_section_vma (abfd, bfd_get_section (sym)); + + print_symbol (abfd, sym, archive_bfd); + } +} + +/* Print a single symbol. */ + +static void +print_symbol (abfd, sym, archive_bfd) + bfd *abfd; + asymbol *sym; + bfd *archive_bfd; +{ + PROGRESS (1); + + (*format->print_symbol_filename) (archive_bfd, abfd); + + if (undefined_only) + { + if (bfd_is_und_section (bfd_get_section (sym))) + print_symname ("%s\n", bfd_asymbol_name (sym), abfd); + } + else + { + symbol_info syminfo; + + bfd_get_symbol_info (abfd, sym, &syminfo); + (*format->print_symbol_info) (&syminfo, abfd); + putchar ('\n'); + } +} + +/* The following 3 groups of functions are called unconditionally, + once at the start of processing each file of the appropriate type. + They should check `filename_per_file' and `filename_per_symbol', + as appropriate for their output format, to determine whether to + print anything. */ + +/* Print the name of an object file given on the command line. */ + +static void +print_object_filename_bsd (filename) + char *filename; +{ + if (filename_per_file && !filename_per_symbol) + printf ("\n%s:\n", filename); +} + +static void +print_object_filename_sysv (filename) + char *filename; +{ + if (undefined_only) + printf ("\n\nUndefined symbols from %s:\n\n", filename); + else + printf ("\n\nSymbols from %s:\n\n", filename); + printf ("\ +Name Value Class Type Size Line Section\n\n"); +} + +static void +print_object_filename_posix (filename) + char *filename; +{ + if (filename_per_file && !filename_per_symbol) + printf ("%s:\n", filename); +} + +/* Print the name of an archive file given on the command line. */ + +static void +print_archive_filename_bsd (filename) + char *filename; +{ + if (filename_per_file) + printf ("\n%s:\n", filename); +} + +static void +print_archive_filename_sysv (filename) + char *filename; +{ +} + +static void +print_archive_filename_posix (filename) + char *filename; +{ +} + +/* Print the name of an archive member file. */ + +static void +print_archive_member_bsd (archive, filename) + char *archive; + CONST char *filename; +{ + if (!filename_per_symbol) + printf ("\n%s:\n", filename); +} + +static void +print_archive_member_sysv (archive, filename) + char *archive; + CONST char *filename; +{ + if (undefined_only) + printf ("\n\nUndefined symbols from %s[%s]:\n\n", archive, filename); + else + printf ("\n\nSymbols from %s[%s]:\n\n", archive, filename); + printf ("\ +Name Value Class Type Size Line Section\n\n"); +} + +static void +print_archive_member_posix (archive, filename) + char *archive; + CONST char *filename; +{ + if (!filename_per_symbol) + printf ("%s[%s]:\n", archive, filename); +} + +/* Print the name of the file (and archive, if there is one) + containing a symbol. */ + +static void +print_symbol_filename_bsd (archive_bfd, abfd) + bfd *archive_bfd, *abfd; +{ + if (filename_per_symbol) + { + if (archive_bfd) + printf ("%s:", bfd_get_filename (archive_bfd)); + printf ("%s:", bfd_get_filename (abfd)); + } +} + +static void +print_symbol_filename_sysv (archive_bfd, abfd) + bfd *archive_bfd, *abfd; +{ + if (filename_per_symbol) + { + if (archive_bfd) + printf ("%s:", bfd_get_filename (archive_bfd)); + printf ("%s:", bfd_get_filename (abfd)); + } +} + +static void +print_symbol_filename_posix (archive_bfd, abfd) + bfd *archive_bfd, *abfd; +{ + if (filename_per_symbol) + { + if (archive_bfd) + printf ("%s[%s]: ", bfd_get_filename (archive_bfd), + bfd_get_filename (abfd)); + else + printf ("%s: ", bfd_get_filename (abfd)); + } +} + +/* Print a symbol value. */ + +static void +print_value (val) + bfd_vma val; +{ +#if ! defined (BFD64) || BFD_HOST_64BIT_LONG + printf (value_format, val); +#else + /* We have a 64 bit value to print, but the host is only 32 bit. */ + if (print_radix == 16) + fprintf_vma (stdout, val); + else + { + char buf[30]; + char *s; + + s = buf + sizeof buf; + *--s = '\0'; + while (val > 0) + { + *--s = (val % print_radix) + '0'; + val /= print_radix; + } + while ((buf + sizeof buf - 1) - s < 16) + *--s = '0'; + printf ("%s", s); + } +#endif +} + +/* Print a line of information about a symbol. */ + +static void +print_symbol_info_bsd (info, abfd) + symbol_info *info; + bfd *abfd; +{ + if (info->type == 'U') + { + printf ("%*s", +#ifdef BFD64 + 16, +#else + 8, +#endif + ""); + } + else + print_value (info->value); + printf (" %c", info->type); + if (info->type == '-') + { + /* A stab. */ + printf (" "); + printf (other_format, info->stab_other); + printf (" "); + printf (desc_format, info->stab_desc); + printf (" %5s", info->stab_name); + } + print_symname (" %s", info->name, abfd); +} + +static void +print_symbol_info_sysv (info, abfd) + symbol_info *info; + bfd *abfd; +{ + print_symname ("%-20s|", info->name, abfd); /* Name */ + if (info->type == 'U') + printf (" "); /* Value */ + else + print_value (info->value); + printf ("| %c |", info->type); /* Class */ + if (info->type == '-') + { + /* A stab. */ + printf ("%18s| ", info->stab_name); /* (C) Type */ + printf (desc_format, info->stab_desc); /* Size */ + printf ("| |"); /* Line, Section */ + } + else + printf (" | | |"); /* Type, Size, Line, Section */ +} + +static void +print_symbol_info_posix (info, abfd) + symbol_info *info; + bfd *abfd; +{ + print_symname ("%s ", info->name, abfd); + printf ("%c ", info->type); + if (info->type == 'U') + printf (" "); + else + print_value (info->value); + /* POSIX.2 wants the symbol size printed here, when applicable; + BFD currently doesn't provide it, so we take the easy way out by + considering it to never be applicable. */ +} + +static void +print_symdef_entry (abfd) + bfd *abfd; +{ + symindex idx = BFD_NO_MORE_SYMBOLS; + carsym *thesym; + boolean everprinted = false; + + for (idx = bfd_get_next_mapent (abfd, idx, &thesym); + idx != BFD_NO_MORE_SYMBOLS; + idx = bfd_get_next_mapent (abfd, idx, &thesym)) + { + bfd *elt; + if (!everprinted) + { + printf ("\nArchive index:\n"); + everprinted = true; + } + elt = bfd_get_elt_at_index (abfd, idx); + if (thesym->name != (char *) NULL) + { + print_symname ("%s", thesym->name, abfd); + printf (" in %s\n", bfd_get_filename (elt)); + } + } +} diff --git a/gnu/usr.bin/binutils/binutils/not-ranlib.c b/gnu/usr.bin/binutils/binutils/not-ranlib.c new file mode 100644 index 00000000000..afb9ceb3d67 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/not-ranlib.c @@ -0,0 +1,3 @@ +/* Linked with ar.o to flag that this program is 'ar' (not 'ranlib'). */ + +int is_ranlib = 0; diff --git a/gnu/usr.bin/binutils/binutils/not-strip.c b/gnu/usr.bin/binutils/binutils/not-strip.c new file mode 100644 index 00000000000..98093ce391a --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/not-strip.c @@ -0,0 +1,4 @@ +/* Linked with objcopy.o to flag that this program is 'objcopy' (not + 'strip'). */ + +int is_strip = 0; diff --git a/gnu/usr.bin/binutils/binutils/objcopy.1 b/gnu/usr.bin/binutils/binutils/objcopy.1 new file mode 100644 index 00000000000..7694cf49a3f --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/objcopy.1 @@ -0,0 +1,254 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH objcopy 1 "October 1994" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +objcopy \- copy and translate object files + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B objcopy +.RB "[\|" \-F\ \fIbfdname\fR\ |\ \fB\-\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-I\ \fIbfdname\fR\ |\ \fB\-\-input\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-O\ \fIbfdname\fR\ |\ \fB\-\-output\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-R\ \fIsectionname\fR\ |\ \fB\-\-remove\-section=\fIsectionname\fR "\|]" +.RB "[\|" \-S\fR\ |\ \fB\-\-strip\-all\fR "\|]" +.RB "[\|" \-g\fR\ |\ \fB\-\-strip\-debug\fR "\|]" +.RB "[\|" \-\-strip\-unneeded\fR "\|]" +.RB "[\|" \-K\ \fIsymbolname\fR\ |\ \fB\-\-keep\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-N\ \fIsymbolname\fR\ |\ \fB\-\-strip\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-x\fR\ |\ \fB\-\-discard\-all\fR "\|]" +.RB "[\|" \-X\fR\ |\ \fB\-\-discard\-locals\fR "\|]" +.RB "[\|" \-b\ \fIbyte\fR\ |\ \fB\-\-byte=\fIbyte\fR "\|]" +.RB "[\|" \-i\ \fIinterleave\fR\ |\ \fB\-\-interleave=\fIinterleave\fR "\|]" +.RB "[\|" \-\-gap\-fill=\fIval\fR "\|]" +.RB "[\|" \-\-pad\-to=\fIaddress\fR "\|]" +.RB "[\|" \-\-set\-start=\fIval\fR "\|]" +.RB "[\|" \-\-adjust\-start=\fIincr\fR "\|]" +.RB "[\|" \-\-adjust\-vma=\fIincr\fR "\|]" +.RB "[\|" \-\-adjust\-section\-vma=\fIsection{=,+,-}val\fR "\|]" +.RB "[\|" \-\-adjust\-warnings\fR "\|]" +.RB "[\|" \-\-no\-adjust\-warnings\fR "\|]" +.RB "[\|" \-\-set\-section\-flags=\fIsection=flags\fR "\|]" +.RB "[\|" \-\-add\-section=\fIsectionname=filename\fR "\|]" +.RB "[\|" \-v\ |\ \-\-verbose\fR "\|]" +.RB "[\|" \-V\ |\ \-\-version\fR "\|]" +.RB "[\|" \-\-help\fR "\|]" +.B infile +.RB "[\|" outfile\fR "\|]" +.SH DESCRIPTION +The GNU +.B objcopy +utility copies the contents of an object file to another. +.B objcopy +uses the GNU BFD Library to read and write the object files. It can +write the destination object file in a format different from that of +the source object file. The exact behavior of +.B objcopy +is controlled by command-line options. +.PP +.B objcopy +creates temporary files to do its translations and deletes them +afterward. +.B objcopy +uses BFD to do all its translation work; it knows about all the +formats BFD knows about, and thus is able to recognize most formats +without being told explicitly. +.PP +.B objcopy +can be used to generate S-records by using an output target of +.B srec +(e.g., use +.B -O srec). +.PP +.B objcopy +can be used to generate a raw binary file by using an output target of +.B binary +(e.g., use +.B -O binary). +When +.B objcopy +generates a raw binary file, it will essentially produce a memory dump +of the contents of the input object file. All symbols and relocation +information will be discarded. The memory dump will start at the +virtual address of the lowest section copied into the output file. +.PP +When generating an S-record or a raw binary file, it may be helpful to +use +.B -S +to remove sections containing debugging information. In some cases +.B -R +will be useful to remove sections which contain information which is +not needed by the binary file. +.PP +.I infile +and +.I outfile +are the source and output files respectively. If you do not specify +.IR outfile , +.B objcopy +creates a temporary file and destructively renames the result with the +name of the input file. + +.SH OPTIONS +.TP +.B \-I \fIbfdname\fR, \fB\-\-input\-target=\fIbfdname +Consider the source file's object format to be +.IR bfdname , +rather than attempting to deduce it. +.TP +.B \-O \fIbfdname\fR, \fB\-\-output\-target=\fIbfdname +Write the output file using the object format +.IR bfdname . +.TP +.B \-F \fIbfdname\fR, \fB\-\-target=\fIbfdname +Use +.I bfdname +as the object format for both the input and the output file; i.e. +simply transfer data from source to destination with no translation. +.TP +.B \-R \fIsectionname\fR, \fB\-\-remove-section=\fIsectionname +Remove the named section from the file. This option may be given more +than once. Note that using this option inappropriately may make the +output file unusable. +.TP +.B \-S\fR, \fB\-\-strip\-all +Do not copy relocation and symbol information from the source file. +.TP +.B \-g\fR, \fB\-\-strip\-debug +Do not copy debugging symbols from the source file. +.TP +.B \-\-strip\-unneeded +Strip all symbols that are not needed for relocation processing. +.TP +.B \-K \fIsymbolname\fR, \fB\-\-keep\-symbol=\fIsymbolname +Copy only symbol \fIsymbolname\fP from the source file. This option +may be given more than once. +.TP +.B \-N \fIsymbolname\fR, \fB\-\-strip\-symbol=\fIsymbolname +Do not copy symbol \fIsymbolname\fP from the source file. This option +may be given more than once, and may be combined with strip options +other than \fB\-K\fR. +.TP +.B \-x\fR, \fB \-\-discard\-all +Do not copy non-global symbols from the source file. +.TP +.B \-X\fR, \fB\-\-discard\-locals +Do not copy compiler-generated local symbols. (These usually start +with "L" or "."). +.TP +.B \-b \fIbyte\fR, \fB\-\-byte=\fIbyte +Keep only every \fIbyte\fPth byte of the input file (header data is +not affected). \fIbyte\fP can be in the range from 0 to the +interleave-1. This option is useful for creating files to program +ROMs. It is typically used with an srec output target. +.TP +.B \-i \fIinterleave\fR, \fB\-\-interleave=\fIinterleave +Only copy one out of every \fIinterleave\fP bytes. Which one to copy is +selected by the \fB\-b\fP or \fB\-\-byte\fP option. The default is 4. +The interleave is ignored if neither \fB\-b\fP nor \fB\-\-byte\fP is given. +.TP +.B \-\-gap\-fill=\fIval +Fill gaps between sections with \fIval\fP. This is done by increasing +the size of the section with the lower address, and filling in the extra +space created with \fIval\fP. +.TP +.B \-\-pad\-to=\fIaddress +Pad the output file up to the virtual address \fIaddress\fP. This is +done by increasing the size of the last section. The extra space is +filled in with the value specified by \fB\-\-gap\-fill\fP (default +zero). +.TP +.B \fB\-\-set\-start=\fIval +Set the start address of the new file to \fIval\fP. Not all object +file formats support setting the start address. +.TP +.B \fB\-\-adjust\-start=\fIincr +Adjust the start address by adding \fIincr\fP. Not all object file +formats support setting the start address. +.TP +.B \fB\-\-adjust\-vma=\fIincr +Adjust the address of all sections, as well as the start address, by +adding \fIincr\fP. Some object file formats do not permit section +addresses to be changed arbitrarily. Note that this does not relocate +the sections; if the program expects sections to be loaded at a +certain address, and this option is used to change the sections such +that they are loaded at a different address, the program may fail. +.TP +.B \fB\-\-adjust\-section\-vma=\fIsection{=,+,-}val +Set or adjust the address of the named \fIsection\fP. If \fI=\fP is +used, the section address is set to \fIval\fP. Otherwise, \fIval\fP +is added to or subtracted from the section address. See the comments +under \fB\-\-adjust\-vma\fP, above. If \fIsection\fP does not exist +in the input file, a warning will be issued, unless +\fB\-\-no\-adjust\-warnings\fP is used. +.TP +.B \fB\-\-adjust\-warnings +If \fB\-\-adjust\-section\-vma\fP is used, and the named section does +not exist, issue a warning. This is the default. +.TP +.B \fB\-\-no\-adjust\-warnings +Do not issue a warning if \fB\-\-adjust\-section\-vma\fP is used, even +if the named section does not exist. +.TP +.B \fB\-\-set\-section\-flags=\fIsection=flags +Set the flags for the named section. The \fIflags\fP argument is a +comma separated string of flag names. The recognized names are +\fIalloc\fP, \fIload\fP, \fIreadonly\fP, \fIcode\fP, \fIdata\fP, and +\fIrom\fP. Not all flags are meaningful for all object file +formats. +.TP +.B \fB\-\-add\-section=\fIsectionname=filename +Add a new section named \fIsectionname\fR while copying the file. The +contents of the new section are taken from the file \fIfilename\fR. +The size of the section will be the size of the file. This option +only works on file formats which can support sections with arbitrary +names. +.TP +.B \-v\fR, \fB\-\-verbose +Verbose output: list all object files modified. In the case of +archives, "\fBobjcopy \-V\fR" lists all members of the archive. +.TP +.B \-V\fR, \fB\-\-version +Show the version number of +.B objcopy +and exit. +.TP +.B \-\-help +Show a summary of the options to +.B objcopy +and exit. +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (June 1993). + +.SH COPYING +Copyright (c) 1993,1994 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/gnu/usr.bin/binutils/binutils/objcopy.c b/gnu/usr.bin/binutils/binutils/objcopy.c new file mode 100644 index 00000000000..6d05cbd92d2 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/objcopy.c @@ -0,0 +1,1844 @@ +/* objcopy.c -- copy object file from input to output, optionally massaging it. + Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public 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 "progress.h" +#include "bucomm.h" +#include +#include "libiberty.h" +#include + +static flagword parse_flags PARAMS ((const char *)); +static struct section_list *find_section_list PARAMS ((const char *, boolean)); +static void setup_section PARAMS ((bfd *, asection *, PTR)); +static void copy_section PARAMS ((bfd *, asection *, PTR)); +static void get_sections PARAMS ((bfd *, asection *, PTR)); +static int compare_section_vma PARAMS ((const PTR, const PTR)); +static void add_strip_symbol PARAMS ((const char *)); +static boolean is_strip_symbol PARAMS ((const char *)); +static boolean is_strip_section PARAMS ((bfd *, asection *)); +static unsigned int filter_symbols + PARAMS ((bfd *, asymbol **, asymbol **, long)); +static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR)); + +#define nonfatal(s) {bfd_nonfatal(s); status = 1; return;} + +static asymbol **isympp = NULL; /* Input symbols */ +static asymbol **osympp = NULL; /* Output symbols that survive stripping */ + +/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */ +static int copy_byte = -1; +static int interleave = 4; + +static boolean verbose; /* Print file and target names. */ +static int status = 0; /* Exit status. */ + +enum strip_action + { + strip_undef, + strip_none, /* don't strip */ + strip_debug, /* strip all debugger symbols */ + strip_unneeded, /* strip unnecessary symbols */ + strip_all /* strip all symbols */ + }; + +/* Which symbols to remove. */ +static enum strip_action strip_symbols; + +enum locals_action + { + locals_undef, + locals_start_L, /* discard locals starting with L */ + locals_all /* discard all locals */ + }; + +/* Which local symbols to remove. Overrides strip_all. */ +static enum locals_action discard_locals; + +/* Structure used to hold lists of sections and actions to take. */ + +struct section_list +{ + /* Next section to adjust. */ + struct section_list *next; + /* Section name. */ + const char *name; + /* Whether this entry was used. */ + boolean used; + /* Whether to remove this section. */ + boolean remove; + /* Whether to adjust or set VMA. */ + enum { ignore_vma, adjust_vma, set_vma } adjust; + /* Amount to adjust by or set to. */ + bfd_vma val; + /* Whether to set the section flags. */ + boolean set_flags; + /* What to set the section flags to. */ + flagword flags; +}; + +static struct section_list *adjust_sections; +static boolean sections_removed; + +/* Adjustments to the start address. */ +static bfd_vma adjust_start = 0; +static boolean set_start_set = false; +static bfd_vma set_start; + +/* Adjustments to section VMA's. */ +static bfd_vma adjust_section_vma = 0; + +/* Filling gaps between sections. */ +static boolean gap_fill_set = false; +static bfd_byte gap_fill = 0; + +/* Pad to a given address. */ +static boolean pad_to_set = false; +static bfd_vma pad_to; + +/* List of sections to add. */ + +struct section_add +{ + /* Next section to add. */ + struct section_add *next; + /* Name of section to add. */ + const char *name; + /* Name of file holding section contents. */ + const char *filename; + /* Size of file. */ + size_t size; + /* Contents of file. */ + bfd_byte *contents; + /* BFD section, after it has been added. */ + asection *section; +}; + +static struct section_add *add_sections; + +/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ + +#define OPTION_ADD_SECTION 150 +#define OPTION_ADJUST_START (OPTION_ADD_SECTION + 1) +#define OPTION_ADJUST_VMA (OPTION_ADJUST_START + 1) +#define OPTION_ADJUST_SECTION_VMA (OPTION_ADJUST_VMA + 1) +#define OPTION_ADJUST_WARNINGS (OPTION_ADJUST_SECTION_VMA + 1) +#define OPTION_GAP_FILL (OPTION_ADJUST_WARNINGS + 1) +#define OPTION_NO_ADJUST_WARNINGS (OPTION_GAP_FILL + 1) +#define OPTION_PAD_TO (OPTION_NO_ADJUST_WARNINGS + 1) +#define OPTION_SET_SECTION_FLAGS (OPTION_PAD_TO + 1) +#define OPTION_SET_START (OPTION_SET_SECTION_FLAGS + 1) +#define OPTION_STRIP_UNNEEDED (OPTION_SET_START + 1) + +/* Options to handle if running as "strip". */ + +static struct option strip_options[] = +{ + {"discard-all", no_argument, 0, 'x'}, + {"discard-locals", no_argument, 0, 'X'}, + {"format", required_argument, 0, 'F'}, /* Obsolete */ + {"help", no_argument, 0, 'h'}, + {"input-format", required_argument, 0, 'I'}, /* Obsolete */ + {"input-target", required_argument, 0, 'I'}, + {"keep-symbol", required_argument, 0, 'K'}, + {"output-format", required_argument, 0, 'O'}, /* Obsolete */ + {"output-target", required_argument, 0, 'O'}, + {"remove-section", required_argument, 0, 'R'}, + {"strip-all", no_argument, 0, 's'}, + {"strip-debug", no_argument, 0, 'S'}, + {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED}, + {"strip-symbol", required_argument, 0, 'N'}, + {"target", required_argument, 0, 'F'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {0, no_argument, 0, 0} +}; + +/* Options to handle if running as "objcopy". */ + +static struct option copy_options[] = +{ + {"add-section", required_argument, 0, OPTION_ADD_SECTION}, + {"adjust-start", required_argument, 0, OPTION_ADJUST_START}, + {"adjust-vma", required_argument, 0, OPTION_ADJUST_VMA}, + {"adjust-section-vma", required_argument, 0, OPTION_ADJUST_SECTION_VMA}, + {"adjust-warnings", no_argument, 0, OPTION_ADJUST_WARNINGS}, + {"byte", required_argument, 0, 'b'}, + {"discard-all", no_argument, 0, 'x'}, + {"discard-locals", no_argument, 0, 'X'}, + {"format", required_argument, 0, 'F'}, /* Obsolete */ + {"gap-fill", required_argument, 0, OPTION_GAP_FILL}, + {"help", no_argument, 0, 'h'}, + {"input-format", required_argument, 0, 'I'}, /* Obsolete */ + {"input-target", required_argument, 0, 'I'}, + {"interleave", required_argument, 0, 'i'}, + {"keep-symbol", required_argument, 0, 'K'}, + {"no-adjust-warnings", no_argument, 0, OPTION_NO_ADJUST_WARNINGS}, + {"output-format", required_argument, 0, 'O'}, /* Obsolete */ + {"output-target", required_argument, 0, 'O'}, + {"pad-to", required_argument, 0, OPTION_PAD_TO}, + {"remove-section", required_argument, 0, 'R'}, + {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS}, + {"set-start", required_argument, 0, OPTION_SET_START}, + {"strip-all", no_argument, 0, 'S'}, + {"strip-debug", no_argument, 0, 'g'}, + {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED}, + {"strip-symbol", required_argument, 0, 'N'}, + {"target", required_argument, 0, 'F'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {0, no_argument, 0, 0} +}; + +/* IMPORTS */ +extern char *program_name; +extern char *program_version; + +/* This flag distinguishes between strip and objcopy: + 1 means this is 'strip'; 0 means this is 'objcopy'. + -1 means if we should use argv[0] to decide. */ +extern int is_strip; + + +static void +copy_usage (stream, exit_status) + FILE *stream; + int exit_status; +{ + fprintf (stream, "\ +Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\ + [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\ + [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ + [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\ + [--discard-locals] [--remove-section=section] [--gap-fill=val]\n", + program_name); + fprintf (stream, "\ + [--pad-to=address] [--set-start=val] [--adjust-start=incr]\n\ + [--adjust-vma=incr] [--adjust-section-vma=section{=,+,-}val]\n\ + [--adjust-warnings] [--no-adjust-warnings]\n\ + [--set-section-flags=section=flags] [--add-section=sectionname=filename]\n\ + [--keep-symbol symbol] [-K symbol] [--strip-symbol symbol] [-N symbol]\n\ + [--verbose] [--version] [--help]\n\ + in-file [out-file]\n"); + list_supported_targets (program_name, stream); + exit (exit_status); +} + +static void +strip_usage (stream, exit_status) + FILE *stream; + int exit_status; +{ + fprintf (stream, "\ +Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\ + [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ + [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\ + [--discard-locals] [--keep-symbol symbol] [-K symbol]\n\ + [--strip-symbol symbol] [-N symbol] [--remove-section=section]\n\ + [--verbose] [--version] [--help] file...\n", + program_name); + list_supported_targets (program_name, stream); + exit (exit_status); +} + +/* Parse section flags into a flagword, with a fatal error if the + string can't be parsed. */ + +static flagword +parse_flags (s) + const char *s; +{ + flagword ret; + const char *snext; + int len; + + ret = SEC_NO_FLAGS; + + do + { + snext = strchr (s, ','); + if (snext == NULL) + len = strlen (s); + else + { + len = snext - s; + ++snext; + } + +#define PARSE_FLAG(fname,fval) if (strncmp (fname, s, len) == 0) ret |= fval; + PARSE_FLAG ("alloc", SEC_ALLOC); + PARSE_FLAG ("load", SEC_LOAD); + PARSE_FLAG ("readonly", SEC_READONLY); + PARSE_FLAG ("code", SEC_CODE); + PARSE_FLAG ("data", SEC_DATA); + PARSE_FLAG ("rom", SEC_ROM); +#undef PARSE_FLAG + + s = snext; + } + while (s != NULL); + + return ret; +} + +/* Find and optionally add an entry in the adjust_sections list. */ + +static struct section_list * +find_section_list (name, add) + const char *name; + boolean add; +{ + register struct section_list *p; + + for (p = adjust_sections; p != NULL; p = p->next) + if (strcmp (p->name, name) == 0) + return p; + + if (! add) + return NULL; + + p = (struct section_list *) xmalloc (sizeof (struct section_list)); + p->name = name; + p->used = false; + p->remove = false; + p->adjust = ignore_vma; + p->val = 0; + p->set_flags = false; + p->flags = 0; + + p->next = adjust_sections; + adjust_sections = p; + + return p; +} + +/* Make a list of symbols to explicitly strip out, or to keep. A + linked list is good enough for a small number from the command + line, but this will slow things down a lot if many symbols are + being deleted. */ + +struct symlist +{ + const char *name; + struct symlist *next; +}; + +/* List of symbols to strip. */ + +static struct symlist *strip_specific_list = NULL; + +/* If this is false, we strip the symbols in strip_specific_list. + Otherwise, we keep only the symbols in the list. */ + +static boolean keep_symbols = false; + +/* Add a symbol to strip_specific_list. */ + +static void +add_strip_symbol (name) + const char *name; +{ + struct symlist *tmp_list; + + tmp_list = (struct symlist *) xmalloc (sizeof (struct symlist)); + tmp_list->name = name; + tmp_list->next = strip_specific_list; + strip_specific_list = tmp_list; +} + +/* See whether a symbol should be stripped or kept based on + strip_specific_list and keep_symbols. */ + +static boolean +is_strip_symbol (name) + const char *name; +{ + struct symlist *tmp_list; + + for (tmp_list = strip_specific_list; tmp_list; tmp_list = tmp_list->next) + { + if (strcmp (name, tmp_list->name) == 0) + return keep_symbols ? false : true; + } + return keep_symbols; +} + +/* See if a section is being removed. */ + +static boolean +is_strip_section (abfd, sec) + bfd *abfd; + asection *sec; +{ + struct section_list *p; + + if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0 + && (strip_symbols == strip_debug + || strip_symbols == strip_unneeded + || strip_symbols == strip_all + || discard_locals == locals_all)) + return true; + + if (! sections_removed) + return false; + p = find_section_list (bfd_get_section_name (abfd, sec), false); + return p != NULL && p->remove ? true : false; +} + +/* Choose which symbol entries to copy; put the result in OSYMS. + We don't copy in place, because that confuses the relocs. + Return the number of symbols to print. */ + +static unsigned int +filter_symbols (abfd, osyms, isyms, symcount) + bfd *abfd; + asymbol **osyms, **isyms; + long symcount; +{ + register asymbol **from = isyms, **to = osyms; + long src_count = 0, dst_count = 0; + + for (; src_count < symcount; src_count++) + { + asymbol *sym = from[src_count]; + flagword flags = sym->flags; + int keep; + + if ((flags & BSF_KEEP) != 0) /* Used in relocation. */ + keep = 1; + else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */ + || bfd_is_und_section (bfd_get_section (sym)) + || bfd_is_com_section (bfd_get_section (sym))) + keep = strip_symbols != strip_unneeded; + else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */ + keep = (strip_symbols != strip_debug + && strip_symbols != strip_unneeded); + else /* Local symbol. */ + keep = (strip_symbols != strip_unneeded + && (discard_locals != locals_all + && (discard_locals != locals_start_L + || ! bfd_is_local_label (abfd, sym)))); + + if (keep && is_strip_symbol (bfd_asymbol_name (sym))) + keep = 0; + if (keep && is_strip_section (abfd, bfd_get_section (sym))) + keep = 0; + + if (keep) + to[dst_count++] = sym; + } + + return dst_count; +} + +/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long. + Adjust *SIZE. */ + +void +filter_bytes (memhunk, size) + char *memhunk; + bfd_size_type *size; +{ + char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size; + + for (; from < end; from += interleave) + *to++ = *from; + *size /= interleave; +} + +/* Copy object file IBFD onto OBFD. */ + +static void +copy_object (ibfd, obfd) + bfd *ibfd; + bfd *obfd; +{ + bfd_vma start; + long symcount; + asection **osections = NULL; + bfd_size_type *gaps = NULL; + bfd_size_type max_gap = 0; + + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) + { + nonfatal (bfd_get_filename (obfd)); + } + + if (verbose) + printf ("copy from %s(%s) to %s(%s)\n", + bfd_get_filename(ibfd), bfd_get_target(ibfd), + bfd_get_filename(obfd), bfd_get_target(obfd)); + + if (set_start_set) + start = set_start; + else + start = bfd_get_start_address (ibfd); + start += adjust_start; + + if (!bfd_set_start_address (obfd, start) + || !bfd_set_file_flags (obfd, + (bfd_get_file_flags (ibfd) + & bfd_applicable_file_flags (obfd)))) + { + nonfatal (bfd_get_filename (ibfd)); + } + + /* Copy architecture of input file to output file */ + if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), + bfd_get_mach (ibfd))) + { + fprintf (stderr, "Output file cannot represent architecture %s\n", + bfd_printable_arch_mach (bfd_get_arch (ibfd), + bfd_get_mach (ibfd))); + } + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) + { + nonfatal (bfd_get_filename(ibfd)); + } + + if (isympp) + free (isympp); + if (osympp != isympp) + free (osympp); + + /* bfd mandates that all output sections be created and sizes set before + any output is done. Thus, we traverse all sections multiple times. */ + bfd_map_over_sections (ibfd, setup_section, (void *) obfd); + + if (add_sections != NULL) + { + struct section_add *padd; + struct section_list *pset; + + for (padd = add_sections; padd != NULL; padd = padd->next) + { + padd->section = bfd_make_section (obfd, padd->name); + if (padd->section == NULL) + { + fprintf (stderr, "%s: can't create section `%s': %s\n", + program_name, padd->name, + bfd_errmsg (bfd_get_error ())); + status = 1; + return; + } + else + { + flagword flags; + + if (! bfd_set_section_size (obfd, padd->section, padd->size)) + nonfatal (bfd_get_filename (obfd)); + + pset = find_section_list (padd->name, false); + if (pset != NULL) + pset->used = true; + + if (pset != NULL && pset->set_flags) + flags = pset->flags | SEC_HAS_CONTENTS; + else + flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA; + if (! bfd_set_section_flags (obfd, padd->section, flags)) + nonfatal (bfd_get_filename (obfd)); + + if (pset != NULL + && (pset->adjust == adjust_vma + || pset->adjust == set_vma)) + { + if (! bfd_set_section_vma (obfd, padd->section, pset->val)) + nonfatal (bfd_get_filename (obfd)); + } + } + } + } + + if (gap_fill_set || pad_to_set) + { + asection **set; + unsigned int c, i; + + /* We must fill in gaps between the sections and/or we must pad + the last section to a specified address. We do this by + grabbing a list of the sections, sorting them by VMA, and + increasing the section sizes as required to fill the gaps. + We write out the gap contents below. */ + + c = bfd_count_sections (obfd); + osections = (asection **) xmalloc (c * sizeof (asection *)); + set = osections; + bfd_map_over_sections (obfd, get_sections, (void *) &set); + + qsort (osections, c, sizeof (asection *), compare_section_vma); + + gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type)); + memset (gaps, 0, c * sizeof (bfd_size_type)); + + if (gap_fill_set) + { + for (i = 0; i < c - 1; i++) + { + flagword flags; + bfd_size_type size; + bfd_vma gap_start, gap_stop; + + flags = bfd_get_section_flags (obfd, osections[i]); + if ((flags & SEC_HAS_CONTENTS) == 0 + || (flags & SEC_LOAD) == 0) + continue; + + size = bfd_section_size (obfd, osections[i]); + gap_start = bfd_section_vma (obfd, osections[i]) + size; + gap_stop = bfd_section_vma (obfd, osections[i + 1]); + if (gap_start < gap_stop) + { + if (! bfd_set_section_size (obfd, osections[i], + size + (gap_stop - gap_start))) + { + fprintf (stderr, "%s: Can't fill gap after %s: %s\n", + program_name, + bfd_get_section_name (obfd, osections[i]), + bfd_errmsg (bfd_get_error())); + status = 1; + break; + } + gaps[i] = gap_stop - gap_start; + if (max_gap < gap_stop - gap_start) + max_gap = gap_stop - gap_start; + } + } + } + + if (pad_to_set) + { + bfd_vma vma; + bfd_size_type size; + + vma = bfd_section_vma (obfd, osections[c - 1]); + size = bfd_section_size (obfd, osections[c - 1]); + if (vma + size < pad_to) + { + if (! bfd_set_section_size (obfd, osections[c - 1], + pad_to - vma)) + { + fprintf (stderr, "%s: Can't add padding to %s: %s\n", + program_name, + bfd_get_section_name (obfd, osections[c - 1]), + bfd_errmsg (bfd_get_error ())); + status = 1; + } + else + { + gaps[c - 1] = pad_to - (vma + size); + if (max_gap < pad_to - (vma + size)) + max_gap = pad_to - (vma + size); + } + } + } + } + + /* Symbol filtering must happen after the output sections have + been created, but before their contents are set. */ + if (strip_symbols == strip_all) + { + osympp = isympp = NULL; + symcount = 0; + } + else + { + long symsize; + + symsize = bfd_get_symtab_upper_bound (ibfd); + if (symsize < 0) + { + nonfatal (bfd_get_filename (ibfd)); + } + + osympp = isympp = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (ibfd, isympp); + if (symcount < 0) + { + nonfatal (bfd_get_filename (ibfd)); + } + + if (strip_symbols == strip_debug + || strip_symbols == strip_unneeded + || discard_locals != locals_undef + || strip_specific_list != NULL + || sections_removed) + { + /* Mark symbols used in output relocations so that they + are kept, even if they are local labels or static symbols. + + Note we iterate over the input sections examining their + relocations since the relocations for the output sections + haven't been set yet. mark_symbols_used_in_relocations will + ignore input sections which have no corresponding output + section. */ + bfd_map_over_sections (ibfd, + mark_symbols_used_in_relocations, + (PTR)isympp); + osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *)); + symcount = filter_symbols (ibfd, osympp, isympp, symcount); + } + } + + bfd_set_symtab (obfd, osympp, symcount); + + /* This has to happen after the symbol table has been set. */ + bfd_map_over_sections (ibfd, copy_section, (void *) obfd); + + if (add_sections != NULL) + { + struct section_add *padd; + + for (padd = add_sections; padd != NULL; padd = padd->next) + { + if (! bfd_set_section_contents (obfd, padd->section, + (PTR) padd->contents, + (file_ptr) 0, + (bfd_size_type) padd->size)) + nonfatal (bfd_get_filename (obfd)); + } + } + + if (gap_fill_set || pad_to_set) + { + bfd_byte *buf; + int c, i; + + /* Fill in the gaps. */ + + if (max_gap > 8192) + max_gap = 8192; + buf = (bfd_byte *) xmalloc (max_gap); + memset (buf, gap_fill, (size_t) max_gap); + + c = bfd_count_sections (obfd); + for (i = 0; i < c; i++) + { + if (gaps[i] != 0) + { + bfd_size_type left; + file_ptr off; + + left = gaps[i]; + off = bfd_section_size (obfd, osections[i]) - left; + while (left > 0) + { + bfd_size_type now; + + if (left > 8192) + now = 8192; + else + now = left; + if (! bfd_set_section_contents (obfd, osections[i], buf, + off, now)) + { + nonfatal (bfd_get_filename (obfd)); + } + left -= now; + off += now; + } + } + } + } + + /* Allow the BFD backend to copy any private data it understands + from the input BFD to the output BFD. This is done last to + permit the routine to look at the filtered symbol table, which is + important for the ECOFF code at least. */ + if (!bfd_copy_private_bfd_data (ibfd, obfd)) + { + fprintf (stderr, "%s: %s: error copying private BFD data: %s\n", + program_name, bfd_get_filename (obfd), + bfd_errmsg (bfd_get_error ())); + status = 1; + return; + } +} + +static char * +cat (a, b, c) + char *a; + char *b; + char *c; +{ + size_t size = strlen (a) + strlen (b) + strlen (c); + char *r = xmalloc (size + 1); + + strcpy (r, a); + strcat (r, b); + strcat (r, c); + return r; +} + +/* Read each archive element in turn from IBFD, copy the + contents to temp file, and keep the temp file handle. */ + +static void +copy_archive (ibfd, obfd, output_target) + bfd *ibfd; + bfd *obfd; + char *output_target; +{ + struct name_list + { + struct name_list *next; + char *name; + bfd *obfd; + } *list, *l; + bfd **ptr = &obfd->archive_head; + bfd *this_element; + char *dir = make_tempname (bfd_get_filename (obfd)); + + /* Make a temp directory to hold the contents. */ + if (mkdir (dir, 0700) != 0) + { + fatal ("cannot mkdir %s for archive copying (error: %s)", + dir, strerror (errno)); + } + obfd->has_armap = ibfd->has_armap; + + list = NULL; + + this_element = bfd_openr_next_archived_file (ibfd, NULL); + while (this_element != (bfd *) NULL) + { + /* Create an output file for this member. */ + char *output_name = cat (dir, "/", bfd_get_filename(this_element)); + bfd *output_bfd = bfd_openw (output_name, output_target); + bfd *last_element; + + l = (struct name_list *) xmalloc (sizeof (struct name_list)); + l->name = output_name; + l->next = list; + list = l; + + if (output_bfd == (bfd *) NULL) + { + nonfatal (output_name); + } + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) + { + nonfatal (bfd_get_filename (obfd)); + } + + if (bfd_check_format (this_element, bfd_object) == true) + { + copy_object (this_element, output_bfd); + } + + bfd_close (output_bfd); + + /* Open the newly output file and attach to our list. */ + output_bfd = bfd_openr (output_name, output_target); + + l->obfd = output_bfd; + + *ptr = output_bfd; + ptr = &output_bfd->next; + + last_element = this_element; + + this_element = bfd_openr_next_archived_file (ibfd, last_element); + + bfd_close (last_element); + } + *ptr = (bfd *) NULL; + + if (!bfd_close (obfd)) + { + nonfatal (bfd_get_filename (obfd)); + } + + if (!bfd_close (ibfd)) + { + nonfatal (bfd_get_filename (ibfd)); + } + + /* Delete all the files that we opened. */ + for (l = list; l != NULL; l = l->next) + { + bfd_close (l->obfd); + unlink (l->name); + } + rmdir (dir); +} + +/* The top-level control. */ + +static void +copy_file (input_filename, output_filename, input_target, output_target) + char *input_filename; + char *output_filename; + char *input_target; + char *output_target; +{ + bfd *ibfd; + char **matching; + + /* To allow us to do "strip *" without dying on the first + non-object file, failures are nonfatal. */ + + ibfd = bfd_openr (input_filename, input_target); + if (ibfd == NULL) + { + nonfatal (input_filename); + } + + if (bfd_check_format (ibfd, bfd_archive)) + { + bfd *obfd; + + /* bfd_get_target does not return the correct value until + bfd_check_format succeeds. */ + if (output_target == NULL) + output_target = bfd_get_target (ibfd); + + obfd = bfd_openw (output_filename, output_target); + if (obfd == NULL) + { + nonfatal (output_filename); + } + copy_archive (ibfd, obfd, output_target); + } + else if (bfd_check_format_matches (ibfd, bfd_object, &matching)) + { + bfd *obfd; + + /* bfd_get_target does not return the correct value until + bfd_check_format succeeds. */ + if (output_target == NULL) + output_target = bfd_get_target (ibfd); + + obfd = bfd_openw (output_filename, output_target); + if (obfd == NULL) + { + nonfatal (output_filename); + } + + copy_object (ibfd, obfd); + + if (!bfd_close (obfd)) + { + nonfatal (output_filename); + } + + if (!bfd_close (ibfd)) + { + nonfatal (input_filename); + } + } + else + { + bfd_nonfatal (input_filename); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + status = 1; + } +} + +/* Create a section in OBFD with the same name and attributes + as ISECTION in IBFD. */ + +static void +setup_section (ibfd, isection, obfdarg) + bfd *ibfd; + sec_ptr isection; + PTR obfdarg; +{ + bfd *obfd = (bfd *) obfdarg; + struct section_list *p; + sec_ptr osection; + bfd_vma vma; + bfd_vma lma; + flagword flags; + char *err; + + if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0 + && (strip_symbols == strip_debug + || strip_symbols == strip_unneeded + || strip_symbols == strip_all + || discard_locals == locals_all)) + return; + + p = find_section_list (bfd_section_name (ibfd, isection), false); + if (p != NULL) + p->used = true; + + if (p != NULL && p->remove) + return; + + osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection)); + if (osection == NULL) + { + err = "making"; + goto loser; + } + + if (!bfd_set_section_size (obfd, + osection, + bfd_section_size (ibfd, isection))) + { + err = "size"; + goto loser; + } + + vma = bfd_section_vma (ibfd, isection); + if (p != NULL && p->adjust == adjust_vma) + vma += p->val; + else if (p != NULL && p->adjust == set_vma) + vma = p->val; + else + vma += adjust_section_vma; + if (! bfd_set_section_vma (obfd, osection, vma)) + { + err = "vma"; + goto loser; + } + + lma = isection->lma; + if (p != NULL && p->adjust == adjust_vma) + lma += p->val; + else if (p != NULL && p->adjust == set_vma) + lma = p->val; + else + lma += adjust_section_vma; + osection->lma = lma; + + if (bfd_set_section_alignment (obfd, + osection, + bfd_section_alignment (ibfd, isection)) + == false) + { + err = "alignment"; + goto loser; + } + + flags = bfd_get_section_flags (ibfd, isection); + if (p != NULL && p->set_flags) + flags = p->flags | (flags & SEC_HAS_CONTENTS); + if (!bfd_set_section_flags (obfd, osection, flags)) + { + err = "flags"; + goto loser; + } + + /* This used to be mangle_section; we do here to avoid using + bfd_get_section_by_name since some formats allow multiple + sections with the same name. */ + isection->output_section = osection; + isection->output_offset = 0; + + /* Allow the BFD backend to copy any private data it understands + from the input section to the output section. */ + if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection)) + { + err = "private data"; + goto loser; + } + + /* All went well */ + return; + +loser: + fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n", + program_name, + bfd_get_filename (ibfd), bfd_section_name (ibfd, isection), + err, bfd_errmsg (bfd_get_error ())); + status = 1; +} + +/* Copy the data of input section ISECTION of IBFD + to an output section with the same name in OBFD. + If stripping then don't copy any relocation info. */ + +static void +copy_section (ibfd, isection, obfdarg) + bfd *ibfd; + sec_ptr isection; + PTR obfdarg; +{ + bfd *obfd = (bfd *) obfdarg; + struct section_list *p; + arelent **relpp; + long relcount; + sec_ptr osection; + bfd_size_type size; + + if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0 + && (strip_symbols == strip_debug + || strip_symbols == strip_unneeded + || strip_symbols == strip_all + || discard_locals == locals_all)) + { + return; + } + + p = find_section_list (bfd_section_name (ibfd, isection), false); + + if (p != NULL && p->remove) + return; + + osection = isection->output_section; + size = bfd_get_section_size_before_reloc (isection); + + if (size == 0 || osection == 0) + return; + + if (strip_symbols == strip_all) + bfd_set_reloc (obfd, osection, (arelent **) NULL, 0); + else + { + long relsize; + + relsize = bfd_get_reloc_upper_bound (ibfd, isection); + if (relsize < 0) + { + nonfatal (bfd_get_filename (ibfd)); + } + if (relsize == 0) + bfd_set_reloc (obfd, osection, (arelent **) NULL, 0); + else + { + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp); + if (relcount < 0) + { + nonfatal (bfd_get_filename (ibfd)); + } + bfd_set_reloc (obfd, osection, relpp, relcount); + } + } + + isection->_cooked_size = isection->_raw_size; + isection->reloc_done = true; + + if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS) + { + PTR memhunk = (PTR) xmalloc ((unsigned) size); + + if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0, + size)) + { + nonfatal (bfd_get_filename (ibfd)); + } + + if (copy_byte >= 0) + { + filter_bytes (memhunk, &size); + /* The section has gotten smaller. */ + if (!bfd_set_section_size (obfd, osection, size)) + nonfatal (bfd_get_filename (obfd)); + } + + if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0, + size)) + { + nonfatal (bfd_get_filename (obfd)); + } + free (memhunk); + } +} + +/* Get all the sections. This is used when --gap-fill or --pad-to is + used. */ + +static void +get_sections (obfd, osection, secppparg) + bfd *obfd; + asection *osection; + PTR secppparg; +{ + asection ***secppp = (asection ***) secppparg; + + **secppp = osection; + ++(*secppp); +} + +/* Sort sections by VMA. This is called via qsort, and is used when + --gap-fill or --pad-to is used. We force non loadable or empty + sections to the front, where they are easier to ignore. */ + +static int +compare_section_vma (arg1, arg2) + const PTR arg1; + const PTR arg2; +{ + const asection **sec1 = (const asection **) arg1; + const asection **sec2 = (const asection **) arg2; + flagword flags1, flags2; + + /* Sort non loadable sections to the front. */ + flags1 = (*sec1)->flags; + flags2 = (*sec2)->flags; + if ((flags1 & SEC_HAS_CONTENTS) == 0 + || (flags1 & SEC_LOAD) == 0) + { + if ((flags2 & SEC_HAS_CONTENTS) != 0 + && (flags2 & SEC_LOAD) != 0) + return -1; + } + else + { + if ((flags2 & SEC_HAS_CONTENTS) == 0 + || (flags2 & SEC_LOAD) == 0) + return 1; + } + + /* Sort sections by VMA. */ + if ((*sec1)->vma > (*sec2)->vma) + return 1; + else if ((*sec1)->vma < (*sec2)->vma) + return -1; + + /* Sort sections with the same VMA by size. */ + if ((*sec1)->_raw_size > (*sec2)->_raw_size) + return 1; + else if ((*sec1)->_raw_size < (*sec2)->_raw_size) + return -1; + + return 0; +} + +/* Mark all the symbols which will be used in output relocations with + the BSF_KEEP flag so that those symbols will not be stripped. + + Ignore relocations which will not appear in the output file. */ + +static void +mark_symbols_used_in_relocations (ibfd, isection, symbolsarg) + bfd *ibfd; + sec_ptr isection; + PTR symbolsarg; +{ + asymbol **symbols = (asymbol **) symbolsarg; + long relsize; + arelent **relpp; + long relcount, i; + + /* Ignore an input section with no corresponding output section. */ + if (isection->output_section == NULL) + return; + + relsize = bfd_get_reloc_upper_bound (ibfd, isection); + if (relsize < 0) + bfd_fatal (bfd_get_filename (ibfd)); + + if (relsize == 0) + return; + + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols); + if (relcount < 0) + bfd_fatal (bfd_get_filename (ibfd)); + + /* Examine each symbol used in a relocation. If it's not one of the + special bfd section symbols, then mark it with BSF_KEEP. */ + for (i = 0; i < relcount; i++) + { + if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol + && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol + && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol) + (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP; + } + + if (relpp != NULL) + free (relpp); +} + +/* The number of bytes to copy at once. */ +#define COPY_BUF 8192 + +/* Copy file FROM to file TO, performing no translations. + Return 0 if ok, -1 if error. */ + +static int +simple_copy (from, to) + char *from, *to; +{ + int fromfd, tofd, nread; + int saved; + char buf[COPY_BUF]; + + fromfd = open (from, O_RDONLY); + if (fromfd < 0) + return -1; + tofd = creat (to, 0777); + if (tofd < 0) + { + saved = errno; + close (fromfd); + errno = saved; + return -1; + } + while ((nread = read (fromfd, buf, sizeof buf)) > 0) + { + if (write (tofd, buf, nread) != nread) + { + saved = errno; + close (fromfd); + close (tofd); + errno = saved; + return -1; + } + } + saved = errno; + close (fromfd); + close (tofd); + if (nread < 0) + { + errno = saved; + return -1; + } + return 0; +} + +#ifndef S_ISLNK +#ifdef S_IFLNK +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#else +#define S_ISLNK(m) 0 +#define lstat stat +#endif +#endif + +/* Rename FROM to TO, copying if TO is a link. + Assumes that TO already exists, because FROM is a temp file. + Return 0 if ok, -1 if error. */ + +static int +smart_rename (from, to) + char *from, *to; +{ + struct stat s; + int ret = 0; + + if (lstat (to, &s)) + return -1; + + /* Use rename only if TO is not a symbolic link and has + only one hard link. */ + if (!S_ISLNK (s.st_mode) && s.st_nlink == 1) + { + ret = rename (from, to); + if (ret == 0) + { + /* Try to preserve the permission bits and ownership of TO. */ + chmod (to, s.st_mode & 07777); + chown (to, s.st_uid, s.st_gid); + } + else + { + /* We have to clean up here. */ + int saved = errno; + fprintf (stderr, "%s: %s: ", program_name, to); + errno = saved; + perror ("rename"); + unlink (from); + } + } + else + { + ret = simple_copy (from, to); + if (ret != 0) + { + int saved = errno; + fprintf (stderr, "%s: %s: ", program_name, to); + errno = saved; + perror ("simple_copy"); + } + unlink (from); + } + return ret; +} + +static int +strip_main (argc, argv) + int argc; + char *argv[]; +{ + char *input_target = NULL, *output_target = NULL; + boolean show_version = false; + int c, i; + struct section_list *p; + + while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:sSgxXVv", + strip_options, (int *) 0)) != EOF) + { + switch (c) + { + case 'I': + input_target = optarg; + break; + case 'O': + output_target = optarg; + break; + case 'F': + input_target = output_target = optarg; + break; + case 'R': + p = find_section_list (optarg, true); + p->remove = true; + sections_removed = true; + break; + case 's': + strip_symbols = strip_all; + break; + case 'S': + case 'g': + strip_symbols = strip_debug; + break; + case OPTION_STRIP_UNNEEDED: + strip_symbols = strip_unneeded; + break; + case 'K': + if (! keep_symbols && strip_specific_list != NULL) + { + fprintf (stderr, "%s: Can not specify both -K and -N\n", + program_name); + strip_usage (stderr, 1); + } + keep_symbols = true; + add_strip_symbol (optarg); + break; + case 'N': + if (keep_symbols) + { + fprintf (stderr, "%s: Can not specify both -K and -N\n", + program_name); + strip_usage (stderr, 1); + } + add_strip_symbol (optarg); + break; + case 'x': + discard_locals = locals_all; + break; + case 'X': + discard_locals = locals_start_L; + break; + case 'v': + verbose = true; + break; + case 'V': + show_version = true; + break; + case 0: + break; /* we've been given a long option */ + case 'h': + strip_usage (stdout, 0); + default: + strip_usage (stderr, 1); + } + } + + if (show_version) + { + printf ("GNU %s version %s\n", program_name, program_version); + exit (0); + } + + /* Default is to strip all symbols. */ + if (strip_symbols == strip_undef + && discard_locals == locals_undef + && strip_specific_list == NULL) + strip_symbols = strip_all; + + if (output_target == (char *) NULL) + output_target = input_target; + + i = optind; + if (i == argc) + strip_usage (stderr, 1); + + for (; i < argc; i++) + { + int hold_status = status; + + char *tmpname = make_tempname (argv[i]); + status = 0; + copy_file (argv[i], tmpname, input_target, output_target); + if (status == 0) + { + smart_rename (tmpname, argv[i]); + status = hold_status; + } + else + unlink (tmpname); + free (tmpname); + } + + return 0; +} + +static int +copy_main (argc, argv) + int argc; + char *argv[]; +{ + char *input_filename = NULL, *output_filename = NULL; + char *input_target = NULL, *output_target = NULL; + boolean show_version = false; + boolean adjust_warn = true; + int c; + struct section_list *p; + + while ((c = getopt_long (argc, argv, "b:i:I:K:N:s:O:d:F:R:SgxXVv", + copy_options, (int *) 0)) != EOF) + { + switch (c) + { + case 'b': + copy_byte = atoi(optarg); + if (copy_byte < 0) + { + fprintf (stderr, "%s: byte number must be non-negative\n", + program_name); + exit (1); + } + break; + case 'i': + interleave = atoi(optarg); + if (interleave < 1) + { + fprintf(stderr, "%s: interleave must be positive\n", + program_name); + exit (1); + } + break; + case 'I': + case 's': /* "source" - 'I' is preferred */ + input_target = optarg; + break; + case 'O': + case 'd': /* "destination" - 'O' is preferred */ + output_target = optarg; + break; + case 'F': + input_target = output_target = optarg; + break; + case 'R': + p = find_section_list (optarg, true); + p->remove = true; + sections_removed = true; + break; + case 'S': + strip_symbols = strip_all; + break; + case 'g': + strip_symbols = strip_debug; + break; + case OPTION_STRIP_UNNEEDED: + strip_symbols = strip_unneeded; + break; + case 'K': + if (! keep_symbols && strip_specific_list != NULL) + { + fprintf (stderr, "%s: Can not specify both -K and -N\n", + program_name); + strip_usage (stderr, 1); + } + keep_symbols = true; + add_strip_symbol (optarg); + break; + case 'N': + if (keep_symbols) + { + fprintf (stderr, "%s: Can not specify both -K and -N\n", + program_name); + strip_usage (stderr, 1); + } + add_strip_symbol (optarg); + break; + case 'x': + discard_locals = locals_all; + break; + case 'X': + discard_locals = locals_start_L; + break; + case 'v': + verbose = true; + break; + case 'V': + show_version = true; + break; + case OPTION_ADD_SECTION: + { + const char *s; + struct stat st; + struct section_add *pa; + int len; + char *name; + FILE *f; + + s = strchr (optarg, '='); + if (s == NULL) + { + fprintf (stderr, + "%s: bad format for --add-section NAME=FILENAME\n", + program_name); + exit (1); + } + + if (stat (s + 1, &st) < 0) + { + fprintf (stderr, "%s: ", program_name); + perror (s + 1); + exit (1); + } + + pa = (struct section_add *) xmalloc (sizeof (struct section_add)); + + len = s - optarg; + name = (char *) xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + pa->name = name; + + pa->filename = s + 1; + + pa->size = st.st_size; + + pa->contents = (bfd_byte *) xmalloc (pa->size); + f = fopen (pa->filename, FOPEN_RB); + if (f == NULL) + { + fprintf (stderr, "%s: ", program_name); + perror (pa->filename); + exit (1); + } + if (fread (pa->contents, 1, pa->size, f) == 0 + || ferror (f)) + { + fprintf (stderr, "%s: %s: fread failed\n", + program_name, pa->filename); + exit (1); + } + fclose (f); + + pa->next = add_sections; + add_sections = pa; + } + break; + case OPTION_ADJUST_START: + adjust_start = parse_vma (optarg, "--adjust-start"); + break; + case OPTION_ADJUST_SECTION_VMA: + { + const char *s; + int len; + char *name; + + s = strchr (optarg, '='); + if (s == NULL) + { + s = strchr (optarg, '+'); + if (s == NULL) + { + s = strchr (optarg, '-'); + if (s == NULL) + { + fprintf (stderr, + "%s: bad format for --adjust-section-vma\n", + program_name); + exit (1); + } + } + } + + len = s - optarg; + name = (char *) xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + + p = find_section_list (name, true); + + p->val = parse_vma (s + 1, "--adjust-section-vma"); + + if (*s == '=') + p->adjust = set_vma; + else + { + p->adjust = adjust_vma; + if (*s == '-') + p->val = - p->val; + } + } + break; + case OPTION_ADJUST_VMA: + adjust_section_vma = parse_vma (optarg, "--adjust-vma"); + adjust_start = adjust_section_vma; + break; + case OPTION_ADJUST_WARNINGS: + adjust_warn = true; + break; + case OPTION_GAP_FILL: + { + bfd_vma gap_fill_vma; + + gap_fill_vma = parse_vma (optarg, "--gap-fill"); + gap_fill = (bfd_byte) gap_fill_vma; + if ((bfd_vma) gap_fill != gap_fill_vma) + { + fprintf (stderr, "%s: warning: truncating gap-fill from 0x", + program_name); + fprintf_vma (stderr, gap_fill_vma); + fprintf (stderr, "to 0x%x\n", (unsigned int) gap_fill); + } + gap_fill_set = true; + } + break; + case OPTION_NO_ADJUST_WARNINGS: + adjust_warn = false; + break; + case OPTION_PAD_TO: + pad_to = parse_vma (optarg, "--pad-to"); + pad_to_set = true; + break; + case OPTION_SET_SECTION_FLAGS: + { + const char *s; + int len; + char *name; + + s = strchr (optarg, '='); + if (s == NULL) + { + fprintf (stderr, "%s: bad format for --set-section-flags\n", + program_name); + exit (1); + } + + len = s - optarg; + name = (char *) xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + + p = find_section_list (name, true); + + p->set_flags = true; + p->flags = parse_flags (s + 1); + } + break; + case OPTION_SET_START: + set_start = parse_vma (optarg, "--set-start"); + set_start_set = true; + break; + case 0: + break; /* we've been given a long option */ + case 'h': + copy_usage (stdout, 0); + default: + copy_usage (stderr, 1); + } + } + + if (show_version) + { + printf ("GNU %s version %s\n", program_name, program_version); + exit (0); + } + + if (copy_byte >= interleave) + { + fprintf (stderr, "%s: byte number must be less than interleave\n", + program_name); + exit (1); + } + + if (optind == argc || optind + 2 < argc) + copy_usage (stderr, 1); + + input_filename = argv[optind]; + if (optind + 1 < argc) + output_filename = argv[optind + 1]; + + /* Default is to strip no symbols. */ + if (strip_symbols == strip_undef && discard_locals == locals_undef) + strip_symbols = strip_none; + + if (output_target == (char *) NULL) + output_target = input_target; + + /* If there is no destination file then create a temp and rename + the result into the input. */ + + if (output_filename == (char *) NULL) + { + char *tmpname = make_tempname (input_filename); + copy_file (input_filename, tmpname, input_target, output_target); + if (status == 0) + smart_rename (tmpname, input_filename); + else + unlink (tmpname); + } + else + { + copy_file (input_filename, output_filename, input_target, output_target); + } + + if (adjust_warn) + { + for (p = adjust_sections; p != NULL; p = p->next) + { + if (! p->used && p->adjust != ignore_vma) + { + fprintf (stderr, "%s: warning: --adjust-section-vma %s%c0x", + program_name, p->name, + p->adjust == set_vma ? '=' : '+'); + fprintf_vma (stderr, p->val); + fprintf (stderr, " never used\n"); + } + } + } + + return 0; +} + +int +main (argc, argv) + int argc; + char *argv[]; +{ + program_name = argv[0]; + xmalloc_set_program_name (program_name); + + START_PROGRESS (program_name, 0); + + strip_symbols = strip_undef; + discard_locals = locals_undef; + + bfd_init (); + + if (is_strip < 0) + { + int i = strlen (program_name); + is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip") == 0); + } + + if (is_strip) + strip_main (argc, argv); + else + copy_main (argc, argv); + + END_PROGRESS (program_name); + + return status; +} diff --git a/gnu/usr.bin/binutils/binutils/objdump.1 b/gnu/usr.bin/binutils/binutils/objdump.1 new file mode 100644 index 00000000000..1f39a35842d --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/objdump.1 @@ -0,0 +1,338 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH objdump 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +objdump \- display information from object files. + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B objdump +.RB "[\|" \-a | \-\-archive\-headers "\|]" +.RB "[\|" "\-b\ "\c +.I bfdname\c +.RB " | " "\-\-target="\c +.I bfdname\c +\&\|] +.RB "[\|" \-d | \-\-disassemble "\|]" +.RB "[\|" \-D | \-\-disassemble-all "\|]" +.RB "[\|" \-f | \-\-file\-headers "\|]" +.RB "[\|" \-h | \-\-section\-headers +.RB "| " \-\-headers "\|]" +.RB "[\|" \-i | \-\-info "\|]" +.RB "[\|" "\-j\ "\c +.I section\c +.RB " | " "\-\-section="\c +.I section\c +\&\|] +.RB "[\|" \-l | \-\-line\-numbers "\|]" +.RB "[\|" "\-m\ "\c +.I machine\c +.RB " | " "\-\-architecture="\c +.I machine\c +\&\|] +.RB "[\|" \-r | \-\-reloc "\|]" +.RB "[\|" \-R | \-\-dynamic\-reloc "\|]" +.RB "[\|" \-s | \-\-full\-contents "\|]" +.RB "[\|" \-S | \-\-source "\|]" +.RB "[\|" \-\-stabs "\|]" +.RB "[\|" \-t | \-\-syms "\|]" +.RB "[\|" \-T | \-\-dynamic\-syms "\|]" +.RB "[\|" \-x | \-\-all\-headers "\|]" +.RB "[\|" "\-\-start\-address="\c +.I address\c +\&\|] +.RB "[\|" "\-\-stop\-address="\c +.I address\c +\&\|] +.RB "[\|" \-\-version "\|]" +.RB "[\|" \-\-help "\|]" +.I objfile\c +\&.\|.\|. +.ad b +.hy 1 +.SH DESCRIPTION +\c +.B objdump\c +\& displays information about one or more object files. +The options control what particular information to display. This +information is mostly useful to programmers who are working on the +compilation tools, as opposed to programmers who just want their +program to compile and work. +.PP +.IR "objfile" .\|.\|. +are the object files to be examined. When you specify archives, +\c +.B objdump\c +\& shows information on each of the member object files. + +.SH OPTIONS +Where long and short forms of an option are shown together, they are +equivalent. At least one option besides +.B \-l +(\fB\-\-line\-numbers\fP) must be given. + +.TP +.B \-a +.TP +.B \-\-archive\-headers +If any files from \c +.I objfile\c +\& are archives, display the archive +header information (in a format similar to `\|\c +.B ls \-l\c +\|'). Besides the +information you could list with `\|\c +.B ar tv\c +\|', `\|\c +.B objdump \-a\c +\|' shows +the object file format of each archive member. + +.TP +.BI "\-b " "bfdname"\c +.TP +.BI "\-\-target=" "bfdname" +Specify the object-code format for the object files to be +\c +.I bfdname\c +\&. This may not be necessary; \c +.I objdump\c +\& can +automatically recognize many formats. For example, +.sp +.br +objdump\ \-b\ oasys\ \-m\ vax\ \-h\ fu.o +.br +.sp +display summary information from the section headers (`\|\c +.B \-h\c +\|') of +`\|\c +.B fu.o\c +\|', which is explicitly identified (`\|\c +.B \-m\c +\|') as a Vax object +file in the format produced by Oasys compilers. You can list the +formats available with the `\|\c +.B \-i\c +\|' option. + +.TP +.B \-d +.TP +.B \-\-disassemble +Display the assembler mnemonics for the machine +instructions from \c +.I objfile\c +\&. +This option only disassembles those sections which are +expected to contain instructions. + +.TP +.B \-D +.TP +.B \-\-disassemble-all +Like \fB\-d\fP, but disassemble the contents of all sections, not just +those expected to contain instructions. + +.TP +.B \-f +.TP +.B \-\-file\-headers +Display summary information from the overall header of +each file in \c +.I objfile\c +\&. + +.TP +.B \-h +.TP +.B \-\-section\-headers +.TP +.B \-\-headers +Display summary information from the section headers of the +object file. + +.TP +.B \-\-help +Print a summary of the options to +.B objdump +and exit. + +.TP +.B \-i +.TP +.B \-\-info +Display a list showing all architectures and object formats available +for specification with \c +.B \-b\c +\& or \c +.B \-m\c +\&. + +.TP +.BI "\-j " "name"\c +.TP +.BI "\-\-section=" "name" +Display information only for section \c +.I name\c +\&. + +.TP +.B \-l +.TP +.B \-\-line\-numbers +Label the display (using debugging information) with the filename +and source line numbers corresponding to the object code shown. +Only useful with \fB\-d\fP or \fB\-D\fP. + +.TP +.BI "\-m " "machine"\c +.TP +.BI "\-\-architecture=" "machine" +Specify the object files \c +.I objfile\c +\& are for architecture +\c +.I machine\c +\&. You can list available architectures using the `\|\c +.B \-i\c +\|' +option. + +.TP +.B \-r +.TP +.B \-\-reloc +Print the relocation entries of the file. If used with \fB\-d\fP or +\fB\-d\fP, the relocations are printed interspersed with the +disassembly. + +.TP +.B \-R +.TP +.B \-\-dynamic\-reloc +Print the dynamic relocation entries of the file. This is only +meaningful for dynamic objects, such as certain types of shared +libraries. + +.TP +.B \-s +.TP +.B \-\-full\-contents +Display the full contents of any sections requested. + +.TP +.B \-S +.TP +.B \-\-source +Display source code intermixed with disassembly, if possible. Implies +\fB-d\fP. + +.TP +.B \-\-stabs +Display the contents of the .stab, .stab.index, and .stab.excl +sections from an ELF file. This is only useful on systems (such as +Solaris 2.0) in which .stab debugging symbol-table entries are carried +in an ELF section. In most other file formats, debugging symbol-table +entries are interleaved with linkage symbols, and are visible in the +\-\-syms output. + +.TP +.BI "\-\-start\-address=" "address" +Start displaying data at the specified address. This affects the output +of the +.B \-d\c +, +.B \-r +and +.B \-s +options. + +.TP +.BI "\-\-stop\-address=" "address" +Stop displaying data at the specified address. This affects the output +of the +.B \-d\c +, +.B \-r +and +.B \-s +options. + +.TP +.B \-t +.TP +.B \-\-syms +Symbol Table. Print the symbol table entries of the file. +This is similar to the information provided by the `\|\c +.B nm\c +\|' program. + +.TP +.B \-T +.TP +.B \-\-dynamic\-syms +Dynamic Symbol Table. Print the dynamic symbol table entries of the +file. This is only meaningful for dynamic objects, such as certain +types of shared libraries. This is similar to the information +provided by the `\|\c +.B nm\c +\|' program when given the +.B \-D (\-\-dynamic) +option. + +.TP +.B \-\-version +Print the version number of +.B objdump +and exit. + +.TP +.B \-x +.TP +.B \-\-all\-headers +Display all available header information, including the symbol table and +relocation entries. Using `\|\c +.B \-x\c +\|' is equivalent to specifying all of +`\|\c +.B \-a \-f \-h \-r \-t\c +\|'. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (October 1991); +.BR nm "(" 1 ")." + +.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/gnu/usr.bin/binutils/binutils/objdump.c b/gnu/usr.bin/binutils/binutils/objdump.c new file mode 100644 index 00000000000..13ee1d4321c --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/objdump.c @@ -0,0 +1,1960 @@ +/* objdump.c -- dump information about an object file. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "bfd.h" +#include "getopt.h" +#include "progress.h" +#include "bucomm.h" +#include +#include "dis-asm.h" +#include "libiberty.h" + +/* Internal headers for the ELF .stab-dump code - sorry. */ +#define BYTES_IN_WORD 32 +#include "aout/aout64.h" + +#ifdef NEED_DECLARATION_FPRINTF +/* This is needed by INIT_DISASSEMBLE_INFO. */ +extern int fprintf (); +#endif + +char *default_target = NULL; /* default at runtime */ + +extern char *program_version; + +int show_version = 0; /* show the version number */ +int dump_section_contents; /* -s */ +int dump_section_headers; /* -h */ +boolean dump_file_header; /* -f */ +int dump_symtab; /* -t */ +int dump_dynamic_symtab; /* -T */ +int dump_reloc_info; /* -r */ +int dump_dynamic_reloc_info; /* -R */ +int dump_ar_hdrs; /* -a */ +int dump_private_headers; /* -p */ +int with_line_numbers; /* -l */ +boolean with_source_code; /* -S */ +int dump_stab_section_info; /* --stabs */ +boolean disassemble; /* -d */ +boolean disassemble_all; /* -D */ +boolean formats_info; /* -i */ +char *only; /* -j secname */ +int wide_output; /* -w */ +bfd_vma start_address = (bfd_vma) -1; /* --start-address */ +bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */ + +/* Extra info to pass to the disassembler address printing function. */ +struct objdump_disasm_info { + bfd *abfd; + asection *sec; + boolean require_sec; +}; + +/* Architecture to disassemble for, or default if NULL. */ +char *machine = (char *) NULL; + +/* The symbol table. */ +asymbol **syms; + +/* Number of symbols in `syms'. */ +long symcount = 0; + +/* The sorted symbol table. */ +asymbol **sorted_syms; + +/* Number of symbols in `sorted_syms'. */ +long sorted_symcount = 0; + +/* The dynamic symbol table. */ +asymbol **dynsyms; + +/* Number of symbols in `dynsyms'. */ +long dynsymcount = 0; + +/* Forward declarations. */ + +static void +display_file PARAMS ((char *filename, char *target)); + +static void +dump_data PARAMS ((bfd *abfd)); + +static void +dump_relocs PARAMS ((bfd *abfd)); + +static void +dump_dynamic_relocs PARAMS ((bfd * abfd)); + +static void +dump_reloc_set PARAMS ((bfd *, arelent **, long)); + +static void +dump_symbols PARAMS ((bfd *abfd, boolean dynamic)); + +static void +display_bfd PARAMS ((bfd *abfd)); + +static void +objdump_print_value PARAMS ((bfd_vma, FILE *)); + +static void +objdump_print_address PARAMS ((bfd_vma, struct disassemble_info *)); + +static void +show_line PARAMS ((bfd *, asection *, bfd_vma)); + +void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, "\ +Usage: %s [-ahifdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n\ + [--archive-headers] [--target=bfdname] [--disassemble]\n\ + [--disassemble-all] [--file-headers] [--section-headers] [--headers]\n\ + [--info] [--section=section-name] [--line-numbers] [--source]\n", + program_name); + fprintf (stream, "\ + [--architecture=machine] [--reloc] [--full-contents] [--stabs]\n\ + [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n\ + [--wide] [--version] [--help] [--private-headers]\n\ + [--start-address=addr] [--stop-address=addr] objfile...\n\ +at least one option besides -l (--line-numbers) must be given\n"); + list_supported_targets (program_name, stream); + exit (status); +} + +/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ + +#define OPTION_START_ADDRESS (150) +#define OPTION_STOP_ADDRESS (OPTION_START_ADDRESS + 1) + +static struct option long_options[]= +{ + {"all-headers", no_argument, NULL, 'x'}, + {"private-headers", no_argument, NULL, 'p'}, + {"architecture", required_argument, NULL, 'm'}, + {"archive-headers", no_argument, NULL, 'a'}, + {"disassemble", no_argument, NULL, 'd'}, + {"disassemble-all", no_argument, NULL, 'D'}, + {"dynamic-reloc", no_argument, NULL, 'R'}, + {"dynamic-syms", no_argument, NULL, 'T'}, + {"file-headers", no_argument, NULL, 'f'}, + {"full-contents", no_argument, NULL, 's'}, + {"headers", no_argument, NULL, 'h'}, + {"help", no_argument, NULL, 'H'}, + {"info", no_argument, NULL, 'i'}, + {"line-numbers", no_argument, NULL, 'l'}, + {"reloc", no_argument, NULL, 'r'}, + {"section", required_argument, NULL, 'j'}, + {"section-headers", no_argument, NULL, 'h'}, + {"source", no_argument, NULL, 'S'}, + {"stabs", no_argument, &dump_stab_section_info, 1}, + {"start-address", required_argument, NULL, OPTION_START_ADDRESS}, + {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS}, + {"syms", no_argument, NULL, 't'}, + {"target", required_argument, NULL, 'b'}, + {"version", no_argument, &show_version, 1}, + {"wide", no_argument, &wide_output, 'w'}, + {0, no_argument, 0, 0} +}; + +static void +dump_section_header (abfd, section, ignored) + bfd *abfd; + asection *section; + PTR ignored; +{ + char *comma = ""; + +#define PF(x,y) \ + if (section->flags & x) { printf("%s%s",comma,y); comma = ", "; } + + + printf ("SECTION %d [%s]\t: size %08x", + section->index, + section->name, + (unsigned) bfd_get_section_size_before_reloc (section)); + printf (" vma "); + printf_vma (section->vma); + printf (" lma "); + printf_vma (section->lma); + printf (" align 2**%u%s ", + section->alignment_power, (wide_output) ? "" : "\n"); + PF (SEC_ALLOC, "ALLOC"); + PF (SEC_CONSTRUCTOR, "CONSTRUCTOR"); + PF (SEC_CONSTRUCTOR_TEXT, "CONSTRUCTOR TEXT"); + PF (SEC_CONSTRUCTOR_DATA, "CONSTRUCTOR DATA"); + PF (SEC_CONSTRUCTOR_BSS, "CONSTRUCTOR BSS"); + PF (SEC_LOAD, "LOAD"); + PF (SEC_RELOC, "RELOC"); +#ifdef SEC_BALIGN + PF (SEC_BALIGN, "BALIGN"); +#endif + PF (SEC_READONLY, "READONLY"); + PF (SEC_CODE, "CODE"); + PF (SEC_DATA, "DATA"); + PF (SEC_ROM, "ROM"); + PF (SEC_DEBUGGING, "DEBUGGING"); + PF (SEC_NEVER_LOAD, "NEVER_LOAD"); + printf ("\n"); +#undef PF +} + +static void +dump_headers (abfd) + bfd *abfd; +{ + bfd_map_over_sections (abfd, dump_section_header, (PTR) NULL); +} + +static asymbol ** +slurp_symtab (abfd) + bfd *abfd; +{ + asymbol **sy = (asymbol **) NULL; + long storage; + + if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) + { + printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd)); + symcount = 0; + return NULL; + } + + storage = bfd_get_symtab_upper_bound (abfd); + if (storage < 0) + bfd_fatal (bfd_get_filename (abfd)); + + if (storage) + { + sy = (asymbol **) xmalloc (storage); + } + symcount = bfd_canonicalize_symtab (abfd, sy); + if (symcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + if (symcount == 0) + fprintf (stderr, "%s: %s: No symbols\n", + program_name, bfd_get_filename (abfd)); + return sy; +} + +/* Read in the dynamic symbols. */ + +static asymbol ** +slurp_dynamic_symtab (abfd) + bfd *abfd; +{ + asymbol **sy = (asymbol **) NULL; + long storage; + + storage = bfd_get_dynamic_symtab_upper_bound (abfd); + if (storage < 0) + { + if (!(bfd_get_file_flags (abfd) & DYNAMIC)) + { + fprintf (stderr, "%s: %s: not a dynamic object\n", + program_name, bfd_get_filename (abfd)); + dynsymcount = 0; + return NULL; + } + + bfd_fatal (bfd_get_filename (abfd)); + } + + if (storage) + { + sy = (asymbol **) xmalloc (storage); + } + dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, sy); + if (dynsymcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + if (dynsymcount == 0) + fprintf (stderr, "%s: %s: No dynamic symbols\n", + program_name, bfd_get_filename (abfd)); + return sy; +} + +/* Filter out (in place) symbols that are useless for disassembly. + COUNT is the number of elements in SYMBOLS. + Return the number of useful symbols. */ + +long +remove_useless_symbols (symbols, count) + asymbol **symbols; + long count; +{ + register asymbol **in_ptr = symbols, **out_ptr = symbols; + + while (--count >= 0) + { + asymbol *sym = *in_ptr++; + + if (sym->name == NULL || sym->name[0] == '\0') + continue; + if (sym->flags & (BSF_DEBUGGING)) + continue; + if (bfd_is_und_section (sym->section) + || bfd_is_com_section (sym->section)) + continue; + + *out_ptr++ = sym; + } + return out_ptr - symbols; +} + +/* Sort symbols into value order. */ + +static int +compare_symbols (ap, bp) + const PTR ap; + const PTR bp; +{ + const asymbol *a = *(const asymbol **)ap; + const asymbol *b = *(const asymbol **)bp; + const char *an, *bn; + size_t anl, bnl; + boolean af, bf; + flagword aflags, bflags; + + if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) + return 1; + else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) + return -1; + + if (a->section > b->section) + return 1; + else if (a->section < b->section) + return -1; + + an = bfd_asymbol_name (a); + bn = bfd_asymbol_name (b); + anl = strlen (an); + bnl = strlen (bn); + + /* The symbols gnu_compiled and gcc2_compiled convey no real + information, so put them after other symbols with the same value. */ + + af = (strstr (an, "gnu_compiled") != NULL + || strstr (an, "gcc2_compiled") != NULL); + bf = (strstr (bn, "gnu_compiled") != NULL + || strstr (bn, "gcc2_compiled") != NULL); + + if (af && ! bf) + return 1; + if (! af && bf) + return -1; + + /* We use a heuristic for the file name, to try to sort it after + more useful symbols. It may not work on non Unix systems, but it + doesn't really matter; the only difference is precisely which + symbol names get printed. */ + +#define file_symbol(s, sn, snl) \ + (((s)->flags & BSF_FILE) != 0 \ + || ((sn)[(snl) - 2] == '.' \ + && ((sn)[(snl) - 1] == 'o' \ + || (sn)[(snl) - 1] == 'a'))) + + af = file_symbol (a, an, anl); + bf = file_symbol (b, bn, bnl); + + if (af && ! bf) + return 1; + if (! af && bf) + return -1; + + /* Finally, try to sort global symbols before local symbols before + debugging symbols. */ + + aflags = a->flags; + bflags = b->flags; + + if ((aflags & BSF_DEBUGGING) != (bflags & BSF_DEBUGGING)) + { + if ((aflags & BSF_DEBUGGING) != 0) + return 1; + else + return -1; + } + if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL)) + { + if ((aflags & BSF_LOCAL) != 0) + return 1; + else + return -1; + } + + return 0; +} + +/* Sort relocs into address order. */ + +static int +compare_relocs (ap, bp) + const PTR ap; + const PTR bp; +{ + const arelent *a = *(const arelent **)ap; + const arelent *b = *(const arelent **)bp; + + if (a->address > b->address) + return 1; + else if (a->address < b->address) + return -1; + + /* So that associated relocations tied to the same address show up + in the correct order, we don't do any further sorting. */ + if (a > b) + return 1; + else if (a < b) + return -1; + else + return 0; +} + +/* Print VMA to STREAM with no leading zeroes. */ + +static void +objdump_print_value (vma, stream) + bfd_vma vma; + FILE *stream; +{ + char buf[30]; + char *p; + + sprintf_vma (buf, vma); + for (p = buf; *p == '0'; ++p) + ; + fprintf (stream, "%s", p); +} + +/* Print VMA symbolically to INFO if possible. */ + +static void +objdump_print_address (vma, info) + bfd_vma vma; + struct disassemble_info *info; +{ + /* @@ Would it speed things up to cache the last two symbols returned, + and maybe their address ranges? For many processors, only one memory + operand can be present at a time, so the 2-entry cache wouldn't be + constantly churned by code doing heavy memory accesses. */ + + /* Indices in `sorted_syms'. */ + long min = 0; + long max = sorted_symcount; + long thisplace; + + fprintf_vma (info->stream, vma); + + if (sorted_symcount < 1) + return; + + /* Perform a binary search looking for the closest symbol to the + required value. We are searching the range (min, max]. */ + while (min + 1 < max) + { + asymbol *sym; + + thisplace = (max + min) / 2; + sym = sorted_syms[thisplace]; + + if (bfd_asymbol_value (sym) > vma) + max = thisplace; + else if (bfd_asymbol_value (sym) < vma) + min = thisplace; + else + { + min = thisplace; + break; + } + } + + /* The symbol we want is now in min, the low end of the range we + were searching. If there are several symbols with the same + value, we want the first one. */ + thisplace = min; + while (thisplace > 0 + && (bfd_asymbol_value (sorted_syms[thisplace]) + == bfd_asymbol_value (sorted_syms[thisplace - 1]))) + --thisplace; + + { + /* If the file is relocateable, and the symbol could be from this + section, prefer a symbol from this section over symbols from + others, even if the other symbol's value might be closer. + + Note that this may be wrong for some symbol references if the + sections have overlapping memory ranges, but in that case there's + no way to tell what's desired without looking at the relocation + table. */ + struct objdump_disasm_info *aux; + long i; + + aux = (struct objdump_disasm_info *) info->application_data; + if (sorted_syms[thisplace]->section != aux->sec + && (aux->require_sec + || ((aux->abfd->flags & HAS_RELOC) != 0 + && vma >= bfd_get_section_vma (aux->abfd, aux->sec) + && vma < (bfd_get_section_vma (aux->abfd, aux->sec) + + bfd_section_size (aux->abfd, aux->sec))))) + { + for (i = thisplace + 1; i < sorted_symcount; i++) + { + if (bfd_asymbol_value (sorted_syms[i]) + != bfd_asymbol_value (sorted_syms[thisplace])) + break; + } + --i; + for (; i >= 0; i--) + { + if (sorted_syms[i]->section == aux->sec + && (i == 0 + || sorted_syms[i - 1]->section != aux->sec + || (bfd_asymbol_value (sorted_syms[i]) + != bfd_asymbol_value (sorted_syms[i - 1])))) + { + thisplace = i; + break; + } + } + + if (sorted_syms[thisplace]->section != aux->sec) + { + /* We didn't find a good symbol with a smaller value. + Look for one with a larger value. */ + for (i = thisplace + 1; i < sorted_symcount; i++) + { + if (sorted_syms[i]->section == aux->sec) + { + thisplace = i; + break; + } + } + } + + if (sorted_syms[thisplace]->section != aux->sec + && (aux->require_sec + || ((aux->abfd->flags & HAS_RELOC) != 0 + && vma >= bfd_get_section_vma (aux->abfd, aux->sec) + && vma < (bfd_get_section_vma (aux->abfd, aux->sec) + + bfd_section_size (aux->abfd, aux->sec))))) + { + bfd_vma secaddr; + + fprintf (info->stream, " <%s", + bfd_get_section_name (aux->abfd, aux->sec)); + secaddr = bfd_get_section_vma (aux->abfd, aux->sec); + if (vma < secaddr) + { + fprintf (info->stream, "-"); + objdump_print_value (secaddr - vma, info->stream); + } + else if (vma > secaddr) + { + fprintf (info->stream, "+"); + objdump_print_value (vma - secaddr, info->stream); + } + fprintf (info->stream, ">"); + return; + } + } + } + + fprintf (info->stream, " <%s", sorted_syms[thisplace]->name); + if (bfd_asymbol_value (sorted_syms[thisplace]) > vma) + { + fprintf (info->stream, "-"); + objdump_print_value (bfd_asymbol_value (sorted_syms[thisplace]) - vma, + info->stream); + } + else if (vma > bfd_asymbol_value (sorted_syms[thisplace])) + { + fprintf (info->stream, "+"); + objdump_print_value (vma - bfd_asymbol_value (sorted_syms[thisplace]), + info->stream); + } + fprintf (info->stream, ">"); +} + +/* Hold the last function name and the last line number we displayed + in a disassembly. */ + +static char *prev_functionname; +static unsigned int prev_line; + +/* We keep a list of all files that we have seen when doing a + dissassembly with source, so that we know how much of the file to + display. This can be important for inlined functions. */ + +struct print_file_list +{ + struct print_file_list *next; + char *filename; + unsigned int line; + FILE *f; +}; + +static struct print_file_list *print_files; + +/* The number of preceding context lines to show when we start + displaying a file for the first time. */ + +#define SHOW_PRECEDING_CONTEXT_LINES (5) + +/* Skip ahead to a given line in a file, optionally printing each + line. */ + +static void +skip_to_line PARAMS ((struct print_file_list *, unsigned int, boolean)); + +static void +skip_to_line (p, line, show) + struct print_file_list *p; + unsigned int line; + boolean show; +{ + while (p->line < line) + { + char buf[100]; + + if (fgets (buf, sizeof buf, p->f) == NULL) + { + fclose (p->f); + p->f = NULL; + break; + } + + if (show) + printf ("%s", buf); + + if (strchr (buf, '\n') != NULL) + ++p->line; + } +} + +/* Show the line number, or the source line, in a dissassembly + listing. */ + +static void +show_line (abfd, section, off) + bfd *abfd; + asection *section; + bfd_vma off; +{ + CONST char *filename; + CONST char *functionname; + unsigned int line; + + if (! with_line_numbers && ! with_source_code) + return; + + if (! bfd_find_nearest_line (abfd, section, syms, off, &filename, + &functionname, &line)) + return; + + if (filename != NULL && *filename == '\0') + filename = NULL; + if (functionname != NULL && *functionname == '\0') + functionname = NULL; + + if (with_line_numbers) + { + if (functionname != NULL + && (prev_functionname == NULL + || strcmp (functionname, prev_functionname) != 0)) + printf ("%s():\n", functionname); + if (line > 0 && line != prev_line) + printf ("%s:%u\n", filename == NULL ? "???" : filename, line); + } + + if (with_source_code + && filename != NULL + && line > 0) + { + struct print_file_list **pp, *p; + + for (pp = &print_files; *pp != NULL; pp = &(*pp)->next) + if (strcmp ((*pp)->filename, filename) == 0) + break; + p = *pp; + + if (p != NULL) + { + if (p != print_files) + { + int l; + + /* We have reencountered a file name which we saw + earlier. This implies that either we are dumping out + code from an included file, or the same file was + linked in more than once. There are two common cases + of an included file: inline functions in a header + file, and a bison or flex skeleton file. In the + former case we want to just start printing (but we + back up a few lines to give context); in the latter + case we want to continue from where we left off. I + can't think of a good way to distinguish the cases, + so I used a heuristic based on the file name. */ + if (strcmp (p->filename + strlen (p->filename) - 2, ".h") != 0) + l = p->line; + else + { + l = line - SHOW_PRECEDING_CONTEXT_LINES; + if (l <= 0) + l = 1; + } + + if (p->f == NULL) + { + p->f = fopen (p->filename, "r"); + p->line = 0; + } + if (p->f != NULL) + skip_to_line (p, l, false); + + if (print_files->f != NULL) + { + fclose (print_files->f); + print_files->f = NULL; + } + } + + if (p->f != NULL) + { + skip_to_line (p, line, true); + *pp = p->next; + p->next = print_files; + print_files = p; + } + } + else + { + FILE *f; + + f = fopen (filename, "r"); + if (f != NULL) + { + int l; + + p = ((struct print_file_list *) + xmalloc (sizeof (struct print_file_list))); + p->filename = xmalloc (strlen (filename) + 1); + strcpy (p->filename, filename); + p->line = 0; + p->f = f; + + if (print_files != NULL && print_files->f != NULL) + { + fclose (print_files->f); + print_files->f = NULL; + } + p->next = print_files; + print_files = p; + + l = line - SHOW_PRECEDING_CONTEXT_LINES; + if (l <= 0) + l = 1; + skip_to_line (p, l, false); + if (p->f != NULL) + skip_to_line (p, line, true); + } + } + } + + if (functionname != NULL + && (prev_functionname == NULL + || strcmp (functionname, prev_functionname) != 0)) + { + if (prev_functionname != NULL) + free (prev_functionname); + prev_functionname = xmalloc (strlen (functionname) + 1); + strcpy (prev_functionname, functionname); + } + + if (line > 0 && line != prev_line) + prev_line = line; +} + +void +disassemble_data (abfd) + bfd *abfd; +{ + long i; + disassembler_ftype disassemble_fn = 0; /* New style */ + struct disassemble_info disasm_info; + struct objdump_disasm_info aux; + asection *section; + boolean done_dot = false; + + print_files = NULL; + prev_functionname = NULL; + prev_line = -1; + + /* We make a copy of syms to sort. We don't want to sort syms + because that will screw up the relocs. */ + sorted_syms = (asymbol **) xmalloc (symcount * sizeof (asymbol *)); + memcpy (sorted_syms, syms, symcount * sizeof (asymbol *)); + + sorted_symcount = remove_useless_symbols (sorted_syms, symcount); + + /* Sort the symbols into section and symbol order */ + qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); + + INIT_DISASSEMBLE_INFO(disasm_info, stdout); + disasm_info.application_data = (PTR) &aux; + aux.abfd = abfd; + disasm_info.print_address_func = objdump_print_address; + + if (machine != (char *) NULL) + { + const bfd_arch_info_type *info = bfd_scan_arch (machine); + if (info == NULL) + { + fprintf (stderr, "%s: Can't use supplied machine %s\n", + program_name, + machine); + exit (1); + } + abfd->arch_info = info; + } + + disassemble_fn = disassembler (abfd); + if (!disassemble_fn) + { + fprintf (stderr, "%s: Can't disassemble for architecture %s\n", + program_name, + bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); + exit (1); + } + + for (section = abfd->sections; + section != (asection *) NULL; + section = section->next) + { + bfd_byte *data = NULL; + bfd_size_type datasize = 0; + arelent **relbuf = NULL; + arelent **relpp = NULL; + arelent **relppend = NULL; + long stop; + + if ((section->flags & SEC_LOAD) == 0 + || (! disassemble_all + && only == NULL + && (section->flags & SEC_CODE) == 0)) + continue; + if (only != (char *) NULL && strcmp (only, section->name) != 0) + continue; + + if (dump_reloc_info + && (section->flags & SEC_RELOC) != 0) + { + long relsize; + + relsize = bfd_get_reloc_upper_bound (abfd, section); + if (relsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + + if (relsize > 0) + { + long relcount; + + relbuf = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (abfd, section, relbuf, syms); + if (relcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + + /* Sort the relocs by address. */ + qsort (relbuf, relcount, sizeof (arelent *), compare_relocs); + + relpp = relbuf; + relppend = relpp + relcount; + } + } + + printf ("Disassembly of section %s:\n", section->name); + + datasize = bfd_get_section_size_before_reloc (section); + if (datasize == 0) + continue; + + data = (bfd_byte *) xmalloc ((size_t) datasize); + + bfd_get_section_contents (abfd, section, data, 0, datasize); + + aux.sec = section; + disasm_info.buffer = data; + disasm_info.buffer_vma = section->vma; + disasm_info.buffer_length = datasize; + if (start_address == (bfd_vma) -1 + || start_address < disasm_info.buffer_vma) + i = 0; + else + i = start_address - disasm_info.buffer_vma; + if (stop_address == (bfd_vma) -1) + stop = datasize; + else + { + if (stop_address < disasm_info.buffer_vma) + stop = 0; + else + stop = stop_address - disasm_info.buffer_vma; + if (stop > disasm_info.buffer_length) + stop = disasm_info.buffer_length; + } + while (i < stop) + { + int bytes; + boolean need_nl = false; + + if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && + data[i + 3] == 0) + { + if (done_dot == false) + { + printf ("...\n"); + done_dot = true; + } + bytes = 4; + } + else + { + done_dot = false; + if (with_line_numbers || with_source_code) + show_line (abfd, section, i); + aux.require_sec = true; + objdump_print_address (section->vma + i, &disasm_info); + aux.require_sec = false; + putchar (' '); + + bytes = (*disassemble_fn) (section->vma + i, &disasm_info); + if (bytes < 0) + break; + + if (!wide_output) + putchar ('\n'); + else + need_nl = true; + } + + if (dump_reloc_info + && (section->flags & SEC_RELOC) != 0) + { + while (relpp < relppend + && ((*relpp)->address >= (bfd_vma) i + && (*relpp)->address < (bfd_vma) i + bytes)) + { + arelent *q; + const char *sym_name; + + q = *relpp; + + printf ("\t\tRELOC: "); + + printf_vma (section->vma + q->address); + + printf (" %s ", q->howto->name); + + if (q->sym_ptr_ptr != NULL + && *q->sym_ptr_ptr != NULL) + { + sym_name = bfd_asymbol_name (*q->sym_ptr_ptr); + if (sym_name == NULL || *sym_name == '\0') + { + asection *sym_sec; + + sym_sec = bfd_get_section (*q->sym_ptr_ptr); + sym_name = bfd_get_section_name (abfd, sym_sec); + if (sym_name == NULL || *sym_name == '\0') + sym_name = "*unknown*"; + } + } + + printf ("%s", sym_name); + + if (q->addend) + { + printf ("+0x"); + printf_vma (q->addend); + } + + printf ("\n"); + need_nl = false; + ++relpp; + } + } + + if (need_nl) + printf ("\n"); + + i += bytes; + } + + free (data); + if (relbuf != NULL) + free (relbuf); + } + free (sorted_syms); +} + + +/* Define a table of stab values and print-strings. We wish the initializer + could be a direct-mapped table, but instead we build one the first + time we need it. */ + +char **stab_name; + +struct stab_print { + int value; + char *string; +}; + +struct stab_print stab_print[] = { +#define __define_stab(NAME, CODE, STRING) {CODE, STRING}, +#include "aout/stab.def" +#undef __define_stab + {0, ""} +}; + +void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name, + char *strsect_name)); + +/* Dump the stabs sections from an object file that has a section that + uses Sun stabs encoding. It has to use some hooks into BFD because + string table sections are not normally visible to BFD callers. */ + +void +dump_stabs (abfd) + bfd *abfd; +{ + /* Allocate and initialize stab name array if first time. */ + if (stab_name == NULL) + { + int i; + + stab_name = (char **) xmalloc (256 * sizeof(char *)); + /* Clear the array. */ + for (i = 0; i < 256; i++) + stab_name[i] = NULL; + /* Fill in the defined stabs. */ + for (i = 0; *stab_print[i].string; i++) + stab_name[stab_print[i].value] = stab_print[i].string; + } + + dump_section_stabs (abfd, ".stab", ".stabstr"); + dump_section_stabs (abfd, ".stab.excl", ".stab.exclstr"); + dump_section_stabs (abfd, ".stab.index", ".stab.indexstr"); + dump_section_stabs (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$"); +} + +static struct internal_nlist *stabs; +static bfd_size_type stab_size; + +static char *strtab; +static bfd_size_type stabstr_size; + +/* Read ABFD's stabs section STABSECT_NAME into `stabs' + and string table section STRSECT_NAME into `strtab'. + If the section exists and was read, allocate the space and return true. + Otherwise return false. */ + +boolean +read_section_stabs (abfd, stabsect_name, strsect_name) + bfd *abfd; + char *stabsect_name; + char *strsect_name; +{ + asection *stabsect, *stabstrsect; + + stabsect = bfd_get_section_by_name (abfd, stabsect_name); + if (0 == stabsect) + { + printf ("No %s section present\n\n", stabsect_name); + return false; + } + + stabstrsect = bfd_get_section_by_name (abfd, strsect_name); + if (0 == stabstrsect) + { + fprintf (stderr, "%s: %s has no %s section\n", program_name, + bfd_get_filename (abfd), strsect_name); + return false; + } + + stab_size = bfd_section_size (abfd, stabsect); + stabstr_size = bfd_section_size (abfd, stabstrsect); + + stabs = (struct internal_nlist *) xmalloc (stab_size); + strtab = (char *) xmalloc (stabstr_size); + + if (! bfd_get_section_contents (abfd, stabsect, (PTR) stabs, 0, stab_size)) + { + fprintf (stderr, "%s: Reading %s section of %s failed: %s\n", + program_name, stabsect_name, bfd_get_filename (abfd), + bfd_errmsg (bfd_get_error ())); + free (stabs); + free (strtab); + return false; + } + + if (! bfd_get_section_contents (abfd, stabstrsect, (PTR) strtab, 0, + stabstr_size)) + { + fprintf (stderr, "%s: Reading %s section of %s failed: %s\n", + program_name, strsect_name, bfd_get_filename (abfd), + bfd_errmsg (bfd_get_error ())); + free (stabs); + free (strtab); + return false; + } + + return true; +} + +#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); \ +} + +/* Print ABFD's stabs section STABSECT_NAME (in `stabs'), + using string table section STRSECT_NAME (in `strtab'). */ + +void +print_section_stabs (abfd, stabsect_name, strsect_name) + bfd *abfd; + char *stabsect_name; + char *strsect_name; +{ + int i; + unsigned file_string_table_offset = 0, next_file_string_table_offset = 0; + struct internal_nlist *stabp = stabs, + *stabs_end = (struct internal_nlist *) (stab_size + (char *) stabs); + + printf ("Contents of %s section:\n\n", stabsect_name); + printf ("Symnum n_type n_othr n_desc n_value n_strx String\n"); + + /* Loop through all symbols and print them. + + We start the index at -1 because there is a dummy symbol on + the front of stabs-in-{coff,elf} sections that supplies sizes. */ + + for (i = -1; stabp < stabs_end; stabp++, i++) + { + SWAP_SYMBOL (stabp, abfd); + printf ("\n%-6d ", i); + /* Either print the stab name, or, if unnamed, print its number + again (makes consistent formatting for tools like awk). */ + if (stab_name[stabp->n_type]) + printf ("%-6s", stab_name[stabp->n_type]); + else if (stabp->n_type == N_UNDF) + printf ("HdrSym"); + else + printf ("%-6d", stabp->n_type); + printf (" %-6d %-6d ", stabp->n_other, stabp->n_desc); + printf_vma (stabp->n_value); + printf (" %-6lu", stabp->n_strx); + + /* Symbols with type == 0 (N_UNDF) specify the length of the + string table associated with this file. We use that info + to know how to relocate the *next* file's string table indices. */ + + if (stabp->n_type == N_UNDF) + { + file_string_table_offset = next_file_string_table_offset; + next_file_string_table_offset += stabp->n_value; + } + else + { + /* Using the (possibly updated) string table offset, print the + string (if any) associated with this symbol. */ + + if ((stabp->n_strx + file_string_table_offset) < stabstr_size) + printf (" %s", &strtab[stabp->n_strx + file_string_table_offset]); + else + printf (" *"); + } + } + printf ("\n\n"); +} + +void +dump_section_stabs (abfd, stabsect_name, strsect_name) + bfd *abfd; + char *stabsect_name; + char *strsect_name; +{ + asection *s; + + /* Check for section names for which stabsect_name is a prefix, to + handle .stab0, etc. */ + for (s = abfd->sections; + s != NULL; + s = s->next) + { + if (strncmp (stabsect_name, s->name, strlen (stabsect_name)) == 0 + && strncmp (strsect_name, s->name, strlen (strsect_name)) != 0) + { + if (read_section_stabs (abfd, s->name, strsect_name)) + { + print_section_stabs (abfd, s->name, strsect_name); + free (stabs); + free (strtab); + } + } + } +} + +static void +dump_bfd_header (abfd) + bfd *abfd; +{ + char *comma = ""; + + printf ("architecture: %s, ", + bfd_printable_arch_mach (bfd_get_arch (abfd), + bfd_get_mach (abfd))); + printf ("flags 0x%08x:\n", abfd->flags); + +#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";} + PF (HAS_RELOC, "HAS_RELOC"); + PF (EXEC_P, "EXEC_P"); + PF (HAS_LINENO, "HAS_LINENO"); + PF (HAS_DEBUG, "HAS_DEBUG"); + PF (HAS_SYMS, "HAS_SYMS"); + PF (HAS_LOCALS, "HAS_LOCALS"); + PF (DYNAMIC, "DYNAMIC"); + PF (WP_TEXT, "WP_TEXT"); + PF (D_PAGED, "D_PAGED"); + PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE"); + printf ("\nstart address 0x"); + printf_vma (abfd->start_address); +} + +static void +dump_bfd_private_header (abfd) +bfd *abfd; +{ + bfd_print_private_bfd_data (abfd, stdout); +} +static void +display_bfd (abfd) + bfd *abfd; +{ + char **matching; + + if (!bfd_check_format_matches (abfd, bfd_object, &matching)) + { + bfd_nonfatal (bfd_get_filename (abfd)); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + return; + } + + printf ("\n%s: file format %s\n", bfd_get_filename (abfd), + abfd->xvec->name); + if (dump_ar_hdrs) + print_arelt_descr (stdout, abfd, true); + if (dump_file_header) + dump_bfd_header (abfd); + if (dump_private_headers) + dump_bfd_private_header (abfd); + putchar ('\n'); + if (dump_section_headers) + dump_headers (abfd); + if (dump_symtab || dump_reloc_info || disassemble) + { + syms = slurp_symtab (abfd); + } + if (dump_dynamic_symtab || dump_dynamic_reloc_info) + { + dynsyms = slurp_dynamic_symtab (abfd); + } + if (dump_symtab) + dump_symbols (abfd, false); + if (dump_dynamic_symtab) + dump_symbols (abfd, true); + if (dump_stab_section_info) + dump_stabs (abfd); + if (dump_reloc_info && ! disassemble) + dump_relocs (abfd); + if (dump_dynamic_reloc_info) + dump_dynamic_relocs (abfd); + if (dump_section_contents) + dump_data (abfd); + if (disassemble) + disassemble_data (abfd); + if (syms) + { + free (syms); + syms = NULL; + } + if (dynsyms) + { + free (dynsyms); + dynsyms = NULL; + } +} + +static void +display_file (filename, target) + char *filename; + char *target; +{ + bfd *file, *arfile = (bfd *) NULL; + + file = bfd_openr (filename, target); + if (file == NULL) + { + bfd_nonfatal (filename); + return; + } + + if (bfd_check_format (file, bfd_archive) == true) + { + bfd *last_arfile = NULL; + + printf ("In archive %s:\n", bfd_get_filename (file)); + for (;;) + { + bfd_set_error (bfd_error_no_error); + + arfile = bfd_openr_next_archived_file (file, arfile); + if (arfile == NULL) + { + if (bfd_get_error () != bfd_error_no_more_archived_files) + { + bfd_nonfatal (bfd_get_filename (file)); + } + break; + } + + display_bfd (arfile); + + if (last_arfile != NULL) + bfd_close (last_arfile); + last_arfile = arfile; + } + + if (last_arfile != NULL) + bfd_close (last_arfile); + } + else + display_bfd (file); + + bfd_close (file); +} + +/* Actually display the various requested regions */ + +static void +dump_data (abfd) + bfd *abfd; +{ + asection *section; + bfd_byte *data = 0; + bfd_size_type datasize = 0; + bfd_size_type i; + bfd_size_type start, stop; + + for (section = abfd->sections; section != NULL; section = + section->next) + { + int onaline = 16; + + if (only == (char *) NULL || + strcmp (only, section->name) == 0) + { + if (section->flags & SEC_HAS_CONTENTS) + { + printf ("Contents of section %s:\n", section->name); + + if (bfd_section_size (abfd, section) == 0) + continue; + data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, section)); + datasize = bfd_section_size (abfd, section); + + + bfd_get_section_contents (abfd, section, (PTR) data, 0, bfd_section_size (abfd, section)); + + if (start_address == (bfd_vma) -1 + || start_address < section->vma) + start = 0; + else + start = start_address - section->vma; + if (stop_address == (bfd_vma) -1) + stop = bfd_section_size (abfd, section); + else + { + if (stop_address < section->vma) + stop = 0; + else + stop = stop_address - section->vma; + if (stop > bfd_section_size (abfd, section)) + stop = bfd_section_size (abfd, section); + } + for (i = start; i < stop; i += onaline) + { + bfd_size_type j; + + printf (" %04lx ", (unsigned long int) (i + section->vma)); + for (j = i; j < i + onaline; j++) + { + if (j < stop) + printf ("%02x", (unsigned) (data[j])); + else + printf (" "); + if ((j & 3) == 3) + printf (" "); + } + + printf (" "); + for (j = i; j < i + onaline; j++) + { + if (j >= stop) + printf (" "); + else + printf ("%c", isprint (data[j]) ? data[j] : '.'); + } + putchar ('\n'); + } + free (data); + } + } + } +} + +/* Should perhaps share code and display with nm? */ +static void +dump_symbols (abfd, dynamic) + bfd *abfd; + boolean dynamic; +{ + asymbol **current; + long max; + long count; + + if (dynamic) + { + current = dynsyms; + max = dynsymcount; + if (max == 0) + return; + printf ("DYNAMIC SYMBOL TABLE:\n"); + } + else + { + current = syms; + max = symcount; + if (max == 0) + return; + printf ("SYMBOL TABLE:\n"); + } + + for (count = 0; count < max; count++) + { + if (*current) + { + bfd *cur_bfd = bfd_asymbol_bfd(*current); + if (cur_bfd) + { + bfd_print_symbol (cur_bfd, + stdout, + *current, bfd_print_symbol_all); + printf ("\n"); + } + } + current++; + } + printf ("\n"); + printf ("\n"); +} + +static void +dump_relocs (abfd) + bfd *abfd; +{ + arelent **relpp; + long relcount; + asection *a; + + for (a = abfd->sections; a != (asection *) NULL; a = a->next) + { + long relsize; + + if (bfd_is_abs_section (a)) + continue; + if (bfd_is_und_section (a)) + continue; + if (bfd_is_com_section (a)) + continue; + + if (only) + { + if (strcmp (only, a->name)) + continue; + } + else if ((a->flags & SEC_RELOC) == 0) + continue; + + relsize = bfd_get_reloc_upper_bound (abfd, a); + if (relsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + + printf ("RELOCATION RECORDS FOR [%s]:", a->name); + + if (relsize == 0) + { + printf (" (none)\n\n"); + } + else + { + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (abfd, a, relpp, syms); + if (relcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + else if (relcount == 0) + { + printf (" (none)\n\n"); + } + else + { + printf ("\n"); + dump_reloc_set (abfd, relpp, relcount); + printf ("\n\n"); + } + free (relpp); + } + } +} + +static void +dump_dynamic_relocs (abfd) + bfd *abfd; +{ + long relsize; + arelent **relpp; + long relcount; + + relsize = bfd_get_dynamic_reloc_upper_bound (abfd); + if (relsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + + printf ("DYNAMIC RELOCATION RECORDS"); + + if (relsize == 0) + { + printf (" (none)\n\n"); + } + else + { + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms); + if (relcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + else if (relcount == 0) + { + printf (" (none)\n\n"); + } + else + { + printf ("\n"); + dump_reloc_set (abfd, relpp, relcount); + printf ("\n\n"); + } + free (relpp); + } +} + +static void +dump_reloc_set (abfd, relpp, relcount) + bfd *abfd; + arelent **relpp; + long relcount; +{ + arelent **p; + + /* Get column headers lined up reasonably. */ + { + static int width; + if (width == 0) + { + char buf[30]; + sprintf_vma (buf, (bfd_vma) -1); + width = strlen (buf) - 7; + } + printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, ""); + } + + for (p = relpp; relcount && *p != (arelent *) NULL; p++, relcount--) + { + arelent *q = *p; + CONST char *sym_name; + CONST char *section_name; + + if (start_address != (bfd_vma) -1 + && q->address < start_address) + continue; + if (stop_address != (bfd_vma) -1 + && q->address > stop_address) + continue; + + if (q->sym_ptr_ptr && *q->sym_ptr_ptr) + { + sym_name = (*(q->sym_ptr_ptr))->name; + section_name = (*(q->sym_ptr_ptr))->section->name; + } + else + { + sym_name = NULL; + section_name = NULL; + } + if (sym_name) + { + printf_vma (q->address); + printf (" %-16s %s", + q->howto->name, + sym_name); + } + else + { + if (section_name == (CONST char *) NULL) + section_name = "*unknown*"; + printf_vma (q->address); + printf (" %-16s [%s]", + q->howto->name, + section_name); + } + if (q->addend) + { + printf ("+0x"); + printf_vma (q->addend); + } + printf ("\n"); + } +} + +/* The length of the longest architecture name + 1. */ +#define LONGEST_ARCH sizeof("rs6000:6000") + +#ifndef L_tmpnam +#define L_tmpnam 25 +#endif + +/* List the targets that BFD is configured to support, each followed + by its endianness and the architectures it supports. */ + +static void +display_target_list () +{ + extern char *tmpnam (); + extern bfd_target *bfd_target_vector[]; + char tmparg[L_tmpnam]; + char *dummy_name; + int t; + + dummy_name = tmpnam (tmparg); + for (t = 0; bfd_target_vector[t]; t++) + { + bfd_target *p = bfd_target_vector[t]; + bfd *abfd = bfd_openw (dummy_name, p->name); + int a; + + printf ("%s\n (header %s, data %s)\n", p->name, + p->header_byteorder_big_p ? "big endian" : "little endian", + p->byteorder_big_p ? "big endian" : "little endian"); + + if (abfd == NULL) + { + bfd_nonfatal (dummy_name); + continue; + } + + if (! bfd_set_format (abfd, bfd_object)) + { + if (bfd_get_error () != bfd_error_invalid_operation) + bfd_nonfatal (p->name); + continue; + } + + for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++) + if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0)) + printf (" %s\n", + bfd_printable_arch_mach ((enum bfd_architecture) a, 0)); + } + unlink (dummy_name); +} + +/* Print a table showing which architectures are supported for entries + FIRST through LAST-1 of bfd_target_vector (targets across, + architectures down). */ + +static void +display_info_table (first, last) + int first; + int last; +{ + extern bfd_target *bfd_target_vector[]; + extern char *tmpnam (); + char tmparg[L_tmpnam]; + int t, a; + char *dummy_name; + + /* Print heading of target names. */ + printf ("\n%*s", (int) LONGEST_ARCH, " "); + for (t = first; t < last && bfd_target_vector[t]; t++) + printf ("%s ", bfd_target_vector[t]->name); + putchar ('\n'); + + dummy_name = tmpnam (tmparg); + for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++) + if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0) + { + printf ("%*s ", (int) LONGEST_ARCH - 1, + bfd_printable_arch_mach (a, 0)); + for (t = first; t < last && bfd_target_vector[t]; t++) + { + bfd_target *p = bfd_target_vector[t]; + boolean ok = true; + bfd *abfd = bfd_openw (dummy_name, p->name); + + if (abfd == NULL) + { + bfd_nonfatal (p->name); + ok = false; + } + + if (ok) + { + if (! bfd_set_format (abfd, bfd_object)) + { + if (bfd_get_error () != bfd_error_invalid_operation) + bfd_nonfatal (p->name); + ok = false; + } + } + + if (ok) + { + if (! bfd_set_arch_mach (abfd, a, 0)) + ok = false; + } + + if (ok) + printf ("%s ", p->name); + else + { + int l = strlen (p->name); + while (l--) + putchar ('-'); + putchar (' '); + } + } + putchar ('\n'); + } + unlink (dummy_name); +} + +/* Print tables of all the target-architecture combinations that + BFD has been configured to support. */ + +static void +display_target_tables () +{ + int t, columns; + extern bfd_target *bfd_target_vector[]; + char *colum; + extern char *getenv (); + + columns = 0; + colum = getenv ("COLUMNS"); + if (colum != NULL) + columns = atoi (colum); + if (columns == 0) + columns = 80; + + t = 0; + while (bfd_target_vector[t] != NULL) + { + int oldt = t, wid; + + wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1; + ++t; + while (wid < columns && bfd_target_vector[t] != NULL) + { + int newwid; + + newwid = wid + strlen (bfd_target_vector[t]->name) + 1; + if (newwid >= columns) + break; + wid = newwid; + ++t; + } + display_info_table (oldt, t); + } +} + +static void +display_info () +{ + printf ("BFD header file version %s\n", BFD_VERSION); + display_target_list (); + display_target_tables (); +} + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + char *target = default_target; + boolean seenflag = false; + + program_name = *argv; + xmalloc_set_program_name (program_name); + + START_PROGRESS (program_name, 0); + + bfd_init (); + + while ((c = getopt_long (argc, argv, "pib:m:VdDlfahrRtTxsSj:w", long_options, + (int *) 0)) + != EOF) + { + if (c != 'l' && c != OPTION_START_ADDRESS && c != OPTION_STOP_ADDRESS) + seenflag = true; + switch (c) + { + case 0: + break; /* we've been given a long option */ + case 'm': + machine = optarg; + break; + case 'j': + only = optarg; + break; + case 'l': + with_line_numbers = 1; + break; + case 'b': + target = optarg; + break; + case 'f': + dump_file_header = true; + break; + case 'i': + formats_info = true; + break; + case 'p': + dump_private_headers = 1; + break; + case 'x': + dump_private_headers = 1; + dump_symtab = 1; + dump_reloc_info = 1; + dump_file_header = true; + dump_ar_hdrs = 1; + dump_section_headers = 1; + break; + case 't': + dump_symtab = 1; + break; + case 'T': + dump_dynamic_symtab = 1; + break; + case 'd': + disassemble = true; + break; + case 'D': + disassemble = disassemble_all = true; + break; + case 'S': + disassemble = true; + with_source_code = true; + break; + case 's': + dump_section_contents = 1; + break; + case 'r': + dump_reloc_info = 1; + break; + case 'R': + dump_dynamic_reloc_info = 1; + break; + case 'a': + dump_ar_hdrs = 1; + break; + case 'h': + dump_section_headers = 1; + break; + case 'H': + usage (stdout, 0); + case 'V': + show_version = 1; + break; + case 'w': + wide_output = 1; + break; + case OPTION_START_ADDRESS: + start_address = parse_vma (optarg, "--start-address"); + break; + case OPTION_STOP_ADDRESS: + stop_address = parse_vma (optarg, "--stop-address"); + break; + default: + usage (stderr, 1); + } + } + + if (show_version) + { + printf ("GNU %s version %s\n", program_name, program_version); + exit (0); + } + + if (seenflag == false) + usage (stderr, 1); + + if (formats_info) + { + display_info (); + } + else + { + if (optind == argc) + display_file ("a.out", target); + else + for (; optind < argc;) + display_file (argv[optind++], target); + } + + END_PROGRESS (program_name); + + return 0; +} diff --git a/gnu/usr.bin/binutils/binutils/ranlib.1 b/gnu/usr.bin/binutils/binutils/ranlib.1 new file mode 100644 index 00000000000..7efb5c8e850 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/ranlib.1 @@ -0,0 +1,83 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH ranlib 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +ranlib \- generate index to archive. + +.SH SYNOPSIS +.hy 0 +.na +.B ranlib \c +.RB "[\|" \-v | \-V "\|]" +.I archive\c +\& +.ad b +.hy 1 +.SH DESCRIPTION +.B ranlib +generates an index to the contents of an archive, and +stores it in the archive. The index lists each symbol defined by a +member of an archive that is a relocatable object file. +.PP +You may use +.RB ` "nm \-s" ' +or +.RB ` "nm \-\-print-armap" ' +to list this index. +.PP +An archive with such an index speeds up linking to the library, and +allows routines in the library to call each other without regard to +their placement in the archive. +.PP +The GNU +.B ranlib +program is another form of GNU +.BR ar ; +running +.B ranlib +is completely equivalent to executing +.RB ` "ar \-s" '. + +.SH OPTIONS +.TP +.B \-v +Print the version number of +.B ranlib +and exit. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (October 1991); +.BR ar "(" 1 ")," +.BR nm "(" 1 ")." + + +.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/gnu/usr.bin/binutils/binutils/ranlib.sh b/gnu/usr.bin/binutils/binutils/ranlib.sh new file mode 100644 index 00000000000..2b6fbc479c6 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/ranlib.sh @@ -0,0 +1,3 @@ +#!/bin/sh +# A simple ranlib script, to use less disk space than a ranlib program. +ar s $1 diff --git a/gnu/usr.bin/binutils/binutils/sanity.sh b/gnu/usr.bin/binutils/binutils/sanity.sh new file mode 100644 index 00000000000..942cabf9ac0 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/sanity.sh @@ -0,0 +1,50 @@ +#!/bin/sh +### quick sanity test for the binutils. +### +### This file was written and is maintained by K. Richard Pixley, +### rich@cygnus.com. + +### fail on errors +set -e + +### first arg is directory in which binaries to be tested reside. +case "$1" in +"") BIN=. ;; +*) BIN="$1" ;; +esac + +### size +for i in size objdump nm ar strip ranlib ; do + ${BIN}/size ${BIN}/$i > /dev/null +done + +### objdump +for i in size objdump nm ar strip ranlib ; do + ${BIN}/objdump -ahifdrtxsl ${BIN}/$i > /dev/null +done + +### nm +for i in size objdump nm ar strip ranlib ; do + ${BIN}/nm ${BIN}/$i > /dev/null +done + +### strip +TMPDIR=./binutils-$$ +mkdir ${TMPDIR} + +cp ${BIN}/strip ${TMPDIR}/strip + +for i in size objdump nm ar ranlib ; do + cp ${BIN}/$i ${TMPDIR}/$i + ${BIN}/strip ${TMPDIR}/$i + cp ${BIN}/$i ${TMPDIR}/$i + ${TMPDIR}/strip ${TMPDIR}/$i +done + +### ar + +### ranlib + +rm -rf ${TMPDIR} + +exit 0 diff --git a/gnu/usr.bin/binutils/binutils/size.1 b/gnu/usr.bin/binutils/binutils/size.1 new file mode 100644 index 00000000000..3b19bd25930 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/size.1 @@ -0,0 +1,161 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH size 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +size \- list section sizes and total size. + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B size +.RB "[\|" \-A \||\| \-B \||\| \c +.BI "\-\-format=" compatibility\c +\&\|] +.RB "[\|" \-\-help "\|]" +.RB "[\|" \-d \||\| \-o \||\| \-x\c +\||\|\c +.BI "\-\-radix=" number\c +\&\|] +.RB "[\|" \c +.BI "\-\-target=" bfdname\c +\&\|] +.RB "[\|" \-V \||\| \-\-version "\|]" +.I objfile\c +\&.\|.\|. +.ad b +.hy 1 +.SH DESCRIPTION +The GNU \c +.B size\c +\& utility lists the section sizes\(em\&and the total +size\(em\&for each of the object files +.I objfile +in its argument list. +By default, one line of output is generated for each object file or each +module in an archive. + +.SH OPTIONS +.TP +.B \-A +.TP +.B \-B +.TP +.BI "\-\-format " "compatibility" +Using one of these options, you can choose whether the output from GNU +\c +.B size\c +\& resembles output from System V \c +.B size\c +\& (using `\|\c +.B \-A\c +\|', +or `\|\c +.B \-\-format=sysv\c +\|'), or Berkeley \c +.B size\c +\& (using `\|\c +.B \-B\c +\|', or +`\|\c +.B \-\-format=berkeley\c +\|'). The default is the one-line format similar to +Berkeley's. + +.TP +.B \-\-help +Show a summary of acceptable arguments and options. + +.TP +.B \-d +.TP +.B \-o +.TP +.B \-x +.TP +.BI "\-\-radix " "number" +Using one of these options, you can control whether the size of each +section is given in decimal (`\|\c +.B \-d\c +\|', or `\|\c +.B \-\-radix 10\c +\|'); octal +(`\|\c +.B \-o\c +\|', or `\|\c +.B \-\-radix 8\c +\|'); or hexadecimal (`\|\c +.B \-x\c +\|', or +`\|\c +.B \-\-radix 16\c +\|'). In `\|\c +.B \-\-radix \c +.I number\c +\&\c +\|', only the three +values (8, 10, 16) are supported. The total size is always given in two +radices; decimal and hexadecimal for `\|\c +.B \-d\c +\|' or `\|\c +.B \-x\c +\|' output, or +octal and hexadecimal if you're using `\|\c +.B \-o\c +\|'. + +.TP +.BI "\-\-target " "bfdname" +You can specify a particular object-code format for \c +.I objfile\c +\& as +\c +.I bfdname\c +\&. This may not be necessary; \c +.I size\c +\& can +automatically recognize many formats. See +.BR objdump ( 1 ) +for information +on listing available formats. + +.TP +.B \-V +.TP +.B \-\-version +Display version number information on \c +.B size\c +\& itself. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.BR info ; +.IR "The GNU Binary Utilities" , + Roland H. Pesch (October 1991); +.BR ar "(" 1 ")," +.BR objdump ( 1 ). + +.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/gnu/usr.bin/binutils/binutils/size.c b/gnu/usr.bin/binutils/binutils/size.c new file mode 100644 index 00000000000..cf460574514 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/size.c @@ -0,0 +1,428 @@ +/* size.c -- report size of various sections of an executable file. + Copyright 1991, 92, 93, 94 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Extensions/incompatibilities: + o - BSD output has filenames at the end. + o - BSD output can appear in different radicies. + o - SysV output has less redundant whitespace. Filename comes at end. + o - SysV output doesn't show VMA which is always the same as the PMA. + o - We also handle core files. + o - We also handle archives. + If you write shell scripts which manipulate this info then you may be + out of luck; there's no --compatibility or --pedantic option. +*/ + +#include "bfd.h" +#include "getopt.h" +#include "bucomm.h" +#include "libiberty.h" + +#ifndef BSD_DEFAULT +#define BSD_DEFAULT 1 +#endif + +/* Program options. */ + +enum + { + decimal, octal, hex + } radix = decimal; +int berkeley_format = BSD_DEFAULT; /* 0 means use AT&T-style output. */ +int show_version = 0; +int show_help = 0; + +/* Program exit status. */ +int return_code = 0; + +/* IMPORTS */ +extern char *program_version; +extern char *target; + +/* Forward declarations */ + +static void display_file PARAMS ((char *filename)); + +static void print_sizes PARAMS ((bfd * file)); + +static void berkeley_sum PARAMS ((bfd *, sec_ptr, PTR)); + +void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, "\ +Usage: %s [-ABdoxV] [--format=berkeley|sysv] [--radix=8|10|16]\n\ + [--target=bfdname] [--version] [--help] [file...]\n", program_name); +#if BSD_DEFAULT + fputs ("default is --format=berkeley\n", stream); +#else + fputs ("default is --format=sysv\n", stream); +#endif + list_supported_targets (program_name, stream); + exit (status); +} + +struct option long_options[] = +{ + {"format", required_argument, 0, 200}, + {"radix", required_argument, 0, 201}, + {"target", required_argument, 0, 202}, + {"version", no_argument, &show_version, 1}, + {"help", no_argument, &show_help, 1}, + {0, no_argument, 0, 0} +}; + +int +main (argc, argv) + int argc; + char **argv; +{ + int temp; + int c; + + program_name = *argv; + xmalloc_set_program_name (program_name); + + bfd_init (); + + while ((c = getopt_long (argc, argv, "ABVdox", long_options, + (int *) 0)) != EOF) + switch (c) + { + case 200: /* --format */ + switch (*optarg) + { + case 'B': + case 'b': + berkeley_format = 1; + break; + case 'S': + case 's': + berkeley_format = 0; + break; + default: + fprintf (stderr, "invalid argument to --format: %s\n", optarg); + usage (stderr, 1); + } + break; + + case 202: /* --target */ + target = optarg; + break; + + case 201: /* --radix */ +#ifdef ANSI_LIBRARIES + temp = strtol (optarg, NULL, 10); +#else + temp = atol (optarg); +#endif + switch (temp) + { + case 10: + radix = decimal; + break; + case 8: + radix = octal; + break; + case 16: + radix = hex; + break; + default: + printf ("Invalid radix: %s\n", optarg); + usage (stderr, 1); + } + break; + + case 'A': + berkeley_format = 0; + break; + case 'B': + berkeley_format = 1; + break; + case 'V': + show_version = 1; + break; + case 'd': + radix = decimal; + break; + case 'x': + radix = hex; + break; + case 'o': + radix = octal; + break; + case 0: + break; + case '?': + usage (stderr, 1); + } + + if (show_version) + { + printf ("GNU %s version %s\n", program_name, program_version); + exit (0); + } + if (show_help) + usage (stdout, 0); + + if (optind == argc) + display_file ("a.out"); + else + for (; optind < argc;) + display_file (argv[optind++]); + + return return_code; +} + +/* Display stats on file or archive member ABFD. */ + +void +display_bfd (abfd) + bfd *abfd; +{ + char **matching; + + if (bfd_check_format (abfd, bfd_archive)) + /* An archive within an archive. */ + return; + + if (bfd_check_format_matches (abfd, bfd_object, &matching)) + { + print_sizes (abfd); + printf ("\n"); + return; + } + + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + bfd_nonfatal (bfd_get_filename (abfd)); + list_matching_formats (matching); + free (matching); + return_code = 3; + return; + } + + if (bfd_check_format_matches (abfd, bfd_core, &matching)) + { + CONST char *core_cmd; + + print_sizes (abfd); + fputs (" (core file", stdout); + + core_cmd = bfd_core_file_failing_command (abfd); + if (core_cmd) + printf (" invoked as %s", core_cmd); + + puts (")\n"); + return; + } + + bfd_nonfatal (bfd_get_filename (abfd)); + + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + + return_code = 3; +} + +static void +display_archive (file) + bfd *file; +{ + bfd *arfile = (bfd *) NULL; + + for (;;) + { + bfd_set_error (bfd_error_no_error); + + arfile = bfd_openr_next_archived_file (file, arfile); + if (arfile == NULL) + { + if (bfd_get_error () != bfd_error_no_more_archived_files) + { + bfd_nonfatal (bfd_get_filename (file)); + return_code = 2; + } + break; + } + + display_bfd (arfile); + /* Don't close the archive elements; we need them for next_archive */ + } +} + +static void +display_file (filename) + char *filename; +{ + bfd *file = bfd_openr (filename, target); + if (file == NULL) + { + bfd_nonfatal (filename); + return_code = 1; + return; + } + + if (bfd_check_format (file, bfd_archive) == true) + display_archive (file); + else + display_bfd (file); + + if (bfd_close (file) == false) + { + bfd_nonfatal (filename); + return_code = 1; + return; + } +} + +/* This is what lexical functions are for. */ + +void +lprint_number (width, num) + int width; + bfd_size_type num; +{ + printf ((radix == decimal ? "%-*lu\t" : + ((radix == octal) ? "%-*lo\t" : "%-*lx\t")), + width, (unsigned long) num); +} + +void +rprint_number (width, num) + int width; + bfd_size_type num; +{ + printf ((radix == decimal ? "%*lu\t" : + ((radix == octal) ? "%*lo\t" : "%*lx\t")), + width, (unsigned long) num); +} + +static bfd_size_type bsssize; +static bfd_size_type datasize; +static bfd_size_type textsize; + +static void +berkeley_sum (abfd, sec, ignore) + bfd *abfd; + sec_ptr sec; + PTR ignore; +{ + bfd_size_type size; + + size = bfd_get_section_size_before_reloc (sec); + if (bfd_get_section_flags (abfd, sec) & SEC_CODE) + textsize += size; + else if (bfd_get_section_flags (abfd, sec) & SEC_DATA) + datasize += size; + else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC) + bsssize += size; +} + +void +print_berkeley_format (abfd) + bfd *abfd; +{ + static int files_seen = 0; + bfd_size_type total; + + bsssize = 0; + datasize = 0; + textsize = 0; + + bfd_map_over_sections (abfd, berkeley_sum, (PTR) NULL); + + if (files_seen++ == 0) +#if 0 + /* Intel doesn't like bss/stk because they don't have core files. */ + puts ((radix == octal) ? "text\tdata\tbss/stk\toct\thex\tfilename" : + "text\tdata\tbss/stk\tdec\thex\tfilename"); +#else + puts ((radix == octal) ? "text\tdata\tbss\toct\thex\tfilename" : + "text\tdata\tbss\tdec\thex\tfilename"); +#endif + + total = textsize + datasize + bsssize; + + lprint_number (7, textsize); + lprint_number (7, datasize); + lprint_number (7, bsssize); + printf (((radix == octal) ? "%-7lo\t%-7lx\t" : "%-7lu\t%-7lx\t"), + (unsigned long) total, (unsigned long) total); + + fputs (bfd_get_filename (abfd), stdout); + if (bfd_my_archive (abfd)) + printf (" (ex %s)", bfd_get_filename (bfd_my_archive (abfd))); +} + +/* I REALLY miss lexical functions! */ +bfd_size_type svi_total = 0; + +void +sysv_internal_printer (file, sec, ignore) + bfd *file; + sec_ptr sec; + PTR ignore; +{ + bfd_size_type size = bfd_section_size (file, sec); + if (!bfd_is_abs_section (sec) + && !bfd_is_com_section (sec) + && !bfd_is_und_section (sec)) + { + svi_total += size; + + printf ("%-12s", bfd_section_name (file, sec)); + rprint_number (8, size); + printf (" "); + rprint_number (8, bfd_section_vma (file, sec)); + printf ("\n"); + } +} + +void +print_sysv_format (file) + bfd *file; +{ + svi_total = 0; + + printf ("%s ", bfd_get_filename (file)); + if (bfd_my_archive (file)) + printf (" (ex %s)", bfd_get_filename (bfd_my_archive (file))); + + puts (":\nsection\t\tsize\t addr"); + bfd_map_over_sections (file, sysv_internal_printer, (PTR) NULL); + + printf ("Total "); + rprint_number (8, svi_total); + printf ("\n\n"); +} + +static void +print_sizes (file) + bfd *file; +{ + if (berkeley_format) + print_berkeley_format (file); + else + print_sysv_format (file); +} diff --git a/gnu/usr.bin/binutils/binutils/srconv.c b/gnu/usr.bin/binutils/binutils/srconv.c new file mode 100644 index 00000000000..ba227fae9cc --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/srconv.c @@ -0,0 +1,2023 @@ +/* srconv.c -- Sysroff conversion program + Copyright (C) 1994 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public 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 Steve Chamberlain (sac@cygnus.com) + + This program can be used to convert a coff object file + into a Hitachi OM/LM (Sysroff) format. + + All debugging information is preserved */ + +#include +#include "bucomm.h" +#include "sysroff.h" +#include "coffgrok.h" +#include +#include + +#include "coff/internal.h" +#include "../bfd/libcoff.h" + +#define PROGRAM_VERSION "1.5" +/*#define FOOP1 1 */ + +static int sh; +static int h8300; +static void wr_cs (); +static void walk_tree_scope (); +static void wr_globals (); +static int find_base (); + +static FILE *file; +static bfd *abfd; +static int debug = 0; +static int quick = 0; +static int noprescan = 0; +static struct coff_ofile *tree; +/* Obsolete ?? + static int absolute_p; + */ + +static int segmented_p; +static int code; + +static int ids1[20000]; +static int ids2[20000]; + +static int base1 = 0x18; +static int base2 = 0x2018; + +char * +xcalloc (a, b) + int a; + int b; +{ + char *r = xmalloc (a * b); + memset (r, 0, a * b); + return r; +} + +static int +get_member_id (x) + int x; +{ + if (ids2[x]) + { + return ids2[x]; + } + ids2[x] = base2++; + return ids2[x]; +} + +static int +get_ordinary_id (x) + int x; +{ + if (ids1[x]) + { + return ids1[x]; + } + ids1[x] = base1++; + return ids1[x]; +} +static char * +section_translate (n) + char *n; +{ + if (strcmp (n, ".text") == 0) + return "P"; + if (strcmp (n, ".data") == 0) + return "D"; + if (strcmp (n, ".bss") == 0) + return "B"; + return n; +} + + + +#define DATE "940201073000"; /* Just a time on my birthday */ + + +static +char * +strip_suffix (name) + char *name; +{ + int i; + char *res; + for (i = 0; name[i] != 0 && name[i] != '.'; i++) + ; + res = (char *) xmalloc (i + 1); + memcpy (res, name, i); + res[i] = 0; + return res; +} + + +/* IT LEN stuff CS */ +static void +checksum (file, ptr, size, code) + FILE *file; + char *ptr; + int size; + int code; +{ + int j; + int last; + int sum = 0; + int bytes = size / 8; + last = !(code & 0xff00); + if (size & 0x7) + abort (); + ptr[0] = code | (last ? 0x80 : 0); + ptr[1] = bytes + 1; + + for (j = 0; j < bytes; j++) + { + sum += ptr[j]; + } + /* Glue on a checksum too */ + ptr[bytes] = ~sum; + fwrite (ptr, bytes + 1, 1, file); +} + + + + +static void +writeINT (n, ptr, idx, size, file) + int n; + char *ptr; + int *idx; + int size; + FILE *file; +{ + int byte = *idx / 8; + + if (size == -2) + { + if (sh) + size = 4; + else if (h8300) + size = 2; + } + else if (size == -1) + size = 0; + + if (byte > 240) + { + /* Lets write out that record and do another one */ + checksum (file, ptr, *idx, code | 0x1000); + *idx = 16; + byte = *idx / 8; + } + switch (size) + { + case 0: + break; + case 1: + ptr[byte] = n; + break; + case 2: + ptr[byte + 0] = n >> 8; + ptr[byte + 1] = n; + break; + case 4: + ptr[byte + 0] = n >> 24; + ptr[byte + 1] = n >> 16; + ptr[byte + 2] = n >> 8; + ptr[byte + 3] = n >> 0; + break; + default: + abort (); + } + *idx += size * 8; +} + + +static void +writeBITS (val, ptr, idx, size) + int val; + char *ptr; + int *idx; + int size; +{ + int byte = *idx / 8; + int bit = *idx % 8; + int old; + *idx += size; + + old = ptr[byte]; + /* Turn off all about to change bits */ + old &= ~((~0 >> (8 - bit - size)) & ((1 << size) - 1)); + /* Turn on the bits we want */ + old |= (val & ((1 << size) - 1)) << (8 - bit - size); + ptr[byte] = old; +} + +static void +writeBARRAY (data, ptr, idx, size, file) + barray data; + char *ptr; + int *idx; + int size; + FILE *file; +{ + int i; + writeINT (data.len, ptr, idx, 1, file); + for (i = 0; i < data.len; i++) + { + writeINT (data.data[i], ptr, idx, 1, file); + } +} + + +static void +writeCHARS (string, ptr, idx, size, file) + char *string; + char *ptr; + int *idx; + int size; + FILE *file; +{ + int i = *idx / 8; + + if (i > 240) + { + /* Lets write out that record and do another one */ + checksum (file, ptr, *idx, code | 0x1000); + *idx = 16; + i = *idx / 8; + } + + if (size == 0) + { + /* Variable length string */ + size = strlen (string); + ptr[i++] = size; + } + + /* BUG WAITING TO HAPPEN */ + memcpy (ptr + i, string, size); + i += size; + *idx = i * 8; +} + +#define SYSROFF_SWAP_OUT +#include "sysroff.c" + + +static char *rname_sh[] = +{ + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15" +}; + +static char *rname_h8300[] = +{ + "ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "ER7", "PC", "CCR" +}; + +static void +wr_tr () +{ + /* The TR block is not normal - it doesn't have any contents. */ + + static char b[] = { + 0xff, /* IT */ + 0x03, /* RL */ + 0xfd, /* CS */ + }; + fwrite (b, 1, sizeof (b), file); +} + +static void +wr_un (ptr, sfile, first, nsecs) + struct coff_ofile *ptr; + struct coff_sfile *sfile; + int first; + int nsecs; +{ + struct IT_un un; + + struct coff_symbol *s; + + un.spare1 = 0; + + if (abfd->flags & EXEC_P) + un.format = FORMAT_LM; + else + un.format = FORMAT_OM; + un.spare1 = 0; + + +#if 0 + un.nsections = ptr->nsections - 1; /* Don't count the abs section */ +#else + /*NEW - only count sections with size */ + un.nsections = nsecs; +#endif + + un.nextdefs = 0; + un.nextrefs = 0; + /* Count all the undefined and defined variables with global scope */ + + if (first) + { + for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list) + { + if (s->visible->type == coff_vis_ext_def + || s->visible->type == coff_vis_common) + un.nextdefs++; + + if (s->visible->type == coff_vis_ext_ref) + un.nextrefs++; + } + } + if (sh) + un.tool = "C_SH"; + else if (h8300) + un.tool = "C_H8/300H"; + un.tcd = DATE; + un.linker = "L_GX00"; + un.lcd = DATE; + un.name = sfile->name; + sysroff_swap_un_out (file, &un); +} + + +static void +wr_hd (p) + struct coff_ofile *p; +{ + struct IT_hd hd; + + hd.spare1 = 0; + if (abfd->flags & EXEC_P) + { + hd.mt = MTYPE_ABS_LM; + } + else + { + hd.mt = MTYPE_OMS_OR_LMS; + } + hd.cd = DATE; + + hd.nu = p->nsources; /* Always one unit */ + hd.code = 0; /* Always ASCII */ + hd.ver = "0200"; /* Version 2.00 */ + switch (abfd->arch_info->arch) + { + case bfd_arch_h8300: + hd.au = 8; + hd.si = 32; + hd.afl = 2; + hd.spcsz = 0; + hd.segsz = 0; + hd.segsh = 0; + hd.cpu = "H8300H"; + h8300 = 1; + break; + case bfd_arch_sh: + hd.au = 8; + hd.si = 32; + hd.afl = 4; + hd.spcsz = 0; + hd.segsz = 0; + hd.segsh = 0; + hd.cpu = "SH"; + sh = 1; + break; + default: + abort (); + } + + if (!abfd->flags & EXEC_P) + { + hd.ep = 0; + } + else + { + hd.ep = 1; + hd.uan = 0; + hd.sa = 0; + hd.sad = 0; + hd.address = bfd_get_start_address (abfd); + } + + hd.os = ""; + hd.sys = ""; + hd.mn = strip_suffix (abfd->filename); + + + sysroff_swap_hd_out (file, &hd); +} + + +static void +wr_sh (p, sec) + struct coff_ofile *p; + struct coff_section *sec; +{ + struct IT_sh sh; + sh.unit = 0; + sh.section = sec->number; +#ifdef FOOP1 + sh.section = 0; +#endif + sysroff_swap_sh_out (file, &sh); +} + + +static void +wr_ob (p, section) + struct coff_ofile *p; + struct coff_section *section; +{ + int i; + int first = 1; + unsigned char stuff[200]; + + i = 0; + while (i < section->bfd_section->_raw_size) + { + struct IT_ob ob; + int todo = 200; /* Copy in 200 byte lumps */ + ob.spare = 0; + if (i + todo > section->bfd_section->_raw_size) + todo = section->bfd_section->_raw_size - i; + + if (first) + { + ob.saf = 1; + if (abfd->flags & EXEC_P) + ob.address = section->address; + else + ob.address = 0; + + first = 0; + } + else + { + ob.saf = 0; + } + + ob.cpf = 0; /* Never compress */ + ob.data.len = todo; + bfd_get_section_contents (abfd, section->bfd_section, stuff, i, todo); + ob.data.data = stuff; + sysroff_swap_ob_out (file, &ob /*, i + todo < section->size */ ); + i += todo; + } + /* Now fill the rest with blanks */ + while (i < section->size) + { + struct IT_ob ob; + int todo = 200; /* Copy in 200 byte lumps */ + ob.spare = 0; + if (i + todo > section->size) + todo = section->size - i; + ob.saf = 0; + + ob.cpf = 0; /* Never compress */ + ob.data.len = todo; + memset (stuff, 0, todo); + ob.data.data = stuff; + sysroff_swap_ob_out (file, &ob); + i += todo; + } + /* Now fill the rest with blanks */ + +} + +static void +wr_rl (ptr, sec) + struct coff_ofile *ptr; + struct coff_section *sec; +{ + int nr = sec->nrelocs; + int i; + for (i = 0; i < nr; i++) + { + struct coff_reloc *r = sec->relocs + i; + struct coff_symbol *ref; + struct IT_rl rl; + rl.apol = 0; + rl.boundary = 0; + rl.segment = 1; + rl.sign = 0; + rl.check = 0; + rl.addr = r->offset; + rl.bitloc = 0; + rl.flen = 32; /* SH Specific */ + /* What sort of reloc ? Look in the section to find out */ + ref = r->symbol; + if (ref->visible->type == coff_vis_ext_ref) + { + rl.bcount = 4; /* Always 4 for us */ + rl.op = OP_EXT_REF; + rl.symn = ref->er_number; + } + else if (ref->visible->type == coff_vis_common) + { + rl.bcount = 11; /* Always 11 for us */ + rl.op = OP_SEC_REF; + rl.secn = ref->where->section->number; + rl.copcode_is_3 = 3; + rl.alength_is_4 = 4; + rl.addend = ref->where->offset - ref->where->section->address; + rl.aopcode_is_0x20 = 0x20; + } + + else + { + rl.bcount = 11; /* Always 11 for us */ + rl.op = OP_SEC_REF; + rl.secn = ref->where->section->number; + rl.copcode_is_3 = 3; + rl.alength_is_4 = 4; + rl.addend = -ref->where->section->address; + rl.aopcode_is_0x20 = 0x20; + } + rl.end = 0xff; + if (rl.op == OP_SEC_REF + || rl.op == OP_EXT_REF) + { + sysroff_swap_rl_out (file, &rl); + } + } +} + +static void +wr_object_body (p) + struct coff_ofile *p; +{ + int i; + for (i = 1; i < p->nsections; i++) + { + wr_sh (p, p->sections + i); + wr_ob (p, p->sections + i); + wr_rl (p, p->sections + i); + } +} + +static void +wr_dps_start (sfile, section, scope, type, nest) + struct coff_sfile *sfile; + struct coff_section *section; + struct coff_scope *scope; + int type; + int nest; +{ + struct IT_dps dps; + dps.end = 0; + dps.opt = 0; + dps.type = type; + if (scope->sec) + { + dps.san = scope->sec->number; + dps.address = scope->offset - find_base (sfile, scope->sec); + dps.block_size = scope->size; + if (debug) + { + printf ("DPS %s %d %x\n", + sfile->name, + nest, + dps.address); + + } + } + else + { + dps.san = 0; + dps.address = 0; + dps.block_size = 0; + } + + dps.nesting = nest; + dps.neg = 0x1001; + sysroff_swap_dps_out (file, &dps); +} + +static void +wr_dps_end (section, scope, type) + struct coff_section *section; + struct coff_scope *scope; + int type; +{ + struct IT_dps dps; + dps.end = 1; + dps.type = type; + sysroff_swap_dps_out (file, &dps); +} + +static int * +nints (x) + int x; +{ + return (int *) (xcalloc (sizeof (int), x)); +} + +static void walk_tree_symbol (); +static void +walk_tree_type_1 (sfile, symbol, type, nest) + struct coff_sfile *sfile; + struct coff_symbol *symbol; + struct coff_type *type; + int nest; +{ + switch (type->type) + { + case coff_secdef_type: + case coff_basic_type: + { + struct IT_dbt dbt; + + switch (type->u.basic) + { + case T_NULL: + case T_VOID: + dbt.btype = BTYPE_VOID; + dbt.sign = BTYPE_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + break; + case T_CHAR: + dbt.btype = BTYPE_CHAR; + dbt.sign = BTYPE_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + break; + case T_SHORT: + case T_INT: + case T_LONG: + dbt.btype = BTYPE_INT; + dbt.sign = SIGN_SIGNED; + dbt.fptype = FPTYPE_NOTSPEC; + break; + case T_FLOAT: + dbt.btype = BTYPE_FLOAT; + dbt.fptype = FPTYPE_SINGLE; + break; + case T_DOUBLE: + dbt.btype = BTYPE_FLOAT; + dbt.fptype = FPTYPE_DOUBLE; + break; + case T_LNGDBL: + dbt.btype = BTYPE_FLOAT; + dbt.fptype = FPTYPE_EXTENDED; + break; + case T_UCHAR: + dbt.btype = BTYPE_CHAR; + dbt.sign = SIGN_UNSIGNED; + dbt.fptype = FPTYPE_NOTSPEC; + break; + case T_USHORT: + case T_UINT: + case T_ULONG: + dbt.btype = BTYPE_INT; + dbt.sign = SIGN_UNSIGNED; + dbt.fptype = FPTYPE_NOTSPEC; + break; + } + dbt.bitsize = type->size; + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + break; + } + case coff_pointer_type: + { + struct IT_dpt dpt; + walk_tree_type_1 (sfile, symbol, type->u.pointer.points_to, nest + 1); + dpt.neg = 0x1001; + sysroff_swap_dpt_out (file, &dpt); + break; + } + + case coff_function_type: + { + struct IT_dfp dfp; + struct coff_symbol *param; + dfp.end = 0; + dfp.spare = 0; + dfp.nparams = type->u.function.parameters->nvars; + dfp.neg = 0x1001; + + walk_tree_type_1 (sfile, symbol, type->u.function.function_returns, nest + 1); + + sysroff_swap_dfp_out (file, &dfp); + + for (param = type->u.function.parameters->vars_head; + param; + param = param->next) + { + walk_tree_symbol (sfile, 0, param, nest); + } + dfp.end = 1; + sysroff_swap_dfp_out (file, &dfp); + break; + } + + case coff_structdef_type: + { + struct IT_dbt dbt; + struct IT_dds dds; + struct coff_symbol *member; + dds.spare = 0; + dbt.btype = BTYPE_STRUCT; + dbt.bitsize = type->size; + dbt.sign = SIGN_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + dbt.sid = get_member_id (type->u.astructdef.idx); + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + dds.end = 0; + dds.neg = 0x1001; + sysroff_swap_dds_out (file, &dds); + for (member = type->u.astructdef.elements->vars_head; + member; + member = member->next) + { + walk_tree_symbol (sfile, 0, member, nest + 1); + } + + dds.end = 1; + sysroff_swap_dds_out (file, &dds); + + } + break; + case coff_structref_type: + { + struct IT_dbt dbt; + dbt.btype = BTYPE_TAG; + dbt.bitsize = type->size; + dbt.sign = SIGN_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + if (type->u.astructref.ref) + { + dbt.sid = get_member_id (type->u.astructref.ref->number); + } + else + { + dbt.sid = 0; + } + + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + } + break; + case coff_array_type: + { + struct IT_dar dar; + int j; + int dims = 1; /* Only output one dimension at a time */ + dar.dims = dims; + dar.variable = nints (dims); + dar.subtype = nints (dims); + dar.spare = nints (dims); + dar.max_variable = nints (dims); + dar.maxspare = nints (dims); + dar.max = nints (dims); + dar.min_variable = nints (dims); + dar.min = nints (dims); + dar.minspare = nints (dims); + dar.neg = 0x1001; + dar.length = type->size / type->u.array.dim; + for (j = 0; j < dims; j++) + { + dar.variable[j] = VARIABLE_FIXED; + dar.subtype[j] = SUB_INTEGER; + dar.spare[j] = 0; + dar.max_variable[j] = 0; + dar.max[j] = type->u.array.dim; + dar.min_variable[j] = 0; + dar.min[j] = 1; /* Why isn't this 0 ? */ + } + walk_tree_type_1 (sfile, symbol, type->u.array.array_of, nest + 1); + sysroff_swap_dar_out (file, &dar); + } + break; + case coff_enumdef_type: + { + struct IT_dbt dbt; + struct IT_den den; + struct coff_symbol *member; + dbt.btype = BTYPE_ENUM; + dbt.bitsize = type->size; + dbt.sign = SIGN_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + dbt.sid = get_member_id (type->u.aenumdef.idx); + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + + den.end = 0; + den.neg = 0x1001; + den.spare = 0; + sysroff_swap_den_out (file, &den); + for (member = type->u.aenumdef.elements->vars_head; + member; + member = member->next) + { + walk_tree_symbol (sfile, 0, member, nest + 1); + } + + den.end = 1; + sysroff_swap_den_out (file, &den); + } + break; + + break; + case coff_enumref_type: + { + struct IT_dbt dbt; + dbt.btype = BTYPE_TAG; + dbt.bitsize = type->size; + dbt.sign = SIGN_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + dbt.sid = get_member_id (type->u.aenumref.ref->number); + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + } + break; + default: + abort (); + } +} + +/* Obsolete ? + static void + dty_start () + { + struct IT_dty dty; + dty.end = 0; + dty.neg = 0x1001; + dty.spare = 0; + sysroff_swap_dty_out (file, &dty); + } + + static void + dty_stop () + { + struct IT_dty dty; + dty.end = 0; + dty.neg = 0x1001; + dty.end = 1; + sysroff_swap_dty_out (file, &dty); + } + + + static void + dump_tree_structure (sfile, symbol, type, nest) + struct coff_sfile *sfile; + struct coff_symbol *symbol; + struct coff_type *type; + int nest; + { + if (symbol->type->type == coff_function_type) + { + + + } + + } + */ + +static void +walk_tree_type (sfile, symbol, type, nest) + + struct + coff_sfile *sfile; + struct coff_symbol *symbol; + struct coff_type *type; + int nest; +{ + if (symbol->type->type == coff_function_type) + { + + struct IT_dty dty; + dty.end = 0; + dty.neg = 0x1001; + + sysroff_swap_dty_out (file, &dty); + walk_tree_type_1 (sfile, symbol, type, nest); + dty.end = 1; + sysroff_swap_dty_out (file, &dty); + + wr_dps_start (sfile, + symbol->where->section, + symbol->type->u.function.code, + BLOCK_TYPE_FUNCTION, nest); + wr_dps_start (sfile, symbol->where->section, + symbol->type->u.function.code, + BLOCK_TYPE_BLOCK, nest); + walk_tree_scope (symbol->where->section, + sfile, + symbol->type->u.function.code, + nest + 1, BLOCK_TYPE_BLOCK); + + wr_dps_end (symbol->where->section, + symbol->type->u.function.code, + BLOCK_TYPE_BLOCK); + wr_dps_end (symbol->where->section, + symbol->type->u.function.code, BLOCK_TYPE_FUNCTION); + + } + else + { + struct IT_dty dty; + dty.end = 0; + dty.neg = 0x1001; + sysroff_swap_dty_out (file, &dty); + walk_tree_type_1 (sfile, symbol, type, nest); + dty.end = 1; + sysroff_swap_dty_out (file, &dty); + } + +} + + + +static void +walk_tree_symbol (sfile, section, symbol, nest) + struct coff_sfile *sfile; + struct coff_section *section; + struct coff_symbol *symbol; + int nest; +{ + struct IT_dsy dsy; + + dsy.spare2 = 0; + dsy.nesting = nest; + + switch (symbol->type->type) + { + case coff_function_type: + dsy.type = STYPE_FUNC; + dsy.assign = 1; + break; + case coff_structref_type: + case coff_pointer_type: + case coff_array_type: + case coff_basic_type: + case coff_enumref_type: + dsy.type = STYPE_VAR; + dsy.assign = 1; + break; + case coff_enumdef_type: + dsy.type = STYPE_TAG; + dsy.assign = 0; + dsy.magic = 2; + break; + case coff_structdef_type: + dsy.type = STYPE_TAG; + dsy.assign = 0; + dsy.magic = symbol->type->u.astructdef.isstruct ? 0 : 1; + break; + case coff_secdef_type: + return; + default: + abort (); + } + + if (symbol->where->where == coff_where_member_of_struct) + { + dsy.assign = 0; + dsy.type = STYPE_MEMBER; + } + if (symbol->where->where == coff_where_member_of_enum) + { + dsy.type = STYPE_ENUM; + dsy.assign = 0; + dsy.evallen = 4; + dsy.evalue = symbol->where->offset; + } + + if (symbol->type->type == coff_structdef_type + || symbol->where->where == coff_where_entag + || symbol->where->where == coff_where_strtag) + { + dsy.snumber = get_member_id (symbol->number); + } + else + { + dsy.snumber = get_ordinary_id (symbol->number); + } + + + dsy.sname = symbol->name[0] == '_' ? symbol->name + 1 : symbol->name; + + switch (symbol->visible->type) + { + case coff_vis_common: + case coff_vis_ext_def: + dsy.ainfo = AINFO_STATIC_EXT_DEF; + break; + case coff_vis_ext_ref: + dsy.ainfo = AINFO_STATIC_EXT_REF; + break; + case coff_vis_int_def: + dsy.ainfo = AINFO_STATIC_INT; + break; + case coff_vis_auto: + case coff_vis_autoparam: + dsy.ainfo = AINFO_AUTO; + break; + case coff_vis_register: + case coff_vis_regparam: + dsy.ainfo = AINFO_REG; + break; + break; + case coff_vis_tag: + case coff_vis_member_of_struct: + case coff_vis_member_of_enum: + break; + default: + abort (); + } + + dsy.dlength = symbol->type->size; + switch (symbol->where->where) + { + case coff_where_memory: + + dsy.section = symbol->where->section->number; +#ifdef FOOP + dsy.section = 0; +#endif + break; + case coff_where_member_of_struct: + case coff_where_member_of_enum: + case coff_where_stack: + case coff_where_register: + case coff_where_unknown: + case coff_where_strtag: + + case coff_where_entag: + case coff_where_typedef: + break; + default: + abort (); + } + + switch (symbol->where->where) + { + case coff_where_memory: + dsy.address = symbol->where->offset - find_base (sfile, symbol->where->section); + break; + case coff_where_stack: + dsy.address = symbol->where->offset; + break; + case coff_where_member_of_struct: + + + if (symbol->where->bitsize) + { + int bits = (symbol->where->offset * 8 + symbol->where->bitoffset); + dsy.bitunit = 1; + dsy.field_len = symbol->where->bitsize; + dsy.field_off = (bits / 32) * 4; + dsy.field_bitoff = bits % 32; + } + else + { + dsy.bitunit = 0; + + dsy.field_len = symbol->type->size; + dsy.field_off = symbol->where->offset; + } + break; + case coff_where_member_of_enum: + /* dsy.bitunit = 0; + dsy.field_len = symbol->type->size; + dsy.field_off = symbol->where->offset; */ + break; + case coff_where_register: + case coff_where_unknown: + case coff_where_strtag: + + case coff_where_entag: + case coff_where_typedef: + break; + default: + abort (); + } + + if (symbol->where->where == coff_where_register) + { + if (sh) + dsy.reg = rname_sh[symbol->where->offset]; + else if (h8300) + dsy.reg = rname_h8300[symbol->where->offset]; + } + + switch (symbol->visible->type) + { + case coff_vis_common: + /* We do this 'cause common C symbols are treated as extdefs */ + case coff_vis_ext_def: + case coff_vis_ext_ref: + + dsy.ename = symbol->name; + break; + + case coff_vis_regparam: + case coff_vis_autoparam: + dsy.type = STYPE_PARAMETER; + break; + + case coff_vis_int_def: + + case coff_vis_auto: + case coff_vis_register: + case coff_vis_tag: + case coff_vis_member_of_struct: + case coff_vis_member_of_enum: + break; + default: + abort (); + } + + dsy.sfn = 0; + dsy.sln = 2; + + dsy.neg = 0x1001; + + + sysroff_swap_dsy_out (file, &dsy); + + walk_tree_type (sfile, symbol, symbol->type, nest); +} + + +static void +walk_tree_scope (section, sfile, scope, nest, type) + struct coff_section *section; + struct coff_sfile *sfile; + struct coff_scope *scope; + int nest; + int type; +{ + struct coff_symbol *vars; + struct coff_scope *child; + + if (scope->vars_head + || (scope->list_head && scope->list_head->vars_head)) + { + wr_dps_start (sfile, section, scope, type, nest); + + if (nest == 0) + wr_globals (tree, sfile, nest + 1); + + for (vars = scope->vars_head; vars; vars = vars->next) + { + walk_tree_symbol (sfile, section, vars, nest); + } + + for (child = scope->list_head; child; child = child->next) + { + walk_tree_scope (section, sfile, child, nest + 1, BLOCK_TYPE_BLOCK); + } + + wr_dps_end (section, scope, type); + } +} +static void +walk_tree_sfile (section, sfile) + struct coff_section *section; + struct coff_sfile *sfile; +{ + walk_tree_scope (section, sfile, sfile->scope, 0, BLOCK_TYPE_COMPUNIT); + +} + +static void +wr_program_structure (p, sfile) + struct coff_ofile *p; + struct coff_sfile *sfile; +{ + + walk_tree_sfile (p->sections + 4, sfile); + +} + +static void +wr_du (p, sfile, n) + struct coff_ofile *p; + struct coff_sfile *sfile; + int n; +{ + struct IT_du du; + int lim; +#if 0 + struct coff_symbol *symbol; + static int incit = 0x500000; + int used = 0; +#endif + int i; + int j; + unsigned int *lowest = (unsigned *) nints (p->nsections); + unsigned int *highest = (unsigned *) nints (p->nsections); + du.spare = 0; + du.format = abfd->flags & EXEC_P ? 0 : 1; + du.optimized = 0; + du.unit = n; + du.sections = p->nsections - 1; + du.san = (int *) xcalloc (sizeof (int), du.sections); + du.address = nints (du.sections); + du.length = nints (du.sections); + + for (i = 0; i < du.sections; i++) + { + lowest[i] = ~0; + highest[i] = 0; + } + + /* Look through all the symbols and try and work out the extents in this + source file */ +#if 0 + for (symbol = sfile->scope->vars_head; + symbol; + symbol = symbol->next) + { + if (symbol->type->type == coff_secdef_type) + { + unsigned int low = symbol->where->offset; + unsigned int high = symbol->where->offset + symbol->type->size - 1; + struct coff_section *section = symbol->where->section; + + int sn = section->number; + if (low < lowest[sn]) + lowest[sn] = low; + if (high > highest[sn]) + highest[sn] = high; + } + } + + + for (i = 0; i < du.sections; i++) + { + if (highest[i] == 0) + { + lowest[i] = highest[i] = incit; + } + du.san[used] = i; + du.length[used] = highest[i] - lowest[i]; + du.address[used] = abfd->flags & EXEC_P ? lowest[i] : 0; + if (debug) + { + printf (" section %6s 0x%08x..0x%08x\n", + p->sections[i + 1].name, + lowest[i], + highest[i]); + } + used++; + } + +#endif + lim = du.sections; + for (j = 0; j < lim; j++) + { + int src = j; + int dst = j; + du.san[dst] = dst; + if (sfile->section[src].init) + { + du.length[dst] + = sfile->section[src].high - sfile->section[src].low + 1; + du.address[dst] + = sfile->section[src].low; + } + else + { + du.length[dst] = 0; + du.address[dst] = 0; + } + if (debug) + { + if (sfile->section[src].parent) + { + printf (" section %6s 0x%08x..0x%08x\n", + sfile->section[src].parent->name, + du.address[dst], + du.address[dst] + du.length[dst] - 1); + } + } + du.sections = dst + 1; + } + + du.tool = "c_gcc"; + du.date = DATE; + + sysroff_swap_du_out (file, &du); +} + +static void +wr_dus (p, sfile) + struct coff_ofile *p; + struct coff_sfile *sfile; +{ + + struct IT_dus dus; + + dus.efn = 0x1001; + dus.ns = 1; /* p->nsources; sac 14 jul 94 */ + dus.drb = nints (dus.ns); + dus.fname = (char **) xcalloc (sizeof (char *), dus.ns); + dus.spare = nints (dus.ns); + dus.ndir = 0; + /* Find the filenames */ +#if 0 + i = 0; + + for (sfile = p->source_head; + sfile; + sfile = sfile->next) + { + dus.drb[i] = 0; + dus.spare[i] = 0; + dus.fname[i] = sfile->name; + i++; + } +#else + dus.drb[0] = 0; + dus.fname[0] = sfile->name; +#endif + + sysroff_swap_dus_out (file, &dus); + +} + +/* Find the offset of the .text section for this sfile in the + .text section for the output file */ + +static int +find_base (sfile, section) + struct coff_sfile *sfile; + struct coff_section *section; +{ + return sfile->section[section->number].low; +} +static void +wr_dln (p, sfile, n) + struct coff_ofile *p; + struct coff_sfile *sfile; + int n; + +{ +#if 0 + if (n == 0) + { + /* Count up all the linenumbers */ + struct coff_symbol *sy; + int lc = 0; + struct IT_dln dln; + + int idx; + + for (sy = p->symbol_list_head; + sy; + sy = sy->next_in_ofile_list) + { + struct coff_type *t = sy->type; + if (t->type == coff_function_type) + { + struct coff_line *l = t->u.function.lines; + lc += l->nlines; + } + } + + dln.sfn = nints (lc); + dln.sln = nints (lc); + dln.lln = nints (lc); + dln.section = nints (lc); + + dln.from_address = nints (lc); + dln.to_address = nints (lc); + + + dln.neg = 0x1001; + + dln.nln = lc; + + /* Run through once more and fill up the structure */ + idx = 0; + for (sy = p->symbol_list_head; + sy; + sy = sy->next_in_ofile_list) + { + if (sy->type->type == coff_function_type) + { + int i; + struct coff_line *l = sy->type->u.function.lines; + for (i = 0; i < l->nlines; i++) + { + dln.section[idx] = sy->where->section->number; + dln.sfn[idx] = n; + dln.sln[idx] = l->lines[i]; + dln.from_address[idx] = l->addresses[i]; + if (idx) + dln.to_address[idx - 1] = dln.from_address[idx]; + idx++; + } + } + n++; + } + sysroff_swap_dln_out (file, &dln); + } + +#endif +#if 1 + /* Count up all the linenumbers */ + + struct coff_symbol *sy; + int lc = 0; + struct IT_dln dln; + + int idx; + + for (sy = sfile->scope->vars_head; + sy; + sy = sy->next) + { + struct coff_type *t = sy->type; + if (t->type == coff_function_type) + { + struct coff_line *l = t->u.function.lines; + if (l) + lc += l->nlines; + } + } + + dln.sfn = nints (lc); + dln.sln = nints (lc); + dln.cc = nints (lc); + dln.section = nints (lc); + + dln.from_address = nints (lc); + dln.to_address = nints (lc); + + + dln.neg = 0x1001; + + dln.nln = lc; + + /* Run through once more and fill up the structure */ + idx = 0; + for (sy = sfile->scope->vars_head; + sy; + sy = sy->next) + { + if (sy->type->type == coff_function_type) + { + int i; + struct coff_line *l = sy->type->u.function.lines; + if (l) + { + int base = find_base (sfile, sy->where->section); + for (i = 0; i < l->nlines; i++) + { + dln.section[idx] = sy->where->section->number; + dln.sfn[idx] = 0; + dln.sln[idx] = l->lines[i]; + dln.from_address[idx] = + l->addresses[i] + sy->where->section->address - base; + dln.cc[idx] = 0; + if (idx) + dln.to_address[idx - 1] = dln.from_address[idx]; + idx++; + + } + dln.to_address[idx - 1] = dln.from_address[idx - 1] + 2; + } + } + } + if (lc) + sysroff_swap_dln_out (file, &dln); +#endif +} + +/* Write the global symbols out to the debug info */ +static void +wr_globals (p, sfile, n) + struct coff_ofile *p; + struct coff_sfile *sfile; + int n; +{ + struct coff_symbol *sy; + for (sy = p->symbol_list_head; + sy; + sy = sy->next_in_ofile_list) + { + if (sy->visible->type == coff_vis_ext_def + || sy->visible->type == coff_vis_ext_ref) + { + /* Only write out symbols if they belong to + the current source file */ + if (sy->sfile == sfile) + walk_tree_symbol (sfile, 0, sy, 0); + + } + } +} + +static void +wr_debug (p) + struct coff_ofile *p; +{ + struct coff_sfile *sfile; + int n = 0; + for (sfile = p->source_head; + sfile; + sfile = sfile->next) + + { + if (debug) + { + printf ("%s\n", sfile->name); + } + wr_du (p, sfile, n); + wr_dus (p, sfile); + wr_program_structure (p, sfile); + wr_dln (p, sfile, n); + n++; + } +} + +static void +wr_cs () +{ + /* It seems that the CS struct is not normal - the size is wrong + heres one I prepared earlier.. */ + static char b[] = { + 0x80, /* IT */ + 0x21, /* RL */ + 0x00, /* number of chars in variable length part */ + 0x80, /* hd */ + 0x00, /* hs */ + 0x80, /* un */ + 0x00, /* us */ + 0x80, /* sc */ + 0x00, /* ss */ + 0x80, /* er */ + 0x80, /* ed */ + 0x80, /* sh */ + 0x80, /* ob */ + 0x80, /* rl */ + 0x80, /* du */ + 0x80, /* dps */ + 0x80, /* dsy */ + 0x80, /* dty */ + 0x80, /* dln */ + 0x80, /* dso */ + 0x80, /* dus */ + 0x00, /* dss */ + 0x80, /* dbt */ + 0x00, /* dpp */ + 0x80, /* dfp */ + 0x80, /* den */ + 0x80, /* dds */ + 0x80, /* dar */ + 0x80, /* dpt */ + 0x00, /* dul */ + 0x00, /* dse */ + 0x00, /* dot */ + 0xDE /* CS */ + }; + fwrite (b, 1, sizeof (b), file); +} + +/* Write out the SC records for a unit. Create an SC + for all the sections which appear in the output file, even + if there isn't an equivalent one on the input */ + +static int +wr_sc (ptr, sfile) + struct coff_ofile *ptr; + struct coff_sfile *sfile; +{ + int i; +int scount = 0; + /* First work out the total number of sections */ + + int total_sec = ptr->nsections; + + struct myinfo + { + struct coff_section *sec; + struct coff_symbol *symbol; + }; + struct coff_symbol *symbol; + + struct myinfo *info + = (struct myinfo *) calloc (total_sec, sizeof (struct myinfo)); + + + + for (i = 0; i < total_sec; i++) + { + info[i].sec = ptr->sections + i; + info[i].symbol = 0; + } + + for (symbol = sfile->scope->vars_head; + symbol; + symbol = symbol->next) + { + + if (symbol->type->type == coff_secdef_type) + { + for (i = 0; i < total_sec; i++) + { + if (symbol->where->section == info[i].sec) + { + info[i].symbol = symbol; + break; + } + } + } + } + + /* Now output all the section info, and fake up some stuff for sections + we don't have */ + + for (i = 1; i < total_sec; i++) + { + struct IT_sc sc; + char *name; + symbol = info[i].symbol; + sc.spare = 0; + sc.spare1 = 0; + if (!symbol) + { + /* Don't have a symbol set aside for this section, which means that nothing + in this file does anything for the section. */ + sc.format = !(abfd->flags & EXEC_P); + sc.addr = 0; + sc.length = 0; + name = info[i].sec->name; + } + else + { + if (abfd->flags & EXEC_P) + { + sc.format = 0; + sc.addr = symbol->where->offset; + } + else + { + sc.format = 1; + sc.addr = 0; + } + sc.length = symbol->type->size; + name = symbol->name; + } + + sc.align = 4; + + sc.concat = CONCAT_SIMPLE; + sc.read = 3; + sc.write = 3; + sc.exec = 3; + sc.init = 3; + sc.mode = 3; + sc.spare = 0; + sc.segadd = 0; + sc.spare1 = 0; /* If not zero, then it doesn't work */ + sc.name = section_translate (name); + if (strlen (sc.name) == 1) + { + switch (sc.name[0]) + { + case 'D': + case 'B': + sc.contents = CONTENTS_DATA; + break; + default: + sc.contents = CONTENTS_CODE; + } + } + else + { + sc.contents = CONTENTS_CODE; + } + /* NEW */ + if (sc.length) { + sysroff_swap_sc_out (file, &sc); + scount++; + } + } +return scount; +} + + +/* Write out the ER records for a unit. */ +static void +wr_er (ptr, sfile, first) + struct coff_ofile *ptr; + struct coff_sfile *sfile; + int first; +{ + int idx = 0; + struct coff_symbol *sym; + if (first) + { + for (sym = ptr->symbol_list_head; sym; sym = sym->next_in_ofile_list) + { + if (sym->visible->type == coff_vis_ext_ref) + { + struct IT_er er; + er.spare = 0; + er.type = ER_NOTSPEC; + er.name = sym->name; + sysroff_swap_er_out (file, &er); + sym->er_number = idx++; + } + } + } +} + +/* Write out the ED records for a unit. */ +static void +wr_ed (ptr, sfile, first) + struct coff_ofile *ptr; + struct coff_sfile *sfile; + int first; +{ + struct coff_symbol *s; + if (first) + { + for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list) + { + if (s->visible->type == coff_vis_ext_def + || s->visible->type == coff_vis_common) + { + struct IT_ed ed; + + ed.section = s->where->section->number; + ed.spare = 0; + if (s->where->section->data) + { + ed.type = ED_TYPE_DATA; + } + else if (s->where->section->code & SEC_CODE) + { + ed.type = ED_TYPE_ENTRY; + } + else + { + ed.type = ED_TYPE_NOTSPEC; + ed.type = ED_TYPE_DATA; + } + ed.address = s->where->offset - s->where->section->address; + ed.name = s->name; + sysroff_swap_ed_out (file, &ed); + } + } + } +} + +static void +wr_unit_info (ptr) + struct coff_ofile *ptr; +{ + struct coff_sfile *sfile; + int first = 1; + for (sfile = ptr->source_head; + sfile; + sfile = sfile->next) + { + long p1; + long p2; + int nsecs; + p1 = ftell (file); + wr_un (ptr, sfile, first, 0); + nsecs = wr_sc (ptr, sfile); + p2 = ftell (file); + fseek (file, p1, SEEK_SET); + wr_un (ptr, sfile, first, nsecs); + fseek (file, p2, SEEK_SET); + wr_er (ptr, sfile, first); + wr_ed (ptr, sfile, first); + first = 0; + } +} + +static void +wr_module (p) + struct coff_ofile *p; +{ + wr_cs (); + wr_hd (p); + wr_unit_info (p); + wr_object_body (p); + wr_debug (p); + wr_tr (); +} + +static int +align (x) + int x; +{ + return (x + 3) & ~3; +} + +/* Find all the common variables and turn them into + ordinary defs - dunno why, but thats what hitachi does with 'em */ + +static void +prescan (tree) + struct coff_ofile *tree; +{ + struct coff_symbol *s; + struct coff_section *common_section; + /* Find the common section - always section 3 */ + common_section = tree->sections + 3; + for (s = tree->symbol_list_head; + s; + s = s->next_in_ofile_list) + { + if (s->visible->type == coff_vis_common) + { + struct coff_where *w = s->where; + /* s->visible->type = coff_vis_ext_def; leave it as common */ + common_section->size = align (common_section->size); + w->offset = common_section->size + common_section->address; + w->section = common_section; + common_section->size += s->type->size; + common_section->size = align (common_section->size); + } + } +} + +char *program_name; + +static void +show_usage (file, status) + FILE *file; + int status; +{ + fprintf (file, "Usage: %s [-dhVq] in-file [out-file]\n", program_name); + exit (status); +} + +static void +show_help () +{ + printf ("%s: Convert a COFF object file into a SYSROFF object file\n", + program_name); + show_usage (stdout, 0); +} + + + +int +main (ac, av) + int ac; + char *av[]; +{ + int opt; + static struct option long_options[] = + { + {"debug", no_argument, 0, 'd'}, + {"quick", no_argument, 0, 'q'}, + {"noprescan", no_argument, 0, 'n'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {NULL, no_argument, 0, 0} + }; + char **matching; + char *input_file; + + char *output_file; + program_name = av[0]; + xmalloc_set_program_name (program_name); + + while ((opt = getopt_long (ac, av, "dhVqn", long_options, + (int *) NULL)) + != EOF) + { + switch (opt) + { + case 'q': + quick = 1; + break; + case 'n': + noprescan = 1; + break; + case 'd': + debug = 1; + break; + case 'h': + show_help (); + /*NOTREACHED */ + case 'V': + printf ("GNU %s version %s\n", program_name, PROGRAM_VERSION); + exit (0); + /*NOTREACHED */ + case 0: + break; + default: + show_usage (stderr, 1); + /*NOTREACHED */ + } + } + + /* The input and output files may be named on the command line. */ + output_file = NULL; + if (optind < ac) + { + input_file = av[optind]; + ++optind; + if (optind < ac) + { + output_file = av[optind]; + ++optind; + if (optind < ac) + show_usage (stderr, 1); + if (strcmp (input_file, output_file) == 0) + { + fprintf (stderr, + "%s: input and output files must be different\n", + program_name); + exit (1); + } + } + } + else + input_file = 0; + + if (!input_file) + { + fprintf (stderr, "%s: no input file specified\n", + program_name); + exit (1); + } + + if (!output_file) + { + /* Take a .o off the input file and stick on a .obj. If + it doesn't end in .o, then stick a .obj on anyway */ + + int len = strlen (input_file); + output_file = xmalloc (len + 5); + strcpy (output_file, input_file); + if (len > 3 + && output_file[len - 2] == '.' + && output_file[len - 1] == 'o') + { + output_file[len] = 'b'; + output_file[len + 1] = 'j'; + output_file[len + 2] = 0; + } + else + { + strcat (output_file, ".obj"); + } + } + + abfd = bfd_openr (input_file, 0); + + if (!abfd) + bfd_fatal (input_file); + + if (!bfd_check_format_matches (abfd, bfd_object, &matching)) + { + bfd_nonfatal (input_file); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + exit (1); + } + + file = fopen (output_file, FOPEN_WB); + + if (!file) + { + fprintf (stderr, "%s: unable to open output file %s\n", + program_name, output_file); + exit (1); + } + + if (debug) + printf ("ids %d %d\n", base1, base2); + tree = coff_grok (abfd); + if (!noprescan) + prescan (tree); + wr_module (tree); + return 0; +} diff --git a/gnu/usr.bin/binutils/binutils/strings.1 b/gnu/usr.bin/binutils/binutils/strings.1 new file mode 100644 index 00000000000..408de29400b --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/strings.1 @@ -0,0 +1,151 @@ +.\" Copyright (c) 1993 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH strings 1 "25 June 1993" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +strings \- print the strings of printable characters in files + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B strings +.RB "[\|" \-a | \-\c +.RB | \-\-all "\|]" +.RB "[\|" \-f | \-\-print\-file\-name "\|]" +.RB "[\|" \-o "\|]" +.RB "[\|" \-\-help "\|]" +.RB "[\|" \-v | \-\-version "\|]" +.RB "[\|" \-n +.I min\-len\c +.RI | \-min\-len\c +.RB | "\-\-bytes="\c +.I min\-len\c +\&\|] +.RB "[\|" \-t +.I {o,x,d}\c +.RB "[\|" "\-\-target=\fIbfdname" "\|]" +.RB | "\-\-radix="\c +.I {o,x,d}\c +\&\|] +.I file\c +.ad b +.hy 1 +.SH DESCRIPTION +For each +.I file +given, GNU \c +.B strings +prints the printable character sequences that are at least 4 +characters long (or the number given with the options below) and are +followed by an unprintable character. By default, it only prints the +strings from the initialized and loaded sections of object files; for +other types of files, it prints the strings from the whole file. + +.PP +.B strings +is mainly useful for determining the contents of non-text files. + +.SH OPTIONS +The long and short forms of options, shown here as alternatives, are +equivalent. + +.TP +.B \-a +.TP +.B \-\-all +.TP +.B \- +Do not scan only the initialized and loaded sections of object files; +scan the whole files. + +.TP +.B \-f +.TP +.B \-\-print\-file\-name +Print the name of the file before each string. + +.TP +.B \-\-help +Print a summary of the options to +.B strings +on the standard output and exit. + +.TP +.B \-v +.TP +.B \-\-version +Print the version number +of +.B strings +on the standard output and exit. + +.TP +.B "\-n \fImin\-len\fP" +.TP +.B "\-\fImin\-len\fP" +.TP +.B "\-bytes=\fImin\-len\fP" +Print sequences of characters that are at least +.I min\-len +characters long, instead of the default 4. + +.TP +.BR "\-t " {o,x,d} +.TP +.BR "\-\-radix=" {o,x,d} +Print the offset within the file before each string. The single +character argument specifies the radix of the offset\(emoctal, +hexadecimal, or decimal. + +.TP +.BI "\-\-target=" "bfdname" +Specify an object code format other than your system's default format. +See +.BR objdump ( 1 ), +for information on listing available formats. + +.TP +.B \-o +Like +.BR "\-t o" . + +.PP + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (October 1991); +.BR ar ( 1 ), +.BR nm ( 1 ), +.BR objdump ( 1 ), +.BR ranlib ( 1 ). + + +.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/gnu/usr.bin/binutils/binutils/strings.c b/gnu/usr.bin/binutils/binutils/strings.c new file mode 100644 index 00000000000..fadcbe0ccda --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/strings.c @@ -0,0 +1,502 @@ +/* strings -- print the strings of printable characters in files + Copyright (C) 1993, 94 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. */ + +/* Usage: strings [options] file... + + Options: + --all + -a + - Do not scan only the initialized data section of object files. + + --print-file-name + -f Print the name of the file before each string. + + --bytes=min-len + -n min-len + -min-len Print graphic char sequences, MIN-LEN or more bytes long, + that are followed by a NUL or a newline. Default is 4. + + --radix={o,x,d} + -t {o,x,d} Print the offset within the file before each string, + in octal/hex/decimal. + + -o Like -to. (Some other implementations have -o like -to, + others like -td. We chose one arbitrarily.) + + --target=BFDNAME + Specify a non-default object file format. + + --help + -h Print the usage message on the standard output. + + --version + -v Print the program version number. + + Written by Richard Stallman + and David MacKenzie . */ + +#include "bfd.h" +#include +#include +#include +#include +#include "bucomm.h" +#include "libiberty.h" + +#ifdef isascii +#define isgraphic(c) (isascii (c) && isprint (c)) +#else +#define isgraphic(c) (isprint (c)) +#endif + +#ifndef errno +extern int errno; +#endif + +/* The BFD section flags that identify an initialized data section. */ +#define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS) + +/* Radix for printing addresses (must be 8, 10 or 16). */ +static int address_radix; + +/* Minimum length of sequence of graphic chars to trigger output. */ +static int string_min; + +/* true means print address within file for each string. */ +static boolean print_addresses; + +/* true means print filename for each string. */ +static boolean print_filenames; + +/* true means for object files scan only the data section. */ +static boolean datasection_only; + +/* true if we found an initialized data section in the current file. */ +static boolean got_a_section; + +/* The BFD object file format. */ +static char *target; + +extern char *program_version; + +static struct option long_options[] = +{ + {"all", no_argument, NULL, 'a'}, + {"print-file-name", no_argument, NULL, 'f'}, + {"bytes", required_argument, NULL, 'n'}, + {"radix", required_argument, NULL, 't'}, + {"target", required_argument, NULL, 'T'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} +}; + +static boolean strings_file PARAMS ((char *file)); +static int integer_arg PARAMS ((char *s)); +static void print_strings PARAMS ((char *filename, FILE *stream, + file_ptr address, int stop_point, + int magiccount, char *magic)); +static void usage PARAMS ((FILE *stream, int status)); + +void +main (argc, argv) + int argc; + char **argv; +{ + int optc; + int exit_status = 0; + boolean files_given = false; + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + string_min = -1; + print_addresses = false; + print_filenames = false; + datasection_only = true; + target = NULL; + + while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789", + long_options, (int *) 0)) != EOF) + { + switch (optc) + { + case 'a': + datasection_only = false; + break; + + case 'f': + print_filenames = true; + break; + + case 'h': + usage (stdout, 0); + + case 'n': + string_min = integer_arg (optarg); + if (string_min < 1) + { + fprintf (stderr, "%s: invalid number %s\n", + program_name, optarg); + exit (1); + } + break; + + case 'o': + print_addresses = true; + address_radix = 8; + break; + + case 't': + print_addresses = true; + if (optarg[1] != '\0') + usage (stderr, 1); + switch (optarg[0]) + { + case 'o': + address_radix = 8; + break; + + case 'd': + address_radix = 10; + break; + + case 'x': + address_radix = 16; + break; + + default: + usage (stderr, 1); + } + break; + + case 'T': + target = optarg; + break; + + case 'v': + printf ("GNU %s version %s\n", program_name, program_version); + exit (0); + + case '?': + usage (stderr, 1); + + default: + if (string_min < 0) + string_min = optc; + else + string_min = string_min * 10 + optc - '0'; + break; + } + } + + if (string_min < 0) + string_min = 4; + + bfd_init (); + + if (optind >= argc) + { + datasection_only = false; + print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL); + files_given = true; + } + else + { + for (; optind < argc; ++optind) + { + if (strcmp (argv[optind], "-") == 0) + datasection_only = false; + else + { + files_given = true; + exit_status |= (strings_file (argv[optind]) == false); + } + } + } + + if (files_given == false) + usage (stderr, 1); + + exit (exit_status); +} + +/* Scan section SECT of the file ABFD, whose printable name is FILE. + If it contains initialized data, + set `got_a_section' and print the strings in it. */ + +static void +strings_a_section (abfd, sect, file) + bfd *abfd; + asection *sect; + PTR file; +{ + if ((sect->flags & DATA_FLAGS) == DATA_FLAGS) + { + bfd_size_type sz = bfd_get_section_size_before_reloc (sect); + PTR mem = xmalloc (sz); + if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz)) + { + got_a_section = true; + print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem); + } + free (mem); + } +} + +/* Scan all of the sections in FILE, and print the strings + in the initialized data section(s). + + Return true if successful, + false if not (such as if FILE is not an object file). */ + +static boolean +strings_object_file (file) + char *file; +{ + bfd *abfd = bfd_openr (file, target); + + if (abfd == NULL) + { + /* Treat the file as a non-object file. */ + return false; + } + + /* This call is mainly for its side effect of reading in the sections. + We follow the traditional behavior of `strings' in that we don't + complain if we don't recognize a file to be an object file. */ + if (bfd_check_format (abfd, bfd_object) == false) + { + bfd_close (abfd); + return false; + } + + got_a_section = false; + bfd_map_over_sections (abfd, strings_a_section, file); + + if (!bfd_close (abfd)) + { + bfd_nonfatal (file); + return false; + } + + return got_a_section; +} + +/* Print the strings in FILE. Return true if ok, false if an error occurs. */ + +static boolean +strings_file (file) + char *file; +{ + /* If we weren't told to scan the whole file, + try to open it as an object file and only look at + initialized data sections. If that fails, fall back to the + whole file. */ + if (!datasection_only || !strings_object_file (file)) + { + FILE *stream; + + stream = fopen (file, "rb"); + /* Not all systems permit "rb", so try "r" if it failed. */ + if (stream == NULL) + stream = fopen (file, "r"); + if (stream == NULL) + { + fprintf (stderr, "%s: ", program_name); + perror (file); + return false; + } + + print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0); + + if (fclose (stream) == EOF) + { + fprintf (stderr, "%s: ", program_name); + perror (file); + return false; + } + } + + return true; +} + +/* Find the strings in file FILENAME, read from STREAM. + Assume that STREAM is positioned so that the next byte read + is at address ADDRESS in the file. + Stop reading at address STOP_POINT in the file, if nonzero. + + If STREAM is NULL, do not read from it. + The caller can supply a buffer of characters + to be processed before the data in STREAM. + MAGIC is the address of the buffer and + MAGICCOUNT is how many characters are in it. + Those characters come at address ADDRESS and the data in STREAM follow. */ + +static void +print_strings (filename, stream, address, stop_point, magiccount, magic) + char *filename; + FILE *stream; + file_ptr address; + int stop_point; + int magiccount; + char *magic; +{ + char *buf = (char *) xmalloc (string_min + 1); + + while (1) + { + file_ptr start; + int i; + int c; + + /* See if the next `string_min' chars are all graphic chars. */ + tryline: + if (stop_point && address >= stop_point) + break; + start = address; + for (i = 0; i < string_min; i++) + { + if (magiccount) + { + magiccount--; + c = *magic++; + } + else + { + if (stream == NULL) + return; + c = getc (stream); + if (c == EOF) + return; + } + address++; + if (!isgraphic (c)) + /* Found a non-graphic. Try again starting with next char. */ + goto tryline; + buf[i] = c; + } + + /* We found a run of `string_min' graphic characters. Print up + to the next non-graphic character. */ + + if (print_filenames) + printf ("%s: ", filename); + if (print_addresses) + switch (address_radix) + { + case 8: + printf ("%7lo ", (unsigned long) start); + break; + + case 10: + printf ("%7ld ", (long) start); + break; + + case 16: + printf ("%7lx ", (unsigned long) start); + break; + } + + buf[i] = '\0'; + fputs (buf, stdout); + + while (1) + { + if (magiccount) + { + magiccount--; + c = *magic++; + } + else + { + if (stream == NULL) + break; + c = getc (stream); + if (c == EOF) + break; + } + address++; + if (! isgraphic (c)) + break; + putchar (c); + } + + putchar ('\n'); + } +} + +/* Parse string S as an integer, using decimal radix by default, + but allowing octal and hex numbers as in C. */ + +static int +integer_arg (s) + char *s; +{ + int value; + int radix = 10; + char *p = s; + int c; + + if (*p != '0') + radix = 10; + else if (*++p == 'x') + { + radix = 16; + p++; + } + else + radix = 8; + + value = 0; + while (((c = *p++) >= '0' && c <= '9') + || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z')) + { + value *= radix; + if (c >= '0' && c <= '9') + value += c - '0'; + else + value += (c & ~40) - 'A'; + } + + if (c == 'b') + value *= 512; + else if (c == 'B') + value *= 1024; + else + p--; + + if (*p) + { + fprintf (stderr, "%s: invalid integer argument %s\n", program_name, s); + exit (1); + } + return value; +} + +static void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, "\ +Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\ + [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\ + [--target=bfdname] [--help] [--version] file...\n", + program_name); + list_supported_targets (program_name, stream); + exit (status); +} diff --git a/gnu/usr.bin/binutils/binutils/strip.1 b/gnu/usr.bin/binutils/binutils/strip.1 new file mode 100644 index 00000000000..7ecadaa1fd8 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/strip.1 @@ -0,0 +1,171 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH strip 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +strip \- Discard symbols from object files. + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B strip +.RB "[\|" \-F\ \fIbfdname\fR\ |\ \fB\-\-target=\fIbfdname\fP "\|]" +.RB "[\|" \-I\ \fIbfdname\fR\ |\ \fB\-\-input\-target=\fIbfdname\fP "\|]" +.RB "[\|" \-O\ \fIbfdname\fR\ |\ \fB\-\-output\-target=\fIbfdname\fP "\|]" +.RB "[\|" \-R\ \fIsectionname\fR\ |\ \fB\-\-remove\-section=\fIsectionname\fP "\|]" +.RB "[\|" \-s\fR\ |\ \fB\-\-strip\-all "\|]" +.RB "[\|" \-S\fR\ |\ \fB\-g\fR\ |\ \fB\-\-strip\-debug "\|]" +.RB "[\|" \-\-strip\-unneeded\fR "\|]" +.RB "[\|" \-x\fR\ |\ \fB\-\-discard\-all "\|]" +.RB "[\|" \-X\fR\ |\ \fB\-\-discard\-locals "\|]" +.RB "[\|" \-K\ \fIsymbolname\fR\ |\ \fB\-\-keep\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-N\ \fIsymbolname\fR\ |\ \fB\-\-strip\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-v\fR\ |\ \fB\-\-verbose "\|]" +.RB "[\|" \-V\fR\ |\ \fB\-\-version "\|]" +.RB "[\|" \-V\fR\ |\ \fB\-\-help "\|]" +.I objfile\c +\&.\|.\|. + +.SH DESCRIPTION +GNU +.B strip +discards all symbols from the object files +.IR objfile . +The list of object files may include archives. +At least one object file must be given. + +.P +.B strip +modifies the files named in its argument, +rather than writing modified copies under different names. + +.SH OPTIONS +.TP +.B "\-F \fIbfdname" +.TP +.B "\-\-target=\fIbfdname" +Treat the original \fIobjfile\fP as a file with the object +code format \fIbfdname\fP, and rewrite it in the same format. + +.TP +.B \-\-help +Show a summary of the options to +.B strip +and exit. + +.TP +.B "\-I \fIbfdname +.TP +.B "\-\-input\-target=\fIbfdname" +Treat the original \fIobjfile\fP as a file with the object +code format \fIbfdname\fP. + +.TP +.B "\-O \fIbfdname\fP" +.TP +.B "\-\-output\-target=\fIbfdname" +Replace \fIobjfile\fP with a file in the output format \fIbfdname\fP. + +.TP +.B "\-R \fIsectionname\fP" +.TP +.B "\-\-remove\-section=\fIsectionname" +Remove the named section from the file. This option may be given more +than once. Note that using this option inappropriately may make the +object file unusable. + +.TP +.B \-s +.TP +.B \-\-strip\-all +Remove all symbols. + +.TP +.B \-S +.TP +.B \-g +.TP +.B \-\-strip\-debug +Remove debugging symbols only. + +.TP +.B \-\-strip\-unneeded +Strip all symbols that are not needed for relocation processing. + +.TP +.B \-N \fIsymbolname\fR +.TP +.B \-\-strip\-symbol=\fIsymbolname +Remove symbol \fIsymbolname\fP from the source file. This option +may be given more than once, and may be combined with other strip +options. + +.TP +.B \-x +.TP +.B \-\-discard\-all +Remove non-global symbols. + +.TP +.B \-X +.TP +.B \-\-discard\-locals +Remove compiler-generated local symbols. +(These usually start with ``L'' or ``.''.) + +.TP +.B \-K \fIsymbolname\fR, \fB\-\-keep\-symbol=\fIsymbolname +Copy only symbol \fIsymbolname\fP from the source file. This option +may be given more than once. + +.TP +.B \-N \fIsymbolname\fR, \fB\-\-strip\-symbol=\fIsymbolname +Do not copy symbol \fIsymbolname\fP from the source file. This option +may be given more than once, and may be combined with strip options +other than \fB\-K\fR. + +.TP +.B \-v +.TP +.B \-\-verbose +Verbose output: list all object files modified. In the case of +archives, +.B "strip \-V" +lists all members of the archive. + +.TP +.B \-V +.TP +.B \-\-version +Show the version number for \fBstrip\fP and exit. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.BR info ; +.IR "The GNU Binary Utilities" , +Roland H. Pesch (October 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/gnu/usr.bin/binutils/binutils/sysdump.c b/gnu/usr.bin/binutils/binutils/sysdump.c new file mode 100644 index 00000000000..5f158e9b99e --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/sysdump.c @@ -0,0 +1,765 @@ +/* Sysroff object format dumper. + Copyright (C) 1994 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public 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 Steve Chamberlain . + + This program reads a SYSROFF object file and prints it in an + almost human readable form to stdout. */ + +#include "bfd.h" +#include "bucomm.h" + +#include +#include +#include +#include +#include "sysroff.h" + +#define PROGRAM_VERSION "1.0" +static int h8300; +static int sh; +static int dump = 1; +static int segmented_p; +static int code; +static FILE *file; + +static char * +xcalloc (a, b) + int a; + int b; +{ + char *r = xmalloc (a * b); + memset (r, 0, a * b); + return r; +} + +char * +getCHARS (ptr, idx, size, max) + unsigned char *ptr; + int *idx; + int size; + int max; +{ + int oc = *idx / 8; + char *r; + int b = size; + if (b >= max) + { + return "*undefined*"; + } + + if (b == 0) + { + /* Got to work out the length of the string from self */ + b = ptr[oc++]; + (*idx) += 8; + } + + *idx += b * 8; + r = xcalloc (b + 1, 1); + memcpy (r, ptr + oc, b); + r[b] = 0; + return r; +} + +static void +dh (ptr, size) + unsigned char *ptr; + int size; +{ + int i; + int j; + int span = 16; + + printf ("\n************************************************************\n"); + + for (i = 0; i < size; i += span) + { + for (j = 0; j < span; j++) + { + if (j + i < size) + printf ("%02x ", ptr[i + j]); + else + printf (" "); + } + + for (j = 0; j < span && j + i < size; j++) + { + int c = ptr[i + j]; + if (c < 32 || c > 127) + c = '.'; + printf ("%c", c); + } + printf ("\n"); + } +} + +int +fillup (ptr) + char *ptr; +{ + int size; + int sum; + int i; + size = getc (file) - 2; + fread (ptr, 1, size, file); + sum = code + size + 2; + for (i = 0; i < size; i++) + { + sum += ptr[i]; + } + + if ((sum & 0xff) != 0xff) + { + printf ("SUM IS %x\n", sum); + } + if (dump) + dh (ptr, size); + + return size - 1; +} + +barray +getBARRAY (ptr, idx, dsize, max) + unsigned char *ptr; + int *idx; + int dsize; + int max; +{ + barray res; + int i; + int byte = *idx / 8; + int size = ptr[byte++]; + res.len = size; + res.data = (unsigned char *) xmalloc (size); + for (i = 0; i < size; i++) + { + res.data[i] = ptr[byte++]; + } + return res; +} + +int +getINT (ptr, idx, size, max) + unsigned char *ptr; + int *idx; + int size; + int max; +{ + int n = 0; + int byte = *idx / 8; + + if (byte >= max) + { + return 0; + } + if (size == -2) + size = 4; + if (size == -1) + size = 0; + switch (size) + { + case 0: + return 0; + case 1: + n = (ptr[byte]); + break; + case 2: + n = (ptr[byte + 0] << 8) + ptr[byte + 1]; + break; + case 4: + n = (ptr[byte + 0] << 24) + (ptr[byte + 1] << 16) + (ptr[byte + 2] << 8) + (ptr[byte + 3]); + break; + default: + abort (); + } + *idx += size * 8; + return n; +} + +int +getBITS (ptr, idx, size) + char *ptr; + int *idx; + int size; +{ + int byte = *idx / 8; + int bit = *idx % 8; + + *idx += size; + + return (ptr[byte] >> (8 - bit - size)) & ((1 << size) - 1); +} + +static void +itheader (name, code) + char *name; + int code; +{ + printf ("\n%s 0x%02x\n", name, code); +} + +static int indent; +static void +p () +{ + int i; + for (i = 0; i < indent; i++) + { + printf ("| "); + } + printf ("> "); +} + +static void +tabout () +{ + p (); +} + +static void +pbarray (y) + barray *y; +{ + int x; + printf ("%d (", y->len); + for (x = 0; x < y->len; x++) + { + printf ("(%02x %c)", y->data[x], isprint (y->data[x]) ? y->data[x] : '.'); + } + printf (")\n"); +} + +#define SYSROFF_PRINT +#define SYSROFF_SWAP_IN + +#include "sysroff.c" + +/* + * FIXME: sysinfo, which generates sysroff.[ch] from sysroff.info, can't + * hack the special case of the tr block, which has no contents. So we + * implement our own functions for reading in and printing out the tr + * block. + */ + +#define IT_tr_CODE 0x7f +void +sysroff_swap_tr_in() +{ + char raw[255]; + + memset(raw, 0, 255); + fillup(raw); +} + +void +sysroff_print_tr_out() +{ + itheader("tr", IT_tr_CODE); +} + +static int +getone (type) + int type; +{ + int c = getc (file); + code = c; + + if ((c & 0x7f) != type) + { + ungetc (c, file); + return 0; + } + + switch (c & 0x7f) + { + case IT_cs_CODE: + { + struct IT_cs dummy; + sysroff_swap_cs_in (&dummy); + sysroff_print_cs_out (&dummy); + } + break; + case IT_dln_CODE: + { + struct IT_dln dummy; + sysroff_swap_dln_in (&dummy); + sysroff_print_dln_out (&dummy); + } + break; + case IT_hd_CODE: + { + struct IT_hd dummy; + sysroff_swap_hd_in (&dummy); + sysroff_print_hd_out (&dummy); + } + break; + case IT_dar_CODE: + { + struct IT_dar dummy; + sysroff_swap_dar_in (&dummy); + sysroff_print_dar_out (&dummy); + } + break; + case IT_dsy_CODE: + { + struct IT_dsy dummy; + sysroff_swap_dsy_in (&dummy); + sysroff_print_dsy_out (&dummy); + } + break; + case IT_dfp_CODE: + { + struct IT_dfp dummy; + sysroff_swap_dfp_in (&dummy); + sysroff_print_dfp_out (&dummy); + } + break; + case IT_dso_CODE: + { + struct IT_dso dummy; + sysroff_swap_dso_in (&dummy); + sysroff_print_dso_out (&dummy); + } + break; + case IT_dpt_CODE: + { + struct IT_dpt dummy; + sysroff_swap_dpt_in (&dummy); + sysroff_print_dpt_out (&dummy); + } + break; + case IT_den_CODE: + { + struct IT_den dummy; + sysroff_swap_den_in (&dummy); + sysroff_print_den_out (&dummy); + } + break; + case IT_dbt_CODE: + { + struct IT_dbt dummy; + sysroff_swap_dbt_in (&dummy); + sysroff_print_dbt_out (&dummy); + } + break; + case IT_dty_CODE: + { + struct IT_dty dummy; + sysroff_swap_dty_in (&dummy); + sysroff_print_dty_out (&dummy); + } + break; + case IT_un_CODE: + { + struct IT_un dummy; + sysroff_swap_un_in (&dummy); + sysroff_print_un_out (&dummy); + } + break; + case IT_sc_CODE: + { + struct IT_sc dummy; + sysroff_swap_sc_in (&dummy); + sysroff_print_sc_out (&dummy); + } + break; + case IT_er_CODE: + { + struct IT_er dummy; + sysroff_swap_er_in (&dummy); + sysroff_print_er_out (&dummy); + } + break; + case IT_ed_CODE: + { + struct IT_ed dummy; + sysroff_swap_ed_in (&dummy); + sysroff_print_ed_out (&dummy); + } + break; + case IT_sh_CODE: + { + struct IT_sh dummy; + sysroff_swap_sh_in (&dummy); + sysroff_print_sh_out (&dummy); + } + break; + case IT_ob_CODE: + { + struct IT_ob dummy; + sysroff_swap_ob_in (&dummy); + sysroff_print_ob_out (&dummy); + } + break; + case IT_rl_CODE: + { + struct IT_rl dummy; + sysroff_swap_rl_in (&dummy); + sysroff_print_rl_out (&dummy); + } + break; + case IT_du_CODE: + { + struct IT_du dummy; + sysroff_swap_du_in (&dummy); + + sysroff_print_du_out (&dummy); + } + break; + case IT_dus_CODE: + { + struct IT_dus dummy; + sysroff_swap_dus_in (&dummy); + sysroff_print_dus_out (&dummy); + } + break; + case IT_dul_CODE: + { + struct IT_dul dummy; + sysroff_swap_dul_in (&dummy); + sysroff_print_dul_out (&dummy); + } + break; + case IT_dss_CODE: + { + struct IT_dss dummy; + sysroff_swap_dss_in (&dummy); + sysroff_print_dss_out (&dummy); + } + break; + case IT_hs_CODE: + { + struct IT_hs dummy; + sysroff_swap_hs_in (&dummy); + sysroff_print_hs_out (&dummy); + } + break; + case IT_dps_CODE: + { + struct IT_dps dummy; + sysroff_swap_dps_in (&dummy); + sysroff_print_dps_out (&dummy); + } + break; + case IT_tr_CODE: + { + sysroff_swap_tr_in (); + sysroff_print_tr_out (); + } + break; + case IT_dds_CODE: + { + struct IT_dds dummy; + sysroff_swap_dds_in (&dummy); + sysroff_print_dds_out (&dummy); + } + break; + default: + printf ("GOT A %x\n", c); + return 0; + break; + } + return 1; +} + +static int +opt (x) + int x; +{ + return getone (x); +} + +static void +unit_info_list () +{ + while (opt (IT_un_CODE)) + { + getone (IT_us_CODE); + + while (getone (IT_sc_CODE)) + getone (IT_ss_CODE); + + while (getone (IT_er_CODE)) + ; + + while (getone (IT_ed_CODE)) + ; + } +} + +static void +object_body_list () +{ + while (getone (IT_sh_CODE)) + { + while (getone (IT_ob_CODE)) + ; + while (getone (IT_rl_CODE)) + ; + } +} + +static void +must (x) + int x; +{ + if (!getone (x)) + { + printf ("WANTED %x!!\n", x); + } +} + +static void +tab (i, s) + int i; + char *s; +{ + indent += i; + if (s) + { + p (); + printf (s); + printf ("\n"); + } +} + +static void derived_type (); + +static void +dump_symbol_info () +{ + tab (1, "SYMBOL INFO"); + while (opt (IT_dsy_CODE)) + { + if (opt (IT_dty_CODE)) + { + must (IT_dbt_CODE); + derived_type (); + must (IT_dty_CODE); + } + } + tab (-1, ""); +} + +static void +derived_type () +{ + tab (1, "DERIVED TYPE"); + while (1) + { + if (opt (IT_dpp_CODE)) + { + dump_symbol_info (); + must (IT_dpp_CODE); + } + else if (opt (IT_dfp_CODE)) + { + dump_symbol_info (); + must (IT_dfp_CODE); + } + else if (opt (IT_den_CODE)) + { + dump_symbol_info (); + must (IT_den_CODE); + } + else if (opt (IT_den_CODE)) + { + dump_symbol_info (); + must (IT_den_CODE); + } + else if (opt (IT_dds_CODE)) + { + dump_symbol_info (); + must (IT_dds_CODE); + } + else if (opt (IT_dar_CODE)) + { + } + else if (opt (IT_dpt_CODE)) + { + } + else if (opt (IT_dul_CODE)) + { + } + else if (opt (IT_dse_CODE)) + { + } + else if (opt (IT_dot_CODE)) + { + } + else + break; + } + + tab (-1, ""); +} + +static void +program_structure () +{ + tab (1, "PROGRAM STRUCTURE"); + while (opt (IT_dps_CODE)) + { + must (IT_dso_CODE); + opt (IT_dss_CODE); + dump_symbol_info (); + must (IT_dps_CODE); + } + tab (-1, ""); +} + +static void +debug_list () +{ + tab (1, "DEBUG LIST"); + + must (IT_du_CODE); + opt (IT_dus_CODE); + program_structure (); + must (IT_dln_CODE); + + tab (-1, ""); +} + +static void +module () +{ + int c = 0; + int l = 0; + + tab (1, "MODULE***\n"); + + do + { + c = getc (file); + ungetc (c, file); + + c &= 0x7f; + } + while (getone (c) && c != IT_tr_CODE); + +#if 0 + must (IT_cs_CODE); + must (IT_hd_CODE); + opt (IT_hs_CODE); + + unit_info_list (); + object_body_list (); + debug_list (); + + must (IT_tr_CODE); +#endif + tab (-1, ""); + + c = getc (file); + while (c != EOF) + { + printf ("%02x ", c); + l++; + if (l == 32) + { + printf ("\n"); + l = 0; + } + c = getc (file); + } +} + +char *program_name; + +static void +show_usage (file, status) + FILE *file; + int status; +{ + fprintf (file, "Usage: %s [-hV] in-file\n", program_name); + exit (status); +} + +static void +show_help () +{ + printf ("%s: Print a human readable interpretation of a SYSROFF object file\n", + program_name); + show_usage (stdout, 0); +} + +int +main (ac, av) + int ac; + char **av; +{ + char *input_file = NULL; + int opt; + static struct option long_options[] = + { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {NULL, no_argument, 0, 0} + }; + + program_name = av[0]; + xmalloc_set_program_name (program_name); + + while ((opt = getopt_long (ac, av, "hV", long_options, (int *) NULL)) != EOF) + { + switch (opt) + { + case 'h': + show_help (); + /*NOTREACHED*/ + case 'V': + printf ("GNU %s version %s\n", program_name, PROGRAM_VERSION); + exit (0); + /*NOTREACHED*/ + case 0: + break; + default: + show_usage (stderr, 1); + /*NOTREACHED*/ + } + } + + /* The input and output files may be named on the command line. */ + + if (optind < ac) + { + input_file = av[optind]; + } + + if (!input_file) + { + fprintf (stderr, "%s: no input file specified\n", + program_name); + exit (1); + } + + file = fopen (input_file, FOPEN_RB); + if (!file) + { + fprintf (stderr, "%s: cannot open input file %s\n", + program_name, input_file); + exit (1); + } + + module (); + return 0; +} diff --git a/gnu/usr.bin/binutils/binutils/sysinfo.c b/gnu/usr.bin/binutils/binutils/sysinfo.c new file mode 100644 index 00000000000..ae97bf6ffb6 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/sysinfo.c @@ -0,0 +1,1249 @@ + +/* A Bison parser, made from ./sysinfo.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define COND 258 +#define REPEAT 259 +#define TYPE 260 +#define NAME 261 +#define NUMBER 262 +#define UNIT 263 + +#line 1 "./sysinfo.y" + +#include +#include + +extern char *word; +extern char writecode; +extern int number; +extern int unit; +char nice_name[1000]; +char *it; +int sofar; +int width; +int code; +char * repeat; +char *oldrepeat; +char *name; +int rdepth; +char *loop [] = {"","n","m","/*BAD*/"}; +char *names[] = {" ","[n]","[n][m]"}; +char *pnames[]= {"","*","**"}; + +#line 24 "./sysinfo.y" +typedef union { + int i; + char *s; +} 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 + +#ifndef YYDEBUG +#define YYDEBUG 1 +#endif + +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 55 +#define YYFLAG -32768 +#define YYNTBASE 11 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 263 ? yytranslate[x] : 29) + +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, 2, 2, 2, 5, + 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 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, 7, + 8, 9, 10 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 4, 7, 8, 9, 16, 19, 22, 25, + 26, 27, 34, 35, 42, 43, 54, 56, 57, 61, + 64, 68, 69, 70, 74, 75 +}; + +static const short yyrhs[] = { -1, + 12, 13, 0, 14, 13, 0, 0, 0, 5, 8, + 9, 15, 16, 6, 0, 21, 16, 0, 19, 16, + 0, 17, 16, 0, 0, 0, 5, 4, 8, 18, + 16, 6, 0, 0, 5, 3, 8, 20, 16, 6, + 0, 0, 5, 24, 5, 23, 25, 6, 26, 22, + 27, 6, 0, 7, 0, 0, 5, 8, 6, 0, + 9, 10, 0, 5, 8, 6, 0, 0, 0, 5, + 28, 6, 0, 0, 28, 5, 8, 8, 6, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 38, 59, 75, 76, 79, 130, 150, 152, 153, 154, + 157, 186, 204, 217, 230, 233, 338, 340, 343, 348, + 354, 356, 359, 360, 362, 363 +}; + +static const char * const yytname[] = { "$","error","$undefined.","COND","REPEAT", +"'('","')'","TYPE","NAME","NUMBER","UNIT","top","@1","it_list","it","@2","it_field_list", +"repeat_it_field","@3","cond_it_field","@4","it_field","@5","attr_type","attr_desc", +"attr_size","attr_id","enums","enum_list","" +}; +#endif + +static const short yyr1[] = { 0, + 12, 11, 13, 13, 15, 14, 16, 16, 16, 16, + 18, 17, 20, 19, 22, 21, 23, 23, 24, 25, + 26, 26, 27, 27, 28, 28 +}; + +static const short yyr2[] = { 0, + 0, 2, 2, 0, 0, 6, 2, 2, 2, 0, + 0, 6, 0, 6, 0, 10, 1, 0, 3, 2, + 3, 0, 0, 3, 0, 5 +}; + +static const short yydefact[] = { 1, + 4, 0, 2, 4, 0, 3, 5, 10, 0, 0, + 10, 10, 10, 0, 0, 0, 0, 6, 9, 8, + 7, 13, 11, 0, 18, 10, 10, 19, 17, 0, + 0, 0, 0, 0, 14, 12, 20, 22, 0, 15, + 0, 23, 21, 25, 0, 0, 16, 0, 24, 0, + 0, 26, 0, 0, 0 +}; + +static const short yydefgoto[] = { 53, + 1, 3, 4, 8, 10, 11, 27, 12, 26, 13, + 42, 30, 17, 34, 40, 45, 46 +}; + +static const short yypact[] = {-32768, + 3, 2,-32768, 3, 4,-32768,-32768, 6, 0, 8, + 6, 6, 6, 9, 10, 11, 7,-32768,-32768,-32768, +-32768,-32768,-32768, 14, 15, 6, 6,-32768,-32768, 12, + 17, 18, -1, 19,-32768,-32768,-32768, 21, 20,-32768, + 23, 22,-32768,-32768, 24, 1,-32768, 25,-32768, 26, + 29,-32768, 31, 32,-32768 +}; + +static const short yypgoto[] = {-32768, +-32768, 33,-32768,-32768, -11,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768 +}; + + +#define YYLAST 37 + + +static const short yytable[] = { 19, + 20, 21, 14, 15, 16, 48, 49, 2, 37, 5, + 9, 25, 7, 18, 31, 32, 22, 23, 24, 28, + 33, 29, 35, 36, 38, 39, 44, 41, 43, 47, + 54, 55, 50, 51, 52, 0, 6 +}; + +static const short yycheck[] = { 11, + 12, 13, 3, 4, 5, 5, 6, 5, 10, 8, + 5, 5, 9, 6, 26, 27, 8, 8, 8, 6, + 9, 7, 6, 6, 6, 5, 5, 8, 6, 6, + 0, 0, 8, 8, 6, -1, 4 +}; +/* -*-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 +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #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 reallocate 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 reallocate 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 1: +#line 38 "./sysinfo.y" +{ + switch (writecode) + { + case 'i': + printf("#ifdef SYSROFF_SWAP_IN\n"); + break; + case 'p': + printf("#ifdef SYSROFF_p\n"); + break; + case 'd': + break; + case 'g': + printf("#ifdef SYSROFF_SWAP_OUT\n"); + break; + case 'c': + printf("#ifdef SYSROFF_PRINT\n"); + printf("#include \n"); + printf("#include \n"); + break; + } + ; + break;} +case 2: +#line 59 "./sysinfo.y" +{ + switch (writecode) { + case 'i': + case 'p': + case 'g': + case 'c': + printf("#endif\n"); + break; + case 'd': + break; + } +; + break;} +case 5: +#line 81 "./sysinfo.y" +{ + it = yyvsp[-1].s; code = yyvsp[0].i; + switch (writecode) + { + case 'd': + printf("\n\n\n#define IT_%s_CODE 0x%x\n", it,code); + printf("struct IT_%s { \n", it); + break; + case 'i': + printf("void sysroff_swap_%s_in(ptr)\n",yyvsp[-1].s); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("char raw[255];\n"); + printf("\tint idx = 0 ;\n"); + printf("\tint size;\n"); + printf("memset(raw,0,255);\n"); + printf("memset(ptr,0,sizeof(*ptr));\n"); + printf("size = fillup(raw);\n"); + break; + case 'g': + printf("void sysroff_swap_%s_out(file,ptr)\n",yyvsp[-1].s); + printf("FILE * file;\n"); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("\tchar raw[255];\n"); + printf("\tint idx = 16 ;\n"); + printf("\tmemset (raw, 0, 255);\n"); + printf("\tcode = IT_%s_CODE;\n", it); + break; + case 'o': + printf("void sysroff_swap_%s_out(abfd,ptr)\n",yyvsp[-1].s); + printf("bfd * abfd;\n"); + printf("struct IT_%s *ptr;\n",it); + printf("{\n"); + printf("int idx = 0 ;\n"); + break; + case 'c': + printf("void sysroff_print_%s_out(ptr)\n",yyvsp[-1].s); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("itheader(\"%s\", IT_%s_CODE);\n",yyvsp[-1].s,yyvsp[-1].s); + break; + + case 't': + break; + } + + ; + break;} +case 6: +#line 131 "./sysinfo.y" +{ + switch (writecode) { + case 'd': + printf("};\n"); + break; + case 'g': + printf("\tchecksum(file,raw, idx, IT_%s_CODE);\n", it); + + case 'i': + + case 'o': + case 'c': + printf("}\n"); + } +; + break;} +case 11: +#line 158 "./sysinfo.y" +{ + rdepth++; + switch (writecode) + { + case 'c': + if (rdepth==1) + printf("\tprintf(\"repeat %%d\\n\", %s);\n",yyvsp[0].s); + if (rdepth==2) + printf("\tprintf(\"repeat %%d\\n\", %s[n]);\n",yyvsp[0].s); + case 'i': + case 'g': + case 'o': + + if (rdepth==1) + { + printf("\t{ int n; for (n = 0; n < %s; n++) {\n", yyvsp[0].s); + } + if (rdepth == 2) { + printf("\t{ int m; for (m = 0; m < %s[n]; m++) {\n", yyvsp[0].s); + } + + break; + } + + oldrepeat = repeat; + repeat = yyvsp[0].s; + ; + break;} +case 12: +#line 188 "./sysinfo.y" +{ + repeat = oldrepeat; + oldrepeat =0; + rdepth--; + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\t}}\n"); + } + ; + break;} +case 13: +#line 205 "./sysinfo.y" +{ + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\tif (%s) {\n", yyvsp[0].s); + break; + } + ; + break;} +case 14: +#line 218 "./sysinfo.y" +{ + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\t}\n"); + } + ; + break;} +case 15: +#line 232 "./sysinfo.y" +{name = yyvsp[0].s; ; + break;} +case 16: +#line 234 "./sysinfo.y" +{ + char *desc = yyvsp[-8].s; + char *type = yyvsp[-6].s; + int size = yyvsp[-5].i; + char *id = yyvsp[-3].s; +char *p = names[rdepth]; +char *ptr = pnames[rdepth]; + switch (writecode) + { + case 'g': + if (size % 8) + { + + printf("\twriteBITS(ptr->%s%s,raw,&idx,%d);\n", + id, + names[rdepth], size); + + } + else { + printf("\twrite%s(ptr->%s%s,raw,&idx,%d,file);\n", + type, + id, + names[rdepth],size/8); + } + break; + case 'i': + { + + if (rdepth >= 1) + + { + printf("if (!ptr->%s) ptr->%s = (%s*)xcalloc(%s, sizeof(ptr->%s[0]));\n", + id, + id, + type, + repeat, + id); + } + + if (rdepth == 2) + { + printf("if (!ptr->%s[n]) ptr->%s[n] = (%s**)xcalloc(%s[n], sizeof(ptr->%s[n][0]));\n", + id, + id, + type, + repeat, + id); + } + + } + + if (size % 8) + { + printf("\tptr->%s%s = getBITS(raw,&idx, %d,size);\n", + id, + names[rdepth], + size); + } + else { + printf("\tptr->%s%s = get%s(raw,&idx, %d,size);\n", + id, + names[rdepth], + type, + size/8); + } + break; + case 'o': + printf("\tput%s(raw,%d,%d,&idx,ptr->%s%s);\n", type,size/8,size%8,id,names[rdepth]); + break; + case 'd': + if (repeat) + printf("\t/* repeat %s */\n", repeat); + + if (type[0] == 'I') { + printf("\tint %s%s; \t/* %s */\n",ptr,id, desc); + } + else if (type[0] =='C') { + printf("\tchar %s*%s;\t /* %s */\n",ptr,id, desc); + } + else { + printf("\tbarray %s%s;\t /* %s */\n",ptr,id, desc); + } + break; + case 'c': + printf("tabout();\n"); + printf("\tprintf(\"/*%-30s*/ ptr->%s = \");\n", desc, id); + + if (type[0] == 'I') + printf("\tprintf(\"%%d\\n\",ptr->%s%s);\n", id,p); + else if (type[0] == 'C') + printf("\tprintf(\"%%s\\n\",ptr->%s%s);\n", id,p); + + else if (type[0] == 'B') + { + printf("\tpbarray(&ptr->%s%s);\n", id,p); + } + else abort(); + break; + } + ; + break;} +case 17: +#line 339 "./sysinfo.y" +{ yyval.s = yyvsp[0].s; ; + break;} +case 18: +#line 340 "./sysinfo.y" +{ yyval.s = "INT";; + break;} +case 19: +#line 345 "./sysinfo.y" +{ yyval.s = yyvsp[-1].s; ; + break;} +case 20: +#line 350 "./sysinfo.y" +{ yyval.i = yyvsp[-1].i * yyvsp[0].i; ; + break;} +case 21: +#line 355 "./sysinfo.y" +{ yyval.s = yyvsp[-1].s; ; + break;} +case 22: +#line 356 "./sysinfo.y" +{ yyval.s = "dummy";; + break;} +case 26: +#line 364 "./sysinfo.y" +{ + switch (writecode) + { + case 'd': + printf("#define %s %s\n", yyvsp[-2].s,yyvsp[-1].s); + break; + case 'c': + printf("if (ptr->%s%s == %s) { tabout(); printf(\"%s\\n\");}\n", name, names[rdepth],yyvsp[-1].s,yyvsp[-2].s); + } + ; + 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 *) malloc(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 379 "./sysinfo.y" + +/* four modes + + -d write structure defintions for sysroff in host format + -i write functions to swap into sysroff format in + -o write functions to swap into sysroff format out + -c write code to print info in human form */ + +int yydebug; +char writecode; + +int +main(ac,av) +int ac; +char **av; +{ + yydebug=0; + if (ac > 1) + writecode = av[1][1]; +if (writecode == 'd') + { + printf("typedef struct { unsigned char *data; int len; } barray; \n"); + printf("typedef int INT;\n"); + printf("typedef char * CHARS;\n"); + + } + yyparse(); +return 0; +} + +int yyerror(s) + char *s; +{ + fprintf(stderr, "%s\n" , s); +} diff --git a/gnu/usr.bin/binutils/binutils/sysinfo.h b/gnu/usr.bin/binutils/binutils/sysinfo.h new file mode 100644 index 00000000000..e8e2d25765e --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/sysinfo.h @@ -0,0 +1,13 @@ +typedef union { + int i; + char *s; +} YYSTYPE; +#define COND 258 +#define REPEAT 259 +#define TYPE 260 +#define NAME 261 +#define NUMBER 262 +#define UNIT 263 + + +extern YYSTYPE yylval; diff --git a/gnu/usr.bin/binutils/binutils/sysinfo.y b/gnu/usr.bin/binutils/binutils/sysinfo.y new file mode 100644 index 00000000000..0e0141aff0f --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/sysinfo.y @@ -0,0 +1,413 @@ +%{ +#include +#include + +extern char *word; +extern char writecode; +extern int number; +extern int unit; +char nice_name[1000]; +char *it; +int sofar; +int width; +int code; +char * repeat; +char *oldrepeat; +char *name; +int rdepth; +char *loop [] = {"","n","m","/*BAD*/"}; +char *names[] = {" ","[n]","[n][m]"}; +char *pnames[]= {"","*","**"}; +%} + + +%union { + int i; + char *s; +} +%token COND +%token REPEAT +%token '(' ')' +%token TYPE +%token NAME +%token NUMBER UNIT +%type attr_size +%type attr_desc attr_id attr_type +%% + +top: { + switch (writecode) + { + case 'i': + printf("#ifdef SYSROFF_SWAP_IN\n"); + break; + case 'p': + printf("#ifdef SYSROFF_p\n"); + break; + case 'd': + break; + case 'g': + printf("#ifdef SYSROFF_SWAP_OUT\n"); + break; + case 'c': + printf("#ifdef SYSROFF_PRINT\n"); + printf("#include \n"); + printf("#include \n"); + break; + } + } +it_list { + switch (writecode) { + case 'i': + case 'p': + case 'g': + case 'c': + printf("#endif\n"); + break; + case 'd': + break; + } +} + + ; + + +it_list: it it_list + | + ; + +it: + '(' NAME NUMBER + { + it = $2; code = $3; + switch (writecode) + { + case 'd': + printf("\n\n\n#define IT_%s_CODE 0x%x\n", it,code); + printf("struct IT_%s { \n", it); + break; + case 'i': + printf("void sysroff_swap_%s_in(ptr)\n",$2); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("char raw[255];\n"); + printf("\tint idx = 0 ;\n"); + printf("\tint size;\n"); + printf("memset(raw,0,255);\n"); + printf("memset(ptr,0,sizeof(*ptr));\n"); + printf("size = fillup(raw);\n"); + break; + case 'g': + printf("void sysroff_swap_%s_out(file,ptr)\n",$2); + printf("FILE * file;\n"); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("\tchar raw[255];\n"); + printf("\tint idx = 16 ;\n"); + printf("\tmemset (raw, 0, 255);\n"); + printf("\tcode = IT_%s_CODE;\n", it); + break; + case 'o': + printf("void sysroff_swap_%s_out(abfd,ptr)\n",$2); + printf("bfd * abfd;\n"); + printf("struct IT_%s *ptr;\n",it); + printf("{\n"); + printf("int idx = 0 ;\n"); + break; + case 'c': + printf("void sysroff_print_%s_out(ptr)\n",$2); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("itheader(\"%s\", IT_%s_CODE);\n",$2,$2); + break; + + case 't': + break; + } + + } + it_field_list +')' +{ + switch (writecode) { + case 'd': + printf("};\n"); + break; + case 'g': + printf("\tchecksum(file,raw, idx, IT_%s_CODE);\n", it); + + case 'i': + + case 'o': + case 'c': + printf("}\n"); + } +} +; + + + +it_field_list: + it_field it_field_list + | cond_it_field it_field_list + | repeat_it_field it_field_list + | + ; + +repeat_it_field: '(' REPEAT NAME + { + rdepth++; + switch (writecode) + { + case 'c': + if (rdepth==1) + printf("\tprintf(\"repeat %%d\\n\", %s);\n",$3); + if (rdepth==2) + printf("\tprintf(\"repeat %%d\\n\", %s[n]);\n",$3); + case 'i': + case 'g': + case 'o': + + if (rdepth==1) + { + printf("\t{ int n; for (n = 0; n < %s; n++) {\n", $3); + } + if (rdepth == 2) { + printf("\t{ int m; for (m = 0; m < %s[n]; m++) {\n", $3); + } + + break; + } + + oldrepeat = repeat; + repeat = $3; + } + + it_field_list ')' + + { + repeat = oldrepeat; + oldrepeat =0; + rdepth--; + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\t}}\n"); + } + } + ; + + +cond_it_field: '(' COND NAME + { + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\tif (%s) {\n", $3); + break; + } + } + + it_field_list ')' + { + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\t}\n"); + } + } + ; + +it_field: + '(' attr_desc '(' attr_type attr_size ')' attr_id + {name = $7; } + enums ')' + { + char *desc = $2; + char *type = $4; + int size = $5; + char *id = $7; +char *p = names[rdepth]; +char *ptr = pnames[rdepth]; + switch (writecode) + { + case 'g': + if (size % 8) + { + + printf("\twriteBITS(ptr->%s%s,raw,&idx,%d);\n", + id, + names[rdepth], size); + + } + else { + printf("\twrite%s(ptr->%s%s,raw,&idx,%d,file);\n", + type, + id, + names[rdepth],size/8); + } + break; + case 'i': + { + + if (rdepth >= 1) + + { + printf("if (!ptr->%s) ptr->%s = (%s*)xcalloc(%s, sizeof(ptr->%s[0]));\n", + id, + id, + type, + repeat, + id); + } + + if (rdepth == 2) + { + printf("if (!ptr->%s[n]) ptr->%s[n] = (%s**)xcalloc(%s[n], sizeof(ptr->%s[n][0]));\n", + id, + id, + type, + repeat, + id); + } + + } + + if (size % 8) + { + printf("\tptr->%s%s = getBITS(raw,&idx, %d,size);\n", + id, + names[rdepth], + size); + } + else { + printf("\tptr->%s%s = get%s(raw,&idx, %d,size);\n", + id, + names[rdepth], + type, + size/8); + } + break; + case 'o': + printf("\tput%s(raw,%d,%d,&idx,ptr->%s%s);\n", type,size/8,size%8,id,names[rdepth]); + break; + case 'd': + if (repeat) + printf("\t/* repeat %s */\n", repeat); + + if (type[0] == 'I') { + printf("\tint %s%s; \t/* %s */\n",ptr,id, desc); + } + else if (type[0] =='C') { + printf("\tchar %s*%s;\t /* %s */\n",ptr,id, desc); + } + else { + printf("\tbarray %s%s;\t /* %s */\n",ptr,id, desc); + } + break; + case 'c': + printf("tabout();\n"); + printf("\tprintf(\"/*%-30s*/ ptr->%s = \");\n", desc, id); + + if (type[0] == 'I') + printf("\tprintf(\"%%d\\n\",ptr->%s%s);\n", id,p); + else if (type[0] == 'C') + printf("\tprintf(\"%%s\\n\",ptr->%s%s);\n", id,p); + + else if (type[0] == 'B') + { + printf("\tpbarray(&ptr->%s%s);\n", id,p); + } + else abort(); + break; + } + } + + ; + + +attr_type: + TYPE { $$ = $1; } + | { $$ = "INT";} + ; + +attr_desc: + '(' NAME ')' + { $$ = $2; } + ; + +attr_size: + NUMBER UNIT + { $$ = $1 * $2; } + ; + + +attr_id: + '(' NAME ')' { $$ = $2; } + | { $$ = "dummy";} + ; + +enums: + | '(' enum_list ')' ; + +enum_list: + | + enum_list '(' NAME NAME ')' { + switch (writecode) + { + case 'd': + printf("#define %s %s\n", $3,$4); + break; + case 'c': + printf("if (ptr->%s%s == %s) { tabout(); printf(\"%s\\n\");}\n", name, names[rdepth],$4,$3); + } + } + + ; + + + +%% +/* four modes + + -d write structure defintions for sysroff in host format + -i write functions to swap into sysroff format in + -o write functions to swap into sysroff format out + -c write code to print info in human form */ + +int yydebug; +char writecode; + +int +main(ac,av) +int ac; +char **av; +{ + yydebug=0; + if (ac > 1) + writecode = av[1][1]; +if (writecode == 'd') + { + printf("typedef struct { unsigned char *data; int len; } barray; \n"); + printf("typedef int INT;\n"); + printf("typedef char * CHARS;\n"); + + } + yyparse(); +return 0; +} + +int yyerror(s) + char *s; +{ + fprintf(stderr, "%s\n" , s); +} diff --git a/gnu/usr.bin/binutils/binutils/syslex.c b/gnu/usr.bin/binutils/binutils/syslex.c new file mode 100644 index 00000000000..338dd6c0b69 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/syslex.c @@ -0,0 +1,1651 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/cvs/src/gnu/usr.bin/binutils/binutils/Attic/syslex.c,v 1.1.1.1 1996/01/08 11:03:58 niklas Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 25 +#define YY_END_OF_BUFFER 26 +static yyconst short int yy_accept[81] = + { 0, + 0, 0, 26, 25, 7, 8, 5, 25, 1, 2, + 11, 11, 6, 3, 4, 25, 25, 25, 25, 25, + 25, 25, 0, 9, 11, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, + 13, 0, 0, 0, 0, 16, 0, 0, 0, 0, + 0, 12, 15, 0, 23, 0, 0, 0, 0, 0, + 0, 14, 18, 0, 0, 0, 0, 0, 17, 0, + 24, 0, 0, 0, 20, 22, 0, 21, 19, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 5, 1, 1, 1, 1, 1, 6, + 7, 1, 1, 1, 1, 1, 1, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1, 10, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 1, 12, 1, 1, 1, 13, 14, 15, 16, + + 17, 18, 19, 20, 21, 1, 1, 22, 1, 23, + 24, 25, 1, 26, 27, 28, 29, 30, 1, 31, + 32, 33, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[34] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 3, 3, 1, + 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1 + } ; + +static yyconst short int yy_base[84] = + { 0, + 0, 0, 100, 101, 101, 101, 101, 94, 101, 101, + 26, 28, 0, 101, 101, 82, 26, 18, 74, 79, + 78, 81, 88, 101, 32, 0, 0, 76, 65, 62, + 61, 75, 20, 59, 61, 66, 58, 0, 57, 56, + 54, 63, 53, 62, 54, 101, 59, 48, 53, 46, + 59, 101, 44, 43, 101, 41, 55, 46, 53, 44, + 31, 101, 101, 39, 27, 21, 39, 19, 101, 35, + 101, 33, 26, 29, 101, 101, 28, 101, 101, 101, + 58, 61, 41 + } ; + +static yyconst short int yy_def[84] = + { 0, + 80, 1, 80, 80, 80, 80, 80, 81, 80, 80, + 80, 80, 82, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 81, 80, 80, 83, 82, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 83, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, + 80, 80, 80 + } ; + +static yyconst short int yy_nxt[135] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 4, 4, 4, 4, 4, + 19, 4, 4, 4, 4, 20, 21, 4, 4, 22, + 4, 4, 4, 25, 25, 25, 25, 32, 29, 25, + 25, 33, 44, 38, 79, 78, 30, 77, 45, 76, + 75, 74, 73, 72, 71, 70, 26, 31, 23, 23, + 23, 27, 69, 27, 68, 67, 66, 65, 64, 63, + 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, + 52, 51, 50, 49, 48, 47, 46, 43, 42, 41, + 40, 39, 24, 37, 36, 35, 34, 28, 24, 80, + + 3, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80 + } ; + +static yyconst short int yy_chk[135] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 11, 11, 12, 12, 18, 17, 25, + 25, 18, 33, 83, 77, 74, 17, 73, 33, 72, + 70, 68, 67, 66, 65, 64, 11, 17, 81, 81, + 81, 82, 61, 82, 60, 59, 58, 57, 56, 54, + 53, 51, 50, 49, 48, 47, 45, 44, 43, 42, + 41, 40, 39, 37, 36, 35, 34, 32, 31, 30, + 29, 28, 23, 22, 21, 20, 19, 16, 8, 3, + + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "./syslex.l" +#define INITIAL 0 +#line 2 "./syslex.l" +#include "sysinfo.h" +char *word; +int number; +int unit; + +#ifndef yywrap +static int yywrap () { return 1; } +#endif +#line 424 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 11 "./syslex.l" + +#line 573 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 81 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 101 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 12 "./syslex.l" +{ return '(';} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 13 "./syslex.l" +{ return ')';} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 14 "./syslex.l" +{ return '[';} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 15 "./syslex.l" +{ return ']';} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 16 "./syslex.l" +{ ; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 17 "./syslex.l" +{ ; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 18 "./syslex.l" +{ ; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 19 "./syslex.l" +{ ; } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 20 "./syslex.l" +{ +yylval.s = malloc(strlen (yytext)); +strcpy(yylval.s, yytext+1); +yylval.s[strlen(yylval.s)-1] = 0; + return NAME; + } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 27 "./syslex.l" +{ + yylval.i = strtol(yytext,0,16); + return NUMBER; + } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 32 "./syslex.l" +{ + yylval.i = atoi(yytext); + return NUMBER; + } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 38 "./syslex.l" +{ yylval.i =1 ;return UNIT;} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 39 "./syslex.l" +{ yylval.i = 1; return UNIT;} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 40 "./syslex.l" +{ yylval.i= 8; return UNIT;} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 41 "./syslex.l" +{ yylval.i = 8; return UNIT;} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 43 "./syslex.l" +{ yylval.s = "INT"; return TYPE;} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 44 "./syslex.l" +{ yylval.s = "BARRAY"; return TYPE;} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 45 "./syslex.l" +{ yylval.s = "CHARS"; return TYPE;} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 46 "./syslex.l" +{ yylval.i = 0; return NUMBER;} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 47 "./syslex.l" +{ yylval.i = -4; return NUMBER;} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 48 "./syslex.l" +{ yylval.i = -2; return NUMBER; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 49 "./syslex.l" +{ yylval.i = -1; return NUMBER; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 50 "./syslex.l" +{ return COND;} + YY_BREAK +case 24: +YY_RULE_SETUP +#line 51 "./syslex.l" +{ return REPEAT;} + YY_BREAK +case 25: +YY_RULE_SETUP +#line 52 "./syslex.l" +ECHO; + YY_BREAK +#line 792 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 81 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 81 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 80); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 52 "./syslex.l" diff --git a/gnu/usr.bin/binutils/binutils/syslex.l b/gnu/usr.bin/binutils/binutils/syslex.l new file mode 100644 index 00000000000..a39484287a7 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/syslex.l @@ -0,0 +1,51 @@ +%{ +#include "sysinfo.h" +char *word; +int number; +int unit; + +#ifndef yywrap +static int yywrap () { return 1; } +#endif +%} +%% +"(" { return '(';} +")" { return ')';} +"[" { return '[';} +"]" { return ']';} +" " { ; } +";".* { ; } +"\t" { ; } +"\n" { ; } +"\""[^\"]*"\"" { +yylval.s = malloc(strlen (yytext)); +strcpy(yylval.s, yytext+1); +yylval.s[strlen(yylval.s)-1] = 0; + return NAME; + } + +0x[0-9a-f]+ { + yylval.i = strtol(yytext,0,16); + return NUMBER; + } + +[0-9]+ { + yylval.i = atoi(yytext); + return NUMBER; + } + + +"bits" { yylval.i =1 ;return UNIT;} +"bit" { yylval.i = 1; return UNIT;} +"bytes" { yylval.i= 8; return UNIT;} +"byte" { yylval.i = 8; return UNIT;} + +"int" { yylval.s = "INT"; return TYPE;} +"barray" { yylval.s = "BARRAY"; return TYPE;} +"chars" { yylval.s = "CHARS"; return TYPE;} +"variable" { yylval.i = 0; return NUMBER;} +"counted" { yylval.i = -4; return NUMBER;} +"addrsize" { yylval.i = -2; return NUMBER; } +"segsize" { yylval.i = -1; return NUMBER; } +"cond" { return COND;} +"repeat" { return REPEAT;} diff --git a/gnu/usr.bin/binutils/binutils/sysroff.info b/gnu/usr.bin/binutils/binutils/sysroff.info new file mode 100644 index 00000000000..3af001a1016 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/sysroff.info @@ -0,0 +1,504 @@ +("cs" 0x0 + (("size") (1 byte) ("size")) + + (("hd") (1 byte) ("hd")) + (("hs") (1 byte) ("hs")) + (("un") (1 byte) ("un")) + (("us") (1 byte) ("us")) + + (("sc") (1 byte) ("sc")) + (("ss") (1 byte) ("ss")) + (("er") (1 byte) ("er")) + (("ed") (1 byte) ("ed")) + + (("sh") (1 byte) ("sh")) + (("ob") (1 byte) ("ob")) + (("rl") (1 byte) ("rl")) + (("du") (1 byte) ("du")) + + (("dps") (1 byte) ("dps")) + (("dsy") (1 byte) ("dsy")) + (("dty") (1 byte) ("dty")) + (("dln") (1 byte) ("dln")) + + (("dso") (1 byte) ("dso")) + (("dus") (1 byte) ("dus")) + (("dss") (1 byte) ("dss")) + (("dbt") (1 byte) ("dbt")) + + (("dpp") (1 byte) ("dpp")) + (("dfp") (1 byte) ("dfp")) + (("den") (1 byte) ("den")) + (("dds") (1 byte) ("dds")) + + (("dar") (1 byte) ("dar")) + (("dpt") (1 byte) ("dpt")) + (("dul") (1 byte) ("dul")) + (("dse") (1 byte) ("dse")) + + (("dot") (1 byte) ("dot"))) + + +("hd" 0x04 + (("module type") (4 bits) ("mt") + (("MTYPE_ABS_LM" "0") + ("MTYPE_REL_LM" "1") + ("MTYPE_OMS_OR_LMS" "2") + ("MTYPE_UNSPEC" "0xf"))) + (("spare")(4 bits) ("spare1")) + (("creation date")( chars 12 bytes)( "cd")) + (("number of units") (2 bytes) ("nu")) + (("code") (1 byte) ("code")) + (("version") (chars 4 bytes) ("ver")) + (("address update") (1 byte) ("au")) + (("segment identifier") (1 bit) ("si")) + (("address field length") (4 bits) ("afl")) + (("spare")(3 bits) ("spare2")) + (("space size within segment") (1 byte) ("spcsz")) + (("segment size") (1 byte) ("segsz")) + (("segment shift") (1 byte) ("segsh")) + (("entry point") (1 byte) ("ep")) + (cond "ptr->ep" + (cond "ptr->mt != MTYPE_ABS_LM" + (("unit appearance number") (2 bytes) ("uan")) + (("section appearance number") (2 bytes) ("sa"))) + (cond "segmented_p" + (("segment address") (segsize bytes) ("sad"))) + (("address") (addrsize bytes) ("address"))) + (("os name") (chars variable bytes) ("os")) + (("sys name") (chars variable bytes) ("sys")) + (("module name") (chars variable bytes) ("mn")) + (("cpu") (chars variable bytes) ("cpu"))) + + +("hs" 0x05 + (("neg number") (2 bytes) ("neg"))) + + +("un" 0x06 + (("format") (2 bits) ("format") + (("FORMAT_LM" "0") + ("FORMAT_OM" "1") + ("FORMAT_OMS_OR_LMS" "2"))) + (("spare") (6 bits) ("spare1")) + (("number of sections") (2 bytes) ("nsections")) + (("number of external refs") (2 bytes) ("nextrefs")) + (("number of external defs") (2 bytes) ("nextdefs")) + (("unit name") (chars variable byte) ("name")) + (("tool name") (chars variable byte) ("tool")) + (("creation date") (chars 12 bytes) ("tcd")) + (("linker name") (chars variable byte) ("linker")) + (("creation date") (chars 12 bytes) ("lcd"))) + + +("us" 0x07 + (("negotiation number") (2 bytes) ("neg"))) + + +("sc" 0x08 + (("format") (2 bits) ("format")) + (("spare") (6 bits) ("spare")) + (("segment address") (segsize bytes) ("segadd")) + (("address") (addrsize bytes) ("addr")) + (("length") (addrsize bytes) ("length")) + (("alignment") (addrsize bytes) ("align")) + (("contents") (4 bits) ("contents") + (("CONTENTS_CODE" "0") + ("CONTENTS_DATA" "1") + ("CONTENTS_STACK" "2") + ("CONTENTS_DUMMY" "3") + ("CONTENTS_SPECIAL" "4") + ("CONTENTS_NONSPEC" "0xf"))) + (("concat") (4 bits) ("concat") + (("CONCAT_SIMPLE" "0") + ("CONCAT_SHAREDC" "1") + ("CONCAT_DUMMY" "2") + ("CONCAT_GROUP" "3") + ("CONCAT_SHARED" "4") + ("CONCAT_PRIVATE" "5") + ("CONCAT_UNSPEC" "0xf"))) + (("read") (2 bits) ("read")) + (("write") (2 bits) ("write")) + (("exec") (2 bits) ("exec")) + (("initialized") (2 bits) ("init")) + (("mode") (2 bits) ("mode")) + (("spare") (6 bits) ("spare1")) + (("name") (chars variable byte) ("name"))) + + +("ss" 0x09 + (("neg number") (2 bytes) ("neg"))) + + +("er" 0x0c + (("symbol type") (2 bits) ("type") + (("ER_ENTRY" "0") + ("ER_DATA" "1") + ("ER_NOTDEF" "2") + ("ER_NOTSPEC" "3"))) + (("spare") (6 bits) ("spare")) + (("symbol name") (chars variable byte) ("name"))) + + +("ed" 0x14 + (("section appearance number") (2 bytes) ("section")) + (("symbol type") (3 bits) ("type") + (("ED_TYPE_ENTRY" "0") + ("ED_TYPE_DATA" "1") + ("ED_TYPE_CONST" "2") + ("ED_TYPE_NOTSPEC" "7"))) + (("spare") (5 bits) ("spare")) + (cond "ptr->type==ED_TYPE_ENTRY || ptr->type==ED_TYPE_DATA" + (("symbol address") (addrsize bytes) ("address"))) + (cond "ptr->type==ED_TYPE_CONST" + (("constant value") (addrsize bytes) ("constant"))) + (("symbol name") (chars variable byte) ("name"))) + + +("sh" 0x1a + (("unit appearance number") (2 bytes) ("unit")) + (("section appearance number") (2 bytes) ("section"))) + + +("ob" 0x1c + (("starting address flag") (1 bit) ("saf")) + (("compression flag") (1 bit) ("cpf")) + (("spare") (6 bits) ("spare")) + (cond "ptr->saf" + ( ("starting address") (addrsize bytes) ("address"))) + (cond "ptr->cpf" + (("comp reps") (addrsize bytes) ("compreps"))) + (("data") (barray counted byte) ("data"))) + + +("rl" 0x20 + (("boundary of relocateable area") (4 bits) ("boundary")) + (("address polarity") (1 bit) ("apol")) + (("segment number") (1 bit) ("segment")) + (("sign of relocation") (1 bit) ("sign")) + (("check range") (1 bit) ("check")) + (("reloc address") (addrsize bytes) ("addr")) + + (("bit loc") (1 byte) ("bitloc")) + (("field length") (1 byte) ("flen")) + (("bcount") (1 byte) ("bcount")) + (("operator") (1 byte) ("op") + (("OP_RELOC_ADDR" "1") + ("OP_SEC_REF" "0") + ("OP_EXT_REF" "2"))) + (cond "ptr->op == OP_EXT_REF" + (("symbol number") (2 bytes) ("symn")) ) + + (cond "ptr->op == OP_SEC_REF" + (("section number") (2 bytes) ("secn")) + (("const opcode") (1 byte) ("copcode_is_3")) + (("addend length") (1 byte) ("alength_is_4")) + (("addend") (4 byte) ("addend")) + (("plus opcode") (1 byte) ("aopcode_is_0x20"))) + + (cond "ptr->op == OP_RELOC_ADDR" + (("dunno") (2 bytes) ("dunno"))) + + (("end") (1 byte) ("end"))) + + +("du" 0x30 + (("format") (2 bits) ("format")) + (("optimized") (1 bit) ("optimized")) + (("stackfrmt") (2 bits) ("stackfrmt")) + (("spare") (3 bits) ("spare")) + (("unit number") (2 bytes) ("unit")) + (("sections") (2 bytes) ("sections")) + (repeat "ptr->sections" + (("section appearance number") (2 bytes) ("san")) + (("address") (addrsize bytes) ("address")) + (("section length") (addrsize bytes) ("length"))) + (("tool name") (chars variable byte) ("tool")) + (("creation date") (chars 12 bytes) ("date"))) + + +("dsy" 0x34 + (("symbol type") (7 bits) ("type") + (("STYPE_VAR" "0") + ("STYPE_LAB" "1") + ("STYPE_PROC" "2") + ("STYPE_FUNC" "3") + ("STYPE_TYPE" "4") + ("STYPE_CONST" "5") + ("STYPE_ENTRY" "6") + ("STYPE_MEMBER" "7") + ("STYPE_ENUM" "8") + ("STYPE_TAG" "9") + ("STYPE_PACKAGE" "10") + ("STYPE_GENERIC" "11") + ("STYPE_TASK" "12") + ("STYPE_EXCEPTION" "13") + ("STYPE_PARAMETER" "14") + ("STYPE_EQUATE" "15") + ("STYPE_UNSPEC" "0x7f"))) + (("assignment info") (1 bit) ("assign")) + (("symbol id") (2 bytes) ("snumber")) + (("symbol name") (chars variable bytes) ("sname")) + (("nesting level") (2 bytes) ("nesting")) + (cond "ptr->assign" + (("assignment type") (1 byte) ("ainfo") + (("AINFO_REG" "1") + ("AINFO_STATIC_EXT_DEF" "2") + ("AINFO_STATIC_EXT_REF" "3") + ("AINFO_STATIC_INT" "4") + ("AINFO_STATIC_COM" "5") + ("AINFO_AUTO" "6") + ("AINFO_CONST" "7") + ("AINFO_UNSPEC" "0xff"))) + (("data length") (addrsize bytes) ("dlength")) + (cond "ptr->ainfo == AINFO_STATIC_EXT_DEF + || ptr->ainfo == AINFO_STATIC_INT + || ptr->ainfo == AINFO_STATIC_COM" + (("section number") (2 bytes) ("section"))) + (cond "ptr->ainfo == AINFO_STATIC_EXT_DEF + || ptr->ainfo == AINFO_STATIC_INT + || ptr->ainfo == AINFO_STATIC_COM + || ptr->ainfo == AINFO_AUTO" + (("address") (addrsize bytes) ("address"))) + (cond "ptr->ainfo == AINFO_REG" + (("register name") (chars variable bytes) ("reg"))) + (cond "ptr->ainfo == AINFO_STATIC_EXT_DEF + || ptr->ainfo == AINFO_STATIC_EXT_REF" + (("external name") (chars variable bytes) ("ename"))) + (cond "ptr->ainfo == AINFO_CONST" + (("constant") (chars variable bytes) ("constant")))) + (cond "ptr->type == STYPE_MEMBER" + (("assignment unit") (1 bit) ("bitunit")) + (("spare") (7 bits) ("spare2")) + (("field length") (addrsize bytes) ("field_len")) + (("field offset") (addrsize bytes) ("field_off")) + (cond "ptr->bitunit" + (("bit offset") (addrsize bytes) ("field_bitoff")))) + (cond "ptr->type== STYPE_ENUM" + (("value length") (1 byte) ("evallen")) + (("value") (4 bytes) ("evalue"))) + (cond "ptr->type == STYPE_CONST" + (("value") (chars variable bytes) ("cvalue"))) + (cond "ptr->type == STYPE_EQUATE" + (("value length") (1 byte) ("qvallen")) + (("value") (4 bytes) ("qvalue")) + (("basic type") (1 byte) ("btype")) + (("size information") (addrsize bytes) ("sizeinfo")) + (("sign") (2 bits) ("sign")) + (("floating point type") (6 bits) ("flt_type"))) + (("source file number") (2 bytes) ("sfn")) + (("source line number") (2 bytes) ("sln")) + (("negotiation number") (2 bytes) ("neg")) + (cond "ptr->type == STYPE_TAG" + (("magic") (1 byte) ("magic")))) + + + +("dul" 0x52 + (("max declaration type flag") (1 bit) ("max_variable")) + (("max spare") (7 bits) ("maxspare")) + (cond "ptr->max_variable == 0" + (("maximum") (addrsize bytes) ("max")) + (("max mode") (chars variable bytes) ("maxmode"))) + + (("min declaration type flag") (1 bit) ("min_variable")) + (("min spare") (7 bits) ("minspare")) + (cond "ptr->min_variable == 0" + (("minimum") (addrsize bytes) ("min")) + (("min mode") (chars variable bytes) ("minmode")))) + + +("dty" 0x36 + (("end flag") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("negotiation") (2 bytes) ("neg")))) + + +("dbt" 0x44 + (("basic type") (1 byte) ("btype") + (("BTYPE_VOID" "0") + ("BTYPE_UNDEF" "1") + ("BTYPE_CHAR" "2") + ("BTYPE_INT" "3") + ("BTYPE_FLOAT" "4") + ("BTYPE_BIT" "5") + ("BTYPE_STRING" "6") + ("BTYPE_DECIMAL" "7") + ("BTYPE_ENUM" "8") + ("BTYPE_STRUCT" "9") + ("BTYPE_TYPE" "10") + ("BTYPE_TAG" "11") + ("BTYPE_UNSPEC" "0xff"))) + (("size info") (addrsize bytes) ("bitsize")) + (("sign") (2 bits) ("sign") + (("SIGN_SIGNED" "0") + ("SIGN_UNSIGNED" "1") + ("SIGN_UNSPEC" "3"))) + (("floating point type") (6 bits) ("fptype") + (("FPTYPE_SINGLE" "0") + ("FPTYPE_DOUBLE" "1") + ("FPTYPE_EXTENDED" "2") + ("FPTYPE_NOTSPEC" "0x3f"))) + (cond "ptr->btype==BTYPE_TAG || ptr->btype == BTYPE_TYPE" + (("symbol id") (2 bytes) ("sid"))) + (("negotiation") (2 bytes) ("neg"))) + +("dar" 0x4e + (("element length" ) (addrsize bytes) ("length")) + (("dims") (1 byte) ("dims")) + (repeat "ptr->dims" + (("variable flag") (1 bit) ("variable") + (("VARIABLE_FIXED" "0") + ("VARIABLE_VARIABLE" "1"))) + + (("subscript type") (1 bit) ("subtype") + (("SUB_INTEGER" "0") + ("SUB_TYPE" "1"))) + + (("spare") (6 bits) ("spare")) + + (cond "ptr->subtype[n] == SUB_TYPE" + (("sub symbol id") (2 bytes) ("sid"))) + + (cond "ptr->subtype[n] == SUB_INTEGER" + (("max declaration type flag") (1 bit) ("max_variable")) + (("max spare") (7 bits) ("maxspare")) + ;; FIXME: next field should be conditional on max_variable, + (("maximum") (addrsize bytes) ("max")) + + (("min declaration type flag") (1 bit) ("min_variable")) + (("min spare") (7 bits) ("minspare")) + ;; FIXME: next field should be conditional on min_variable + (("minimum") (addrsize bytes) ("min")))) + (("negotiation") (2 bytes) ("neg"))) + + +("dso" 0x3a + (("function name") (2 bytes) ("sid")) + (("sp update count") (4 bytes) ("spupdates")) + (repeat "ptr->spupdates" + (("update address") (addrsize bytes) ("address")) + (("offset") (addrsize bytes) ("offset")))) + +("dln" 0x38 + (("number of lines") (2 bytes) ("nln")) + (repeat "ptr->nln" + (("source file number") (2 bytes) ("sfn")) + (("source line number") (2 bytes) ("sln")) + (("section number") (2 bytes) ("section")) + (("from address") (addrsize bytes) ("from_address")) + (("to address") (addrsize bytes) ("to_address")) + (("call count") (2 bytes) ("cc")) + ) + (("neg") (2 bytes) ("neg"))) + +("dpp" 0x46 + (("start/end") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("params") (1 byte) ("params")) + (("neg number") (2 bytes) ("neg")))) + +("den" 0x4a + (("start/end") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("neg number") (2 bytes) ("neg")))) + +("dfp" 0x48 + (("start/end flag") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("number of parameters") (1 byte) ("nparams")) + (("neg number") (2 bytes) ("neg")))) + +("dds" 0x4c + (("start/end") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("neg number") (2 bytes) ("neg")))) + +("dpt" 0x50 + (("neg number") (2 bytes) ("neg")) + (("dunno") (1 byte) ("dunno"))) + +("dse" 0x54 + (("neg number") (2 bytes) ("neg")) + (("dunno") (1 byte) ("dunno"))) + +("dot" 0x56 + (("unknown") (1 byte) ("unknown"))) +; FIXME: unknown field should be repeated symbol number? + + +("dss" 0x42 + (("type") (1 byte) ("type")) + (("external/internal") (1 bit) ("internal")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->internal" + ( ("package name") (chars variable byte) ("package"))) + (cond "ptr->internal" + (("symbol id") (2 bytes) ("id"))) + (("record type") (2 bytes) ("record")) + (("rules") (chars variable byte) ("rules")) + (("number of symbols") (2 bytes) ("nsymbols")) + (("unknown" ) (2 bytes) ("fixme"))) + +("pss" 0x40 + (("negotiation number") (2 bytes) ("efn")) + (("number of source files") (2 bytes) ("ns")) + (repeat "ptr->ns" + (("directory reference bit") (1 bit) ("drb")) + (("spare") (7 bits) ("spare")) + (("completed file name") (chars variable byte) ("fname")) + (cond "ptr->drb[n]" + (("directory apperance number") (2 bytes) ("dan")))) + + (("number of directories") (2 bytes) ("ndir")) + (repeat "ptr->ndir" + (("directory name") (chars variable bytes) ("dname")))) + + +; FIXME: the tr block has no contents. sysinfo, etc. aren't prepared +; to deal with that. +; ("tr" 0x7f) + + +("dus" 0x40 + (("negotiation number") (2 bytes) ("efn")) + (("number of source files") (2 bytes) ("ns")) + (repeat "ptr->ns" + (("directory reference bit") (1 bit) ("drb")) + (("spare") (7 bits) ("spare")) + (("completed file name") (chars variable byte) ("fname")) + (cond "ptr->drb[n]" + (("directory apperance number") (2 bytes) ("dan")))) + (("number of directories") (2 bytes) ("ndir")) + (repeat "ptr->ndir" + (("directory name") (chars variable bytes) ("dname")))) + + +("dps" 0x32 + (("start/end flag") (1 bit) ("end")) + (("block type") (7 bits) ("type") + (("BLOCK_TYPE_COMPUNIT" "0") + ("BLOCK_TYPE_PROCEDURE" "2") + ("BLOCK_TYPE_FUNCTION" "3") + ("BLOCK_TYPE_BLOCK" "4") + ("BLOCK_TYPE_BASIC" "9"))) + (cond "!ptr->end" + (("optimization") (1 byte) ("opt")) + (("section number") (2 bytes) ("san")) + (("address") (addrsize bytes) ("address")) + (("block size") (addrsize bytes) ("block_size")) + (("nesting") (1 byte) ("nesting")) + (cond "ptr->type == BLOCK_TYPE_PROCEDURE + || ptr->type == BLOCK_TYPE_FUNCTION" + (("return address") (1 bit) ("retaddr")) + (("interrupt function flag") (1 bit) ("intrflag")) + (("stack update flag") (1 bit) ("stackflag")) + (("intra page JMP") (1 bit) ("intrpagejmp")) + (("spare") (4 bits) ("spare"))) + (("neg number") (2 bytes) ("neg")))) + diff --git a/gnu/usr.bin/binutils/binutils/testsuite/ChangeLog b/gnu/usr.bin/binutils/binutils/testsuite/ChangeLog new file mode 100644 index 00000000000..b55e62d4e16 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/ChangeLog @@ -0,0 +1,347 @@ +Thu Nov 16 16:02:09 1995 Ken Raeburn + + * binutils-all/ar.exp: Switch "verbose -log" to send_output plus + verbose. + +Wed Nov 15 18:34:42 1995 Ken Raeburn + + * binutils-all/objcopy.exp: Simple copy test does appear to work + on i*86-svr4. + +Wed Nov 15 12:19:28 1995 Ian Lance Taylor + + * binutils-all/objcopy.exp: If assembly fails, call unresolved. + Test running objcopy and strip on a final executable. + * binutils-all/testprog.c: New file. + * config/default.exp (STRIP, STRIPFLAGS): Define. + (binutils_compile): New procedure. + * lib/utils-lib.exp (default_binutils_compile): New procedure. + +Fri Nov 3 13:22:33 1995 Ian Lance Taylor + + * lib/utils-lib.exp (default_binutils_run): Don't use verbose + -log, reverting part of Oct 2 change. + +Wed Nov 1 15:09:57 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 + + * binutils-all/objcopy.exp: Add setup_xfails for + m68*-motorola-sysv* and m88*-motorola-sysv*. + +Wed Oct 4 14:38:31 1995 Ian Lance Taylor + + * binutils-all/nm.exp: Add setup_xfails for XCOFF. + +Mon Oct 2 12:41:48 1995 Ian Lance Taylor + + * binutils-all/ar.exp: New file. + * binutils-all/bintest.s: Make text_symbol and data_symbol global. + Add new static symbols static_text_symbol and static_data_symbol. + * binutils-all/nm.exp: Adjust accordingly. + * config/default.exp (AR): Set if not set. + (binutils_remove): New procedure. + * lib/utils-lib.exp (default_binutils_run): Call + prune_system_crud on program output. Use verbose -log instead of + both verbose and send_log. + (default_binutils_remove): New procedure. + + * lib/utils-lib.exp (default_binutils_assemble): Call + prune_system_crud on assembler output. + +Tue Sep 26 14:07:05 1995 Ian Lance Taylor + + * binutils-all/objcopy.exp: Add setup_xfails for simple copy test + for i386 COFF targets. + +Wed Sep 13 13:20:21 1995 Ian Lance Taylor + + * lib/utils-lib.exp (prune_system_crud): Define if not defined. + * binutils-all/objcopy.exp: Call prune_system_crud on cmp output. + +Sat Aug 19 17:38:06 1995 Ian Lance Taylor + + * binutils-all/objcopy.exp: Add xfail for i*86-*-aout* for simple + copy test. + +Wed Aug 16 16:52:53 1995 Ian Lance Taylor + + * binutils-all/nm.exp: Add setup_xfail for mips*-sony-bsd* for + tests which fail on ECOFF targets. + + * binutils-all/objcopy.exp: Change i*86-*-linux xfail for simple + copy test to check for i*86-*-linuxaout* instead. + +Tue Aug 8 17:48:37 1995 Ian Lance Taylor + + * binutils-all/objcopy.exp: Add setup_xfail for a29k-*-vxworks* + for simple copy test. + +Tue Jul 25 11:57:12 1995 Ian Lance Taylor + + * binutils-all/objcopy.exp: Change setup_xfail for simple copy + test from i960-*-vxworks5.1 to i960-*-vxworks*. + +Mon Jul 10 12:25:46 1995 Ian Lance Taylor + + * binutils-all/objcopy.exp: Add setup_xfail for z8*-*-coff for + simple copy test. + * binutils-all/objdump.exp (cpus_expected): Add z8001 and z8002. + +Sun May 21 20:32:53 1995 Jeff Law (law@snake.cs.utah.edu) + + * binutils-all/hppa/objdump.exp (addendbug): Handle PA ELF targets + too. + * binutils-all/objcopy.exp (simple copy): Don't expect PA ELF + targets to fail. + +Tue Apr 4 14:52:08 1995 Jeff Law (law@snake.cs.utah.edu) + + * binutils-all/hppa: Renamed from binutils-hppa. + +Wed Mar 29 12:02:43 1995 Ian Lance Taylor + + * binutils-all/objcopy.exp: Add setup_xfail for simple copy test + for h8500-*-hms and h8500-*-coff. + +Tue Mar 28 11:18:28 1995 Ian Lance Taylor + + * binutils-all/objcopy.exp: Add setup_xfail for simple copy test + for m68*-ericsson-ose and m88*-*-coff. + +Mon Mar 27 11:27:31 1995 Ian Lance Taylor + + * binutils-all/objcopy.exp: Add setup_xfail for simple copy test + for m68*-*-vxworks*. + +Fri Mar 24 11:44:25 1995 Ian Lance Taylor + + * binutils-hppa/objdump.exp: Correct hppa*-*-* check. + +Tue Mar 21 10:48:45 1995 Jeff Law (law@snake.cs.utah.edu) + + * binutils-hppa/addendbug.s: New testcase. + * binutils-hppa/objdump.exp: Run it. + +Mon Mar 20 11:31:05 1995 Ian Lance Taylor + + * lib/utils-lib.exp (default_binutils_run): Quote any dollar signs + in progargs before passing it to exec. + +Fri Mar 17 16:39:31 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/hppa.sed: Sed script to transform bintest.s into proper + PA assembly code. + * binutils-all/nm.exp: Enable these tests on the PA. + * binutils-all/objcopy.exp: Enable these tests on the PA. Expect + simple copy to fail. + * binutils-all/objdump.exp: Enable these tests on the PA. Handle + "CODE" as a section name. + * binutils-all/size.exp: Enable these tests on the PA. + * lib/utils-lib.exp (default_binutils_assemble): For "hppa*-*-*", + run the assembly through a sed script before passing it to the + assembler. + +Wed Mar 15 16:47:13 1995 Ian Lance Taylor + + * binutils-all/objdump.exp: Force section sizes to be interpreted + in hex. Change objdump -h failure mode to always use the same + string. + +Thu Jan 5 13:01:43 1995 Ian Lance Taylor + + * binutils-all/nm.exp: Just check for irix4*, rather than + irix\[0-4\]*, to avoid DejaGnu bug. + +Thu Dec 15 19:35:31 1994 Ken Raeburn + + * binutils-all/objcopy.exp: Expect simple-objcopy test to fail + for various other targets for which gas doesn't use bfd: sh-hms, + m68k-hpux, m68k-sunos, m68k-coff, i386-linux, a29k-udi, a29k-coff, + i960-vxworks5.1, i960-coff, h8300-hms, h8300-coff. + +Wed Dec 14 15:54:46 1994 Ken Raeburn + + * binutils-all/size.exp: Skip tests requiring bintest.o on hppa, + since it (correctly) generates syntax errors on that platform. + * binutils-all/objdump.exp: Ditto. + * binutils-all/nm.exp: Ditto. + * binutils-all/objcopy.exp: Ditto. Also, move setup_xfail for + sh-coff to branch where objcopy execution produced no error + messages. Expect failure for hp300 also. + +Thu Dec 8 14:36:15 1994 Ken Raeburn + + * binutils-all/objdump.exp (cpus_expected): New variable, taken + from objdump -i test, added ns32k and powerpc, sorted. + (objdump -i, -f tests): Use $cpus_expected. + + * binutils-all/objcopy.exp: For simple-copy test, expect failure + for sh-coff. + +Tue Oct 25 16:00:14 1994 Ian Lance Taylor + + * binutils-all/objcopy.exp: Adjust --adjust-section-vma tests for + new S-record section handling. + +Tue Oct 18 11:18:21 1994 Ian Lance Taylor + + * binutils-all/nm.exp: nm with no arguments and nm -P do not work + as expected on ECOFF targets; add calls to setup_xfail. + + * binutils-all/objcopy.exp: New file. + * config/default.exp: Initialize OBJCOPY and OBJCOPYFLAGS. + +Fri Oct 14 14:46:22 1994 Ian Lance Taylor + + Rewrite testsuite. + * configure.in, Makefile.in: Remove. + * binutils-all/configure.in, binutils-all/Makefile.in: Remove. + * binutils-all/bintest.c: Remove. + * binutils-all/bintest.s: New file. + * binutils-all/nm.exp, binutils-all/objdump.exp: Rewrite. + * binutils-all/size.exp: Rewrite. + * config/default.exp: Load utils-lib.exp. Set AS and ASFLAGS. + Don't go up one directory from $base_dir. Create tmpdir. + (binutils_run, binutils-assemble): New procedures. + * config/unix.exp: Remove. + * config/mt-a29k-udi, config/mt-i386-aout: Remove. + * config/mt-i960-nindy, config/mt-lynx, config/mt-m68k: Remove. + * config/mt-mips-ecoff, config/mt-slite: Remove. + * config/mt-sparc-aout, config/mt-vxworks: Remove. + * lib/utils-lib.exp (binutil_version): Don't redirect standard + input when getting version. Don't unset errorInfo. + (default_binutils_run): New procedure. + (default_binutils_assemble): New procedure. + +Thu Sep 29 12:45:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * VMS does not permit `.' in directory names: renamed binutils.all + to binutils-all. + * configure.in (configdirs): Change binutils.all to binutils-all. + +Fri Sep 23 16:01:14 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * configure.in: Use mt-m68k for m68k*-*-aout* and m68k*-*-coff*, + not for m68k-*-*. + +Fri Sep 23 13:54:50 1994 Ken Raeburn + + * binutils.all/objdump.exp: Added ARM to list of CPU types. + +Thu Sep 22 11:04:50 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * binutils.all/objdump.exp: Update for new usage message. + * binutils.all/size.exp: Use a double backslash in the string to + get a single backslash to the regexp matcher. Accept $TEXT$, + $DATA$ and $BSS$ as well as .text, .data and .bss, for HP/UX. + +Fri Sep 2 12:53:10 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/unix.exp: If nm.new does not exist, use [transform nm]. + * config/default.exp: Likewise. + +Wed Aug 24 12:41:37 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * configure.in, binutils.all/configure.in: Change i386 to + i[345]86. + +Tue Jul 19 15:23:53 1994 Bill Cox (bill@rtl.cygnus.com) + + * config/mt-mips-ecoff: Add -Tidp.ld option. + +Thu Jun 30 12:41:55 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * config/default.exp: Use nm.new, not nm, from newly built tree. + +Tue May 17 14:04:05 1994 Bill Cox (bill@rtl.cygnus.com) + + * config/default.exp, config/unix.exp: Replace error + proc calls with perror. + +Tue May 10 11:20:54 1994 Stan Shebs (shebs@andros.cygnus.com) + + * configure.in (sparclite): Match on sparclite*-*-*. + +Wed Apr 13 18:25:19 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/unix.exp: Use nm.new, not nm, from newly built tree. + + * binutils.all/objdump.exp: Add more wildcards to list of + single-letter options in pattern for usage message. + + * binutils.all/nm.exp: Deleted debug-symbols test, since it only + works for a.out/stabs systems. Fixed regexps to make underscores + optional, since some C compilers don't prepend them. Deleted + check for foo.o symbol, since again some systems don't generate + it. + +Mon Apr 11 10:31:00 1994 Bill Cox (bill@rtl.cygnus.com) + + * Makefile.in (check): Set TCL_LIBRARY for runtest. + +Mon Feb 14 19:34:03 1994 Rob Savoye (rob@darkstar.cygnus.com) + + * Makefile.in: Use new config features of DejaGnu in site.exp + file. "Make check" should now work for all crosses. + +Fri Jan 28 18:00:29 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * binutils.all/objdump.exp: In usage message, accept + "section-name" as well as "section_name". + +Mon Jan 17 16:57:02 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * binutils.all/objdump.exp: Trim list of format names expected, + and accept any known CPU type. + +Thu Dec 2 20:50:24 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * Makefile.in: Remove some stuff from the site.exp file. + * config/unix.exp: Add global before seeing if the variables for + nm, objdump, and size exist. + +Wed Nov 3 11:12:32 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * config/udi.exp,unix.exp: Transform tool name. + * binutils.all/*.exp: Clear errorInfo after exec. + +Fri Jul 2 12:41:20 1993 Ian Lance Taylor (ian@cygnus.com) + + * binutils.all/*.exp: Use -- for long arguments rather than +. + +Fri Jun 4 10:52:29 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: change srctrigger to Makefile.in + +Wed May 26 17:27:46 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (FLAGS_TO_PASS): Pass down CC and CFLAGS. + +Fri May 7 13:58:44 1993 Ian Lance Taylor (ian@cygnus.com) + + * binutils.all/objdump.exp: Update for new usage message. + +Mon Apr 19 14:08:52 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * binutils.all/*.exp: Use the new util_test proc. + * Makefile.in: Create a local site.exp file with config info. + +Thu Mar 25 05:38:47 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * nm.all/configure.in (srcname): Delete extra quote. + +Mon Feb 22 07:54:03 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * binutils/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) + + * binutils/testsuite: Initial creation of binutils/testsuite. + Migrated dejagnu testcases and support files for testing nm to + binutils/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. + diff --git a/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/ar.exp b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/ar.exp new file mode 100644 index 00000000000..9dae7f06297 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/ar.exp @@ -0,0 +1,158 @@ +# 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# Written by Ian Lance Taylor + +if {[which $AR] == 0} then { + perror "$AR does not exist" + return +} + +# send_user "Version [binutil_version $AR]" + +# Test long file name support + +proc long_filenames { } { + global AR + global host_triplet + + set testname "ar long file names" + + set n1 "abcdefghijklmnopqrstuvwxyz1" + set n2 "abcdefghijklmnopqrstuvwxyz2" + + binutils_remove tmpdir/$n1 + set f [open tmpdir/$n1 w] + puts $f "first" + close $f + + binutils_remove tmpdir/$n2 + set f [open tmpdir/$n2 w] + puts $f "second" + close $f + + binutils_remove tmpdir/artest.a + set got [binutils_run $AR "rc tmpdir/artest.a tmpdir/$n1 tmpdir/$n2"] + if ![string match "" $got] { + fail $testname + return + } + + binutils_remove tmpdir/$n1 + binutils_remove tmpdir/$n2 + + set got [binutils_run $AR "t tmpdir/artest.a"] + if ![string match "$n1*$n2" $got] { + fail $testname + return + } + + send_log "cd tmpdir; $AR x artest.a\n" + verbose "cd tmpdir; $AR x artest.a" + catch "exec /bin/sh -c \"cd tmpdir; $AR x artest.a\"" exec_output + set exec_output [prune_system_crud $host_triplet $exec_output] + if ![string match "" $exec_output] { + send_log "$exec_output\n" + verbose $exec_output + fail $testname + return + } + + if ![file exists tmpdir/$n1] { + send_log "tmpdir/$n1 does not exist\n" + verbose "tmpdir/$n1 does not exist" + fail $testname + return + } + if ![file exists tmpdir/$n2] { + send_log "tmpdir/$n2 does not exist\n" + verbose "tmpdir/$n2 does not exist" + fail $testname + return + } + + set f [open tmpdir/$n1 r] + if { [gets $f line] == -1 || $line != "first" } { + send_log "tmpdir/$n1 contents:\n" + verbose "tmpdir/$n1 contents:" + send_log "$line\n" + verbose "$line" + close $f + fail $testname + return + } + close $f + + set f [open tmpdir/$n2 r] + if { [gets $f line] == -1 || $line != "second" } { + send_log "tmpdir/$n2 contents:\n" + verbose "tmpdir/$n2 contents:" + send_log "$line\n" + verbose "$line" + close $f + fail $testname + return + } + close $f + + pass $testname +} + +# Test building the symbol table. + +proc symbol_table { } { + global AR + global AS + global NM + global srcdir + global subdir + + set testname "ar symbol table" + + if ![binutils_assemble $AS $srcdir/$subdir/bintest.s tmpdir/bintest.o] { + unresolved $testname + return + } + + binutils_remove tmpdir/artest.a + + set got [binutils_run $AR "rc tmpdir/artest.a tmpdir/bintest.o"] + if ![string match "" $got] { + fail $testname + return + } + + set got [binutils_run $NM "--print-armap tmpdir/artest.a"] + if { ![string match "*text_symbol in bintest.o*" $got] \ + || ![string match "*data_symbol in bintest.o*" $got] \ + || ![string match "*common_symbol in bintest.o*" $got] \ + || [string match "*static_text_symbol in bintest.o*" $got] \ + || [string match "*static_data_symbol in bintest.o*" $got] \ + || [string match "*external_symbol in bintest.o*" $got] } { + fail $testname + return + } + + pass $testname +} + +# Run the tests. + +long_filenames +symbol_table diff --git a/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/bintest.s b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/bintest.s new file mode 100644 index 00000000000..9e006502219 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/bintest.s @@ -0,0 +1,12 @@ + .globl text_symbol + .text +text_symbol: +static_text_symbol: + .long 1 + .long external_symbol + .globl data_symbol + .data +data_symbol: +static_data_symbol: + .long 2 + .comm common_symbol,4 diff --git a/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/hppa/addendbug.s b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/hppa/addendbug.s new file mode 100644 index 00000000000..659306f0741 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/hppa/addendbug.s @@ -0,0 +1,23 @@ + .SPACE $PRIVATE$ + .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 + .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82 + .SPACE $TEXT$ + .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 + .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY + .IMPORT $global$,DATA + .IMPORT $$dyncall,MILLICODE +; gcc_compiled.: + .SPACE $TEXT$ + .SUBSPA $CODE$ + + .align 4 + .EXPORT initialize_char_syntax,CODE + .EXPORT initialize_char_syntax,ENTRY,PRIV_LEV=3,RTNVAL=GR +initialize_char_syntax + .PROC + .CALLINFO FRAME=64,NO_CALLS,SAVE_SP,ENTRY_GR=3 + .ENTRY + addil L'is_idchar-$global$-32,%r27 + .EXIT + .PROCEND +is_idchar .comm 256 diff --git a/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/hppa/objdump.exp b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/hppa/objdump.exp new file mode 100644 index 00000000000..ee0bbbee8b9 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/hppa/objdump.exp @@ -0,0 +1,53 @@ +# 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. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye +# and rewritten by Ian Lance Taylor + +if ![istarget hppa*-*-*] then { + return +} + +if {[which $OBJDUMP] == 0} then { + perror "$OBJDUMP does not exist" + return +} + +send_user "Version [binutil_version $OBJDUMP]" + +if {![binutils_assemble $AS $srcdir$subdir/addendbug.s tmpdir/addendbug.o]} then { + return +} + +# Make sure the SOM BFD code sign extends constants in R_DATA_OVERRIDE fixups. + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -r tmpdir/addendbug.o"] + +if [istarget hppa*-*-*elf*] then { + set want "00000000 R_PARISC_DPREL21L\[ \]+is_idchar\\+0xffffffe0.*" +} else { + set want "00000000 R_DP_RELATIVE\[ \]+is_idchar\\+0xffffffe0.*" +} + + +if [regexp $want $got] then { + pass "addendbug test" +} else { + fail "addendbug test" +} diff --git a/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/nm.exp b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/nm.exp new file mode 100644 index 00000000000..d5dfc789530 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/nm.exp @@ -0,0 +1,115 @@ +# 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. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye +# and rewritten by Ian Lance Taylor + +if {[which $NM] == 0} then { + perror "$NM does not exist" + return +} + +send_user "Version [binutil_version $NM]" + + +if {![binutils_assemble $AS $srcdir$subdir/bintest.s tmpdir/bintest.o]} then { + return +} + +# Test nm with no arguments. + +# This test does not work correctly on ECOFF targets, because ECOFF +# stores most symbols twice, which messes up the nm output. +setup_xfail "alpha*-*-osf*" "alpha*-*-netware*" +setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" +setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" "mips*-sony-bsd*" + +# This test does not work correctly on XCOFF targets, because XCOFF +# does not enter static symbols in the symbol table. +setup_xfail "*-*-aix*" + +set got [binutils_run $NM "$NMFLAGS tmpdir/bintest.o"] + +if [info exists vars] then { unset vars } +while {[regexp "(\[a-zA-Z\]) (\[a-z_\]*_symbol)(.*)" $got all type symbol rest]} { + set vars($symbol) $type + set got $rest +} + +if {![info exists vars(text_symbol)] \ + || $vars(text_symbol) != "T" \ + || ![info exists vars(data_symbol)] \ + || $vars(data_symbol) != "D" \ + || ![info exists vars(common_symbol)] \ + || $vars(common_symbol) != "C" \ + || ![info exists vars(external_symbol)] \ + || $vars(external_symbol) != "U" \ + || ![info exists vars(static_text_symbol)] \ + || $vars(static_text_symbol) != "t" \ + || ![info exists vars(static_data_symbol)] \ + || $vars(static_data_symbol) != "d"} { + fail "nm (no arguments)" +} else { + pass "nm (no arguments)" +} + +# Test nm -g + +set got [binutils_run $NM "$NMFLAGS -g tmpdir/bintest.o"] + +if [info exists vars] then { unset vars } +while {[regexp "(\[a-z_\]*_symbol)(.*)" $got all symbol rest]} { + set vars($symbol) 1 + set got $rest +} + +if {![info exists vars(text_symbol)] \ + || ![info exists vars(data_symbol)] \ + || ![info exists vars(common_symbol)] \ + || ![info exists vars(external_symbol)] \ + || [info exists vars(static_text_symbol)] \ + || [info exists vars(static_data_symbol)]} { + fail "nm -g" +} else { + pass "nm -g" +} + +# Test nm -P + +# This test does not work correctly on ECOFF targets, because ECOFF +# stores most symbols twice, which messes up the nm output. +setup_xfail "alpha*-*-osf*" "alpha*-*-netware*" +setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" +setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" "mips*-sony-bsd*" + +# This test does not work correctly on XCOFF targets, because XCOFF +# does not enter static symbols in the symbol table. +setup_xfail "*-*-aix*" + +set got [binutils_run $NM "$NMFLAGS -P tmpdir/bintest.o"] + +set want "common_symbol C \[0\]*4.*data_symbol D \[0-9a-fA-F\]*.*external_symbol U.*static_data_symbol d \[0-9a-fA-F\]*.*static_text_symbol t \[0-9a-fA-F\]*.*text_symbol T \[0-9a-fA-F\]*" + +if [regexp $want $got] then { + pass "nm -P" +} else { + fail "nm -P" +} + +# There are certainly other tests that could be run. diff --git a/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/objcopy.exp b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/objcopy.exp new file mode 100644 index 00000000000..7e07e2619a8 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/objcopy.exp @@ -0,0 +1,401 @@ +# 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. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# Written by Ian Lance Taylor + +if {[which $OBJCOPY] == 0} then { + perror "$OBJCOPY does not exist" + return +} + +send_user "Version [binutil_version $OBJCOPY]" + +if {![binutils_assemble $AS $srcdir$subdir/bintest.s tmpdir/bintest.o]} then { + unresolved "objcopy (simple copy)" + return +} + +# Test that objcopy does not modify a file when copying it. + +set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS tmpdir/bintest.o tmpdir/copy.o"] + +if ![string match "" $got] then { + fail "objcopy (simple copy)" +} else { + send_log "cmp tmpdir/bintest.o tmpdir/copy.o\n" + verbose "cmp tmpdir/bintest.o tmpdir/copy.o" + catch "exec cmp tmpdir/bintest.o tmpdir/copy.o" exec_output + set exec_output [prune_system_crud $host_triplet $exec_output] + + # On some systems the result of objcopy will not be identical. + # Usually this is just because gas isn't using bfd to write the files + # in the first place, and may order things a little differently. + # Those systems should use setup_xfail here. + + setup_xfail "sh-*-coff" "sh-*-hms" + setup_xfail "arm-*-pe" + setup_xfail "m68*-*-hpux*" "m68*-*-sunos*" "m68*-*-coff" "m68*-*-vxworks*" + setup_xfail "m68*-ericsson-ose" "m68k*-motorola-sysv*" + setup_xfail "i*86-*-linuxaout*" "i*86-*-aout*" + setup_xfail "i*86-*-sysv3" "i*86-*-isc*" "i*86-*-sco*" "i*86-*-coff" + setup_xfail "i*86-*-aix*" "i*86-*-go32*" + setup_xfail "a29k-*-udi" "a29k-*-coff" "a29k-*-vxworks*" + setup_xfail "i960-*-vxworks*" "i960-*-coff" + setup_xfail "h8300-*-hms" "h8300-*-coff" + setup_xfail "h8500-*-hms" "h8500-*-coff" + setup_xfail "hppa*-*-*" + clear_xfail "hppa*-*-*elf*" + setup_xfail "m88*-*-coff" "m88*-motorola-sysv*" + setup_xfail "z8*-*-coff" + + if [string match "" $exec_output] then { + pass "objcopy (simple copy)" + } else { + send_log "$exec_output\n" + verbose "$exec_output" 1 + + fail "objcopy (simple copy)" + } +} + +# Test generating S records. + +set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec tmpdir/bintest.o tmpdir/copy.srec"] + +if ![string match "" $got] then { + fail "objcopy -O srec" +} else { + set file [open tmpdir/copy.srec r] + + # The first S record is fixed by the file name we are using. + gets $file line + send_log "$line\n" + verbose $line + if ![string match $line "S0130000746D706469722F636F70792E7372656397\r"] { + fail "objcopy -O srec (bad header)" + } else { + while {[gets $file line] != -1 \ + && [regexp "^S\[123\]\[0-9a-fA-F\]+\r$" $line]} { + send_log "$line\n" + verbose $line + set line "**EOF**" + } + send_log "$line\n" + verbose $line + if ![regexp "^S\[789\]\[0-9a-fA-F\]+\r$" $line] then { + fail "objcopy -O srec (bad trailer)" + } else { + if {[gets $file line] != -1} then { + send_log "$line\n" + verbose $line + fail "objcopy -O srec (garbage at end)" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f tmpdir/copy.srec"] + if ![regexp "file format srec" $got] then { + fail "objcopy -O srec (objdump failed)" + } else { + pass "objcopy -O srec" + } + } + } + } + + close $file +} + +# Test setting and adjusting the start address. We only test this +# while generating S records, because we may not be able to set the +# start address for other object file formats, and the S record case +# is the only useful one anyhow. + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f tmpdir/bintest.o"] +if ![regexp "start address (\[0-9a-fA-FxX\]+)" $got all origstart] then { + perror "objdump can not recognize bintest.o" + set origstart "" +} else { + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec tmpdir/bintest.o tmpdir/copy.srec --set-start 0x7654"] + if ![string match "" $got] then { + fail "objcopy --set-start" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f tmpdir/copy.srec"] + if ![regexp "file format srec.*start address (\[0-9a-fA-FxX\]+)" $got all srecstart] then { + fail "objcopy --set-start" + } else { + if {$srecstart != 0x7654} then { + fail "objcopy --set-start ($srecstart != 0x7654)" + } else { + pass "objcopy --set-start" + } + } + } + + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec tmpdir/bintest.o tmpdir/copy.srec --adjust-start 0x123"] + if ![string match "" $got] then { + fail "objcopy --adjust-start" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f tmpdir/copy.srec"] + if ![regexp "file format srec.*start address (\[0-9a-fA-FxX\]+)" $got all srecstart] then { + fail "objcopy --adjust-start" + } else { + if {$srecstart != $origstart + 0x123} then { + fail "objcopy --adjust-start ($srecstart != $origstart + 0x123)" + } else { + pass "objcopy --adjust-start" + } + } + } +} + +# Test adjusting the overall VMA, and adjusting the VMA of a +# particular section. We again only test this when # generating S +# records. + +set low "" +set lowname "" + +set headers [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h tmpdir/bintest.o"] + +set headers_regexp "SECTION\[ 0-9\]+\\\[(\[^\]\]*)\\\]\[^\n\r\]*size\[ \]*(\[0-9a-fA-F\]+)\[ \]*vma\[ \]*(\[0-9a-fA-F\]+)(.*)" + +set got $headers +while {[regexp $headers_regexp $got all name size vma rest]} { + set vma 0x$vma + if {$low == "" || $vma < $low} then { + set low $vma + set lowname $name + } + set got $rest +} + +if {$low == "" || $origstart == ""} then { + perror "objdump can not recognize bintest.o" +} else { + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec tmpdir/bintest.o tmpdir/copy.srec --adjust-vma 0x123"] + if ![string match "" $got] then { + fail "objcopy --adjust-vma" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -fh tmpdir/copy.srec"] + set want "file format srec.*start address\[ \]*(\[0-9a-fA-FxX\]+).*vma\[ \]*(\[0-9a-fA-F\]+)" + if ![regexp $want $got all start vma] then { + fail "objcopy --adjust-vma" + } else { + set vma 0x$vma + if {$vma != $low + 0x123} then { + fail "objcopy --adjust-vma ($vma != $low + 0x123)" + } else { + if {$start != $origstart + 0x123} then { + fail "objcopy --adjust-vma ($start != $origstart + 0x123)" + } else { + pass "objcopy --adjust-vma" + } + } + } + } + + set arg "" + set got $headers + while {[regexp $headers_regexp $got all name size vma rest]} { + set vma 0x$vma + if {$vma == $low} then { + set arg "$arg --adjust-section-vma $name+4" + } + set got $rest + } + + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec tmpdir/bintest.o tmpdir/copy.srec $arg"] + if ![string match "" $got] then { + fail "objcopy --adjust-section-vma +" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h tmpdir/copy.srec"] + set want "file format srec.*SECTION\[ \]*0\[^\n\r\]*vma\[ \]*(\[0-9a-fA-F\]+)" + if ![regexp $want $got all vma] then { + fail "objcopy --adjust-section-vma +" + } else { + set vma 0x$vma + if {$vma != $low + 4} then { + fail "objcopy --adjust-section-vma + ($vma != $low + 4)" + } else { + pass "objcopy --adjust-section-vma +" + } + } + } + + regsub -all "\\+4" $arg "=[expr $low + 4]" argeq + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec tmpdir/bintest.o tmpdir/copy.srec $argeq"] + if ![string match "" $got] then { + fail "objcopy --adjust-section-vma =" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h tmpdir/copy.srec"] + set want "file format srec.*SECTION\[ \]*0\[^\n\r\]*vma\[ \]*(\[0-9a-fA-F\]+)" + if ![regexp $want $got all vma] then { + fail "objcopy --adjust-section-vma =" + } else { + set vma 0x$vma + if {$vma != $low + 4} then { + fail "objcopy --adjust-section-vma = ($vma != $low + 4)" + } else { + pass "objcopy --adjust-section-vma =" + } + } + } +} + +# Test stripping an object. + +proc strip_test { } { + global CC + global STRIP + global STRIPFLAGS + global NM + global NMFLAGS + global srcdir + global subdir + + set test "strip" + + if { [which $CC] == 0 } { + untested $test + return + } + + if ![binutils_compile $CC "-g -c" $srcdir/$subdir/testprog.c tmpdir/testprog.o] { + unresolved $test + return + } + + set exec_output [binutils_run $STRIP "$STRIPFLAGS tmpdir/testprog.o"] + if ![string match "" $exec_output] { + fail $test + return + } + + set exec_output [binutils_run $NM "-a $NMFLAGS tmpdir/testprog.o"] + if ![string match "No symbols in *" $exec_output] { + fail $test + return + } + + pass $test +} + +strip_test + +# Build a final executable. + +proc copy_setup { } { + global CC + global srcdir + global subdir + + if ![isnative] { + return 1 + } + + if { [which $CC] == 0 } { + return 2 + } + + if ![binutils_compile $CC "-g" $srcdir/$subdir/testprog.c tmpdir/testprog] { + return 3 + } + + set exec_output [binutils_run tmpdir/testprog ""] + if ![string match "ok" $exec_output] { + return 3 + } + + return 0 +} + +# Test copying an executable. + +proc copy_executable { prog flags test1 test2 } { + + set exec_output [binutils_run $prog "$flags tmpdir/testprog tmpdir/copyprog"] + if ![string match "" $exec_output] { + fail $test1 + fail $test2 + return + } + + set exec_output [binutils_run "cmp" "tmpdir/testprog tmpdir/copyprog"] + + if [string match "" $exec_output] then { + pass $test1 + } else { + send_log "$exec_output\n" + verbose "$exec_output" + # This will fail for many reasons. For example, it will most + # likely fail if the system linker is used. Therefore, we do + # not insist that it pass. If you are using an assembler and + # linker based on the same BFD as objcopy, it is worth + # investigating to see why this failure occurs. + setup_xfail "*-*-*" + fail $test1 + } + + set exec_output [binutils_run tmpdir/copyprog ""] + if ![string match "ok" $exec_output] { + fail $test2 + } else { + pass $test2 + } +} + +# Test stripping an executable + +proc strip_executable { prog flags test } { + + set exec_output [binutils_run $prog "$flags tmpdir/copyprog"] + if ![string match "" $exec_output] { + fail $test + return + } + + set exec_output [binutils_run tmpdir/copyprog ""] + if ![string match "ok" $exec_output] { + fail $test + } else { + pass $test + } +} + +set test1 "simple objcopy of executable" +set test2 "run objcopy of executable" +set test3 "run stripped executable" + +switch [copy_setup] { + "1" { + # do nothing + } + "2" { + untested $test1 + untested $test2 + untested $test3 + } + "3" { + unresolved $test1 + unresolved $test2 + unresolved $test3 + } + "0" { + copy_executable "$OBJCOPY" "$OBJCOPYFLAGS" "$test1" "$test2" + strip_executable "$STRIP" "$STRIPFLAGS" "$test3" + } +} diff --git a/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/objdump.exp b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/objdump.exp new file mode 100644 index 00000000000..0752f72d6c7 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/objdump.exp @@ -0,0 +1,128 @@ +# 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. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye +# and rewritten by Ian Lance Taylor + +if {[which $OBJDUMP] == 0} then { + perror "$OBJDUMP does not exist" + return +} + +send_user "Version [binutil_version $OBJDUMP]" + +# Simple test of objdump -i + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"] + +set cpus_expected "(a29k|alliant|alpha|arm|convex|h8|hppa|i386|i860|i960|m68k|m88k|mips|ns32k|powerpc|pyramid|romp|rs6000|sh|sparc|tahoe|vax|we32k|z8k|z8001|z8002)" + +set want "BFD header file version.*srec.*header .* endian, data .* endian.*$cpus_expected" + +if [regexp $want $got] then { + pass "objdump -i" +} else { + fail "objdump -i" +} + +# The remaining tests require a test file. + + +if {![binutils_assemble $AS $srcdir$subdir/bintest.s tmpdir/bintest.o]} then { + return +} + +# Test objdump -f + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f tmpdir/bintest.o"] + +set want "tmpdir/bintest.o:\[ \]*file format.*architecture:\[ \]*${cpus_expected}.*HAS_RELOC.*HAS_SYMS" + +if ![regexp $want $got] then { + fail "objdump -f" +} else { + pass "objdump -f" +} + +# Test objdump -h + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h tmpdir/bintest.o"] + +set want "tmpdir/bintest.o:\[ \]*file format.*SECTION\[ ]*\[0-9\]+\[ \]*\\\[\[^\]\]*(text|TEXT|CODE)\[^\]\]*\\\]\[ :\]*size\[ \]*(\[0-9a-fA-F\]+)\[ \]*.*SECTION\[ \]*\[0-9\]+\[ \]*\\\[\[^\]\]*(data|DATA)\[^\]\]*\\\]\[ :\]*size\[ \]*(\[0-9a-fA-F\]+)\[ \]*" + +if ![regexp $want $got all text_name text_size data_name data_size] then { + fail "objdump -h" +} else { + verbose "text size is $text_size" + verbose "data size is $data_size" + if {[expr "0x$text_size"] < 8 || [expr "0x$data_size"] < 4} then { + send_log "sizes too small\n" + fail "objdump -h" + } else { + pass "objdump -h" + } +} + +# Test objdump -t + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -t tmpdir/bintest.o"] + +if [info exists vars] then { unset vars } +while {[regexp "(\[a-z\]*_symbol)(.*)" $got all symbol rest]} { + set vars($symbol) 1 + set got $rest +} + +if {![info exists vars(text_symbol)] \ + || ![info exists vars(data_symbol)] \ + || ![info exists vars(common_symbol)] \ + || ![info exists vars(external_symbol)]} then { + fail "objdump -t" +} else { + pass "objdump -t" +} + +# Test objdump -r + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -r tmpdir/bintest.o"] + +set want "tmpdir/bintest.o:\[ \]*file format.*RELOCATION RECORDS FOR \\\[\[^\]\]*(text|TEXT|CODE)\[^\]\]*\\\].*external_symbol" + +if [regexp $want $got] then { + pass "objdump -r" +} else { + fail "objdump -r" +} + +# Test objdump -s + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -s tmpdir/bintest.o"] + +set want "tmpdir/bintest.o:\[ \]*file format.*Contents.*(text|TEXT|CODE)\[^0-9\]*\[ \]*\[0-9a-fA-F\]*\[ \]*(00000001|01000000).*Contents.*(data|DATA)\[^0-9\]*\[ \]*\[0-9a-fA-F\]*\[ \]*(00000002|02000000)" + +if [regexp $want $got] then { + pass "objdump -s" +} else { + fail "objdump -s" +} + +# Options which are not tested: -a -d -D -R -T -x -l --stabs +# I don't see any generic way to test any of these other than -a. +# Tests could be written for specific targets, and that should be done +# if specific problems are found. diff --git a/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/size.exp b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/size.exp new file mode 100644 index 00000000000..72f79134467 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/size.exp @@ -0,0 +1,70 @@ +# 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. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye +# and rewritten by Ian Lance Taylor + +if {[which $SIZE] == 0} then { + perror "$SIZE does not exist" + return +} + +send_user "Version [binutil_version $SIZE]" + + +if {![binutils_assemble $AS $srcdir$subdir/bintest.s tmpdir/bintest.o]} then { + return +} + +set dec "\[0-9\]+" +set hex "\[0-9a-fA-F\]+" + +# Test size with no arguments + +set got [binutils_run $SIZE "$SIZEFLAGS tmpdir/bintest.o"] + +set want "($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($hex)\[ \]+tmpdir/bintest.o" + +if ![regexp $want $got all text data bss dtot hextot] then { + fail "size (no arguments)" +} else { + if {$text < 8 || $data < 4} then { + fail "size (no arguments)" + } else { + pass "size (no arguments)" + } +} + +# Test size -A + +set got [binutils_run $SIZE "$SIZEFLAGS -A tmpdir/bintest.o"] + +set want "tmpdir/bintest.o.*(text|TEXT)\[^\n\r\]*\[ \]($dec)\[ \]+$dec.*(data|DATA)\[^\n\r\]*\[ \]($dec)\[ \]+$dec" + +if ![regexp $want $got all textname textsize dataname datasize] then { + fail "size -A" +} else { + verbose "text size: $textsize" + verbose "data size: $datasize" + if {$textsize < 8 || $datasize < 4} then { + fail "size -A" + } else { + pass "size -A" + } +} diff --git a/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/testprog.c b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/testprog.c new file mode 100644 index 00000000000..210656b4487 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/binutils-all/testprog.c @@ -0,0 +1,28 @@ +/* This program is used to test objcopy and strip. */ + +int common; +int global = 1; +static int local = 2; +static char string[] = "string"; + +int +fn () +{ + return 3; +} + +int +main () +{ + if (common != 0 + || global != 1 + || local != 2 + || strcmp (string, "string") != 0) + { + printf ("failed\n"); + exit (1); + } + + printf ("ok\n"); + exit (0); +} diff --git a/gnu/usr.bin/binutils/binutils/testsuite/config/default.exp b/gnu/usr.bin/binutils/binutils/testsuite/config/default.exp new file mode 100644 index 00000000000..f6ea9310b12 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/config/default.exp @@ -0,0 +1,113 @@ +# 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. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye. (rob@cygnus.com) + +load_lib util-defs.exp +load_lib utils-lib.exp + +if ![info exists AS] then { + set AS [findfile $base_dir/../gas/as.new $base_dir/../gas/as.new [transform as]] +} +if ![info exists ASFLAGS] then { + set ASFLAGS "" +} + +if ![info exists NM] then { + set NM [findfile $base_dir/nm.new $base_dir/nm.new [transform nm]] +} +if ![info exists NMFLAGS] then { + set NMFLAGS "" +} + +if ![info exists SIZE] then { + set SIZE [findfile $base_dir/size] +} +if ![info exists SIZEFLAGS] then { + set SIZEFLAGS "" +} + +if ![info exists OBJDUMP] then { + set OBJDUMP [findfile $base_dir/objdump] +} +if ![info exists OBJDUMPFLAGS] then { + set OBJDUMPFLAGS "" +} + +if ![info exists OBJCOPY] then { + set OBJCOPY [findfile $base_dir/objcopy] +} +if ![info exists OBJCOPYFLAGS] then { + set OBJCOPYFLAGS "" +} + +if ![info exists AR] then { + set AR [findfile $base_dir/ar] +} + +if ![info exists STRIP] then { + set STRIP [findfile $base_dir/strip.new $base_dir/strip.new [transform strip]] +} +if ![info exists STRIPFLAGS] then { + set STRIPFLAGS "" +} + +if ![file isdirectory tmpdir] {catch "exec mkdir tmpdir" status} + +# +# binutils_run +# run a program, returning the output +# sets binutils_run_failed if the program does not exist +# +proc binutils_run { prog progargs } { + default_binutils_run $prog $progargs +} + +# +# binutils_assemble +# assemble a file +# +proc binutils_assemble { as source object } { + default_binutils_assemble $as $source $object +} + +# +# binutils_compile +# compile a file +# +proc binutils_compile { cc flags source object } { + default_binutils_compile $cc $flags $source $object +} + +# +# binutils_remove +# remove a file +# +proc binutils_remove { file } { + default_binutils_remove $file +} + +# +# add some basic error trapping. These mostly catch programming error's +# within the tests themselves +# +expect_before { + buffer_full { perror "internal buffer is full." } + "can't open '*'" { perror "Can't open test file." } +} diff --git a/gnu/usr.bin/binutils/binutils/testsuite/config/hppa.sed b/gnu/usr.bin/binutils/binutils/testsuite/config/hppa.sed new file mode 100644 index 00000000000..d8607d85d0c --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/config/hppa.sed @@ -0,0 +1,4 @@ +s/# Old OSF sed blows up if you have a sed command starting with "#"// +s/# Avoid it by putting the comments within real sed commands.// +s/# Fix the definition of common_symbol to be correct for the PA assebmlers.// +s/ \.comm common_symbol,4/common_symbol .comm 4/ diff --git a/gnu/usr.bin/binutils/binutils/testsuite/lib/utils-lib.exp b/gnu/usr.bin/binutils/binutils/testsuite/lib/utils-lib.exp new file mode 100644 index 00000000000..fce0203caa3 --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/testsuite/lib/utils-lib.exp @@ -0,0 +1,187 @@ +# 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. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye +# and extended by Ian Lance Taylor + +proc binutil_version { prog } { + if {[which $prog] == 0} then { + perror "$prog can't be run, file not found." + return "" + } + catch "exec $prog --version" tmp + # Should find a way to discard constant parts, keep whatever's + # left, so the version string could be almost anything at all... + regexp "version (cygnus-|)\[-0-9.a-zA-Z-\]+" $tmp version + if ![info exists version] then { + return "[which $prog] (no version number)\n" + } + set tmp $version + return "[which $prog] $version\n" +} + +# +# default_binutils_run +# run a program, returning the output +# sets binutils_run_failed if the program does not exist +# +proc default_binutils_run { prog progargs } { + global binutils_run_failed + global host_triplet + + set binutils_run_failed 0 + + if {[which $prog] == 0} then { + perror "$prog does not exist" + set binutils_run_failed 1 + return "" + } + + send_log "$prog $progargs\n" + verbose "$prog $progargs" + + # This used to be + # catch "exec $prog $progargs" exec_output + # but that would evaluate $progargs twice, which would fail if + # any arguments started with `$'. This is a dismal hack to avoid + # this problem. I tried using + # catch { exec $prog $progargs } exec_output + # but that failed because $progargs was not split into words by + # exec. I don't know if this operation can be done correctly. No + # matter how hard I try, I can not convince myself that TCL is a + # language. + regsub -all "\\$" $progargs "\\$" progq + catch "exec $prog $progq" exec_output + set exec_output [prune_system_crud $host_triplet $exec_output] + if {![string match "" $exec_output]} then { + send_log "$exec_output\n" + verbose "$exec_output" + } + return $exec_output +} + +# +# default_binutils_assemble +# assemble a file +# +proc default_binutils_assemble { as source object } { + global ASFLAGS + global srcdir + global host_triplet + + if {[which $as] == 0} then { + perror "$as does not exist" + return 0 + } + + if ![info exists ASFLAGS] { set ASFLAGS "" } + + # The HPPA assembler syntax is a little different than most, to make + # the test source file assemble we need to run it through sed. + # + # This is a hack in that it won't scale well if other targets need + # similar transformations to assemble. We'll generalize the hack + # if/when other targets need similar handling. + if [istarget "hppa*-*-*" ] then { + send_log "sed -f $srcdir/config/hppa.sed < $source | $as $ASFLAGS -o $object\n" + verbose "sed -f $srcdir/config/hppa.sed < $source | $as $ASFLAGS -o $object" + catch "exec sed -f $srcdir/config/hppa.sed < $source | $as $ASFLAGS -o $object" exec_output + } else { + send_log "$as $ASFLAGS -o $object $source\n" + verbose "$as $ASFLAGS -o $object $source" + catch "exec $as $ASFLAGS -o $object $source" exec_output + } + + set exec_output [prune_system_crud $host_triplet $exec_output] + + if [string match "" $exec_output] then { + return 1 + } else { + send_log "$exec_output\n" + verbose "$exec_output" + perror "$source: assembly failed" + return 0 + } +} + +# +# default_binutils_compile +# compile a file +# +proc default_binutils_compile { cc flags source object } { + global CFLAGS + global srcdir + global host_triplet + + if {[which $cc] == 0} then { + perror "$cc does not exist" + return 0 + } + + if ![info exists CFLAGS] { set CFLAGS "" } + + send_log "$cc $flags $CFLAGS -o $object $source\n" + verbose "$cc $flags $CFLAGS -o $object $source" + catch "exec $cc $flags $CFLAGS -o $object $source" exec_output + + set exec_output [prune_system_crud $host_triplet $exec_output] + + if [string match "" $exec_output] then { + return 1 + } else { + send_log "$exec_output\n" + verbose "$exec_output" + perror "$source: assembly failed" + return 0 + } +} + +# +# default_binutils_remove +# remove a file +# +proc default_binutils_remove { file } { + catch "exec rm -f $file" exec_output +} + +# This definition is taken from an unreleased version of DejaGnu. Once +# that version gets released, and has been out in the world for a few +# months at least, it may be safe to delete this copy. +if ![string length [info proc prune_system_crud]] { + # + # prune_system_crud -- delete various system verbosities from TEXT on SYSTEM + # + # An example is: + # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9 + # + # SYSTEM is typical $target_triplet or $host_triplet. + # + # This is useful when trying to do pattern matches on program output. + # Sites with particular verbose os's may wish to override this in site.exp. + # + proc prune_system_crud { system text } { + # This is from sun4's. Do it for all machines for now. + # The "\\1" is to try to preserve a "\n" but only if necessary. + regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text + + # It might be tempting to get carried away and delete blank lines, etc. + # Just delete *exactly* what we're ask to, and that's it. + return $text + } +} diff --git a/gnu/usr.bin/binutils/binutils/version.c b/gnu/usr.bin/binutils/binutils/version.c new file mode 100644 index 00000000000..5a19113953e --- /dev/null +++ b/gnu/usr.bin/binutils/binutils/version.c @@ -0,0 +1,5 @@ +/*** version.c -- version number for binutils. + They all change in lockstep -- it's easier that way +*/ + +char *program_version = VERSION; diff --git a/gnu/usr.bin/binutils/config-ml.in b/gnu/usr.bin/binutils/config-ml.in new file mode 100644 index 00000000000..5e3aca75bad --- /dev/null +++ b/gnu/usr.bin/binutils/config-ml.in @@ -0,0 +1,664 @@ +# Configure fragment invoked in the post-target section for subdirs +# wanting multilib support. +# +# It is advisable to support a few --enable/--disable options to let the +# user select which libraries s/he really wants. +# +# Subdirectories wishing to use multilib should put the following lines +# in the "post-target" section of configure.in. +# +# if [ "${srcdir}" = "." ] ; then +# if [ "${with_target_subdir}" != "." ] ; then +# . ${srcdir}/${with_multisrctop}../../config-ml.in +# else +# . ${srcdir}/${with_multisrctop}../config-ml.in +# fi +# else +# . ${srcdir}/../config-ml.in +# fi +# +# See librx/configure.in in the libg++ distribution for an example of how +# to handle autoconf'd libraries. +# +# Things are complicated because 6 separate cases must be handled: +# 2 (native, cross) x 3 (absolute-path, relative-not-dot, dot) = 6. +# +# srcdir=. is special. It must handle make programs that don't handle VPATH. +# To implement this, a symlink tree is built for each library and for each +# multilib subdir. +# +# The build tree is layed out as +# +# ./ +# libg++ +# newlib +# m68020/ +# libg++ +# newlib +# m68881/ +# libg++ +# newlib +# +# The nice feature about this arrangement is that inter-library references +# in the build tree work without having to care where you are. Note that +# inter-library references also work in the source tree because symlink trees +# are built when srcdir=. +# +# Configure variables: +# ${with_target_subdir} = "." for native, or ${target_alias} for cross. +# Set by top level Makefile. +# ${with_multisrctop} = how many levels of multilibs there are in the source +# tree. It exists to handle the case of configuring in the source tree: +# ${srcdir} is not constant. +# ${with_multisubdir} = name of multilib subdirectory (eg: m68020/m68881). +# +# Makefile variables: +# MULTISRCTOP = number of multilib levels in source tree (+1 if cross) +# MULITBUILDTOP = number of multilib levels in build tree +# MULTIDIRS = list of multilib subdirs (eg: m68000 m68020 ...) +# (only defined in each library's main Makefile). +# MULTISUBDIR = installed subdirectory name with leading '/' (eg: /m68000) +# (only defined in each multilib subdir). + +# FIXME: Multilib is currently disabled by default for everything other than +# newlib. It is up to each target to turn on multilib support for the other +# libraries as desired. + +# We have to handle being invoked by both Cygnus configure and Autoconf. +# We except both to define `srcdir' and `target' (we *could* figure them +# out, but we'd have to do work that they're already done to figure them out). +# We expect Cygnus configure to define `arguments' and Autoconf to define +# `ac_configure_args'. + +if [ -n "${ac_configure_args}" ]; then + Makefile=${ac_file-Makefile} + config_shell=${CONFIG_SHELL-/bin/sh} + arguments="${ac_configure_args}" +else + Makefile=${Makefile-Makefile} + config_shell=${config_shell-/bin/sh} +fi + +# Scan all the arguments and set all the ones we need. + +for option in $arguments +do + case $option in + --*) ;; + -*) option=-$option ;; + esac + + case $option in + --*=*) + optarg=`echo $option | sed -e 's/^[^=]*=//'` + ;; + esac + + case $option in + --disable-*) + enableopt=`echo ${option} | sed 's:^--disable-:enable_:;s:-:_:g'` + eval $enableopt=no + ;; + --enable-*) + case "$option" in + *=*) ;; + *) optarg=yes ;; + esac + enableopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'` + eval $enableopt="$optarg" + ;; + --norecursion | --no*) + norecursion=yes + ;; + --verbose | --v | --verb*) + verbose=--verbose + ;; + --with-*) + case "$option" in + *=*) ;; + *) optarg=yes ;; + esac + withopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'` + eval $withopt="$optarg" + ;; + --without-*) + withopt=`echo ${option} | sed 's:^--::;s:out::;s:-:_:g'` + eval $withopt=no + ;; + esac +done + +# Only do this if --enable-multilib. +if [ "${enable_multilib}" = yes ]; then + +# Compute whether this is the library's top level directory +# (ie: not a multilib subdirectory, and not a subdirectory like libg++/src). +# ${with_multisubdir} tells us we're in the right branch, but we could be +# in a subdir of that. +# ??? The previous version could void this test by separating the process into +# two files: one that only the library's toplevel configure.in ran (to +# configure the multilib subdirs), and another that all configure.in's ran to +# update the Makefile. It seemed reasonable to collapse all multilib support +# into one file, but it does leave us with having to perform this test. +ml_toplevel_p=no +if [ -z "${with_multisubdir}" ]; then + if [ "${srcdir}" = "." ]; then + # ${with_target_subdir} = "." for native, otherwise target alias. + if [ "${with_target_subdir}" = "." ]; then + if [ -f ../config-ml.in ]; then + ml_toplevel_p=yes + fi + else + if [ -f ../../config-ml.in ]; then + ml_toplevel_p=yes + fi + fi + else + if [ -f ${srcdir}/../config-ml.in ]; then + ml_toplevel_p=yes + fi + fi +fi + +# If this is the library's top level directory, set multidirs to the +# multilib subdirs to support. This lives at the top because we need +# `multidirs' set right away, and this section is subject to frequent +# editing (addition of new targets, etc.). + +if [ "${ml_toplevel_p}" = yes ]; then + +case "${target}" in +hppa*-*-*) + multidirs="soft-float" + ;; +m68*-*-aout* | m68*-*-coff* | m68*-*-elf* | m68*-*-vxworks*) + multidirs="m68000 m68020 m68881 msoft-float m68000/m68881 m68000/msoft-float m68020/m68881 m68020/msoft-float" + ;; +i960-*-*) + multidirs=float + ;; +sparclite-*-* | sparclitefrw*-*-*) + multidirs="mfpu msoft-float mflat mno-flat mfpu/mflat mfpu/mno-flat msoft-float/mflat msoft-float/mno-flat" + ;; +sparc-*-* | sparcfrw*-*-*) + multidirs="soft v8 soft/v8" + ;; +z8k-*-coff) + multidirs="z8001 std z8001/std" + ;; +h8300-*-*) + multidirs=h8300h + ;; +h8500-*-*) + multidirs="mbig msmall mcompact mmedium" + ;; +sh-*-*) + multidirs="ml m2 ml/m2" + ;; +mips*-*-*) + # Note that not all of these will be built for a particular + # target; what is build depends upon the output gcc + # --print-multi-lib. We configure them all, to make our life + # simpler here. If somebody cares about configuration + # efficiency, they will need to switch off on the various + # targets to configure just the directories needed for that + # target. + # + # In the long run, it would be better to configure based on + # the output of gcc --print-multi-lib, but, to do that, we + # would have to build gcc before configuring newlib. + # + # Default to including the single-float directories. + if [ x$enable_single_float = x ]; then + enable_single_float=yes + fi + if [ x$enable_single_float = xyes ]; then + multidirs="soft-float single el eb mips1 mips3 soft-float/el soft-float/eb soft-float/mips1 soft-float/mips3 soft-float/el/mips1 soft-float/el/mips3 soft-float/eb/mips1 soft-float/eb/mips3 single/el single/eb single/mips1 single/mips3 single/el/mips1 single/el/mips3 single/eb/mips1 single/eb/mips3 el/mips1 el/mips3 eb/mips1 eb/mips3" + else + multidirs="soft-float el eb mips1 mips3 soft-float/el soft-float/eb soft-float/mips1 soft-float/mips3 soft-float/el/mips1 soft-float/el/mips3 soft-float/eb/mips1 soft-float/eb/mips3 el/mips1 el/mips3 eb/mips1 eb/mips3" + fi + if [ x$enable_biendian = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *endian* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_softfloat = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *soft-float* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_relocatable = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *relocatable* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_sysv = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *sysv* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + ;; +powerpc-ibm-aix* | rs6000-ibm-aix*) + multidirs="soft-float common soft-float/common" + if [ x$enable_softfloat = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *soft-float* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_commoncpu = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *common* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + ;; +powerpc-*-eabiaix*) + multidirs="soft-float relocatable little sysv little/sysv relocatable/little relocatable/sysv relocatable/little/sysv soft-float/relocatable soft-float/little soft-float/sysv soft-float/little/sysv soft-float/relocatable/little soft-float/relocatable/sysv soft-float/relocatable/little/sysv" + if [ x$enable_biendian = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *endian* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_softfloat = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *soft-float* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_relocatable = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *relocatable* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_sysv = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *sysv* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + ;; +powerpc-*-eabi* | powerpc-*-elf* | powerpc-*-sysv4*) + multidirs="soft-float relocatable little aix little/aix relocatable/little relocatable/aix relocatable/little/aix soft-float/relocatable soft-float/little soft-float/aix soft-float/little/aix soft-float/relocatable/little soft-float/relocatable/aix soft-float/relocatable/little/aix aixdesc soft-float/aixdesc" + if [ x$enable_biendian = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *endian* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_softfloat = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *soft-float* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_relocatable = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *relocatable* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_aix = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *aix* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + ;; +powerpcle-*-eabi* | powerpcle-*-elf* | powerpcle-*-sysv4*) + multidirs="soft-float relocatable big aix big/aix relocatable/big relocatable/aix relocatable/big/aix soft-float/relocatable soft-float/big soft-float/aix soft-float/big/aix soft-float/relocatable/big soft-float/relocatable/aix soft-float/relocatable/big/aix" + if [ x$enable_biendian = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *endian* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_softfloat = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *soft-float* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_relocatable = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *relocatable* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + if [ x$enable_aix = xno ] + then + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + *aix* ) : ;; + *) if [ x"$multidirs" = x ]; then multidirs="$x"; else multidirs="${multidirs} ${x}"; fi ;; + esac + done + fi + ;; +*) + multidirs= + ;; +esac + +# Add code to library's top level makefile to handle building the multilib +# subdirs. + +cat > Multi.tem <<\EOF + +# FIXME: There should be an @-sign in front of the `if'. +# Leave out until this is tested a bit more. +multi-do: + if [ -z "$(MULTIDIRS)" ]; then \ + true; \ + else \ + rootpre=`pwd`/; export rootpre; \ + srcrootpre=`cd $(srcdir); pwd`/; export srcrootpre; \ + lib=`echo $${rootpre} | sed -e 's,^.*/\([^/][^/]*\)/$$,\1,'`; \ + compiler="$(CC)"; \ + for i in `$${compiler} --print-multi-lib 2>/dev/null`; do \ + dir=`echo $$i | sed -e 's/;.*$$//'`; \ + if [ "$${dir}" = "." ]; then \ + true; \ + else \ + if [ -d ../$${dir}/$${lib} ]; then \ + flags=`echo $$i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; \ + if (cd ../$${dir}/$${lib}; $(MAKE) $(FLAGS_TO_PASS) \ + CFLAGS="$(CFLAGS) $${flags}" \ + CXXFLAGS="$(CXXFLAGS) $${flags}" \ + LIBCFLAGS="$(LIBCFLAGS) $${flags}" \ + LIBCXXFLAGS="$(LIBCXXFLAGS) $${flags}" \ + $(DO)); then \ + true; \ + else \ + exit 1; \ + fi; \ + else true; \ + fi; \ + fi; \ + done; \ + fi + +# FIXME: There should be an @-sign in front of the `if'. +# Leave out until this is tested a bit more. +multi-clean: + if [ -z "$(MULTIDIRS)" ]; then \ + true; \ + else \ + lib=`pwd | sed -e 's,^.*/\([^/][^/]*\)/$$,\1,'`; \ + for dir in Makefile $(MULTIDIRS); do \ + if [ -f ../$${dir}/$${lib}/Makefile ]; then \ + if (cd ../$${dir}/$${lib}; $(MAKE) $(FLAGS_TO_PASS) $(DO)); \ + then true; \ + else exit 1; \ + fi; \ + else true; \ + fi; \ + done; \ + fi +EOF + +cat ${Makefile} Multi.tem > Makefile.tem +rm -f ${Makefile} Multi.tem +mv Makefile.tem ${Makefile} + +fi # ${ml_toplevel_p} = yes + +if [ "${verbose}" = --verbose ]; then + echo "Adding multilib support to Makefile in `pwd`" + if [ "${ml_toplevel_p}" = yes ]; then + echo "multidirs=${multidirs}" + fi + echo "with_multisubdir=${with_multisubdir}" +fi + +if [ "${srcdir}" = "." ]; then + if [ "${with_target_subdir}" != "." ]; then + ml_srcdotdot="../" + else + ml_srcdotdot="" + fi +else + ml_srcdotdot="" +fi + +if [ -z "${with_multisubdir}" ]; then + ml_subdir= + ml_builddotdot= + : # ml_srcdotdot= # already set +else + ml_subdir="/${with_multisubdir}" + # The '[^/][^/]*' appears that way to work around a SunOS sed bug. + ml_builddotdot=`echo ${with_multisubdir} | sed -e 's:[^/][^/]*:..:g'`/ + if [ "$srcdir" = "." ]; then + ml_srcdotdot=${ml_srcdotdot}${ml_builddotdot} + else + : # ml_srcdotdot= # already set + fi +fi + +if [ "${ml_toplevel_p}" = yes ]; then + ml_do='$(MAKE)' + ml_clean='$(MAKE)' +else + ml_do=true + ml_clean=true +fi + +# TOP is used by newlib and should not be used elsewhere for this purpose. +# MULTI{SRC,BUILD}TOP are the proper ones to use. MULTISRCTOP is empty +# when srcdir != builddir. MULTIBUILDTOP is always some number of ../'s. +# FIXME: newlib needs to be updated to use MULTI{SRC,BUILD}TOP so we can +# delete TOP. Newlib may wish to continue to use TOP for its own purposes +# of course. +# MULTIDIRS is non-empty for the cpu top level Makefile (eg: newlib/Makefile) +# and lists the subdirectories to recurse into. +# MULTISUBDIR is non-empty in each cpu subdirectory's Makefile +# (eg: newlib/h8300h/Makefile) and is the installed subdirectory name with +# a leading '/'. +# MULTIDO is used for targets like all, install, and check where +# $(FLAGS_TO_PASS) augmented with the subdir's compiler option is needed. +# MULTICLEAN is used for the *clean targets. +# +# ??? It is possible to merge MULTIDO and MULTICLEAN into one. They are +# currently kept separate because we don't want the *clean targets to require +# the existence of the compiler (which MULTIDO currently requires) and +# therefore we'd have to record the directory options as well as names +# (currently we just record the names and use --print-multi-lib to get the +# options). + +sed -e "s:^TOP[ ]*=[ ]*\([./]*\)[ ]*$:TOP = ${ml_builddotdot}\1:" \ + -e "s:^MULTISRCTOP[ ]*=.*$:MULTISRCTOP = ${ml_srcdotdot}:" \ + -e "s:^MULTIBUILDTOP[ ]*=.*$:MULTIBUILDTOP = ${ml_builddotdot}:" \ + -e "s:^MULTIDIRS[ ]*=.*$:MULTIDIRS = ${multidirs}:" \ + -e "s:^MULTISUBDIR[ ]*=.*$:MULTISUBDIR = ${ml_subdir}:" \ + -e "s:^MULTIDO[ ]*=.*$:MULTIDO = $ml_do:" \ + -e "s:^MULTICLEAN[ ]*=.*$:MULTICLEAN = $ml_clean:" \ + ${Makefile} > Makefile.tem +rm -f ${Makefile} +mv Makefile.tem ${Makefile} + +# If this is the library's top level, configure each multilib subdir. +# This is done at the end because this is the loop that runs configure +# in each multilib subdir and it seemed reasonable to finish updating the +# Makefile before going on to configure the subdirs. + +if [ "${ml_toplevel_p}" = yes ]; then + +# We must freshly configure each subdirectory. This bit of code is +# actually partially stolen from the main configure script. FIXME. + +if [ -n "${multidirs}" ] && [ -z "${norecursion}" ]; then + + if [ "${verbose}" = --verbose ]; then + echo "Running configure in multilib subdirs ${multidirs}" + echo "pwd: `pwd`" + fi + + ml_origdir=`pwd` + ml_libdir=`echo $ml_origdir | sed -e 's,^.*/,,'` + # cd to top-level-build-dir/${with_target_subdir} + cd .. + + for dir in ${multidirs}; do + + if [ "${verbose}" = --verbose ]; then + echo "Running configure in multilib subdir ${dir}" + echo "pwd: `pwd`" + fi + + if [ -d ${dir} ]; then true; else mkdir ${dir}; fi + if [ -d ${dir}/${ml_libdir} ]; then true; else mkdir ${dir}/${ml_libdir}; fi + + # Eg: if ${dir} = m68000/m68881, dotdot = ../../ + dotdot=../`echo ${dir} | sed -e 's|[^/]||g' -e 's|/|../|g'` + + case ${srcdir} in + ".") + echo Building symlink tree in `pwd`/${dir}/${ml_libdir} + if [ "${with_target_subdir}" != "." ]; then + ml_unsubdir="../" + else + ml_unsubdir="" + fi + (cd ${dir}/${ml_libdir}; + ../${dotdot}${ml_unsubdir}symlink-tree ../${dotdot}${ml_unsubdir}${ml_libdir} "") + newsrcdir="." + srcdiroption= + multisrctop=${dotdot} + ;; + *) + case "${srcdir}" in + /*) # absolute path + newsrcdir=${srcdir} + ;; + *) # otherwise relative + newsrcdir=${dotdot}${srcdir} + ;; + esac + srcdiroption="-srcdir=${newsrcdir}" + multisrctop= + ;; + esac + + case "${progname}" in + /*) recprog=${progname} ;; + *) recprog=${dotdot}${progname} ;; + esac + + # FIXME: POPDIR=${PWD=`pwd`} doesn't work here. + ML_POPDIR=`pwd` + cd ${dir}/${ml_libdir} + + if [ -f ${newsrcdir}/configure ]; then + recprog=${newsrcdir}/configure + fi + if eval ${config_shell} ${recprog} \ + --with-multisubdir=${dir} --with-multisrctop=${multisrctop} \ + $arguments ${srcdiroption} ; then + true + else + exit 1 + fi + + cd ${ML_POPDIR} + + done + + cd ${ml_origdir} +fi + +fi # ${ml_toplevel_p} = yes +fi # ${enable_multilib} = yes diff --git a/gnu/usr.bin/binutils/config.guess b/gnu/usr.bin/binutils/config.guess new file mode 100644 index 00000000000..2ff0eba28ac --- /dev/null +++ b/gnu/usr.bin/binutils/config.guess @@ -0,0 +1,565 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +# +# 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# The master version of this file is at the FSF in /home/gd/gnu/lib. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + alpha:OSF1:V*:*) + # After 1.2, OSF1 uses "V1.3" for uname -r. + echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'` + exit 0 ;; + alpha:OSF1:*:*) + # 1.2 uses "1.2" for uname -r. + echo alpha-dec-osf${UNAME_RELEASE} + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + amiga:NetBSD:*:*) + echo m68k-cbm-netbsd${UNAME_RELEASE} + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + Pyramid*:OSx*:*:*) + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + sun4*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + mips:*:4*:UMIPS) + echo mips-mips-riscos4sysv + exit 0 ;; + mips:*:5*:RISCos) + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ + -o ${TARGET_BINARY_INTERFACE}x = x ] ; then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i[34]86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:4) + if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[3478]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/7?? | 9000/8?[79] ) HP_ARCH=hppa1.1 ;; + 9000/8?? ) HP_ARCH=hppa1.0 ;; + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*C90:*:*:*) + echo c90-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + hp3[0-9][05]:NetBSD:*:*) + echo m68k-hp-netbsd${UNAME_RELEASE} + exit 0 ;; + i[34]86:BSD/386:*:* | *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:NetBSD:*:*) + echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. + ld_help_string=`ld --help 2>&1` + if echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: elf_i[345]86"; then + echo "${UNAME_MACHINE}-unknown-linux" ; exit 0 + elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i[345]86linux"; then + echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0 + elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i[345]86coff"; then + echo "${UNAME_MACHINE}-unknown-linuxcoff" ; exit 0 + elif test "${UNAME_MACHINE}" = "alpha" ; then + echo alpha-unknown-linux ; exit 0 + else + # Either a pre-BFD a.out linker (linuxoldld) or one that does not give us + # useful --help. Gcc wants to distinguish between linuxoldld and linuxaout. + test ! -d /usr/lib/ldscripts/. \ + && echo "${UNAME_MACHINE}-unknown-linuxoldld" && exit 0 + # Determine whether the default compiler is a.out or elf + cat >dummy.c </dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + fi ;; +# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions +# are messed up and put the nodename in both sysname and nodename. + i[34]86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*) + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} + else + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i[34]86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-unknown-sysv32 + fi + exit 0 ;; + Intel:Mach:3*:*) + echo i386-unknown-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M680[234]0:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0) + uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3 && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m680[234]0:LynxOS:2.[23]*:*) + echo m68k-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i[34]86:LynxOS:2.[23]*:*) + echo i386-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.[23]*:*) + echo sparc-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.[23]*:*) + echo rs6000-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3"); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-unknown-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +#if !defined (ultrix) + printf ("vax-dec-bsd\n"); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 +rm -f dummy.c dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/gnu/usr.bin/binutils/config.sub b/gnu/usr.bin/binutils/config.sub new file mode 100644 index 00000000000..cdad52cc6c4 --- /dev/null +++ b/gnu/usr.bin/binutils/config.sub @@ -0,0 +1,1091 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +if [ x$1 = x ] +then + echo Configuration name missing. 1>&2 + echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 + echo "or $0 ALIAS" 1>&2 + echo where ALIAS is a recognized configuration type. 1>&2 + exit 1 +fi + +# First pass through any local machine types. +case $1 in + *local*) + echo $1 + exit 0 + ;; + *) + ;; +esac + +# Separate what the user gave into CPU-COMPANY and OS (if any). +basic_machine=`echo $1 | sed 's/-[^-]*$//'` +if [ $basic_machine != $1 ] +then os=`echo $1 | sed 's/.*-/-/'` +else os=; fi + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp ) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond ) # CYGNUS LOCAL + os= + basic_machine=$1 + ;; + -apple*) # CYGNUS LOCAL + os= + basic_machine=$1 + ;; + -scout) # CYGNUS LOCAL + ;; + -wrs) # CYGNUS LOCAL + os=vxworks + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm | armeb \ + | armel | pyramid \ + | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \ + | alpha | we32k | ns16k | clipper | sparclite | i370 | sh \ + | powerpc | powerpcle | sparc64 | 1750a | dsp16xx | mips64 | mipsel \ + | pdp11 | mips64el | mips64orion | mips64orionel \ + | sparc) + basic_machine=$basic_machine-unknown + ;; + m88110 | m680[01234]0 | m683?2 | m68360 | z8k | v70 | h8500 | w65) # CYGNUS LOCAL + basic_machine=$basic_machine-unknown + ;; + mips64vr4300 | mips64vr4300el) # CYGNUS LOCAL jsmith + basic_machine=$basic_machine-unknown + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + vax-* | tahoe-* | i[345]86-* | i860-* | m68k-* | m68000-* | m88k-* \ + | sparc-* | ns32k-* | fx80-* | arm-* | arme[lb]-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \ + | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \ + | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \ + | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \ + | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-*) + ;; + m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | h8500-*) # CYGNUS LOCAL + ;; + mips64vr4300-* | mips64vr4300el-*) # CYGNUS LOCAL jsmith + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) # CYGNUS LOCAL + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) # CYGNUS LOCAL + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) # CYGNUS LOCAL + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-cbm + ;; + amigados) + basic_machine=m68k-cbm + os=-amigados + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) # CYGNUS LOCAL + basic_machine=m68k-apollo + os=-bsd + ;; + arm | armel | armeb) + basic_machine=arm-arm + os=-aout + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) # CYGNUS LOCAL + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) # CYGNUS LOCAL + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) # CYGNUS LOCAL + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + w89k-*) # CYGNUS LOCAL + basic_machine=hppa1.1-winbond + os=-proelf + ;; + op50n-*) # CYGNUS LOCAL + basic_machine=hppa1.1-oki + os=-proelf + ;; + op60c-*) # CYGNUS LOCAL + basic_machine=hppa1.1-oki + os=-proelf + ;; + hppro) # CYGNUS LOCAL + basic_machine=hppa1.1-hp + os=-proelf + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppaosf) # CYGNUS LOCAL + basic_machine=hppa1.1-hp + os=-osf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + os=-mvs + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[345]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + os=-sysv32 + ;; + i[345]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + os=-sysv4 + ;; + i[345]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + os=-sysv + ;; + i[345]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + os=-solaris2 + ;; + i386mach) # CYGNUS LOCAL + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) # CYGNUS LOCAL + basic_machine=i386-unknown + os=-vsta + ;; + i386-go32 | go32) # CYGNUS LOCAL + basic_machine=i386-unknown + os=-go32 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) # CYGNUS LOCAL + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) # CYGNUS LOCAL + basic_machine=i386-unknown + os=-msdos + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown # CYGNUS LOCAL + os=-netbsd + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) # CYGNUS LOCAL + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + np1) + basic_machine=np1-gould + ;; + OSE68000 | ose68000) # CYGNUS LOCAL + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) # CYGNUS LOCAL + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | p6) + # We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium + basic_machine=i586-intel + ;; + pentium-* | p5-* | p6-*) + # We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + k5) + # We don't have specific support for AMD's K5 yet, so just call it a Pentium + basic_machine=i586-amd + ;; + nexgen) + # We don't have specific support for Nexgen yet, so just call it a Pentium + basic_machine=i586-nexgen + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rom68k) # CYGNUS LOCAL + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) # CYGNUS LOCAL + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs) # CYGNUS LOCAL + basic_machine=sparclite-wrs + os=-vxworks + ;; + sparcfrw) # CYGNUS LOCAL + basic_machine=sparcfrw-sun + os=-sunos4 + ;; + sparcfrwcompat) # CYGNUS LOCAL + basic_machine=sparcfrwcompat-sun + os=-sunos4 + ;; + sparclitefrw) # CYGNUS LOCAL + basic_machine=sparclitefrw-fujitsu + ;; + sparclitefrwcompat) # CYGNUS LOCAL + basic_machine=sparclitefrwcompat-fujitsu + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) # CYGNUS LOCAL + basic_machine=m68k-tandem + ;; + stratus) # CYGNUS LOCAL + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) # CYGNUS LOCAL + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) # CYGNUS LOCAL + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) # CYGNUS LOCAL + basic_machine=w65-wdc + os=-none + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) # CYGNUS LOCAL + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) # CYGNUS LOCAL + basic_machine=hppa1.1-winbond + ;; + op50n) # CYGNUS LOCAL + basic_machine=hppa1.1-oki + ;; + op60c) # CYGNUS LOCAL + basic_machine=hppa1.1-oki + ;; + mips) + basic_machine=mips-mips + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sparc) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) # CYGNUS LOCAL + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) # CYGNUS LOCAL + basic_machine=powerpc-apple + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -unixware* | svr4*) + os=-sysv4 + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative must end in a *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -lites* | -minix* | -genix* | -ultrix* | -irix* \ + | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[345]* \ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigados* | -msdos* | -moss* | -newsos* | -unicos* | -aos* \ + | -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \ + | -riscos* | -linux* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -freebsd* | -riscix* | -lites* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta | -udi | -eabi*) + ;; + # CYGNUS LOCAL + -go32 | -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -proelf | -os9*) + ;; + -macos*) # CYGNUS LOCAL + ;; + -mac*) # CYGNUS LOCAL + os=`echo $os | sed -e 's|mac|macos|'` + ;; + + -mpw*) # CYGNUS LOCAL + ;; + -pe*) + ;; + -win32) + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) # CYGNUS LOCAL + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) # CYGNUS LOCAL + os=-ose + ;; + -es1800*) # CYGNUS LOCAL + os=-ose + ;; + -xenix) + os=-xenix + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) # CYGNUS LOCAL + os=-aout + ;; + mips*-cisco) # CYGNUS LOCAL + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-ibm) + os=-aix + ;; + *-wec) # CYGNUS LOCAL + os=-proelf + ;; + *-winbond) # CYGNUS LOCAL + os=-proelf + ;; + *-oki) # CYGNUS LOCAL + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigados + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + *-rom68k) # CYGNUS LOCAL + os=-coff + ;; + *-*bug) # CYGNUS LOCAL + os=-coff + ;; + *-apple) # CYGNUS LOCAL + os=-macos + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -bosx*) # CYGNUS LOCAL + vendor=bull + ;; + -lynxos*) + vendor=lynx + ;; + -aix*) + vendor=ibm + ;; + -hpux*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxworks*) + vendor=wrs + ;; + -hms*) # CYGNUS LOCAL + vendor=hitachi + ;; + -mpw* | -macos*) # CYGNUS LOCAL + vendor=apple + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os diff --git a/gnu/usr.bin/binutils/config/ChangeLog b/gnu/usr.bin/binutils/config/ChangeLog new file mode 100644 index 00000000000..7576a359bd9 --- /dev/null +++ b/gnu/usr.bin/binutils/config/ChangeLog @@ -0,0 +1,198 @@ +Tue Nov 7 15:41:30 1995 Stan Shebs + + * mpw-mh-mpw (CC_MWC68K, CC_MWCPPC): Remove unused include path. + (CC_MWCPPC): Add -mpw_chars, disable warnings, add comments + explaining reasons for various flags. + (EXTRALIBS_PPC, EXTRALIBS_MWCPPC ): Put runtime library first. + +Fri Oct 13 14:44:25 1995 Jason Molenda (crash@phydeaux.cygnus.com) + + * mh-aix, mh-sun: Removed. + + * mh-decstation (X11_EXTRA_CFLAGS): Define. + + * mh-sco, mh-solaris, mh-sysv4 (X11_EXTRA_LIBS): Define. + + * mh-hp300, mh-hpux, mh-hpux8, mh-solaris, mh-sun3, mh-sysv4: Don't + hardcode location of X stuff here. + +Thu Sep 28 13:14:56 1995 Stan Shebs + + * mpw-mh-mpw: Add definitions for various 68K and PowerMac + compilers, add definitions for library and link steps for + PowerMacs. + +Thu Sep 14 08:20:04 1995 Fred Fish + + * mh-hp300 (CC): Add "CC = cc -Wp,-H256000" to avoid + "too much defining" errors from the HPUX compiler. + +Thu Aug 17 17:28:56 1995 Ken Raeburn + + * mh-hp300 (RANLIB): Use "ar ts", in case GNU ar was used and + didn't build a symbol table. + +Thu Jun 22 17:47:24 1995 Stan Shebs + + * mpw-mh-mpw (CC): Define ANSI_PROTOTYPES. + +Mon Apr 10 12:29:48 1995 Stan Shebs + + * mpw-mh-mpw (EXTRALIBS): Always link in Math.o, CSANELIB.o, + and ToolLibs.o. + + * mpw-mh-mpw (CC): Define ALMOST_STDC. + (CFLAGS): Remove ALMOST_STDC, -mc68881. + (LDFLAGS): add -w. + + * mpw-mh-mpw (CFLAGS): Add -b option to put strings at the ends of + functions. + + * mpw-mh-mpw: New file, host makefile definitions for MPW. + +Fri Mar 31 11:35:17 1995 Jason Molenda (crash@phydeaux.cygnus.com) + + * mt-netware: New file. + +Mon Mar 13 12:31:29 1995 Ian Lance Taylor + + * mh-hpux8: New file. + * mh-hpux: Use X11R5 rather than X11R4. + +Thu Feb 9 11:04:13 1995 Ian Lance Taylor + + * mh-linux (SYSV): Don't define. + (RANLIB): Don't define. + +Wed Jan 11 16:29:34 1995 Jason Merrill + + * m?-*pic (LIBCXXFLAGS): Add -fno-implicit-templates. + +Thu Nov 3 17:27:19 1994 Ken Raeburn + + * mh-irix4 (CC): Increase maximum string length. + + * mh-sco (CC): Define away const, it doesn't work right; elements + of arrays of ptr-to-const are considered const themselves. + +Sat Jul 16 12:17:49 1994 Stan Shebs (shebs@andros.cygnus.com) + + * mh-cxux: New file, from Bob Rusk (rrusk@mail.csd.harris.com). + +Sat Jun 4 17:22:12 1994 Per Bothner (bothner@kalessin.cygnus.com) + + * mh-ncrsvr43: New file from Tom McConnell + . + +Thu May 19 00:32:11 1994 Jeff Law (law@snake.cs.utah.edu) + + * mh-hpux (CC): Add -Wp,-H256000 to avoid "too much defining" + errors from the HPUX 8 compilers. + +Wed May 4 20:14:47 1994 D. V. Henkel-Wallace (gumby@cygnus.com) + + * mh-lynxrs6k: set SHELL to /bin/bash + +Tue Apr 12 12:38:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * mh-irix4 (CC): Change -XNh1500 to -XNh2000. + +Sat Dec 25 20:03:45 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * mt-hppa: Delete. + +Tue Nov 16 22:54:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * mh-a68bsd: Define CC to gcc. + +Mon Nov 15 16:56:51 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * mh-linux: Don't put -static in LDFLAGS. Add comments. + +Mon Nov 15 13:37:58 1993 david d `zoo' zuhn (zoo@cirdan.cygnus.com) + + * mh-sysv4 (AR_FLAGS): change from cq to cr + +Fri Nov 5 08:12:32 1993 D. V. Henkel-Wallace (gumby@blues.cygnus.com) + + * mh-unixware: remove. It's the same as sysv4, and config.guess + can't tell the difference. So don't allow skew. + +Wed Oct 20 20:35:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * mh-hp300: Revert yesterday's change, but add comment explaining. + +Tue Oct 19 18:58:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * mh-hp300: Don't define CFLAGS to empty. Why should hp300 be + different from anything else? ("gdb doesn't understand the native + debug format" isn't a good enough answer because we might be using + gcc). + +Tue Oct 5 12:17:40 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * mh-alphaosf: Remove, no longer necessary now that gdb knows + how to handle OSF/1 shared libraries. + +Tue Jul 6 11:27:33 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * mh-alphaosf: New file. + +Thu Jul 1 15:49:33 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * mh-riscos: New file. + +Mon Jun 14 12:03:18 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com) + + * mh-aix, mh-aix386, mh-decstation, mh-delta88, mh-hpux, mh-irix4, + mh-ncr3000, mh-solaris, mh-sysv, mh-sysv4: remove INSTALL=cp line, + now that we're using install.sh globally + +Fri Jun 4 16:09:34 1993 Ian Lance Taylor (ian@cygnus.com) + + * mh-sysv4 (INSTALL): Use cp, not /usr/ucb/install. + +Thu Apr 8 11:21:52 1993 Ian Lance Taylor (ian@cygnus.com) + + * mt-a29k, mt-ebmon29k, mt-os68k, mt-ose68000, mt-ose68k, + mt-vxworks68, mt-vxworks960: Removed obsolete, unused target + Makefile fragment files. + +Mon Mar 8 15:05:25 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * mh-aix386: New file; old mh-aix, plus no-op RANLIB. + +Thu Oct 1 13:50:48 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * mh-solaris: INSTALL is NOT /usr/ucb/install + +Mon Aug 24 14:25:35 1992 Ian Lance Taylor (ian@cygnus.com) + + * mt-ose68000, mt-ose68k: renamed from mt-OSE*. + +Tue Jul 21 02:11:01 1992 D. V. Henkel-Wallace (gumby@cygnus.com) + + * mt-OSE68k, mt-680000: new configs. + +Thu Jul 16 17:12:09 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * mh-irix4: merged changes from progressive. + +Tue Jun 9 23:29:38 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Everywhere: Change RANLIB=echo>/dev/null (which confuses + some shells - and I don't blame them) to RANLIB=true. + * mh-solaris: Use /usr/ucb/install for INSTALL. + +Sun May 31 14:45:23 1992 Mark Eichin (eichin at cygnus.com) + + * mh-solaris2: Add new configuration for Solaris 2 (sysv, no ranlib) + +Fri Apr 10 23:10:08 1992 Fred Fish (fnf@cygnus.com) + + * mh-ncr3000: Add new configuration for NCR 3000. + +Tue Dec 10 00:10:55 1991 K. Richard Pixley (rich at rtl.cygnus.com) + + * ChangeLog: fresh changelog. + diff --git a/gnu/usr.bin/binutils/config/mh-a68bsd b/gnu/usr.bin/binutils/config/mh-a68bsd new file mode 100644 index 00000000000..c991289dd5f --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-a68bsd @@ -0,0 +1,12 @@ +RANLIB=true + +#None of the Apollo compilers can compile gas or binutils. The preprocessor +# chokes on bfd, the compiler won't let you assign integers to enums, and +# other problems. Defining CC to gcc is a questionable way to say "don't use +# the apollo compiler" (the preferred version of GCC could be called cc, +# or whatever), but I'm not sure leaving CC as cc is any better... + +#CC=cc -A ansi -A runtype,any -A systype,any -U__STDC__ -DNO_STDARG +CC=gcc + +BISON=yacc diff --git a/gnu/usr.bin/binutils/config/mh-aix386 b/gnu/usr.bin/binutils/config/mh-aix386 new file mode 100644 index 00000000000..4accd1cddfb --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-aix386 @@ -0,0 +1 @@ +RANLIB = @: diff --git a/gnu/usr.bin/binutils/config/mh-apollo68 b/gnu/usr.bin/binutils/config/mh-apollo68 new file mode 100644 index 00000000000..4497ed93585 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-apollo68 @@ -0,0 +1,3 @@ +HDEFINES = -DUSG +RANLIB=true +CC= cc -A ansi -A runtype,any -A systype,any -U__STDC__ -DUSG diff --git a/gnu/usr.bin/binutils/config/mh-cxux b/gnu/usr.bin/binutils/config/mh-cxux new file mode 100644 index 00000000000..c5f4bb149e8 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-cxux @@ -0,0 +1,15 @@ +# Configuration for Harris CX/UX 7 (and maybe 6), based on sysv4 configuration. + +# Define SYSV as -DSYSV if you are using a System V operating system. +SYSV = -DSYSV -DSVR4 +RANLIB = true + +# C++ debugging is not yet supported under SVR4 (DWARF) +CXXFLAGS=-O + +# The l flag generates a warning from the SVR4 archiver, remove it. +AR_FLAGS = cq + +# Under CX/UX, we want to tell the compiler to use ANSI mode. +CFLAGS=-Xa -g +LDFLAGS=-Xa -g diff --git a/gnu/usr.bin/binutils/config/mh-decstation b/gnu/usr.bin/binutils/config/mh-decstation new file mode 100644 index 00000000000..37201926d5f --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-decstation @@ -0,0 +1,5 @@ +CC = cc -Wf,-XNg1000 + +# for X11, since the native DECwindows include files are really broken when +# it comes to function prototypes. +X11_EXTRA_CFLAGS = "-DNeedFunctionPrototypes=0" diff --git a/gnu/usr.bin/binutils/config/mh-delta88 b/gnu/usr.bin/binutils/config/mh-delta88 new file mode 100644 index 00000000000..bc9c45302d5 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-delta88 @@ -0,0 +1,4 @@ +RANLIB = true + + + diff --git a/gnu/usr.bin/binutils/config/mh-dgux b/gnu/usr.bin/binutils/config/mh-dgux new file mode 100644 index 00000000000..e7d85d6126a --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-dgux @@ -0,0 +1,4 @@ +HDEFINES=-DHOST_SYS=DGUX_SYS +CC=gcc -Wall -ansi -D__using_DGUX +RANLIB=true + diff --git a/gnu/usr.bin/binutils/config/mh-go32 b/gnu/usr.bin/binutils/config/mh-go32 new file mode 100644 index 00000000000..4f9d27a9346 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-go32 @@ -0,0 +1,27 @@ +CC=i386-go32-gcc +AR=i386-go32-ar +RANLIB=i386-go32-ranlib +CC_FOR_BUILD=gcc +HOST_CC=gcc +HOST_CFLAGS= +CFLAGS=-O2 -fno-omit-frame-pointer +HOST_PREFIX=foo +HOST_PREFIX_1=foo +RANLIB=i386-go32-ranlib +AR=i386-go32-ar +GCC_FOR_TARGET=${target_alias}-gcc +CXX_FOR_TARGET=${target_alias}-gcc +CC_FOR_TARGET=${target_alias}-gcc +AS_FOR_TARGET=${target_alias}-as +AR_FOR_TARGET=${target_alias}-ar +NM_FOR_TARGET=${target_alias}-nm +RANLIB_FOR_TARGET=${target_alias}-ranlib +HOST_PREFIX=cross +HOST_PREFIX_1=cross +MAKEINFOFLAGS=--no-split + +INSTALL_DOSREL=install-dosrel + + + + diff --git a/gnu/usr.bin/binutils/config/mh-hp300 b/gnu/usr.bin/binutils/config/mh-hp300 new file mode 100644 index 00000000000..761724d92de --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-hp300 @@ -0,0 +1,13 @@ +# Define SYSV as -DSYSV if you are using a System V operating system. +SYSV = -DSYSV +# Avoid "too much defining" errors from HPUX compiler. +CC = cc -Wp,-H256000 +# If "ar" in $PATH is GNU ar, the symbol table may need rebuilding. +# If it's HP/UX ar, this should be harmless. +RANLIB = ar ts + +# Native cc can't bootstrap gcc with -g. Defining CFLAGS here loses (a) +# for non-gcc directories, (b) if we are compiling with gcc, not +# native cc. Neither (a) nor (b) has a trivial fix though. + +CFLAGS = diff --git a/gnu/usr.bin/binutils/config/mh-hpux b/gnu/usr.bin/binutils/config/mh-hpux new file mode 100644 index 00000000000..4d71c9dc837 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-hpux @@ -0,0 +1,4 @@ +# Define SYSV as -DSYSV if you are using a System V operating system. +CC = cc -Wp,-H256000 +SYSV = -DSYSV +RANLIB = true diff --git a/gnu/usr.bin/binutils/config/mh-hpux8 b/gnu/usr.bin/binutils/config/mh-hpux8 new file mode 100644 index 00000000000..4d71c9dc837 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-hpux8 @@ -0,0 +1,4 @@ +# Define SYSV as -DSYSV if you are using a System V operating system. +CC = cc -Wp,-H256000 +SYSV = -DSYSV +RANLIB = true diff --git a/gnu/usr.bin/binutils/config/mh-i386win32 b/gnu/usr.bin/binutils/config/mh-i386win32 new file mode 100644 index 00000000000..6f6d998e7d7 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-i386win32 @@ -0,0 +1,26 @@ +CC=i386-win32-gcc +AR=i386-win32-ar +ARFLAGS=rv +RANLIB=i386-win32-ranlib +BISON=byacc +CC_FOR_BUILD=gcc +HOST_CC=gcc +HOST_CFLAGS= +CFLAGS=-O2 +CXXFLAGS=-O2 +HOST_PREFIX=foo +HOST_PREFIX_1=foo +RANLIB=i386-win32-ranlib +AR=i386-win32-ar +GCC_FOR_TARGET=${target_alias}-gcc +CXX_FOR_TARGET=${target_alias}-gcc +CC_FOR_TARGET=${target_alias}-gcc +AS_FOR_TARGET=${target_alias}-as +DLLTOOL_FOR_TARGET=${target_alias}-dlltool +AR_FOR_TARGET=${target_alias}-ar +NM_FOR_TARGET=${target_alias}-nm +RANLIB_FOR_TARGET=${target_alias}-ranlib +LD_FOR_TARGET=${target_alias}-ld +HOST_PREFIX=cross +HOST_PREFIX_1=cross +MAKEINFOFLAGS=--no-split diff --git a/gnu/usr.bin/binutils/config/mh-irix4 b/gnu/usr.bin/binutils/config/mh-irix4 new file mode 100644 index 00000000000..a48334c72f5 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-irix4 @@ -0,0 +1,8 @@ +# Makefile changes for SGI's running IRIX-4.x. +# Tell compiler to use K&R C. We can't compile under the SGI Ansi +# environment. Also bump switch table size so that cp-parse will +# compile. Bump string length limit so linker builds. + +CC = cc -cckr -Wf,-XNg1500 -Wf,-XNk1000 -Wf,-XNh2000 -Wf,-XNl8192 +SYSV = -DSYSV +RANLIB = true diff --git a/gnu/usr.bin/binutils/config/mh-irix5 b/gnu/usr.bin/binutils/config/mh-irix5 new file mode 100644 index 00000000000..8bd7c99f844 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-irix5 @@ -0,0 +1,3 @@ +# Makefile changes for SGI's running IRIX-5.x. +SYSV = -DSYSV +RANLIB = true diff --git a/gnu/usr.bin/binutils/config/mh-linux b/gnu/usr.bin/binutils/config/mh-linux new file mode 100644 index 00000000000..0fb3a054bfc --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-linux @@ -0,0 +1,2 @@ +# This is the Makefile fragment used when running on a Linux host. +# It does not have to do anything at present. diff --git a/gnu/usr.bin/binutils/config/mh-lynxos b/gnu/usr.bin/binutils/config/mh-lynxos new file mode 100644 index 00000000000..9afcb79fca7 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-lynxos @@ -0,0 +1,2 @@ +# /bin/cc is less than useful for our purposes. Always use GCC +CC = /bin/gcc diff --git a/gnu/usr.bin/binutils/config/mh-lynxrs6k b/gnu/usr.bin/binutils/config/mh-lynxrs6k new file mode 100644 index 00000000000..b2793996eff --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-lynxrs6k @@ -0,0 +1,8 @@ +# LynxOS running on the rs6000 doesn't have ranlib +RANLIB = true + +# /bin/cc is less than useful for our purposes. Always use GCC +CC = /usr/cygnus/progressive/bin/gcc + +# /bin/sh is too buggy, so use /bin/bash instead. +SHELL = /bin/bash diff --git a/gnu/usr.bin/binutils/config/mh-ncr3000 b/gnu/usr.bin/binutils/config/mh-ncr3000 new file mode 100644 index 00000000000..5bbd8037009 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-ncr3000 @@ -0,0 +1,17 @@ +# 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 = + +# Define SYSV as -DSYSV if you are using a System V operating system. +SYSV = -DSYSV -DSVR4 +RANLIB = true + +# The l flag generates a warning from the SVR4 archiver, remove it. +AR_FLAGS = cq diff --git a/gnu/usr.bin/binutils/config/mh-ncrsvr43 b/gnu/usr.bin/binutils/config/mh-ncrsvr43 new file mode 100644 index 00000000000..4717f67efaf --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-ncrsvr43 @@ -0,0 +1,9 @@ +# Host configuration file for an NCR 3000 (i486/SVR43) system. + +# The MetaWare compiler will generate a copyright message unless you +# turn it off. +CFLAGS = -g -Hnocopyr + +# Define SYSV as -DSYSV if you are using a System V operating system. +SYSV = -DSYSV -DSVR4 +RANLIB = true diff --git a/gnu/usr.bin/binutils/config/mh-papic b/gnu/usr.bin/binutils/config/mh-papic new file mode 100644 index 00000000000..35cf2c8ee4e --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-papic @@ -0,0 +1 @@ +PICFLAG=-fPIC diff --git a/gnu/usr.bin/binutils/config/mh-riscos b/gnu/usr.bin/binutils/config/mh-riscos new file mode 100644 index 00000000000..e586b30b1a9 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-riscos @@ -0,0 +1,15 @@ +# This is for a MIPS running RISC/os 4.52C. + +# This is needed for GDB, but needs to be in the top-level make because +# if a library is compiled with the bsd headers and gets linked with the +# sysv system libraries all hell can break loose (e.g. a jmp_buf might be +# a different size). +# ptrace(2) apparently has problems in the BSD environment. No workaround is +# known except to select the sysv environment. Could we use /proc instead? +# These "sysv environments" and "bsd environments" often end up being a pain. +# +# This is not part of CFLAGS because perhaps not all C compilers have this +# option. +CC= cc -systype sysv + +RANLIB = true diff --git a/gnu/usr.bin/binutils/config/mh-sco b/gnu/usr.bin/binutils/config/mh-sco new file mode 100644 index 00000000000..cc337c98f93 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-sco @@ -0,0 +1,10 @@ +# Define SYSV as -DSYSV if you are using a System V operating system. +SYSV = -DSYSV +RANLIB = true +# You may need this if you don't have bison. +# BISON = yacc -Sm10400 +# The native C compiler botches some simple uses of const. Unfortunately, +# it doesn't defined anything like "__sco__" for us to test for in ansidecl.h. +CC = cc -Dconst= + +X11_EXTRA_LIBS = -lsocket -lm -lintl -lmalloc diff --git a/gnu/usr.bin/binutils/config/mh-solaris b/gnu/usr.bin/binutils/config/mh-solaris new file mode 100644 index 00000000000..7170cae1a88 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-solaris @@ -0,0 +1,7 @@ +# Makefile changes for Suns running Solaris 2 + +SYSV = -DSYSV +RANLIB = true +CFLAGS = -g + +X11_EXTRA_LIBS = -lnsl -lsocket diff --git a/gnu/usr.bin/binutils/config/mh-sparcpic b/gnu/usr.bin/binutils/config/mh-sparcpic new file mode 100644 index 00000000000..92e48d90fbd --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-sparcpic @@ -0,0 +1 @@ +PICFLAG=-fpic diff --git a/gnu/usr.bin/binutils/config/mh-sun3 b/gnu/usr.bin/binutils/config/mh-sun3 new file mode 100644 index 00000000000..dcd5155b736 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-sun3 @@ -0,0 +1,3 @@ +# Sun's C compiler needs the -J flag to be able to compile cp-parse.c +# without overflowing the jump tables (-J says to use a 32 bit table) +CC = cc -J diff --git a/gnu/usr.bin/binutils/config/mh-sysv b/gnu/usr.bin/binutils/config/mh-sysv new file mode 100644 index 00000000000..16b1187b447 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-sysv @@ -0,0 +1,3 @@ +# Define SYSV as -DSYSV if you are using a System V operating system. +SYSV = -DSYSV +RANLIB = true diff --git a/gnu/usr.bin/binutils/config/mh-sysv4 b/gnu/usr.bin/binutils/config/mh-sysv4 new file mode 100644 index 00000000000..81066510600 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-sysv4 @@ -0,0 +1,11 @@ +# Define SYSV as -DSYSV if you are using a System V operating system. +SYSV = -DSYSV -DSVR4 +RANLIB = true + +# C++ debugging is not yet supported under SVR4 (DWARF) +CXXFLAGS=-O + +# The l flag generates a warning from the SVR4 archiver, remove it. +AR_FLAGS = cr + +X11_EXTRA_LIBS = -lnsl diff --git a/gnu/usr.bin/binutils/config/mh-vaxult2 b/gnu/usr.bin/binutils/config/mh-vaxult2 new file mode 100644 index 00000000000..3de2dc8ffe3 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-vaxult2 @@ -0,0 +1,2 @@ +# The old BSD pcc isn't up to compiling parts of gdb so use gcc +CC = gcc diff --git a/gnu/usr.bin/binutils/config/mh-x86pic b/gnu/usr.bin/binutils/config/mh-x86pic new file mode 100644 index 00000000000..92e48d90fbd --- /dev/null +++ b/gnu/usr.bin/binutils/config/mh-x86pic @@ -0,0 +1 @@ +PICFLAG=-fpic diff --git a/gnu/usr.bin/binutils/config/mpw-mh-mpw b/gnu/usr.bin/binutils/config/mpw-mh-mpw new file mode 100644 index 00000000000..a41dff0bef0 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mpw-mh-mpw @@ -0,0 +1,138 @@ +# This is an MPW makefile fragment. + +# Since there are a multiplicity of Mac compilers and two different +# processors, this file is primarily a library of options for each +# compiler. Somebody else (such as a configure or build script) will +# make the actual choice. + +# Compiler to use for compiling. + +CC_MPW_C = C -d MPW_C -d ALMOST_STDC -d ANSI_PROTOTYPES -d MPW -mc68020 -model far -b -w + +CC_SC = SC -d ALMOST_STDC -d ANSI_PROTOTYPES -d MPW -mc68020 -model far -b -i '' -i : + +CC_MWC68K = MWC68K -d MPW -i "{topsrcdir}"include:mpw:sys: -sym on + +CC_PPCC = PPCC -d powerc=1 -d pascal= -d ALMOST_STDC -d ANSI_PROTOTYPES -d MPW -w + +CC_MRC = MrC -d powerc=1 -d pascal= -d ALMOST_STDC -d ANSI_PROTOTYPES -d MPW -i '' -i : -jm + +CC_SMrC = SMrC -d MPW + +# "-mpw_chars" is necessary because GNU sources often mix signed and +# unsigned casually. +# "-w off" is not a great idea, but CW7 is complaining about enum +# assignments. +# "-opt global,peep,l4,speed" is sometimes good, and sometimes bad. +# We must use {CIncludes} so that MPW tools will work; {MWCIncludes} +# defines stdout, islower, etc, in ways that are incompatible with MPW's +# runtime. However, this cannot be done via -i "{CIncludes}", since +# that does not affect how <>-type includes happen; instead, the variable +# MWCIncludes must be set to point at {CIncludes}. + +CC_MWCPPC = MWCPPC -d MPW -enum int -mpw_chars -sym on -w off + +CC_68K_GCC = gC -Dpascal= -DANSI_PROTOTYPES -DMPW + +CC_PPC_GCC = gC -Dpowerc=1 -Dpascal= -DANSI_PROTOTYPES -DMPW + +# Nothing for the default CFLAGS. + +CFLAGS = + +# These two definitions must *not* have any trailing blanks. + +SEGFLAG_68K = -s + +SEGFLAG_PPC = -d dumdum_ + +# Tool to use for making libraries/archives. + +AR_LIB = Lib + +AR_MWLINK68K = MWLink68K + +AR_PPCLINK = PPCLink -xm library + +AR_MWLINKPPC = MWLinkPPC -xm library + +AR_FLAGS = -o + +RANLIB_NULL = null-command + +RANLIB_RANLIB = ranlib + +# Compiler and/or linker to use for linking. + +CC_LD_LINK = Link -w -d -model far {CC_LD_TOOL_FLAGS} + +CC_LD_MWLINK68K = MWLink68K -w -d -model far {CC_LD_TOOL_FLAGS} -sym on + +CC_LD_PPCLINK = PPCLink -main __start -outputformat xcoff + +CC_LD_MWLINKPPC = MWLinkPPC -w {CC_LD_TOOL_FLAGS} -sym on + +CC_LD_GLD = gC + +# Extension for linker output. + +PROG_EXT_68K = + +PROG_EXT_XCOFF = .xcoff + +# Nothing for the default LDFLAGS. + +LDFLAGS = -w + +CC_LD_TOOL_FLAGS = -c 'MPS ' -t MPST + +# Libraries to link against. + +# It would appear that the math libraries are not +# needed except to provide a definition for scalb, +# which is called from ldexp, which is referenced +# in the m68k opcodes library. + +EXTRALIBS_C = \Option-d + "{CLibraries}"StdClib.o \Option-d + "{CLibraries}"Math.o \Option-d + "{CLibraries}"CSANELib.o \Option-d + "{Libraries}"Stubs.o \Option-d + "{Libraries}"Runtime.o \Option-d + "{Libraries}"Interface.o \Option-d + "{Libraries}"ToolLibs.o + +EXTRALIBS_PPC = \Option-d + "{PPCLibraries}"StdCRuntime.o \Option-d + "{PPCLibraries}"InterfaceLib.xcoff \Option-d + "{PPCLibraries}"MathLib.xcoff \Option-d + "{PPCLibraries}"StdCLib.xcoff \Option-d + "{PPCLibraries}"PPCToolLibs.o \Option-d + "{PPCLibraries}"PPCCRuntime.o + +EXTRALIBS_MWCPPC = \Option-d + "{MWPPCLibraries}"MWStdCRuntime.Lib \Option-d + "{MWPPCLibraries}"InterfaceLib \Option-d + "{MWPPCLibraries}"StdCLib \Option-d + "{MWPPCLibraries}"MathLib \Option-d + "{MWPPCLibraries}"PPCToolLibs.o + +# Tool to make PEF with, if needed. + +MAKEPEF_NULL = null-command + +MAKEPEF_PPC = MakePEF + +MAKEPEF_FLAGS = \Option-d + -l InterfaceLib.xcoff=InterfaceLib \Option-d + -l MathLib.xcoff=MathLib \Option-d + -l StdCLib.xcoff=StdCLib + +MAKEPEF_TOOL_FLAGS = -ft MPST -fc 'MPS ' + +# Resource compiler to use. + +REZ_68K = Rez + +REZ_PPC = Rez -d WANT_CFRG + diff --git a/gnu/usr.bin/binutils/config/mt-netware b/gnu/usr.bin/binutils/config/mt-netware new file mode 100644 index 00000000000..9482f9b36d2 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mt-netware @@ -0,0 +1 @@ +GDB_NLM_DEPS = all-gcc all-ld diff --git a/gnu/usr.bin/binutils/config/mt-papic b/gnu/usr.bin/binutils/config/mt-papic new file mode 100644 index 00000000000..35b8c9e4dc2 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mt-papic @@ -0,0 +1 @@ +PICFLAG_FOR_TARGET=-fPIC diff --git a/gnu/usr.bin/binutils/config/mt-sparcpic b/gnu/usr.bin/binutils/config/mt-sparcpic new file mode 100644 index 00000000000..ff987275575 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mt-sparcpic @@ -0,0 +1 @@ +PICFLAG_FOR_TARGET=-fpic diff --git a/gnu/usr.bin/binutils/config/mt-v810 b/gnu/usr.bin/binutils/config/mt-v810 new file mode 100644 index 00000000000..c5d2a889f5e --- /dev/null +++ b/gnu/usr.bin/binutils/config/mt-v810 @@ -0,0 +1,9 @@ +CC = ca732 +AS = as732 +AR = ar732 +RANLIB = true +NEWLIB_CFLAGS = +TARGET_CFLAGS = +CFLAGS = +INCLUDES = + diff --git a/gnu/usr.bin/binutils/config/mt-x86pic b/gnu/usr.bin/binutils/config/mt-x86pic new file mode 100644 index 00000000000..ff987275575 --- /dev/null +++ b/gnu/usr.bin/binutils/config/mt-x86pic @@ -0,0 +1 @@ +PICFLAG_FOR_TARGET=-fpic diff --git a/gnu/usr.bin/binutils/configure b/gnu/usr.bin/binutils/configure new file mode 100644 index 00000000000..d15abd56129 --- /dev/null +++ b/gnu/usr.bin/binutils/configure @@ -0,0 +1,1231 @@ +#!/bin/sh + +### WARNING: this file contains embedded tabs. Do not run untabify on this file. + +# Configuration script +# Copyright (C) 1988, 90, 91, 92, 93, 94 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public 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 originally written by K. Richard Pixley. + +# +# Shell script to create proper links to machine-dependent files in +# preparation for compilation. +# +# If configure succeeds, it leaves its status in config.status. +# If configure fails after disturbing the status quo, +# config.status is removed. +# + +export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh $0 $argv; kill $$) + +remove=rm +hard_link=ln +symbolic_link='ln -s' + +#for Test +#remove="echo rm" +#hard_link="echo ln" +#symbolic_link="echo ln -s" + +# clear some things potentially inherited from environment. + +Makefile=Makefile +Makefile_in=Makefile.in +arguments=$* +build_alias= +cache_file= +cache_file_option= +configdirs= +exec_prefix= +exec_prefixoption= +fatal= +floating_point=default +gas=default +host_alias=NOHOST +host_makefile_frag= +moveifchange= +norecursion= +other_options= +package_makefile_frag= +prefix=/usr/local +progname= +program_prefix= +program_prefixoption= +program_suffix= +program_suffixoption= +program_transform_name= +program_transform_nameoption= +redirect=">/dev/null" +removing= +site= +site_makefile_frag= +site_option= +srcdir= +srctrigger= +subdirs= +target_alias=NOTARGET +target_makefile_frag= +undefs=NOUNDEFS +version="$Revision: 1.1.1.1 $" +x11=default + +### we might need to use some other shell than /bin/sh for running subshells +# +config_shell=${CONFIG_SHELL-/bin/sh} + +NO_EDIT="This file was generated automatically by configure. Do not edit." + +## this is a little touchy and won't always work, but... +## +## if the argv[0] starts with a slash then it is an absolute name that can (and +## must) be used as is. +## +## otherwise, if argv[0] has no slash in it, we can assume that it is on the +## path. Since PATH might include "." we also add `pwd` to the end of PATH. +## + +progname=$0 +# if PWD already has a value, it is probably wrong. +if [ -n "$PWD" ]; then PWD=`pwd`; fi + +case "${progname}" in +/*) ;; +*/*) ;; +*) + PATH=$PATH:${PWD=`pwd`} ; export PATH + ;; +esac + +# Loop over all args + +while : +do + +# Break out if there are no more args + case $# in + 0) + break + ;; + esac + +# Get the first arg, and shuffle + option=$1 + shift + +# Make all options have two hyphens + orig_option=$option # Save original for error messages + case $option in + --*) ;; + -*) option=-$option ;; + esac + +# Split out the argument for options that take them + case $option in + --*=*) + optarg=`echo $option | sed -e 's/^[^=]*=//'` + ;; +# These options have mandatory values. Since we didn't find an = sign, +# the value must be in the next argument + --b* | --cache* | --ex* | --ho* | --pre* | --program-p* | --program-s* | --program-t* | --si* | --sr* | --ta* | --tm* | --x-*) + optarg=$1 + shift + ;; + esac + +# Now, process the options + case $option in + + --build* | --b*) + case "$build_alias" in + "") build_alias=$optarg ;; + *) echo '***' Can only configure for one build machine at a time. 1>&2 + fatal=yes + ;; + esac + ;; + --cache*) + cache_file=$optarg + ;; + --disable-*) + enableopt=`echo ${option} | sed 's:^--disable-:enable_:;s:-:_:g'` + eval $enableopt=no + disableoptions="$disableoptions $option" + ;; + --enable-*) + case "$option" in + *=*) ;; + *) optarg=yes ;; + esac + + enableopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'` + eval $enableopt="$optarg" + enableoptions="$enableoptions $option" + ;; + --exec-prefix* | --ex*) + exec_prefix=$optarg + exec_prefixoption="--exec-prefix=$optarg" + ;; + --gas | --g*) + gas=yes + ;; + --help | --he*) + fatal=yes + ;; + --host* | --ho*) + case $host_alias in + NOHOST) host_alias=$optarg ;; + *) echo '***' Can only configure for one host at a time. 1>&2 + fatal=yes + ;; + esac + ;; + --nfp | --nf*) + floating_point=no + ;; + --norecursion | --no*) + norecursion=yes + ;; + --prefix* | --pre*) + prefix=$optarg + prefixoption="--prefix=$optarg" + ;; + --program-prefix* | --program-p*) + program_prefix=$optarg + program_prefixoption="--program-prefix=$optarg" + ;; + --program-suffix* | --program-s*) + program_suffix=$optarg + program_suffixoption="--program-suffix=$optarg" + ;; + --program-transform-name* | --program-t*) + # Double any backslashes or dollar signs in the argument + program_transform_name="${program_transform_name} -e `echo ${optarg} | sed -e 's/\\\\/\\\\\\\\/g' -e 's/\\\$/$$/g'`" + program_transform_nameoption="${program_transform_nameoption} --program-transform-name='$optarg'" + ;; + --rm) + removing=--rm + ;; + --silent | --sil* | --quiet | --q*) + redirect=">/dev/null" + verbose=--silent + ;; + --site* | --sit*) + site=$optarg + site_option="--site=$optarg" + ;; + --srcdir*/ | --sr*/) + # Remove trailing slashes. Otherwise, when the file name gets + # bolted into an object file as debug info, it has two slashes + # in it. Ordinarily this is ok, but emacs takes double slash + # to mean "forget the first part". + srcdir=`echo $optarg | sed -e 's:/$::'` + ;; + --srcdir* | --sr*) + srcdir=$optarg + ;; + --target* | --ta*) + case $target_alias in + NOTARGET) target_alias=$optarg ;; + *) echo '***' Can only configure for one target at a time. 1>&2 + fatal=yes + ;; + esac + ;; + --tmpdir* | --tm*) + TMPDIR=$optarg + tmpdiroption="--tmpdir=$optarg" + ;; + --verbose | --v | --verb*) + redirect= + verbose=--verbose + ;; + --version | --V | --vers*) + echo "This is Cygnus Configure version" `echo ${version} | sed 's/[ $:]//g'` + exit 0 + ;; + --with-*) + case "$option" in + *=*) ;; + *) optarg=yes ;; + esac + + withopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'` + eval $withopt="$optarg" + withoptions="$withoptions $option" + ;; + --without-*) + withopt=`echo ${option} | sed 's:^--::;s:out::;s:-:_:g'` + eval $withopt=no + withoutoptions="$withoutoptions $option" + ;; + --x) with_x=yes + withoptions="$withoptions --with-x" + ;; + --x-i* | --x-l*) other_options="$other_options $orig_option" + ;; + --*) + echo "configure: Unrecognized option: \"$orig_option\"; use --help for usage." >&2 + exit 1 + ;; + *) + case $undefs in + NOUNDEFS) undefs=$option ;; + *) echo '***' Can only configure for one host and one target at a time. 1>&2 + fatal=yes + ;; + esac + ;; + esac +done + +# process host and target + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET UNDEFS +# +# The rules are: +# 1. You aren't allowed to specify --host, --target, and undefs at the +# same time. +# 2. Host defaults to undefs. +# 3. If undefs is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target defaults to undefs. +# 5. If undefs is not specified, then target defaults to host. + +case "${fatal}" in +"") + # Make sure that host, target & undefs aren't all specified at the + # same time. + case $host_alias---$target_alias---$undefs in + NOHOST---*---* | *---NOTARGET---* | *---*---NOUNDEFS) + ;; + *) echo '***' Can only configure for one host and one target at a time. 1>&2 + fatal=yes + break 2 + ;; + esac + + # Now, do defaulting for host. + case $host_alias in + NOHOST) + case $undefs in + NOUNDEFS) + # Neither --host option nor undefs were present. + # Call config.guess. + guesssys=`echo ${progname} | sed 's/configure$/config.guess/'` + if host_alias=`${guesssys}` + then + # If the string we are going to use for + # the target is a prefix of the string + # we just guessed for the host, then + # assume we are running native, and force + # the same string for both target and host. + case $target_alias in + NOTARGET) ;; + *) + if expr $host_alias : $target_alias >/dev/null + then + host_alias=$target_alias + fi + ;; + esac + echo "Configuring for a ${host_alias} host." 1>&2 + arguments="--host=$host_alias $arguments" + else + echo 'Config.guess failed to determine the host type. You need to specify one.' 1>&2 + fatal=yes + fi + ;; + *) + host_alias=$undefs + ;; + esac + esac + + # Do defaulting for target. If --target option isn't present, default + # to undefs. If undefs isn't present, default to host. + case $target_alias in + NOTARGET) + case $undefs in + NOUNDEFS) + target_alias=$host_alias + ;; + *) + target_alias=$undefs + ;; + esac + esac + ;; +*) ;; +esac + +if [ -n "${fatal}" -o "${host_alias}" = "help" ] ; then + exec 1>&2 + echo Usage: configure [OPTIONS] [HOST] + echo + echo Options: [defaults in brackets] + echo ' --prefix=MYDIR install into MYDIR [/usr/local]' + echo ' --exec-prefix=MYDIR install host-dependent files into MYDIR [/usr/local]' + echo ' --help print this message [normal config]' + echo ' --build=BUILD configure for building on BUILD [BUILD=HOST]' + echo ' --host=HOST configure for HOST [determined via config.guess]' + echo ' --norecursion configure this directory only [recurse]' + echo ' --program-prefix=FOO prepend FOO to installed program names [""]' + echo ' --program-suffix=FOO append FOO to installed program names [""]' + echo ' --program-transform-name=P transform installed names by sed pattern P [""]' + echo ' --site=SITE configure with site-specific makefile for SITE' + echo ' --srcdir=DIR find the sources in DIR [. or ..]' + echo ' --target=TARGET configure for TARGET [TARGET=HOST]' + echo ' --tmpdir=TMPDIR create temporary files in TMPDIR [/tmp]' + echo ' --nfp configure for software floating point [hard float]' + echo ' --with-FOO, --with-FOO=BAR package FOO is available (parameter BAR)' + echo ' --without-FOO package FOO is NOT available' + echo ' --enable-FOO, --enable-FOO=BAR include feature FOO (parameter BAR)' + echo ' --disable-FOO do not include feature FOO' + echo + echo 'Where HOST and TARGET are something like "sparc-sunos", "mips-sgi-irix5", etc.' + echo + if [ -r config.status ] ; then + cat config.status + fi + + exit 1 +fi + +configsub=`echo ${progname} | sed 's/configure$/config.sub/'` +moveifchange=`echo ${progname} | sed 's/configure$/move-if-change/'` + +# this is a hack. sun4 must always be a valid host alias or this will fail. +if ${configsub} sun4 >/dev/null 2>&1 ; then + true +else + echo '***' cannot find config.sub. 1>&2 + exit 1 +fi + +touch config.junk +if ${moveifchange} config.junk config.trash ; then + true +else + echo '***' cannot find move-if-change. 1>&2 + exit 1 +fi +rm -f config.junk config.trash + +case "${srcdir}" in +"") + if [ -r configure.in ] ; then + srcdir=. + else + if [ -r ${progname}.in ] ; then + srcdir=`echo ${progname} | sed 's:/configure$::'` + else + echo '***' "Can't find configure.in. Try using --srcdir=some_dir" 1>&2 + exit 1 + fi + fi + ;; +*) + # Set srcdir to "." if that's what it is. + # This is important for multilib support. + if [ ! -d ${srcdir} ] ; then + echo "Invalid source directory ${srcdir}" >&2 + exit 1 + fi + pwd=`pwd` + srcpwd=`cd ${srcdir} ; pwd` + if [ "${pwd}" = "${srcpwd}" ] ; then + srcdir=. + fi +esac + +### warn about some conflicting configurations. + +case "${srcdir}" in +".") ;; +*) + if [ -f ${srcdir}/config.status ] ; then + echo '***' Cannot configure here in \"${PWD=`pwd`}\" when \"${srcdir}\" is currently configured. 1>&2 + exit 1 + fi +esac + +# default exec_prefix +case "${exec_prefixoption}" in +"") exec_prefix="\$(prefix)" ;; +*) ;; +esac + +### break up ${srcdir}/configure.in. +case "`grep '^# per\-host:' ${srcdir}/configure.in`" in +"") + echo '***' ${srcdir}/configure.in has no \"per-host:\" line. 1>&2 + # Check for a directory that's been converted to use autoconf since + # it was last configured. + if grep AC_OUTPUT ${srcdir}/configure.in >/dev/null ; then + echo '***' Hmm, looks like this directory has been autoconfiscated. 1>&2 + if [ -r ${srcdir}/configure ] ; then + echo '***' Running the local configure script. 1>&2 + case "${cache_file}" in + "") cache_file_option= ;; + *) cache_file_option="--cache-file=${cache_file}" ;; + esac + srcdiroption="--srcdir=${srcdir}" + case "${build_alias}" in + "") buildopt= ;; + *) buildopt="--build=${build_alias}" ;; + esac + eval exec ${config_shell} ${srcdir}/configure ${verbose} \ + ${buildopt} --host=${host_alias} --target=${target_alias} \ + ${prefixoption} ${tmpdiroption} ${exec_prefixoption} \ + ${srcdiroption} \ + ${program_prefixoption} ${program_suffixoption} \ + ${program_transform_nameoption} ${site_option} \ + ${withoptions} ${withoutoptions} \ + ${enableoptions} ${disableoptions} \ + ${cache_file_option} ${removing} ${other_options} ${redirect} + else + echo '***' There is no configure script present though. 1>&2 + fi + fi + exit 1 + ;; +*) ;; +esac + +case "`grep '^# per\-target:' ${srcdir}/configure.in`" in +"") + echo '***' ${srcdir}/configure.in has no \"per-target:\" line. 1>&2 + exit 1 + ;; +*) ;; +esac + +case "${TMPDIR}" in +"") TMPDIR=/tmp ; export TMPDIR ;; +*) ;; +esac + +# keep this filename short for &%*%$*# 14 char file names +tmpfile=${TMPDIR}/cONf$$ +# Note that under many versions of sh a trap handler for 0 will *override* any +# exit status you explicitly specify! At this point, the only non-error exit +# is at the end of the script; these actions are duplicated there, minus +# the "exit 1". Don't use "exit 0" anywhere after this without resetting the +# trap handler, or you'll lose. +trap "rm -f Makefile.tem ${tmpfile}.com ${tmpfile}.tgt ${tmpfile}.hst ${tmpfile}.pos; exit 1" 0 1 2 15 + +# split ${srcdir}/configure.in into common, per-host, per-target, +# and post-target parts. Post-target is optional. +sed -e '/^# per\-host:/,$d' ${srcdir}/configure.in > ${tmpfile}.com +sed -e '1,/^# per\-host:/d' -e '/^# per\-target:/,$d' ${srcdir}/configure.in > ${tmpfile}.hst +if grep '^# post-target:' ${srcdir}/configure.in >/dev/null ; then + sed -e '1,/^# per\-target:/d' -e '/^# post\-target:/,$d' ${srcdir}/configure.in > ${tmpfile}.tgt + sed -e '1,/^# post\-target:/d' ${srcdir}/configure.in > ${tmpfile}.pos +else + sed -e '1,/^# per\-target:/d' ${srcdir}/configure.in > ${tmpfile}.tgt + echo >${tmpfile}.pos +fi + +### do common part of configure.in + +. ${tmpfile}.com + +# some sanity checks on configure.in +case "${srctrigger}" in +"") + echo '***' srctrigger not set in ${PWD=`pwd`}/configure.in. 1>&2 + exit 1 + ;; +*) ;; +esac + +case "${build_alias}" in +"") + if result=`${config_shell} ${configsub} ${host_alias}` ; then + build_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` + build_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` + build_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` + build=${build_cpu}-${build_vendor}-${build_os} + build_alias=${host_alias} + fi + ;; +*) + if result=`${config_shell} ${configsub} ${build_alias}` ; then + buildopt="--build=${build_alias}" + build_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` + build_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` + build_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` + build=${build_cpu}-${build_vendor}-${build_os} + else + echo "Unrecognized build system name ${build_alias}." 1>&2 + exit 1 + fi + ;; +esac + +if result=`${config_shell} ${configsub} ${host_alias}` ; then + true +else + echo "Unrecognized host system name ${host_alias}." 1>&2 + exit 1 +fi +host_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` +host_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` +host_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` +host=${host_cpu}-${host_vendor}-${host_os} + +. ${tmpfile}.hst + +if result=`${config_shell} ${configsub} ${target_alias}` ; then + true +else + echo "Unrecognized target system name ${target_alias}." 1>&2 + exit 1 +fi +target_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` +target_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` +target_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` +target=${target_cpu}-${target_vendor}-${target_os} + +. ${tmpfile}.tgt + +# Find the source files, if location was not specified. +case "${srcdir}" in +"") + srcdirdefaulted=1 + srcdir=. + if [ ! -r ${srctrigger} ] ; then + srcdir=.. + fi + ;; +*) ;; +esac + +if [ ! -r ${srcdir}/${srctrigger} ] ; then + case "${srcdirdefaulted}" in + "") echo '***' "${progname}: Can't find ${srcname} sources in ${PWD=`pwd`}/${srcdir}" 1>&2 ;; + *) echo '***' "${progname}: Can't find ${srcname} sources in ${PWD=`pwd`}/. or ${PWD=`pwd`}/.." 1>&2 ;; + esac + + echo '***' \(At least ${srctrigger} is missing.\) 1>&2 + exit 1 +fi + +# Some systems (e.g., one of the i386-aix systems the gas testers are +# using) don't handle "\$" correctly, so don't use it here. +tooldir='$(exec_prefix)'/${target_alias} + +if [ "${host_alias}" != "${target_alias}" ] ; then + if [ "${program_prefixoption}" = "" ] ; then + if [ "${program_suffixoption}" = "" ] ; then + if [ "${program_transform_nameoption}" = "" ] ; then + program_prefix=${target_alias}- ; + fi + fi + fi +fi + +# Merge program_prefix and program_suffix onto program_transform_name. +# (program_suffix used to use $, but it's hard to preserve $ through both +# make and sh.) +if [ "${program_suffix}" != "" ] ; then + program_transform_name="-e s,\\\\(.*\\\\),\\\\1${program_suffix}, ${program_transform_name}" +fi + +if [ "${program_prefix}" != "" ] ; then + program_transform_name="-e s,^,${program_prefix}, ${program_transform_name}" +fi + +# If CC and CXX are not set in the environment, and the Makefile +# exists, try to extract them from it. This is to handle running +# ./config.status by hand. +if [ -z "${CC}" -a -r Makefile ]; then + sed -n -e ':loop +/\\$/ N +/\\$/ b loop +s/\\\n//g +/^CC[ ]*=/ s/CC[ ]*=[ ]*\(.*\)/\1/p' < Makefile > Makefile.cc + CC=`tail -1 Makefile.cc` + rm -f Makefile.cc +fi + +if [ -z "${CXX}" -a -r Makefile ]; then + sed -n -e ':loop +/\\$/ N +/\\$/ b loop +s/\\\n//g +/^CXX[ ]*=/ s/CXX[ ]*=[ ]*\(.*\)/\1/p' < Makefile > Makefile.cc + CXX=`tail -1 Makefile.cc` + rm -f Makefile.cc +fi + +if [ "${build}" != "${host}" ]; then + # If we are doing a Canadian Cross, in which the host and build systems + # are not the same, we set reasonable default values for the tools. + + tools="AR AR_FOR_TARGET AS AS_FOR_TARGET BISON CC_FOR_BUILD" + tools="${tools} CC_FOR_TARGET CXX_FOR_TARGET HOST_PREFIX" + tools="${tools} HOST_PREFIX_1 LD LD_FOR_TARGET LEX MAKEINFO NM" + tools="${tools} NM_FOR_TARGET RANLIB RANLIB_FOR_TARGET" + + for var in ${tools}; do + if [ -z "`eval 'echo $'"${var}"`" -a -r Makefile ]; then + sed -n -e ':loop +/\\$/ N +/\\$/ b loop +s/\\\n//g +/^'"${var}"'[ ]*=/ s/'"${var}"'[ ]*=[ ]*\(.*\)/\1/p' \ + < Makefile > Makefile.v + t=`tail -1 Makefile.v` + if [ -n "${t}" ]; then + eval "${var}='${t}'" + fi + rm -f Makefile.v + fi + done + + AR=${AR-${host_alias}-ar} + AR_FOR_TARGET=${AR_FOR_TARGET-${target_alias}-ar} + AS=${AS-${host_alias}-as} + AS_FOR_TARGET=${AS_FOR_TARGET-${target_alias}-as} + CC=${CC-${host_alias}-gcc} + CXX=${CXX-${host_alias}-gcc} + CC_FOR_BUILD=${CC_FOR_BUILD-gcc} + CC_FOR_TARGET=${CC_FOR_TARGET-${target_alias}-gcc} + CXX_FOR_TARGET=${CXX_FOR_TARGET-${target_alias}-gcc} + HOST_PREFIX=${build_alias}- + HOST_PREFIX_1=${build_alias}- + LD=${LD-${host_alias}-ld} + LD_FOR_TARGET=${LD_FOR_TARGET-${target_alias}-ld} + MAKEINFO=${MAKEINFO-makeinfo} + NM=${NM-${host_alias}-nm} + NM_FOR_TARGET=${NM_FOR_TARGET-${target_alias}-nm} + RANLIB=${RANLIB-${host_alias}-ranlib} + RANLIB_FOR_TARGET=${RANLIB_FOR_TARGET-${target_alias}-ranlib} + + if [ -z "${BISON}" ]; then + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/byacc; then + BISON=byacc + break + fi + if test -f $dir/bison; then + BISON=bison + break + fi + if test -f $dir/yacc; then + BISON=yacc + break + fi + done + IFS="$save_ifs" + BISON=${BISON-bison} + fi + + if [ -z "${LEX}" ]; then + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/flex; then + LEX=flex + break + fi + if test -f $dir/lex; then + LEX=lex + break + fi + done + IFS="$save_ifs" + LEX=${LEX-flex} + fi + + # Export variables which autoconf might try to set. + export AS + export AR + export CC_FOR_BUILD + export LD + export NM + export RANLIB +else + # If CC is still not set, try to get gcc. + if [ -z "${CC}" ]; then + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/gcc; then + CC="gcc -O2" + break + fi + done + IFS="$save_ifs" + CC=${CC-cc} + fi + + CXX=${CXX-"gcc"} +fi + +export CC +export CXX + +for subdir in . ${subdirs} ; do + + # ${subdir} is relative path from . to the directory we're currently + # configuring. + # ${invsubdir} is inverse of ${subdir), *with* trailing /, if needed. + invsubdir=`echo ${subdir}/ | sed -e 's|\./||g' -e 's|[^/]*/|../|g'` + + ### figure out what to do with srcdir + case "${srcdir}" in + ".") # no -srcdir option. We're building in place. + makesrcdir=. ;; + /*) # absolute path + makesrcdir=`echo ${srcdir}/${subdir} | sed -e 's|/\.$||'` + ;; + *) # otherwise relative + case "${subdir}" in + .) makesrcdir=${srcdir} ;; + *) makesrcdir=${invsubdir}${srcdir}/${subdir} ;; + esac + ;; + esac + + if [ "${subdir}/" != "./" ] ; then + Makefile=${subdir}/Makefile + fi + + if [ ! -d ${subdir} ] ; then + if mkdir ${subdir} ; then + true + else + echo '***' "${progname}: could not make ${PWD=`pwd`}/${subdir}" 1>&2 + exit 1 + fi + fi + + case "${removing}" in + "") + case "${subdir}" in + .) ;; + *) eval echo Building in ${subdir} ${redirect} ;; + esac + + # FIXME Should this be done recursively ??? (Useful for e.g. gdbtest) + # Set up the list of links to be made. + # ${links} is the list of link names, and ${files} is the list of names to link to. + + # Make the links. + configlinks="${links}" + if [ -r ${subdir}/config.status ] ; then + mv -f ${subdir}/config.status ${subdir}/config.back + fi + while [ -n "${files}" ] ; do + # set file to car of files, files to cdr of files + set ${files}; file=$1; shift; files=$* + set ${links}; link=$1; shift; links=$* + + if [ ! -r ${srcdir}/${file} ] ; then + echo '***' "${progname}: cannot create a link \"${link}\"," 1>&2 + echo '***' "since the file \"${srcdir}/${file}\" does not exist." 1>&2 + exit 1 + fi + + ${remove} -f ${link} + # Make a symlink if possible, otherwise try a hard link + if ${symbolic_link} ${srcdir}/${file} ${link} >/dev/null 2>&1 ; then + true + else + # We need to re-remove the file because Lynx leaves a + # very strange directory there when it fails an NFS symlink. + ${remove} -r -f ${link} + ${hard_link} ${srcdir}/${file} ${link} + fi + if [ ! -r ${link} ] ; then + echo '***' "${progname}: unable to link \"${link}\" to \"${srcdir}/${file}\"." 1>&2 + exit 1 + fi + + echo "Linked \"${link}\" to \"${srcdir}/${file}\"." + done + + # Create a .gdbinit file which runs the one in srcdir + # and tells GDB to look there for source files. + + if [ -r ${srcdir}/${subdir}/.gdbinit ] ; then + case ${srcdir} in + .) ;; + *) cat > ${subdir}/.gdbinit < ${subdir}/Makefile.tem + else + cp ${srcdir}/${subdir}/${Makefile_in} ${subdir}/Makefile.tem + site_makefile_frag= + fi + ;; + esac + # working copy now in ${subdir}/Makefile.tem + + # Conditionalize the makefile for this host. + rm -f ${Makefile} + case "${host_makefile_frag}" in + "") mv ${subdir}/Makefile.tem ${Makefile} ;; + *) + if [ ! -f ${host_makefile_frag} ] ; then + host_makefile_frag=${srcdir}/${host_makefile_frag} + fi + if [ -f ${host_makefile_frag} ] ; then + sed -e "/^####/ r ${host_makefile_frag}" ${subdir}/Makefile.tem > ${Makefile} + else + echo '***' Expected host makefile fragment \"${host_makefile_frag}\" 1>&2 + echo '***' is missing in ${PWD=`pwd`}. 1>&2 + mv ${subdir}/Makefile.tem ${Makefile} + fi + esac + # working copy now in ${Makefile} + + # Conditionalize the makefile for this target. + rm -f ${subdir}/Makefile.tem + case "${target_makefile_frag}" in + "") mv ${Makefile} ${subdir}/Makefile.tem ;; + *) + if [ ! -f ${target_makefile_frag} ] ; then + target_makefile_frag=${srcdir}/${target_makefile_frag} + fi + if [ -f ${target_makefile_frag} ] ; then + sed -e "/^####/ r ${target_makefile_frag}" ${Makefile} > ${subdir}/Makefile.tem + else + mv ${Makefile} ${subdir}/Makefile.tem + target_makefile_frag= + fi + ;; + esac + # real copy now in ${subdir}/Makefile.tem + + # Conditionalize the makefile for this package. + rm -f ${Makefile} + case "${package_makefile_frag}" in + "") mv ${subdir}/Makefile.tem ${Makefile} ;; + *) + if [ ! -f ${package_makefile_frag} ] ; then + package_makefile_frag=${srcdir}/${package_makefile_frag} + fi + if [ -f ${package_makefile_frag} ] ; then + sed -e "/^####/ r ${package_makefile_frag}" ${subdir}/Makefile.tem > ${Makefile} + rm -f ${subdir}/Makefile.tem + else + echo '***' Expected package makefile fragment \"${package_makefile_frag}\" 1>&2 + echo '***' is missing in ${PWD=`pwd`}. 1>&2 + mv ${subdir}/Makefile.tem ${Makefile} + fi + esac + # working copy now in ${Makefile} + + mv ${Makefile} ${subdir}/Makefile.tem + + # real copy now in ${subdir}/Makefile.tem + + # prepend warning about editting, and a bunch of variables. + rm -f ${Makefile} + cat > ${Makefile} <> ${Makefile} << EOF +build_alias = ${build_alias} +build_cpu = ${build_cpu} +build_vendor = ${build_vendor} +build_os = ${build_os} +build_canonical = ${build_cpu}-${build_vendor}-${build_os} +EOF + esac + + case "${package_makefile_frag}" in + "") ;; + /*) echo package_makefile_frag = ${package_makefile_frag} >>${Makefile} ;; + *) echo package_makefile_frag = ${invsubdir}${package_makefile_frag} >>${Makefile} ;; + esac + + case "${target_makefile_frag}" in + "") ;; + /*) echo target_makefile_frag = ${target_makefile_frag} >>${Makefile} ;; + *) echo target_makefile_frag = ${invsubdir}${target_makefile_frag} >>${Makefile} ;; + esac + + case "${host_makefile_frag}" in + "") ;; + /*) echo host_makefile_frag = ${host_makefile_frag} >>${Makefile} ;; + *) echo host_makefile_frag = ${invsubdir}${host_makefile_frag} >>${Makefile} ;; + esac + + if [ "${site_makefile_frag}" != "" ] ; then + echo site_makefile_frag = ${invsubdir}${site_makefile_frag} >>${Makefile} + fi + + # reset prefix, exec_prefix, srcdir, SUBDIRS, NONSUBDIRS, + # remove any form feeds. + if [ -z "${subdirs}" ]; then + rm -f ${subdir}/Makefile.tem2 + sed -e "s:^SUBDIRS[ ]*=.*$:SUBDIRS = ${configdirs}:" \ + -e "s:^NONSUBDIRS[ ]*=.*$:NONSUBDIRS = ${noconfigdirs}:" \ + ${subdir}/Makefile.tem > ${subdir}/Makefile.tem2 + rm -f ${subdir}/Makefile.tem + mv ${subdir}/Makefile.tem2 ${subdir}/Makefile.tem + fi + sed -e "s:^prefix[ ]*=.*$:prefix = ${prefix}:" \ + -e "s:^exec_prefix[ ]*=.*$:exec_prefix = ${exec_prefix}:" \ + -e "/^CC[ ]*=/{ + :loop1 + /\\\\$/ N + /\\\\$/ b loop1 + s/\\\\\\n//g + s%^CC[ ]*=.*$%CC = ${CC}% + }" \ + -e "/^CXX[ ]*=/{ + :loop2 + /\\\\$/ N + /\\\\$/ b loop2 + s/\\\\\\n//g + s%^CXX[ ]*=.*$%CXX = ${CXX}% + }" \ + -e "s:^SHELL[ ]*=.*$:SHELL = ${config_shell}:" \ + -e "s:^srcdir[ ]*=.*$:srcdir = ${makesrcdir}:" \ + -e "s/ //" \ + -e "s:^program_prefix[ ]*=.*$:program_prefix = ${program_prefix}:" \ + -e "s:^program_suffix[ ]*=.*$:program_suffix = ${program_suffix}:" \ + -e "s:^program_transform_name[ ]*=.*$:program_transform_name = ${program_transform_name}:" \ + -e "s:^tooldir[ ]*=.*$:tooldir = ${tooldir}:" \ + ${subdir}/Makefile.tem >> ${Makefile} + + # If this is a Canadian Cross, preset the values of many more + # tools. + if [ "${build}" != "${host}" ]; then + for var in ${tools}; do + val=`eval 'echo $'"${var}"` + sed -e "/^${var}[ ]*=/{ + :loop1 + /\\\\$/ N + /\\\\$/ b loop1 + s/\\\\\\n//g + s%^${var}[ ]*=.*$%${var} = ${val}% + }" ${Makefile} > ${Makefile}.tem + mv -f ${Makefile}.tem ${Makefile} + done + fi + + # final copy now in ${Makefile} + + else + echo "No Makefile.in found in ${srcdir}/${subdir}, unable to configure" 1>&2 + fi + + rm -f ${subdir}/Makefile.tem + + case "${host_makefile_frag}" in + "") using= ;; + *) using="and \"${host_makefile_frag}\"" ;; + esac + + case "${target_makefile_frag}" in + "") ;; + *) using="${using} and \"${target_makefile_frag}\"" ;; + esac + + case "${site_makefile_frag}" in + "") ;; + *) using="${using} and \"${site_makefile_frag}\"" ;; + esac + + newusing=`echo "${using}" | sed 's/and/using/'` + using=${newusing} + echo "Created \"${Makefile}\" in" ${PWD=`pwd`} ${using} + + . ${tmpfile}.pos + + # describe the chosen configuration in config.status. + # Make that file a shellscript which will reestablish + # the same configuration. Used in Makefiles to rebuild + # Makefiles. + + case "${norecursion}" in + "") arguments="${arguments} --norecursion" ;; + *) ;; + esac + + if [ ${subdir} = . ] ; then + echo "#!/bin/sh +# ${NO_EDIT} +# This directory was configured as follows: +${progname}" ${arguments} " +# ${using}" > ${subdir}/config.new + else + echo "#!/bin/sh +# ${NO_EDIT} +# This directory was configured as follows: +cd ${invsubdir} +${progname}" ${arguments} " +# ${using}" > ${subdir}/config.new + fi + chmod a+x ${subdir}/config.new + if [ -r ${subdir}/config.back ] ; then + mv -f ${subdir}/config.back ${subdir}/config.status + fi + ${moveifchange} ${subdir}/config.new ${subdir}/config.status + ;; + + *) rm -f ${Makefile} ${subdir}/config.status ${links} ;; + esac +done + +# If there are subdirectories, then recur. +if [ -z "${norecursion}" -a -n "${configdirs}" ] ; then + for configdir in ${configdirs} ; do + + if [ -d ${srcdir}/${configdir} ] ; then + eval echo Configuring ${configdir}... ${redirect} + case "${srcdir}" in + ".") ;; + *) + if [ ! -d ./${configdir} ] ; then + if mkdir ./${configdir} ; then + true + else + echo '***' "${progname}: could not make ${PWD=`pwd`}/${configdir}" 1>&2 + exit 1 + fi + fi + ;; + esac + + POPDIR=${PWD=`pwd`} + cd ${configdir} + +### figure out what to do with srcdir + case "${srcdir}" in + ".") newsrcdir=${srcdir} ;; # no -srcdir option. We're building in place. + /*) # absolute path + newsrcdir=${srcdir}/${configdir} + srcdiroption="--srcdir=${newsrcdir}" + ;; + *) # otherwise relative + newsrcdir=../${srcdir}/${configdir} + srcdiroption="--srcdir=${newsrcdir}" + ;; + esac + + # Handle --cache-file=../XXX + case "${cache_file}" in + "") # empty + ;; + /*) # absolute path + cache_file_option="--cache-file=${cache_file}" + ;; + *) # relative path + cache_file_option="--cache-file=../${cache_file}" + ;; + esac + +### check for guested configure, otherwise fix possibly relative progname + if [ -f ${newsrcdir}/configure ] ; then + recprog=${newsrcdir}/configure + elif [ -f ${newsrcdir}/configure.in ] ; then + case "${progname}" in + /*) recprog=${progname} ;; + *) recprog=../${progname} ;; + esac + else + eval echo No configuration information in ${configdir} ${redirect} + recprog= + fi + +### The recursion line is here. + if [ ! -z "${recprog}" ] ; then + if eval ${config_shell} ${recprog} ${verbose} ${buildopt} --host=${host_alias} --target=${target_alias} \ + ${prefixoption} ${tmpdiroption} ${exec_prefixoption} \ + ${srcdiroption} ${program_prefixoption} ${program_suffixoption} ${program_transform_nameoption} ${site_option} ${withoptions} ${withoutoptions} ${enableoptions} ${disableoptions} ${cache_file_option} ${removing} ${other_options} ${redirect} ; then + true + else + echo Configure in `pwd` failed, exiting. 1>&2 + exit 1 + fi + fi + + cd ${POPDIR} + fi + done +fi + +# Perform the same cleanup as the trap handler, minus the "exit 1" of course, +# and reset the trap handler. +rm -f ${tmpfile}.com ${tmpfile}.tgt ${tmpfile}.hst ${tmpfile}.pos +trap 0 + +exit 0 + +# +# Local Variables: +# fill-column: 131 +# End: +# + +# end of configure diff --git a/gnu/usr.bin/binutils/configure.bat b/gnu/usr.bin/binutils/configure.bat new file mode 100644 index 00000000000..d76a37ecd9d --- /dev/null +++ b/gnu/usr.bin/binutils/configure.bat @@ -0,0 +1,17 @@ +@echo off + +chdir libiberty +call configure %1 %2 %3 %4 %5 %6 %7 %8 %9 +chdir ..\bfd +call configure %1 %2 %3 %4 %5 %6 %7 %8 %9 +chdir ..\opcodes +call configure %1 %2 %3 %4 %5 %6 %7 %8 %9 +chdir ..\gprof +call configure %1 %2 %3 %4 %5 %6 %7 %8 %9 +chdir ..\binutils +call configure %1 %2 %3 %4 %5 %6 %7 %8 %9 +chdir ..\gas +call configure %1 %2 %3 %4 %5 %6 %7 %8 %9 +chdir ..\ld +call configure %1 %2 %3 %4 %5 %6 %7 %8 %9 +chdir .. diff --git a/gnu/usr.bin/binutils/configure.in b/gnu/usr.bin/binutils/configure.in new file mode 100644 index 00000000000..567a5a1904f --- /dev/null +++ b/gnu/usr.bin/binutils/configure.in @@ -0,0 +1,658 @@ +############################################################################## + +## This file is a shell script fragment that supplies the information +## necessary to tailor a template configure script into the configure +## script appropriate for this directory. For more information, check +## any existing configure script. + +## Be warned, there are two types of configure.in files. There are those +## used by Autoconf, which are macros which are expanded into a configure +## script by autoconf. The other sort, of which this is one, is executed +## by Cygnus configure. + +## For more information on these two systems, check out the documentation +## for 'Autoconf' (autoconf.texi) and 'Configure' (configure.texi). + +############################################################################## + +### To add a new directory to the tree, first choose whether it is a target +### or a host dependent tool. Then put it into the appropriate list +### (library or tools, host or target), doing a dependency sort. For +### example, gdb requires that byacc (or bison) be built first, so it is in +### the ${host_tools} list after byacc and bison. + + +# these libraries are used by various programs built for the host environment +# +host_libs="mmalloc libiberty opcodes bfd readline gash tcl tk tclX" + +if [ "${enable_gdbgui}" = "yes" ] ; then + host_libs="${host_libs} libgui" +fi + +# these tools are built for the host environment +# +host_tools="byacc flex bison binutils ld gas gcc gdb make patch + prms send-pr gprof gdbtest tgas etc expect dejagnu sim + m4 autoconf ispell grep diff rcs cvs fileutils shellutils + textutils wdiff find emacs emacs19 uudecode hello tar gzip indent + recode release sed utils" + + +# these libraries are built for the target environment, and are built after +# the host libraries and the host tools (which may be a cross compiler) +# +target_libs="target-libiberty target-libgloss target-newlib target-libio target-librx target-libstdc++ target-libg++ target-winsup" + + +# these tools are built using the target libs, and are intended to run only +# in the target environment +# +# note: any program that *uses* libraries that are in the "target_libs" +# list belongs in this list. those programs are also very likely +# candidates for the "native_only" list which follows +# +target_tools="target-examples target-groff" + +################################################################################ + +## These two lists are of directories that are to be removed from the +## ${configdirs} list for either cross-compilations or for native- +## compilations. For example, it doesn't make that much sense to +## cross-compile Emacs, nor is it terribly useful to compile target-libiberty in +## a native environment. + +# directories to be built in the native environment only +# +native_only="autoconf cvs emacs emacs19 fileutils find grep gzip hello + indent ispell m4 rcs recode sed shellutils tar textutils gash + uudecode wdiff gprof target-groff" + +# directories to be built in a cross environment only +# +cross_only="target-libiberty target-libgloss target-newlib" + +## All tools belong in one of the four categories, and are assigned above +## We assign ${configdirs} this way to remove all embedded newlines. This +## is important because configure will choke if they ever get through. +## ${configdirs} is directories we build using the host tools. +## ${target_configdirs} is directories we build using the target tools. +# +configdirs=`echo ${host_libs} ${host_tools}` +target_configdirs=`echo ${target_libs} ${target_tools}` + +################################################################################ + +srctrigger=move-if-change +srcname="gnu development package" + +# This gets set non-empty for some net releases of packages. +appdirs="" + +# per-host: + +# Work in distributions that contain no compiler tools, like Autoconf. +if [ -d ${srcdir}/config ]; then +case "${host}" in + m68k-hp-hpux*) host_makefile_frag=config/mh-hp300 ;; + m68k-apollo-sysv*) host_makefile_frag=config/mh-apollo68 ;; + m68k-apollo-bsd*) host_makefile_frag=config/mh-a68bsd ;; + m88k-dg-dgux*) host_makefile_frag=config/mh-dgux ;; + m88k-harris-cxux*) host_makefile_frag=config/mh-cxux ;; + m88k-motorola-sysv*) host_makefile_frag=config/mh-delta88;; + mips*-dec-ultrix*) host_makefile_frag=config/mh-decstation ;; + mips*-sgi-irix[56]*) host_makefile_frag=config/mh-irix5 ;; + mips*-sgi-irix4*) host_makefile_frag=config/mh-irix4 ;; + mips*-sgi-irix3*) host_makefile_frag=config/mh-sysv ;; + mips*-*-sysv4*) host_makefile_frag=config/mh-sysv4 ;; + mips*-*-sysv*) host_makefile_frag=config/mh-riscos ;; + i[345]86-ncr-sysv4.3) host_makefile_frag=config/mh-ncrsvr43 ;; + i[345]86-ncr-sysv4*) host_makefile_frag=config/mh-ncr3000 ;; + i[345]86-*-sco*) host_makefile_frag=config/mh-sco ;; + i[345]86-*-isc*) host_makefile_frag=config/mh-sysv ;; + i[345]86-*-linux*) host_makefile_frag=config/mh-linux ;; + i[345]86-*-solaris2*) host_makefile_frag=config/mh-sysv4 ;; + i[345]86-*-aix*) host_makefile_frag=config/mh-aix386 ;; + i[345]86-*-go32*) host_makefile_frag=config/mh-go32 ;; + i[345]86-*-win32) host_makefile_frag=config/mh-i386win32 ;; + vax-*-ultrix2*) host_makefile_frag=config/mh-vaxult2 ;; + *-*-solaris2*) host_makefile_frag=config/mh-solaris ;; + m68k-sun-sunos*) host_makefile_frag=config/mh-sun3 ;; + *-hp-hpux[78]*) host_makefile_frag=config/mh-hpux8 ;; + *-hp-hpux*) host_makefile_frag=config/mh-hpux ;; + *-*-hiux*) host_makefile_frag=config/mh-hpux ;; + rs6000-*-lynxos*) host_makefile_frag=config/mh-lynxrs6k ;; + *-*-lynxos*) host_makefile_frag=config/mh-lynxos ;; + *-*-sysv4*) host_makefile_frag=config/mh-sysv4 ;; + *-*-sysv*) host_makefile_frag=config/mh-sysv ;; +esac +fi + +# See if we can extract a definition of CC from the fragment. +if [ -z "${CC}" ]; then + if [ -n "${host_makefile_frag}" -a -f "${srcdir}/${host_makefile_frag}" ]; then + xx=`sed -n -e 's/^[ ]*CC[ ]*=[ ]*\(.*\)$/\1/p' < ${srcdir}/${host_makefile_frag}` + if [ -n "${xx}" ] ; then + CC=$xx + fi + fi +fi + +# The Solaris /usr/ucb/cc compiler does not appear to work. +case "${host}" in + sparc-sun-solaris2*) + if [ "`/usr/bin/which ${CC-cc}`" = "/usr/ucb/cc" ] ; then + could_use= + [ -d /opt/SUNWspro/bin ] && could_use="/opt/SUNWspro/bin" + if [ -d /opt/cygnus/bin ] ; then + if [ "$could_use" = "" ] ; then + could_use="/opt/cygnus/bin" + else + could_use="$could_use or /opt/cygnus/bin" + fi + fi + if [ "$could_use" = "" ] ; then + echo "Warning: compilation may fail because you're using" + echo "/usr/ucb/cc. You should change your PATH or CC " + echo "variable and rerun configure." + else + echo "Warning: compilation may fail because you're using" + echo "/usr/ucb/cc, when you should use the C compiler from" + echo "$could_use. You should change your" + echo "PATH or CC variable and rerun configure." + fi + fi + ;; +esac + +# We default to --with-shared on platforms where -fpic is meaningless. +# Well, we don't yet, but we will. +if false && [ "${host}" = "${target}" ] && [ x${enable_shared} = x ]; then + case "${target}" in + alpha-dec-osf*) enable_shared=yes ;; + mips-sgi-irix5*) enable_shared=yes ;; + *) enable_shared=no ;; + esac +fi + +if [ x${enable_shared} = xyes ]; then + waugh= + case "${host}" in + hppa*) waugh=config/mh-papic ;; + i[345]86-*) waugh=config/mh-x86pic ;; + *) waugh=config/mh-${host_cpu}pic ;; + esac + if [ -f ${srcdir}/${waugh} ]; then + if [ -n "${host_makefile_frag}" ] ; then + cat ${srcdir}/${host_makefile_frag} > mh-frag + cat ${srcdir}/${waugh} >> mh-frag + host_makefile_frag=mh-frag + else + host_makefile_frag=${waugh} + fi + fi +fi + +# per-target: + +case "${target}" in + v810*) target_makefile_frag=config/mt-v810 ;; + i[345]86-*-netware*) target_makefile_frag=config/mt-netware ;; + powerpc-*-netware*) target_makefile_frag=config/mt-netware ;; +esac + +skipdirs= +gasdir=gas +use_gnu_ld= +use_gnu_as= + +# some tools are so dependent upon X11 that if we're not building with X, +# it's not even worth trying to configure, much less build, that tool. + +case ${with_x} in + yes | "") # the default value for this tree is that X11 is available + ;; + no) + skipdirs="${skipdirs} tk gash" + ;; + *) + echo "*** bad value \"${with_x}\" for -with-x flag; ignored" 1>&2 + ;; +esac + +# Some tools are only suitable for building in a "native" situation. +# Those are added when we have a host==target configuration. For cross +# toolchains, we add some directories that should only be useful in a +# cross-compiler. + +is_cross_compiler= + +if [ x"${host}" = x"${target}" ] ; then + # when doing a native toolchain, don't build the targets + # that are in the 'cross only' list + skipdirs="${skipdirs} ${cross_only}" + is_cross_compiler=no + target_subdir=. +else + # similarly, don't build the targets in the 'native only' + # list when building a cross compiler + skipdirs="${skipdirs} ${native_only}" + is_cross_compiler=yes + target_subdir=${target_alias} + if [ ! -d ${target_subdir} ] ; then + if mkdir ${target_subdir} ; then true + else + echo "'*** could not make ${PWD=`pwd`}/${target_subdir}" 1>&2 + exit 1 + fi + fi +fi + +copy_dirs= + +# Handle --with-headers=XXX. The contents of the named directory are +# copied to $(tooldir)/sys-include. +if [ x"${with_headers}" != x ]; then + if [ x${is_cross_compiler} = xno ]; then + echo 1>&2 '***' --with-headers is only supported when cross compiling + exit 1 + fi + case "${exec_prefixoption}" in + "") x=${prefix} ;; + *) x=${exec_prefix} ;; + esac + copy_dirs="${copy_dirs} ${with_headers} $x/${target_alias}/sys-include" +fi + +# Handle --with-libs=XXX. Multiple directories are permitted. The +# contents are copied to $(tooldir)/lib. +if [ x"${with_libs}" != x ]; then + if [ x${is_cross_compiler} = xno ]; then + echo 1>&2 '***' --with-libs is only supported when cross compiling + exit 1 + fi + # Copy the libraries in reverse order, so that files in the first named + # library override files in subsequent libraries. + case "${exec_prefixoption}" in + "") x=${prefix} ;; + *) x=${exec_prefix} ;; + esac + for l in ${with_libs}; do + copy_dirs="$l $x/${target_alias}/lib ${copy_dirs}" + done +fi + +# If both --with-headers and --with-libs are specified, default to +# --without-newlib. +if [ x"${with_headers}" != x ] && [ x"${with_libs}" != x ]; then + if [ x"${with_newlib}" = x ]; then + with_newlib=no + fi +fi + +# Recognize --with-newlib/--without-newlib. +if [ x${with_newlib} = xno ]; then + skipdirs="${skipdirs} target-newlib" +elif [ x${with_newlib} = xyes ]; then + skipdirs=`echo " ${skipdirs} " | sed -e 's/ target-newlib / /'` +fi + +# Handle ${copy_dirs} +set fnord ${copy_dirs} +shift +while [ $# != 0 ]; do + if [ -f $2/COPIED ] && [ x"`cat $2/COPIED`" = x"$1" ]; then + : + else + echo Copying $1 to $2 + + # Use the install script to create the directory and all required + # parent directories. + if [ -d $2 ]; then + : + else + echo >config.temp + ${srcdir}/install.sh -c -m 644 config.temp $2/COPIED + fi + + # Copy the directory, assuming we have tar. + # FIXME: Should we use B in the second tar? Not all systems support it. + (cd $1; tar -cf - .) | (cd $2; tar -xpf -) + + # It is the responsibility of the user to correctly adjust all + # symlinks. If somebody can figure out how to handle them correctly + # here, feel free to add the code. + + echo $1 > $2/COPIED + fi + shift; shift +done + +# Configure extra directories which are host specific + +case "${host}" in + i[345]86-*-win32* | i[345]86-*-go32*) + configdirs="$configdirs dosrel" ;; +esac + +# Remove more programs from consideration, based on the host or +# target this usually means that a port of the program doesn't +# exist yet. + +noconfigdirs="" + +case "${host}" in + i[345]86-*-vsta) + noconfigdirs="tcl expect dejagnu make texinfo bison patch flex byacc send-pr gprof uudecode dejagnu diff" + ;; + i[345]86-*-go32) + noconfigdirs="tcl tk expect dejagnu make texinfo bison patch flex byacc send-pr gprof uudecode dejagnu diff" + ;; + i[345]86-*-win32) + noconfigdirs="patch diff flex make tk tcl expect dejagnu cvs autoconf texinfo bison send-pr gprof rcs" + ;; +esac + + +case "${target}" in + *-*-netware) + noconfigdirs="$noconfigdirs target-libg++ target-libstdc++ target-librx target-newlib target-libiberty" + ;; + *-*-vxworks5.1) + noconfigdirs="$noconfigdirs target-newlib" + ;; + alpha-dec-osf*) + # ld works, but does not support shared libraries. emacs doesn't + # work. newlib is not 64 bit ready. I'm not sure about fileutils or grep. + noconfigdirs="$noconfigdirs ld emacs fileutils grep target-newlib" + ;; + alpha*-*-*) + # newlib is not 64 bit ready + noconfigdirs="$noconfigdirs target-newlib" + ;; + arm-*-riscix*) + noconfigdirs="$noconfigdirs ld" + ;; + h8300*-*-* | \ + h8500-*-*) + noconfigdirs="$noconfigdirs target-libg++ target-libstdc++ target-libio target-librx" + ;; + hppa*-*-*elf* | \ + hppa*-*-lites*) + # Do configure ld/binutils/gas for this case. + ;; + hppa*-*-*) + # HP's C compiler doesn't handle Emacs correctly (but on BSD and Mach + # cc is gcc, and on any system a user should be able to link cc to + # whatever they want. FIXME, emacs emacs19). + case "${CC}" in + "" | cc*) noconfigdirs="$noconfigdirs emacs emacs19" ;; + *) ;; + esac + noconfigdirs="$noconfigdirs ld shellutils" + ;; + i[345]86-*-go32) + # but don't build gdb + noconfigdirs="$noconfigdirs gdb target-libg++ target-libstdc++ target-libio target-librx" + ;; + + i[345]86-*-win32) + # Can't build gdb for win32 if not native. + # make/glob's configure uses some AC_TRY_RUN type tests + if [ x${is_cross_compiler} = xyes ]; then + noconfigdirs="$noconfigdirs gdb tk make" + fi + # always build newlib. + skipdirs=`echo " ${skipdirs} " | sed -e 's/ target-newlib / /'` + ;; + i[345]86-*-pe) + noconfigdirs="$noconfigdirs target-libg++ target-libstdc++ target-libio target-librx" + ;; + i[345]86-*-sco*) + noconfigdirs="$noconfigdirs gprof" + ;; + i[345]86-*-solaris2*) + # The linker does static linking correctly, but the Solaris C library + # has bugs such that some important functions won't work when statically + # linked. (See man pages for getpwuid, for example.) + noconfigdirs="$noconfigdirs ld" + ;; + i[345]86-*-sysv4*) + # The SYSV4 C compiler doesn't handle Emacs correctly + case "${CC}" in + "" | cc*) noconfigdirs="$noconfigdirs emacs emacs19" ;; + *) ;; + esac + # but that's okay since emacs doesn't work anyway + noconfigdirs="$noconfigdirs emacs emacs19" + ;; + powerpc-*-aix*) + # copied from rs6000-*-* entry + noconfigdirs="$noconfigdirs gprof cvs" + ;; + powerpc*-*-winnt* | powerpc*-*-pe*) + noconfigdirs="$noconfigdirs gdb" + ;; + rs6000-*-lynxos*) + # The CVS server code doesn't work on the RS/6000 + # Newlib makes problems for libg++ in crosses. + noconfigdirs="$noconfigdirs target-newlib gprof cvs" + ;; + rs6000-*-*) + noconfigdirs="$noconfigdirs gprof" + ;; + m68k-*-netbsd*) + noconfigdirs="$noconfigdirs gdb" + ;; + m68k-apollo-*) + noconfigdirs="$noconfigdirs ld binutils gprof" + ;; + mips*-*-irix5*) + # The GNU linker does not support shared libraries. + # emacs is emacs 18, which does not work on Irix 5 (emacs19 does work) + noconfigdirs="$noconfigdirs ld gprof emacs" + ;; + mips*-dec-bsd*) + noconfigdirs="$noconfigdirs gprof" + ;; + mips*-*-bsd*) + noconfigdirs="$noconfigdirs gprof" + ;; + mips*-*-*) + noconfigdirs="$noconfigdirs gprof" + ;; + romp-*-*) + noconfigdirs="$noconfigdirs bfd binutils ld gas opcodes" + ;; + sh-*-*) + case "${host}" in + i[345]86-*-vsta) ;; # don't add gprof back in + i[345]86-*-go32) ;; # don't add gprof back in + *) skipdirs=`echo " ${skipdirs} " | sed -e 's/ gprof / /'` ;; + esac + ;; + sparc-*-sunos4*) + if [ x${is_cross_compiler} != xno ] ; then + noconfigdirs="$noconfigdirs gdb gdbtest target-newlib" + else + use_gnu_ld=no + fi + ;; + v810-*-*) + noconfigdirs="$noconfigdirs bfd binutils gas gcc gdb ld target-libg++ target-libstdc++ opcodes" + ;; + vax-*-vms) + noconfigdirs="$noconfigdirs bfd binutils gdb ld target-newlib opcodes" + ;; + vax-*-*) + noconfigdirs="$noconfigdirs target-newlib" + ;; + *-*-lynxos*) + # Newlib makes problems for libg++ in crosses. + noconfigdirs="$noconfigdirs target-newlib" + ;; + *-*-macos* | \ + *-*-mpw*) + # Macs want a resource compiler. + configdirs="$configdirs grez" + ;; +esac + +# If we are building a Canadian Cross, discard tools that can not be built +# using a cross compiler. FIXME: These tools should be fixed. +if [ "${build}" != "${host}" ]; then + noconfigdirs="$noconfigdirs expect dejagnu make texinfo diff" +fi + +# Remove the entries in $skipdirs and $noconfigdirs from $configdirs and +# $target_configdirs. +# If we have the source for $noconfigdirs entries, add them to $notsupp. + +notsupp="" +for dir in . $skipdirs $noconfigdirs ; do + dirname=`echo $dir | sed -e s/target-//g` + if [ $dir != . ] && echo " ${configdirs} " | grep " ${dir} " >/dev/null 2>&1; then + configdirs=`echo " ${configdirs} " | sed -e "s/ ${dir} / /"` + if [ -r $srcdir/$dirname/configure ] \ + || [ -r $srcdir/$dirname/configure.in ]; then + if echo " ${skipdirs} " | grep " ${dir} " >/dev/null 2>&1; then + true + else + notsupp="$notsupp $dir" + fi + fi + fi + if [ $dir != . ] && echo " ${target_configdirs} " | grep " ${dir} " >/dev/null 2>&1; then + target_configdirs=`echo " ${target_configdirs} " | sed -e "s/ ${dir} / /"` + if [ -r $srcdir/$dirname/configure ] \ + || [ -r $srcdir/$dirname/configure.in ]; then + if echo " ${skipdirs} " | grep " ${dir} " >/dev/null 2>&1; then + true + else + notsupp="$notsupp $dir" + fi + fi + fi +done + +# Sometimes the tools are distributed with libiberty but with no other +# libraries. In that case, we don't want to build target-libiberty. +if [ -n "${target_configdirs}" ]; then + others= + for i in `echo ${target_configdirs} | sed -e s/target-//g` ; do + if [ "$i" != "libiberty" ]; then + if [ -r $srcdir/$i/configure ] || [ -r $srcdir/$i/configure.in ]; then + others=yes; + break; + fi + fi + done + if [ -z "${others}" ]; then + target_configdirs= + fi +fi + +# Deconfigure all subdirectories, in case we are changing the +# configuration from one where a subdirectory is supported to one where it +# is not. +if [ -z "${norecursion}" -a -n "${configdirs}" ]; then + for i in `echo ${configdirs} | sed -e s/target-//g` ; do + rm -f $i/Makefile + done +fi +if [ -z "${norecursion}" -a -n "${target_configdirs}" ]; then + for i in `echo ${target_configdirs} | sed -e s/target-//` ; do + rm -f ${target_subdir}/$i/Makefile + done +fi + +# Produce a warning message for the subdirs we can't configure. +# This isn't especially interesting in the Cygnus tree, but in the individual +# FSF releases, it's important to let people know when their machine isn't +# supported by the one or two programs in a package. + +if [ -n "${notsupp}" ] && [ -z "${norecursion}" ]; then + # If $appdirs is non-empty, at least one of those directories must still + # be configured, or we error out. (E.g., if the gas release supports a + # specified target in some subdirs but not the gas subdir, we shouldn't + # pretend that all is well.) + if [ -n "$appdirs" ]; then + for dir in $appdirs ; do + if [ -r $dir/Makefile.in ]; then + if echo " ${configdirs} " | grep " ${dir} " >/dev/null 2>&1; then + appdirs="" + break + fi + if echo " ${target_configdirs} " | grep " ${dir} " >/dev/null 2>&1; then + appdirs="" + break + fi + fi + done + if [ -n "$appdirs" ]; then + echo "*** This configuration is not supported by this package." 1>&2 + exit 1 + fi + fi + # Okay, some application will build, or we don't care to check. Still + # notify of subdirs not getting built. + echo "*** This configuration is not supported in the following subdirectories:" 1>&2 + echo " ${notsupp}" 1>&2 + echo " (Any other directories should still work fine.)" 1>&2 +fi + +# Set with_gnu_as and with_gnu_ld as appropriate. +# +# This is done by determining whether or not the appropriate directory +# is available, and by checking whether or not specific configurations +# have requested that this magic not happen. +# +# The command line options always override the explicit settings in +# configure.in, and the settings in configure.in override this magic. +# +# If the default for a toolchain is to use GNU as and ld, and you don't +# want to do that, then you should use the --without-gnu-as and +# --without-gnu-ld options for the configure script. + +if [ x${use_gnu_as} = x ] ; then + if [ x${with_gnu_as} != xno ] && echo " ${configdirs} " | grep " ${gasdir} " > /dev/null 2>&1 && [ -d ${srcdir}/${gasdir} ] ; then + with_gnu_as=yes + withoptions="$withoptions --with-gnu-as" + fi +fi + +if [ x${use_gnu_ld} = x ] ; then + if [ x${with_gnu_ld} != xno ] && echo " ${configdirs} " | grep " ld " > /dev/null 2>&1 && [ -d ${srcdir}/ld ] ; then + with_gnu_ld=yes + withoptions="$withoptions --with-gnu-ld" + fi +fi + +if [ x${enable_shared} = xyes ]; then + case "${target}" in + hppa*) target_makefile_frag=config/mt-papic ;; + i[345]86-*) target_makefile_frag=config/mt-x86pic ;; + *) target_makefile_frag=config/mt-${target_cpu}pic ;; + esac +fi + +# post-target: + +# Record target_configdirs and the configure arguments in Makefile. +target_configdirs=`echo "${target_configdirs}" | sed -e 's/target-//g'` +targargs=`echo "${arguments}" | \ + sed -e 's/--*norecursion//' \ + -e 's/--*cache[a-z-]*=[^ ]*//' \ + -e 's/--*cache[a-z-]*[ ][ ]*[^ ]*//'` +sed -e "s:^TARGET_CONFIGDIRS[ ]*=.*$:TARGET_CONFIGDIRS = ${target_configdirs}:" \ + -e "s%^CONFIG_ARGUMENTS[ ]*=.*$%CONFIG_ARGUMENTS = ${targargs}%" \ + -e "s%^TARGET_SUBDIR[ ]*=.*$%TARGET_SUBDIR = ${target_subdir}%" \ + Makefile > Makefile.tem +rm -f Makefile +mv -f Makefile.tem Makefile + +# +# Local Variables: +# fill-column: 131 +# End: +# diff --git a/gnu/usr.bin/binutils/etc/Makefile.in b/gnu/usr.bin/binutils/etc/Makefile.in new file mode 100644 index 00000000000..699ada6ae9a --- /dev/null +++ b/gnu/usr.bin/binutils/etc/Makefile.in @@ -0,0 +1,100 @@ +# +# Makefile.in for etc +# + +prefix = /usr/local +exec_prefix = $(prefix) + +srcdir = . +bindir = $(exec_prefix)/bin +libdir = $(exec_prefix)/lib +tooldir = $(libdir) +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 + +SHELL = /bin/sh + +INSTALL = install -c +INSTALL_PROGRAM = $(INSTALL) +INSTALL_DATA = $(INSTALL) + +MAKEINFO = makeinfo +TEXI2DVI = texi2dvi + +# Where to find texinfo.tex to format documentation with TeX. +TEXIDIR = $(srcdir)/../texinfo + +#### Host, target, and site specific Makefile fragments come in here. +### + +INFOFILES = configure.info standards.info cfg-paper.info +DVIFILES = configure.dvi standards.dvi cfg-paper.dvi + +all: + +install: $(srcdir)/configure.man + $(INSTALL_DATA) $(srcdir)/configure.man $(man1dir)/configure.1 + +uninstall: + cd $(infodir) && rm -f configure.info* standards.info* cfg-paper.info* + +info: $(INFOFILES) + +install-info: info + if test ! -f configure.info ; then cd $(srcdir); fi; \ + for i in configure.info* standards.info* cfg-paper.info*; do \ + $(INSTALL_DATA) $$i $(infodir)/$$i; \ + done + +dvi: $(DVIFILES) + +configure.info: $(srcdir)/configure.texi + $(MAKEINFO) -o configure.info $(srcdir)/configure.texi + +configure.dvi: $(srcdir)/configure.texi + TEXINPUTS=$(TEXIDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/configure.texi + +standards.info: $(srcdir)/standards.texi + $(MAKEINFO) -I$(srcdir) -o standards.info $(srcdir)/standards.texi + +standards.dvi: $(srcdir)/standards.texi + TEXINPUTS=$(TEXIDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/standards.texi + +cfg-paper.info : $(srcdir)/cfg-paper.texi + $(MAKEINFO) -o cfg-paper.info $(srcdir)/cfg-paper.texi + +cfg-paper.dvi: $(srcdir)/cfg-paper.texi + TEXINPUTS=$(TEXIDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/cfg-paper.texi + + +clean: + rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log + rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs + +mostlyclean: clean + +distclean: clean + rm -f Makefile config.status + +maintainer-clean realclean: distclean + rm -f *.info* + +Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag) + $(SHELL) ./config.status + +## these last targets are for standards.texi conformance +dist: +check: +installcheck: +TAGS: diff --git a/gnu/usr.bin/binutils/etc/cfg-paper.info b/gnu/usr.bin/binutils/etc/cfg-paper.info new file mode 100644 index 00000000000..717ce559186 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/cfg-paper.info @@ -0,0 +1,659 @@ +This is Info file cfg-paper.info, produced by Makeinfo-1.55 from the +input file ./cfg-paper.texi. + + This document attempts to describe the general concepts behind +configuration of the GNU Development Tools. It also discusses common +usage. + + Copyright (C) 1991, 1992, 1994 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. + + 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 Cygnus Support. + +START-INFO-DIR-ENTRY +* configuration: (cfg-paper). Some theory on configuring source. +END-INFO-DIR-ENTRY + + +File: cfg-paper.info, Node: Top, Next: Some Basic Terms, Prev: (dir), Up: (dir) + + This document attempts to describe the general concepts behind +configuration of the GNU Development Tools. It also discusses common +usage. + +* Menu: + +* Some Basic Terms:: Some Basic Terms +* Specifics.:: Specifics +* Building Development Environments:: Building Development Environments +* A Walk Through:: A Walk Through +* Final Notes:: Final Notes +* Index:: Index + + -- The Detailed Node Listing -- + +Some Basic Terms + +* Host Environments:: Host Environments +* Configuration Time Options:: Configuration Time Options + +A Walk Through + +* Native Development Environments:: Native Development Environments +* Emulation Environments:: Emulation Environments +* Simple Cross Environments:: Simple Cross Environments +* Crossing Into Targets:: Crossing Into Targets +* Canadian Cross:: Canadian Cross + +Final Notes + +* Hacking Configurations:: Hacking Configurations + + +File: cfg-paper.info, Node: Some Basic Terms, Next: Specifics., Prev: Top, Up: Top + +Some Basic Terms +**************** + + There are a lot of terms that are frequently used when discussing +development tools. Most of the common terms have been used for many +different concepts such that their meanings have become ambiguous to the +point of being confusing. Typically, we only guess at their meanings +from context and we frequently guess wrong. + + This document uses very few terms by comparison. The intent is to +make the concepts as clear as possible in order to convey the usage and +intent of these tools. + + *Programs* run on *machines*. Programs are very nearly always +written in *source*. Programs are *built* from source. *Compilation* +is a process that is frequently, but not always, used when building +programs. + +* Menu: + +* Host Environments:: Host Environments +* Configuration Time Options:: Configuration Time Options + + +File: cfg-paper.info, Node: Host Environments, Next: Configuration Time Options, Prev: Some Basic Terms, Up: Some Basic Terms + +Host Environments +================= + + In this document, the word *host* refers to the environment in which +the source in question will be compiled. *host* and *host name* have +nothing to do with the proper name of your host, like *ucbvax*, +*prep.ai.mit.edu* or *att.com*. Instead they refer to things like +*sun4* and *dec3100*. + + Forget for a moment that this particular directory of source is the +source for a development environment. Instead, pretend that it is the +source for a simpler, more mundane, application, say, a desk calculator. + + Source that can be compiled in more than one environment, generally +needs to be set up for each environment explicitly. Here we refer to +that process as configuration. That is, we configure the source for a +host. + + For example, if we wanted to configure our mythical desk calculator +to compile on a SparcStation, we might configure for host sun4. With +our configuration system: + + cd desk-calculator ; ./configure sun4 + +does the trick. `configure' is a shell script that sets up Makefiles, +subdirectories, and symbolic links appropriate for compiling the source +on a sun4. + + The *host* environment does not necessarily refer to the machine on +which the tools are built. It is possible to provide a sun3 development +environment on a sun4. If we wanted to use a cross compiler on the sun4 +to build a program intended to be run on a sun3, we would configure the +source for sun3. + + cd desk-calculator ; ./configure sun3 + +The fact that we are actually building the program on a sun4 makes no +difference if the sun3 cross compiler presents an environment that looks +like a sun3 from the point of view of the desk calculator source code. +Specifically, the environment is a sun3 environment if the header files, +predefined symbols, and libraries appear as they do on a sun3. + + Nor does the host environment refer to the the machine on which the +program to be built will run. It is possible to provide a sun3 +emulation environment on a sun4 such that programs built in a sun3 +development environment actually run on the sun4. This technique is +often used within individual programs to remedy deficiencies in the host +operating system. For example, some operating systems do not provide +the `bcopy' function and so it is emulated using the `memcpy' funtion. + + Host environment simply refers to the environment in which the +program will be built from the source. + + +File: cfg-paper.info, Node: Configuration Time Options, Prev: Host Environments, Up: Some Basic Terms + +Configuration Time Options +========================== + + Many programs have compile time options. That is, features of the +program that are either compiled into the program or not based on a +choice made by the person who builds the program. We refer to these as +*configuration options*. For example, our desk calculator might be +capable of being compiled into a program that either uses infix notation +or postfix as a configuration option. For a sun3, to choose infix you +might use: + + ./configure sun3 --enable-notation=infix + +while for a sun4 with postfix you might use: + + ./configure sun4 --enable-notation=postfix + + If we wanted to build both at the same time, the intermediate pieces +used in the build process must be kept separate. + + mkdir ../objdir.sun4 + (cd ../objdir.sun4 ; ../configure sun4 --enable-notation=postfix --srcdir=../src) + mkdir ../objdir.sun3 + (cd ../objdir.sun3 ; ../configure sun3 --enable-notation=infix --srcdir=../src) + +will create subdirectories for the intermediate pieces of the sun4 and +sun3 configurations. This is necessary as previous systems were only +capable of one configuration at a time. Otherwise, a second +configuration would write over the first. We've chosen to retain this +behaviour so the obj directories and the `--srcdir' configuration +option are necessary to get the new behaviour. The order of the +arguments doesn't matter. There should be exactly one argument without +a leading `-' and that argument will be assumed to be the host name. + + From here on the examples will assume that you want to build the +tools *in place* and won't show the `--srcdir' option, but remember +that it is available. + + In order to actually install the program, the configuration system +needs to know where you would like the program installed. The default +location is `/usr/local'. We refer to this location as `$(prefix)'. +All user visible programs will be installed in ``$(prefix)'/bin'. All +other programs and files will be installed in a subdirectory of +``$(prefix)'/lib'. + + You can only change `$(prefix)' as a configuration time option. + + ./configure sun4 --enable-notation=postfix --prefix=/local + +Will configure the source such that: + + make install + +will put its programs in `/local/bin' and `/local/lib/gcc'. If you +change `$(prefix)' after building the source, you will need to: + + make clean + +before the change will be propogated properly. This is because some +tools need to know the locations of other tools. + + With these concepts in mind, we can drop the desk calculator example +and move on to the application that resides in these directories, +namely, the source to a development environment. + + +File: cfg-paper.info, Node: Specifics., Next: Building Development Environments, Prev: Some Basic Terms, Up: Top + +Specifics +********* + + The GNU Development Tools can be built on a wide variety of hosts. +So, of course, they must be configured. Like the last example, + + ./configure sun4 --prefix=/local + ./configure sun3 --prefix=/local + +will configure the source to be built in subdirectories, in order to +keep the intermediate pieces separate, and to be installed in `/local'. + + When built with suitable development environments, these will be +native tools. We'll explain the term *native* later. + + +File: cfg-paper.info, Node: Building Development Environments, Next: A Walk Through, Prev: Specifics., Up: Top + +Building Development Environments +********************************* + + The GNU development tools can not only be built in a number of host +development environments, they can also be configured to create a +number of different development environments on each of those hosts. +We refer to a specific development environment created as a *target*. +That is, the word *target* refers to the development environment +produced by compiling this source and installing the resulting programs. + + For the GNU development tools, the default target is the same as the +host. That is, the development environment produced is intended to be +compatible with the environment used to build the tools. + + In the example above, we created two configurations, one for sun4 and +one for sun3. The first configuration is expecting to be built in a +sun4 development environment, to create a sun4 development environment. +It doesn't necessarily need to be built on a sun4 if a sun4 development +environment is available elsewhere. Likewise, if the available sun4 +development environment produces executables intended for something +other than sun4, then the development environment built from this sun4 +configuration will run on something other than a sun4. From the point +of view of the configuration system and the GNU development tools +source, this doesn't matter. What matters is that they will be built in +a sun4 environment. + + Similarly, the second configuration given above is expecting to be +built in a sun3 development environment, to create a sun3 development +environment. + + The development environment produced is a configuration time option, +just like `$(prefix)'. + + ./configure sun4 --prefix=/local --target=sun3 + ./configure sun3 --prefix=/local --target=sun4 + + In this example, like before, we create two configurations. The +first is intended to be built in a sun4 environment, in subdirectories, +to be installed in `/local'. The second is intended to be built in a +sun3 environment, in subdirectories, to be installed in `/local'. + + Unlike the previous example, the first configuration will produce a +sun3 development environment, perhaps even suitable for building the +second configuration. Likewise, the second configuration will produce +a sun4 development environment, perhaps even suitable for building the +first configuration. + + The development environment used to build these configurations will +determine the machines on which the resulting development environments +can be used. + + +File: cfg-paper.info, Node: A Walk Through, Next: Final Notes, Prev: Building Development Environments, Up: Top + +A Walk Through +************** + +* Menu: + +* Native Development Environments:: Native Development Environments +* Emulation Environments:: Emulation Environments +* Simple Cross Environments:: Simple Cross Environments +* Crossing Into Targets:: Crossing Into Targets +* Canadian Cross:: Canadian Cross + + +File: cfg-paper.info, Node: Native Development Environments, Next: Emulation Environments, Prev: A Walk Through, Up: A Walk Through + +Native Development Environments +=============================== + + Let us assume for a moment that you have a sun4 and that with your +sun4 you received a development environment. This development +environment is intended to be run on your sun4 to build programs that +can be run on your sun4. You could, for instance, run this development +environment on your sun4 to build our example desk calculator program. +You could then run the desk calculator program on your sun4. + + The resulting desk calculator program is referred to as a *native* +program. The development environment itself is composed of native +programs that, when run, build other native programs. Any other program +is referred to as *foreign*. Programs intended for other machines are +foreign programs. + + This type of development environment, which is by far the most +common, is refered to as *native*. That is, a native development +environment runs on some machine to build programs for that same +machine. The process of using a native development environment to +build native programs is called a *native* build. + + ./configure sun4 + +will configure this source such that when built in a sun4 development +environment, with a development environment that builds programs +intended to be run on sun4 machines, the programs built will be native +programs and the resulting development environment will be a native +development environment. + + The development system that came with your sun4 is one such +environment. Using it to build the GNU Development Tools is a very +common activity and the resulting development environment is quite +popular. + + make all + +will build the tools as configured and will assume that you want to use +the native development environment that came with your machine. + + Using a development environment to build a development environment is +called *bootstrapping*. The release of the GNU Development Tools is +capable of bootstrapping itself. This is a very powerful feature that +we'll return to later. For now, let's pretend that you used the native +development environment that came with your sun4 to bootstrap the +release and let's call the new development environment *stage1*. + + Why bother? Well, most people find that the GNU development +environment builds programs that run faster and take up less space than +the native development environments that came with their machines. Some +people didn't get development environments with their machines and some +people just like using the GNU tools better than using other tools. + + While you're at it, if the GNU tools produce better programs, maybe +you should use them to build the GNU tools. So let's pretend that you +do. Let's call the new development environment *stage2*. + + So far you've built a development environment, stage1, and you've +used stage1 to build a new, faster and smaller development environment, +stage2, but you haven't run any of the programs that the GNU tools have +built. You really don't yet know if these tools work. Do you have any +programs built with the GNU tools? Yes, you do. stage2. What does +that program do? It builds programs. Ok, do you have any source handy +to build into a program? Yes, you do. The GNU tools themselves. In +fact, if you use stage2 to build the GNU tools again the resulting +programs should be identical to stage2. Let's pretend that you do and +call the new development environment *stage3*. + + You've just completed what's called a *three stage boot*. You now +have a small, fast, somewhat tested, development environment. + + make bootstrap + +will do a three stage boot across all tools and will compare stage2 to +stage3 and complain if they are not identical. + + Once built, + + make install + +will install the development environment in the default location, or in +`$(prefix)' if you specified an alternate when you configured. + + Any development environment that is not a native development +environment is refered to as a *cross* development environment. There +are many different types of cross development environments but most +fall into one of three basic categories. + + +File: cfg-paper.info, Node: Emulation Environments, Next: Simple Cross Environments, Prev: Native Development Environments, Up: A Walk Through + +Emulation Environments +====================== + + The first category of cross development environment is called +*emulation*. There are two primary types of emulation, but both types +result in programs that run on the native host. + + The first type is *software emulation*. This form of cross +development environment involves a native program that when run on the +native host, is capable of interpreting, and in most aspects running, a +program intended for some other machine. This technique is typically +used when the other machine is either too expensive, too slow, too fast, +or not available, perhaps because it hasn't yet been built. The native, +interpreting program is called a *software emulator*. + + The GNU Development Tools do not currently include any software +emulators. Some do exist and the GNU Development Tools can be +configured to create simple cross development environments for with +these emulators. More on this later. + + The second type of emulation is when source intended for some other +development environment is built into a program intended for the native +host. The concepts of operating system universes and hosted operating +systems are two such development environments. + + +File: cfg-paper.info, Node: Simple Cross Environments, Next: Crossing Into Targets, Prev: Emulation Environments, Up: A Walk Through + +Simple Cross Environments +========================= + + ./configure sun4 --target=a29k + +will configure the tools such that when compiled in a sun4 development +environment the resulting development environment can be used to create +programs intended for an a29k. Again, this does not necessarily mean +that the new development environment can be run on a sun4. That would +depend on the development environment used to build these tools. + + Earlier you saw how to configure the tools to build a native +development environment, that is, a development environment that runs +on your sun4 and builds programs for your sun4. Let's pretend that you +use stage3 to build this simple cross configuration and let's call the +new development environment gcc-a29k. Remember that this is a native +build. Gcc-a29k is a collection of native programs intended to run on +your sun4. That's what stage3 builds, programs for your sun4. +Gcc-a29k represents an a29k development environment that builds +programs intended to run on an a29k. But, remember, gcc-a29k runs on +your sun4. Programs built with gcc-a29k will run on your sun4 only +with the help of an appropriate software emulator. + + Building gcc-a29k is also a bootstrap but of a slightly different +sort. We call gcc-a29k a *simple cross* environment and using gcc-a29k +to build a program intended for a29k is called *crossing to* a29k. +Simple cross environments are the second category of cross development +environments. + + +File: cfg-paper.info, Node: Crossing Into Targets, Next: Canadian Cross, Prev: Simple Cross Environments, Up: A Walk Through + +Crossing Into Targets +===================== + + ./configure a29k --target=a29k + +will configure the tools such that when compiled in an a29k development +environment, the resulting development environment can be used to create +programs intended for an a29k. Again, this does not necessarily mean +that the new development environment can be run on an a29k. That would +depend on the development environment used to build these tools. + + If you've been following along this walk through, then you've already +built an a29k environment, namely gcc-a29k. Let's pretend you use +gcc-a29k to build the current configuration. + + Gcc-a29k builds programs intended for the a29k so the new development +environment will be intended for use on an a29k. That is, this new gcc +consists of programs that are foreign to your sun4. They cannot be run +on your sun4. + + The process of building this configuration is a another bootstrap. +This bootstrap is also a cross to a29k. Because this type of build is +both a bootstrap and a cross to a29k, it is sometimes referred to as a +*cross into* a29k. This new development environment isn't really a +cross development environment at all. It is intended to run on an a29k +to produce programs for an a29k. You'll remember that this makes it, by +definition, an a29k native compiler. *Crossing into* has been +introduced here not because it is a type of cross development +environment, but because it is frequently mistaken as one. The process +is *a cross* but the resulting development environment is a native +development environment. + + You could not have built this configuration with stage3, because +stage3 doesn't provide an a29k environment. Instead it provides a sun4 +environment. + + If you happen to have an a29k lying around, you could now use this +fresh development environment on the a29k to three-stage these tools +all over again. This process would look just like it did when we built +the native sun4 development environment because we would be building +another native development environment, this one on a29k. + + +File: cfg-paper.info, Node: Canadian Cross, Prev: Crossing Into Targets, Up: A Walk Through + +Canadian Cross +============== + + So far you've seen that our development environment source must be +configured for a specific host and for a specific target. You've also +seen that the resulting development environment depends on the +development environment used in the build process. + + When all four match identically, that is, the configured host, the +configured target, the environment presented by the development +environment used in the build, and the machine on which the resulting +development environment is intended to run, then the new development +environment will be a native development environment. + + When all four match except the configured host, then we can assume +that the development environment used in the build is some form of +library emulation. + + When all four match except for the configured target, then the +resulting development environment will be a simple cross development +environment. + + When all four match except for the host on which the development +environment used in the build runs, the build process is a *cross into* +and the resulting development environment will be native to some other +machine. + + Most of the other permutations do exist in some form, but only one +more is interesting to the current discussion. + + ./configure a29k --target=sun3 + +will configure the tools such that when compiled in an a29k development +environment, the resulting development environment can be used to create +programs intended for a sun3. Again, this does not necessarily mean +that the new development environment can be run on an a29k. That would +depend on the development environment used to build these tools. + + If you are still following along, then you have two a29k development +environments, the native development environment that runs on a29k, and +the simple cross that runs on your sun4. If you use the a29k native +development environment on the a29k, you will be doing the same thing we +did a while back, namely building a simple cross from a29k to sun3. +Let's pretend that instead, you use gcc-a29k, the simple cross +development environment that runs on sun4 but produces programs for +a29k. + + The resulting development environment will run on a29k because that's +what gcc-a29k builds, a29k programs. This development environment will +produce programs for a sun3 because that is how it was configured. This +means that the resulting development environment is a simple cross. + + There really isn't a common name for this process because very few +development environments are capable of being configured this +extensively. For the sake of discussion, let's call this process a +*Canadian cross*. It's a three party cross, Canada has a three party +system, hence Canadian Cross. + + +File: cfg-paper.info, Node: Final Notes, Next: Index, Prev: A Walk Through, Up: Top + +Final Notes +*********** + + By *configures*, I mean that links, Makefile, .gdbinit, and +config.status are built. Configuration is always done from the source +directory. + +`./configure NAME' + configures this directory, perhaps recursively, for a single + host+target pair where the host and target are both NAME. If a + previous configuration existed, it will be overwritten. + +`./configure HOSTNAME --target=TARGETNAME' + configures this directory, perhaps recursively, for a single + host+target pair where the host is HOSTNAME and target is + TARGETNAME. If a previous configuration existed, it will be + overwritten. + +* Menu: + +* Hacking Configurations:: Hacking Configurations + + +File: cfg-paper.info, Node: Hacking Configurations, Prev: Final Notes, Up: Final Notes + +Hacking Configurations +====================== + + The configure scripts essentially do three things, create +subdirectories if appropriate, build a `Makefile', and create links to +files, all based on and tailored to, a specific host+target pair. The +scripts also create a `.gdbinit' if appropriate but this is not +tailored. + + The Makefile is created by prepending some variable definitions to a +Makefile template called `Makefile.in' and then inserting host and +target specific Makefile fragments. The variables are set based on the +chosen host+target pair and build style, that is, if you use `--srcdir' +or not. The host and target specific Makefile may or may not exist. + + * Makefiles can be edited directly, but those changes will + eventually be lost. Changes intended to be permanent for a + specific host should be made to the host specific Makefile + fragment. This should be in `./config/mh-HOST' if it exists. + Changes intended to be permanent for a specific target should be + made to the target specific Makefile fragment. This should be in + `./config/mt-TARGET' if it exists. Changes intended to be + permanent for the directory should be made in `Makefile.in'. To + propogate changes to any of these, either use `make Makefile' or + `./config.status' or re-configure. + + +File: cfg-paper.info, Node: Index, Prev: Final Notes, Up: Top + +Index +***** + +* Menu: + +* Bootstrapping: Native Development Environments. +* Building: Some Basic Terms. +* Canadian Cross: Canadian Cross. +* Compilation: Some Basic Terms. +* Cross: Native Development Environments. +* Crossing into: Crossing Into Targets. +* Crossing to: Simple Cross Environments. +* Emulation: Emulation Environments. +* Foreign: Native Development Environments. +* host: Host Environments. +* Machines: Some Basic Terms. +* Native: Native Development Environments. +* Programs: Some Basic Terms. +* Simple cross: Simple Cross Environments. +* Software emulation: Emulation Environments. +* Software emulator: Emulation Environments. +* Source: Some Basic Terms. +* Stage1: Native Development Environments. +* Stage2: Native Development Environments. +* Stage3: Native Development Environments. +* Target: Building Development Environments. +* Three party cross: Canadian Cross. +* Three stage boot: Native Development Environments. + + + +Tag Table: +Node: Top1055 +Node: Some Basic Terms2009 +Node: Host Environments2951 +Node: Configuration Time Options5513 +Node: Specifics.8316 +Node: Building Development Environments8934 +Node: A Walk Through11554 +Node: Native Development Environments11972 +Node: Emulation Environments16221 +Node: Simple Cross Environments17579 +Node: Crossing Into Targets19188 +Node: Canadian Cross21381 +Node: Final Notes24208 +Node: Hacking Configurations25003 +Node: Index26418 + +End Tag Table diff --git a/gnu/usr.bin/binutils/etc/cfg-paper.texi b/gnu/usr.bin/binutils/etc/cfg-paper.texi new file mode 100644 index 00000000000..bcfbb31e13f --- /dev/null +++ b/gnu/usr.bin/binutils/etc/cfg-paper.texi @@ -0,0 +1,717 @@ +\input texinfo +@c %**start of header +@setfilename cfg-paper.info +@settitle On Configuring Development Tools +@c %**end of header +@setchapternewpage off + +@ifinfo +This document attempts to describe the general concepts behind +configuration of the @sc{gnu} Development Tools. +It also discusses common usage. + +Copyright (C) 1991, 1992, 1994 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 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 Cygnus Support. +@end ifinfo + +@titlepage +@sp 10 +@title{On Configuring Development Tools} +@author{K. Richard Pixley, @code{rich@@cygnus.com}} +@author{Cygnus Support} +@page + +@vskip 0pt plus 1filll +Copyright @copyright{} 1991, 1992, 1994 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. + +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 Cygnus Support. +@end titlepage + +@ifinfo +@format +START-INFO-DIR-ENTRY +* configuration: (cfg-paper). Some theory on configuring source. +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@node top, Some Basic Terms, (dir), (dir) + +@ifinfo +This document attempts to describe the general concepts behind +configuration of the @sc{gnu} Development Tools. +It also discusses common usage. +@end ifinfo + +@menu +* Some Basic Terms:: Some Basic Terms +* Specifics.:: Specifics +* Building Development Environments:: Building Development Environments +* A Walk Through:: A Walk Through +* Final Notes:: Final Notes +* Index:: Index + + --- The Detailed Node Listing --- + +Some Basic Terms + +* Host Environments:: Host Environments +* Configuration Time Options:: Configuration Time Options + +A Walk Through + +* Native Development Environments:: Native Development Environments +* Emulation Environments:: Emulation Environments +* Simple Cross Environments:: Simple Cross Environments +* Crossing Into Targets:: Crossing Into Targets +* Canadian Cross:: Canadian Cross + +Final Notes + +* Hacking Configurations:: Hacking Configurations +@end menu + +@node Some Basic Terms, Specifics., top, top +@chapter Some Basic Terms + +There are a lot of terms that are frequently used when discussing +development tools. Most of the common terms have been used for many +different concepts such that their meanings have become ambiguous to the +point of being confusing. Typically, we only guess at their meanings +from context and we frequently guess wrong. + +This document uses very few terms by comparison. The intent is to make +the concepts as clear as possible in order to convey the usage and +intent of these tools. + +@emph{Programs} run on @emph{machines}. Programs are very nearly always +written in @emph{source}. Programs are @emph{built} from source. +@emph{Compilation} is a process that is frequently, but not always, used +when building programs. +@cindex Programs +@cindex Machines +@cindex Source +@cindex Building +@cindex Compilation + +@menu +* Host Environments:: Host Environments +* Configuration Time Options:: Configuration Time Options +@end menu + +@node Host Environments, Configuration Time Options, Some Basic Terms, Some Basic Terms +@section Host Environments + +@cindex host +In this document, the word @emph{host} refers to the environment in +which the source in question will be compiled. @emph{host} and +@emph{host name} have nothing to do with the proper name of your host, +like @emph{ucbvax}, @emph{prep.ai.mit.edu} or @emph{att.com}. Instead +they refer to things like @emph{sun4} and @emph{dec3100}. + +Forget for a moment that this particular directory of source is the +source for a development environment. Instead, pretend that it is the +source for a simpler, more mundane, application, say, a desk calculator. + +Source that can be compiled in more than one environment, generally +needs to be set up for each environment explicitly. Here we refer to +that process as configuration. That is, we configure the source for a +host. + +For example, if we wanted to configure our mythical desk calculator to +compile on a SparcStation, we might configure for host sun4. With our +configuration system: + +@example +cd desk-calculator ; ./configure sun4 +@end example + +@noindent +does the trick. @code{configure} is a shell script that sets up Makefiles, +subdirectories, and symbolic links appropriate for compiling the source +on a sun4. + +The @emph{host} environment does not necessarily refer to the machine on +which the tools are built. It is possible to provide a sun3 development +environment on a sun4. If we wanted to use a cross compiler on the sun4 +to build a program intended to be run on a sun3, we would configure the +source for sun3. + +@example +cd desk-calculator ; ./configure sun3 +@end example + +@noindent +The fact that we are actually building the program on a sun4 makes no +difference if the sun3 cross compiler presents an environment that looks +like a sun3 from the point of view of the desk calculator source code. +Specifically, the environment is a sun3 environment if the header files, +predefined symbols, and libraries appear as they do on a sun3. + +Nor does the host environment refer to the the machine on which the +program to be built will run. It is possible to provide a sun3 +emulation environment on a sun4 such that programs built in a sun3 +development environment actually run on the sun4. This technique is +often used within individual programs to remedy deficiencies in the host +operating system. For example, some operating systems do not provide +the @code{bcopy} function and so it is emulated using the +@code{memcpy} funtion. + +Host environment simply refers to the environment in which the program +will be built from the source. + + +@node Configuration Time Options, , Host Environments, Some Basic Terms +@section Configuration Time Options + +Many programs have compile time options. That is, features of the +program that are either compiled into the program or not based on a +choice made by the person who builds the program. We refer to these as +@emph{configuration options}. For example, our desk calculator might be +capable of being compiled into a program that either uses infix notation +or postfix as a configuration option. For a sun3, to choose infix you +might use: + +@example +./configure sun3 --enable-notation=infix +@end example + +@noindent +while for a sun4 with postfix you might use: + +@example +./configure sun4 --enable-notation=postfix +@end example + +If we wanted to build both at the same time, the intermediate pieces +used in the build process must be kept separate. + +@example +mkdir ../objdir.sun4 +(cd ../objdir.sun4 ; ../configure sun4 --enable-notation=postfix --srcdir=../src) +mkdir ../objdir.sun3 +(cd ../objdir.sun3 ; ../configure sun3 --enable-notation=infix --srcdir=../src) +@end example + +@noindent +will create subdirectories for the intermediate pieces of the sun4 and +sun3 configurations. This is necessary as previous systems were only +capable of one configuration at a time. Otherwise, a second +configuration would write over the first. We've chosen to retain this +behaviour so the obj directories and the @code{--srcdir} configuration +option are necessary to get the new behaviour. The order of the +arguments doesn't matter. There should be exactly one argument without +a leading @samp{-} and that argument will be assumed to be the host +name. + +From here on the examples will assume that you want to build the tools +@emph{in place} and won't show the @code{--srcdir} option, but remember +that it is available. + +In order to actually install the program, the configuration system needs +to know where you would like the program installed. The default +location is @file{/usr/local}. We refer to this location as +@code{$(prefix)}. All user visible programs will be installed in +@file{@code{$(prefix)}/bin}. All other programs and files will be +installed in a subdirectory of @file{@code{$(prefix)}/lib}. + +You can only change @code{$(prefix)} as a configuration time +option. + +@example +./configure sun4 --enable-notation=postfix --prefix=/local +@end example + +@noindent +Will configure the source such that: + +@example +make install +@end example + +@noindent +will put its programs in @file{/local/bin} and @file{/local/lib/gcc}. +If you change @code{$(prefix)} after building the source, you will need +to: + +@example +make clean +@end example + +@noindent +before the change will be propogated properly. This is because some +tools need to know the locations of other tools. + +With these concepts in mind, we can drop the desk calculator example and +move on to the application that resides in these directories, namely, +the source to a development environment. + +@node Specifics., Building Development Environments, Some Basic Terms, top +@chapter Specifics + +The @sc{gnu} Development Tools can be built on a wide variety of hosts. So, +of course, they must be configured. Like the last example, + +@example +./configure sun4 --prefix=/local +./configure sun3 --prefix=/local +@end example + +@noindent +will configure the source to be built in subdirectories, in order to +keep the intermediate pieces separate, and to be installed in +@file{/local}. + +When built with suitable development environments, these will be native +tools. We'll explain the term @emph{native} later. + +@node Building Development Environments, A Walk Through, Specifics., top +@chapter Building Development Environments + +@cindex Target + +The @sc{gnu} development tools can not only be built in a +number of host development environments, they can also be configured to +create a number of different development environments on each of those +hosts. We refer to a specific development environment created as a +@emph{target}. That is, the word @emph{target} refers to the development +environment produced by compiling this source and installing the +resulting programs. + +For the @sc{gnu} development tools, the default target is the +same as the host. That is, the development environment produced is +intended to be compatible with the environment used to build the tools. + +In the example above, we created two configurations, one for sun4 and +one for sun3. The first configuration is expecting to be built in a +sun4 development environment, to create a sun4 development environment. +It doesn't necessarily need to be built on a sun4 if a sun4 development +environment is available elsewhere. Likewise, if the available sun4 +development environment produces executables intended for something +other than sun4, then the development environment built from this sun4 +configuration will run on something other than a sun4. From the point +of view of the configuration system and the @sc{gnu} development tools +source, this doesn't matter. What matters is that they will be built in +a sun4 environment. + +Similarly, the second configuration given above is expecting to be built +in a sun3 development environment, to create a sun3 development +environment. + +The development environment produced is a configuration time option, +just like @code{$(prefix)}. + +@example +./configure sun4 --prefix=/local --target=sun3 +./configure sun3 --prefix=/local --target=sun4 +@end example + +In this example, like before, we create two configurations. The first +is intended to be built in a sun4 environment, in subdirectories, to be +installed in @file{/local}. The second is intended to be built in a +sun3 environment, in subdirectories, to be installed in @file{/local}. + +Unlike the previous example, the first configuration will produce a sun3 +development environment, perhaps even suitable for building the second +configuration. Likewise, the second configuration will produce a sun4 +development environment, perhaps even suitable for building the first +configuration. + +The development environment used to build these configurations will +determine the machines on which the resulting development environments +can be used. + + +@node A Walk Through, Final Notes, Building Development Environments, top +@chapter A Walk Through + + +@menu +* Native Development Environments:: Native Development Environments +* Emulation Environments:: Emulation Environments +* Simple Cross Environments:: Simple Cross Environments +* Crossing Into Targets:: Crossing Into Targets +* Canadian Cross:: Canadian Cross +@end menu + +@node Native Development Environments, Emulation Environments, A Walk Through, A Walk Through +@section Native Development Environments + +Let us assume for a moment that you have a sun4 and that with your sun4 +you received a development environment. This development environment is +intended to be run on your sun4 to build programs that can be run on +your sun4. You could, for instance, run this development environment on +your sun4 to build our example desk calculator program. You could then +run the desk calculator program on your sun4. + +@cindex Native +@cindex Foreign +The resulting desk calculator program is referred to as a @emph{native} +program. The development environment itself is composed of native +programs that, when run, build other native programs. Any other program +is referred to as @emph{foreign}. Programs intended for other machines are +foreign programs. + +This type of development environment, which is by far the most common, +is refered to as @emph{native}. That is, a native development environment +runs on some machine to build programs for that same machine. The +process of using a native development environment to build native +programs is called a @emph{native} build. + +@example +./configure sun4 +@end example + +@noindent +will configure this source such that when built in a sun4 development +environment, with a development environment that builds programs +intended to be run on sun4 machines, the programs built will be native +programs and the resulting development environment will be a native +development environment. + +The development system that came with your sun4 is one such environment. +Using it to build the @sc{gnu} Development Tools is a very common activity +and the resulting development environment is quite popular. + +@example +make all +@end example + +@noindent +will build the tools as configured and will assume that you want to use +the native development environment that came with your machine. + +@cindex Bootstrapping +@cindex Stage1 +Using a development environment to build a development environment is +called @emph{bootstrapping}. The release of the @sc{gnu} +Development Tools is capable of bootstrapping itself. This is a very +powerful feature that we'll return to later. For now, let's pretend +that you used the native development environment that came with your +sun4 to bootstrap the release and let's call the new +development environment @emph{stage1}. + +Why bother? Well, most people find that the @sc{gnu} development +environment builds programs that run faster and take up less space than +the native development environments that came with their machines. Some +people didn't get development environments with their machines and some +people just like using the @sc{gnu} tools better than using other tools. + +@cindex Stage2 +While you're at it, if the @sc{gnu} tools produce better programs, maybe you +should use them to build the @sc{gnu} tools. So let's +pretend that you do. Let's call the new development environment +@emph{stage2}. + +@cindex Stage3 +So far you've built a development environment, stage1, and you've used +stage1 to build a new, faster and smaller development environment, +stage2, but you haven't run any of the programs that the @sc{gnu} tools have +built. You really don't yet know if these tools work. Do you have any +programs built with the @sc{gnu} tools? Yes, you do. stage2. What does +that program do? It builds programs. Ok, do you have any source handy +to build into a program? Yes, you do. The @sc{gnu} tools themselves. In +fact, if you use stage2 to build the @sc{gnu} tools again the resulting +programs should be identical to stage2. Let's pretend that you do and +call the new development environment @emph{stage3}. + +@cindex Three stage boot +You've just completed what's called a @emph{three stage boot}. You now have +a small, fast, somewhat tested, development environment. + +@example +make bootstrap +@end example + +@noindent +will do a three stage boot across all tools and will compare stage2 to +stage3 and complain if they are not identical. + +Once built, + +@example +make install +@end example + +@noindent +will install the development environment in the default location, or in +@code{$(prefix)} if you specified an alternate when you configured. + +@cindex Cross +Any development environment that is not a native development environment +is refered to as a @emph{cross} development environment. There are many +different types of cross development environments but most fall into one +of three basic categories. + + +@node Emulation Environments, Simple Cross Environments, Native Development Environments, A Walk Through +@section Emulation Environments + +@cindex Emulation +The first category of cross development environment is called +@emph{emulation}. There are two primary types of emulation, but both +types result in programs that run on the native host. + +@cindex Software emulation +@cindex Software emulator +The first type is @emph{software emulation}. This form of cross +development environment involves a native program that when run on the +native host, is capable of interpreting, and in most aspects running, a +program intended for some other machine. This technique is typically +used when the other machine is either too expensive, too slow, too fast, +or not available, perhaps because it hasn't yet been built. The native, +interpreting program is called a @emph{software emulator}. + +The @sc{gnu} Development Tools do not currently include any software +emulators. Some do exist and the @sc{gnu} Development Tools can be +configured to create simple cross development environments for with +these emulators. More on this later. + +The second type of emulation is when source intended for some other +development environment is built into a program intended for the native +host. The concepts of operating system universes and hosted operating +systems are two such development environments. + +@node Simple Cross Environments, Crossing Into Targets, Emulation Environments, A Walk Through +@section Simple Cross Environments + +@example +./configure sun4 --target=a29k +@end example + +@noindent +will configure the tools such that when compiled in a sun4 development +environment the resulting development environment can be used to create +programs intended for an a29k. Again, this does not necessarily mean +that the new development environment can be run on a sun4. That would +depend on the development environment used to build these tools. + +Earlier you saw how to configure the tools to build a native development +environment, that is, a development environment that runs on your sun4 +and builds programs for your sun4. Let's pretend that you use stage3 to +build this simple cross configuration and let's call the new development +environment gcc-a29k. Remember that this is a native build. Gcc-a29k +is a collection of native programs intended to run on your sun4. That's +what stage3 builds, programs for your sun4. Gcc-a29k represents an a29k +development environment that builds programs intended to run on an a29k. +But, remember, gcc-a29k runs on your sun4. Programs built with gcc-a29k +will run on your sun4 only with the help of an appropriate software +emulator. + +@cindex Simple cross +@cindex Crossing to +Building gcc-a29k is also a bootstrap but of a slightly different sort. +We call gcc-a29k a @emph{simple cross} environment and using gcc-a29k to +build a program intended for a29k is called @emph{crossing to} a29k. +Simple cross environments are the second category of cross development +environments. + + +@node Crossing Into Targets, Canadian Cross, Simple Cross Environments, A Walk Through +@section Crossing Into Targets + +@example +./configure a29k --target=a29k +@end example + +@noindent +will configure the tools such that when compiled in an a29k development +environment, the resulting development environment can be used to create +programs intended for an a29k. Again, this does not necessarily mean +that the new development environment can be run on an a29k. That would +depend on the development environment used to build these tools. + +If you've been following along this walk through, then you've already +built an a29k environment, namely gcc-a29k. Let's pretend you use +gcc-a29k to build the current configuration. + +Gcc-a29k builds programs intended for the a29k so the new development +environment will be intended for use on an a29k. That is, this new gcc +consists of programs that are foreign to your sun4. They cannot be run +on your sun4. + +@cindex Crossing into +The process of building this configuration is a another bootstrap. This +bootstrap is also a cross to a29k. Because this type of build is both a +bootstrap and a cross to a29k, it is sometimes referred to as a +@emph{cross into} a29k. This new development environment isn't really a +cross development environment at all. It is intended to run on an a29k +to produce programs for an a29k. You'll remember that this makes it, by +definition, an a29k native compiler. @emph{Crossing into} has been +introduced here not because it is a type of cross development +environment, but because it is frequently mistaken as one. The process +is @emph{a cross} but the resulting development environment is a native +development environment. + +You could not have built this configuration with stage3, because stage3 +doesn't provide an a29k environment. Instead it provides a sun4 +environment. + +If you happen to have an a29k lying around, you could now use this fresh +development environment on the a29k to three-stage these tools all over +again. This process would look just like it did when we built the +native sun4 development environment because we would be building another +native development environment, this one on a29k. + + +@node Canadian Cross, , Crossing Into Targets, A Walk Through +@section Canadian Cross + +So far you've seen that our development environment source must be +configured for a specific host and for a specific target. You've also +seen that the resulting development environment depends on the +development environment used in the build process. + +When all four match identically, that is, the configured host, the +configured target, the environment presented by the development +environment used in the build, and the machine on which the resulting +development environment is intended to run, then the new development +environment will be a native development environment. + +When all four match except the configured host, then we can assume that +the development environment used in the build is some form of library +emulation. + +When all four match except for the configured target, then the resulting +development environment will be a simple cross development environment. + +When all four match except for the host on which the development +environment used in the build runs, the build process is a @emph{cross into} +and the resulting development environment will be native to some other +machine. + +Most of the other permutations do exist in some form, but only one more +is interesting to the current discussion. + +@example +./configure a29k --target=sun3 +@end example + +@noindent +will configure the tools such that when compiled in an a29k development +environment, the resulting development environment can be used to create +programs intended for a sun3. Again, this does not necessarily mean +that the new development environment can be run on an a29k. That would +depend on the development environment used to build these tools. + +If you are still following along, then you have two a29k development +environments, the native development environment that runs on a29k, and +the simple cross that runs on your sun4. If you use the a29k native +development environment on the a29k, you will be doing the same thing we +did a while back, namely building a simple cross from a29k to sun3. +Let's pretend that instead, you use gcc-a29k, the simple cross +development environment that runs on sun4 but produces programs for +a29k. + +The resulting development environment will run on a29k because that's +what gcc-a29k builds, a29k programs. This development environment will +produce programs for a sun3 because that is how it was configured. This +means that the resulting development environment is a simple cross. + +@cindex Canadian Cross +@cindex Three party cross +There really isn't a common name for this process because very few +development environments are capable of being configured this +extensively. For the sake of discussion, let's call this process a +@emph{Canadian cross}. It's a three party cross, Canada has a three +party system, hence Canadian Cross. + +@node Final Notes, Index, A Walk Through, top +@chapter Final Notes + +By @emph{configures}, I mean that links, Makefile, .gdbinit, and +config.status are built. Configuration is always done from the source +directory. + +@table @code + +@item ./configure @var{name} +configures this directory, perhaps recursively, for a single host+target +pair where the host and target are both @var{name}. If a previous +configuration existed, it will be overwritten. + +@item ./configure @var{hostname} --target=@var{targetname} +configures this directory, perhaps recursively, for a single host+target +pair where the host is @var{hostname} and target is @var{targetname}. +If a previous configuration existed, it will be overwritten. + +@end table + +@menu +* Hacking Configurations:: Hacking Configurations +@end menu + +@node Hacking Configurations, , Final Notes, Final Notes +@section Hacking Configurations + +The configure scripts essentially do three things, create subdirectories +if appropriate, build a @file{Makefile}, and create links to files, all +based on and tailored to, a specific host+target pair. The scripts also +create a @file{.gdbinit} if appropriate but this is not tailored. + +The Makefile is created by prepending some variable definitions to a +Makefile template called @file{Makefile.in} and then inserting host and +target specific Makefile fragments. The variables are set based on the +chosen host+target pair and build style, that is, if you use +@code{--srcdir} or not. The host and target specific Makefile may or may +not exist. + +@itemize @bullet + +@item +Makefiles can be edited directly, but those changes will eventually be +lost. Changes intended to be permanent for a specific host should be +made to the host specific Makefile fragment. This should be in +@file{./config/mh-@var{host}} if it exists. Changes intended to be +permanent for a specific target should be made to the target specific +Makefile fragment. This should be in @file{./config/mt-@var{target}} if +it exists. Changes intended to be permanent for the directory should be +made in @file{Makefile.in}. To propogate changes to any of these, +either use @code{make Makefile} or @code{./config.status} or +re-configure. + +@end itemize + +@page +@node Index, , Final Notes, top +@appendix Index + +@printindex cp + +@contents +@bye + +@c Local Variables: +@c fill-column: 72 +@c End: diff --git a/gnu/usr.bin/binutils/etc/configure.in b/gnu/usr.bin/binutils/etc/configure.in new file mode 100644 index 00000000000..c94a6237ba8 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/configure.in @@ -0,0 +1,17 @@ +# This file is a shell script fragment that supplies the information +# necessary to tailor a template configure script into the configure +# script appropriate for this directory. For more information, check +# any existing configure script. + +srctrigger=configure.texi +srcname="general documentation" + +# per-host: + +# per-target: + +# +# Local Variables: +# fill-column: 131 +# End: +# diff --git a/gnu/usr.bin/binutils/etc/configure.info b/gnu/usr.bin/binutils/etc/configure.info new file mode 100644 index 00000000000..b1a3f01b5a8 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/configure.info @@ -0,0 +1,64 @@ +This is Info file configure.info, produced by Makeinfo-1.55 from the +input file ./configure.texi. + +START-INFO-DIR-ENTRY +* configure: (configure). Cygnus configure. +END-INFO-DIR-ENTRY + + This document describes the Cygnus Support version of `configure'. + + Copyright (C) 1991, 1992, 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. + + 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 Cygnus Support. + + +Indirect: +configure.info-1: 968 +configure.info-2: 50440 + +Tag Table: +(Indirect) +Node: Top968 +Node: What configure does1463 +Node: Invoking configure4783 +Node: Using configure11838 +Node: What configure really does13103 +Node: Build variables18380 +Node: Build directories20582 +Node: Makefile generation23984 +Node: config.guess25515 +Node: config.status26405 +Node: configure.in26962 +Node: configure variables28632 +Node: Minimal36798 +Node: Declarations37608 +Node: per-host38082 +Node: per-target38819 +Node: post-target39642 +Node: Example40225 +Node: Install locations40932 +Node: prefix41733 +Node: exec_prefix42626 +Node: Install details44431 +Node: Host49368 +Node: Target50004 +Node: Makefile fragments50440 +Node: Makefile extensions52056 +Node: Porting55783 +Node: Programs56235 +Node: Hosts and targets61089 +Node: Sites62752 +Node: Variables Index63452 +Node: Concept Index66624 + +End Tag Table diff --git a/gnu/usr.bin/binutils/etc/configure.info-1 b/gnu/usr.bin/binutils/etc/configure.info-1 new file mode 100644 index 00000000000..52e8c46aae7 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/configure.info-1 @@ -0,0 +1,1174 @@ +This is Info file configure.info, produced by Makeinfo-1.55 from the +input file ./configure.texi. + +START-INFO-DIR-ENTRY +* configure: (configure). Cygnus configure. +END-INFO-DIR-ENTRY + + This document describes the Cygnus Support version of `configure'. + + Copyright (C) 1991, 1992, 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. + + 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 Cygnus Support. + + +File: configure.info, Node: Top, Next: What configure does, Prev: (DIR), Up: (DIR) + +Cygnus configure +**************** + + This file documents the configuration system used and distributed by +Cygnus Support. + +* Menu: + +* What configure does:: What configure does +* Invoking configure:: Invoking configure--basic usage +* Using configure:: More than you ever wanted to know +* Porting:: How to use configure with new programs +* Variables Index:: +* Concept Index:: + + +File: configure.info, Node: What configure does, Next: Invoking configure, Prev: Top, Up: Top + +What `configure' does +********************* + + This manual documents Cygnus `configure', a program which helps to +automate much of the setup activity associated with building large +suites of programs, such the Cygnus Support Developer's Kit. This +manual is therefore geared toward readers who are likely to face the +problem of configuring software in source form before compiling and +installing it. We assume you are an experienced programmer or system +administrator. For further background on this topic, see *Note +Apologia Configure: (cfg-paper)Some Basic Terms, by K. Richard Pixley. + + When `configure' runs, it does the following things: + +** creates build directories* + When you run `configure' with the `--srcdir' option, it uses the + current directory as the "build directory", creating under it a + directory tree that parallels the directory structure of the + source directory. If you don't specify a `srcdir', `configure' + first assumes that the source code you wish to configure is in + your current directory; if it finds no `configure.in' input file + there, it searches in the directory `configure' itself lies in. + (For details, see *Note Build directories: Build directories.) + +** generates `Makefile'* + A `Makefile' template from the source directory, usually called + `Makefile.in', is copied to an output file in the build directory + which is most often named `Makefile'. `configure' places + definitions for a number of standard `Makefile' macros at the + beginning of the output file. If `--prefix=DIR' or + `--exec_prefix=DIR' are specified on the `configure' command line, + corresponding `Makefile' variables are set accordingly. If host, + target, or site-specific `Makefile' fragments exist, these are + inserted into the output file. (For details, see *Note `Makefile' + generation: Makefile generation.) + +** generates `.gdbinit'* + If the source directory contains a `.gdbinit' file and the build + directory is not the same as the source directory, a `.gdbinit' + file is created in the build directory. This `.gdbinit' file + contains commands which allow the source directory to be read when + debugging with the GNU debugger, `gdb'. (*Note Command Files: + (gdb)Command Files.) + +** makes symbolic links* + Most build directories require that some symbolic links with + generic names are built pointing to specific files in the source + directory. If the system where `configure' runs cannot support + symbolic links, hard links are used instead. (For details, see + *Note The `configure.in' input file: configure.in.) + +** generates `config.status'* + `configure' creates a shell script named `config.status' in the + build directory. This shell script, when run from the build + directory (usually from within a `Makefile'), will reconfigure the + build directory (but not its subdirectories). This is most often + used to have a `Makefile' update itself automatically if a new + source directory is available. + +** calls itself recursively* + If the source directory has subdirectories that should also be + configured, `configure' is called for each. + + +File: configure.info, Node: Invoking configure, Next: Using configure, Prev: What configure does, Up: Top + +Invoking `configure' +******************** + + Cygnus `configure' is a shell script which resides in a source tree. +The usual way to invoke `configure' is from the shell, as follows: + + eg$ ./configure HOSTTYPE + +This prepares the source in the current directory (`.') to be compiled +for a HOSTTYPE environment. It assumes that you wish to build programs +and files in the default "build directory" (also the current directory, +`.'). If you do not specify a value for HOSTTYPE, Cygnus `configure' +will attempt to discover this information by itself (*note Determining +system information: config.guess.). For information on HOSTTYPE +environments, *Note Host: Host. + + All GNU software is packaged with one or more `configure' script(s) +(*note How Configuration Should Work: (standards)Configuration.). By +using `configure' you prepare the source for your specific environment +by selecting and using `Makefile' fragments and fragments of shell +scripts, which are prepared in advance and stored with the source. + + `configure''s command-line options also allow you to specify other +aspects of the source configuration: + + configure HOSTTYPE [--target=TARGET] [--srcdir=DIR] [--rm] + [--site=SITE] [--prefix=DIR] [--exec-prefix=DIR] + [--program-prefix=STRING] [--tmpdir=DIR] + [--with-PACKAGE[=YES/NO]] [--without-PACKAGE] + [--enable-FEATURE[=YES/NO]] [--disable-FEATURE] + [--norecursion] [--nfp] [-s] [-v] [-V | --version] [--help] + +`--target=TARGET' + Requests that the sources be configured to target the TARGET + machine. If no target is specified explicitly, the target is + assumed to be the same as the host (i.e., a "native" + configuration). *Note Host: Host, and *Note Target: Target, for + discussions of each. + +`--srcdir=DIR' + Direct each generated `Makefile' to use the sources located in + directory DIR. Use this option whenever you wish the object code + to reside in a different place from the source code. The "build + directory" is always assumed to be the directory you call + `configure' from. See *Note Build directories: Build directories, + for an example. If the source directory is not specified, + `configure' assumes that the source is in your current directory. + If `configure' finds no `configure.in' there, it searches in the + same directory that the `configure' script itself lies in. + Pathnames specified (Values for DIR) can be either absolute + relative to the *build* directory. + +`--rm' + *Remove* the configuration specified by HOSTTYPE and the other + command-line options, rather than create it. + + *Note:* We recommend that you use `make distclean' rather than + use this option; see *Note Invoking `make': (make)Invoking + make, for details on `make distclean'. + +`--site=SITE' + Generate the `Makefile' using site-specific `Makefile' fragments + for SITE. *Note Adding information about local conventions: + Makefile fragments. + +`--prefix=DIR' + Configure the source to install programs and files under directory + DIR. + + This option sets the variable `prefix'. Each generated `Makefile' + will have its `prefix' variables set to this value. (*Note What + `configure' really does: What configure really does.) + +`--exec-prefix=DIR' + Configure the source to install "host dependent" files in DIR. + + This option sets the variable `exec_prefix'. Each generated + `Makefile' will have its `exec_prefix' variables set to this value. + (*Note What `configure' really does: What configure really does.) + +`--program-prefix=STRING' + Configure the source to install certain programs using STRING as a + prefix. This applies to programs which might be used for + cross-compilation, such as the compiler and the binary utilities, + and also to programs which have the same names as common Unix + programs, such as `make'. + + This option sets the variable `program_prefix'. Each generated + `Makefile' will have its `program_prefix' variables set to this + value. (*Note What `configure' really does: What configure really + does.) + +`--tmpdir=TMPDIR' + Use the directory TMPDIR for `configure''s temporary files. The + default is the value of the environment variable `TMPDIR', or + `/tmp' if the environment variable is not set. + +`--with-PACKAGE[=YES/NO]' +`--without-PACKAGE' + Indicate that PACKAGE is present, or not present, depending on + YES/NO. If YES/NO is nonexistent, its value is assumed to be + `yes'. `--without-PACKAGE' is equivalent to `--with-PACKAGE=no'. + + For example, if you wish to configure the program `gcc' for a Sun + SPARCstation running SunOS 4.x, and you want `gcc' to use the GNU + linker `ld', you can configure `gcc' using + + eg$ configure --with-gnu-ld sun4 + + *Note What `configure' really does: What configure really does, for + details. See the installation or release notes for your + particular package for details on which other PACKAGE options are + recognized. + +`--enable-FEATURE[=YES/NO]' +`--disable-FEATURE' + Include FEATURE, or not, depending on YES/NO. If YES/NO is + nonexistent, its value is assumed to be `yes'. + `--disable-FEATURE' is equivalent to `--enable-FEATURE=no'. + + *Note What `configure' really does: What configure really does, for + details. See the installation or release notes for your + particular package for details on which other FEATURE options are + recognized. + +`--norecursion' + Configure only this directory; ignore any subdirectories. This is + used by the executable shell script `config.status' to reconfigure + only the current directory; it is most often used + non-interactively, when `make' is invoked. (*Note + `config.status': config.status.) + +`--nfp' + Assume that the intended HOSTTYPE has no floating point unit. + +`-s' + Suppress status output. This option is used internally by + `configure' when calling itself recursively in subdirectories. You + can override this option with the `--verbose' option. + +`-v' +`--verbose' + Print status lines for each directory configured. Normally, only + the status lines for the initial working directory are printed. + +`--version' +`-V' + Print the `configure' version number. + +`--help' + Print a short summary of how to invoke `configure'. + + *Note:* You may introduce options with a single dash, `-', rather +than two dashes, `--'. However, you may not be able to truncate long +option names when using a single dash. When using two dashes, options +may be abbreviated as long as each option can be uniquely identified. +For example, + eg$ configure --s=/u/me/src HOSTTYPE + +is ambiguous, as `--s' could refer to either `--site' or `--srcdir'. +However, + eg$ configure --src=/u/me/src HOSTTYPE + +is a valid abbreviation. + + +File: configure.info, Node: Using configure, Next: Porting, Prev: Invoking configure, Up: Top + +Using `configure' +***************** + + `configure' prepares source directories for building programs in +them. "Configuring" is the process of preparing software to compile +correctly on a given "host", for a given "target". + + `configure' subsequently writes a configured `Makefile' from a +pre-built template; `configure' uses variables that have been set in the +configuring process to determine the values of some variables in the +`Makefile'. Because of this we will refer to both `configure' +variables and `Makefile' variables. This convention allows us to +determine where the variable should be set initially, in either +`configure.in' or `Makefile.in'. + +* Menu: + +* What configure really does:: What configure really does +* configure.in:: The configure.in input file +* Install locations:: Where to install things once they are built +* Host:: Telling configure what will source will be built +* Target:: Telling configure what the source will target +* Makefile fragments:: Adding information about local conventions +* Makefile extensions:: Extensions to the GNU coding standards + + +File: configure.info, Node: What configure really does, Next: configure.in, Up: Using configure + +What `configure' really does +============================ + + Cygnus `configure' is a shell script that sets up an environment in +which your programs will compile correctly for your machine and +operating system, and will install in proper places. `configure' +accomplishes this task by doing the following: + + * it generates a `Makefile' from a custom template called + `Makefile.in' in each relevant source directory; + + * it customizes the build process to your specifications; you set + certain variables for `configure', either on the command line or + in the file `configure.in', which subsequently sets variables in + each generated `Makefile' to be used by `make' when actually + building the software; + + * it creates "build directories", places for your code to be compiled + in before being installed; + + * it generates a `.gdbinit' in the build directory, if needed, to + communicate to `gdb' where to find the program's source code; + + * it generates a shell script called `config.status' which is used + most often by the `Makefile' to reconfigure itself; + + * it recurses in subdirectories, setting up entire trees so that + they build correctly; if `configure' finds another `configure' + script further down in a given source tree, it knows to use this + script and not recur. + + For the sake of safety (i.e., in order to prevent broken +installations), the GNU coding standards call for software to be +"configured" in such a way that an end user trying to build a given +package will be able to do so by affecting a finite number of +variables. All GNU software comes with an executable `configure' shell +script which sets up an environment within a build directory which will +correctly compile your new package for your host (or, alternatively, +whatever host you specify to `configure'). For further background on +this topic, see *Note Apologia Configure: (cfg-paper)Some Basic Terms, +by K. Richard Pixley. + + Use `configure' to set for the build process: + + * correct values for certain variables; + + * which type of host you wish to configure a given package for + (*note Host: Host.); + + * where you want to install this package (by using `prefix', + `exec-prefix' and `program-prefix'; *note Full descriptions of all + installation directories: Install details.); + + * optionally, which type of machine you wish to "target" this + package's output to (*note Target: Target.); + + * which other GNU packages are already installed and available to + this particular build (by using the `--with-PACKAGE' option; *note + Invoking `configure': Invoking configure.); + + * where to place temporary files (by using the `--tmpdir=DIR' + option; *note Invoking `configure': Invoking configure.); + + * whether to recur in subdirectories (changeable through the + `--norecursion' option; *note Invoking `configure': Invoking + configure.). + + `configure' uses a few other files to complete its tasks. These are +discussed in detail where noted. + +`configure.in' + Input file for `configure'. Shell script fragments reside here. + *Note The `configure.in' input file: configure.in. + +`Makefile.in' + Template which `configure' uses to build a file called `Makefile' + in the "build directory". *Note `Makefile' generation: Makefile + generation. + +`config.sub' + Shell script used by `configure' to expand referents to the + HOSTTYPE argument into a single specification of the form + CPU-VENDOR-OS. For instance, on the command line you can specify + + eg$ ./configure sun4 + + to configure for a Sun SPARCstation running SunOS 4.x. `configure' + consults `config.sub' to find that the three-part specification + for this is + + sparc-sun-sunos4.1.1 + + which notes the CPU as `sparc', the MANUFACTURER as `sun' (Sun + Microsystems), and the OS (operating system) as `sunos4.1.1', the + SunOS 4.1.1 release. *Note Variables available to `configure': + configure variables. + +`config.guess' + If you do not put the HOSTTYPE argument on the command line, + `configure' uses the `config.guess' shell script to make an + analysis of your machine (it assumes that you wish to configure + your software for the type of machine on which you are running). + The output of `config.guess' is a three-part identifier as + described above. + +`config.status' + The final step in configuring a directory is to create a shell + script, `config.status'. The main purpose of this file is to + allow the `Makefile' for the current directory to rebuild itself, + if necessary. *Note `config.status': config.status. + +`config/*' + `configure' uses three types of `Makefile' "fragments", which + reside in the directory `SRCDIR/config/'. *Note Adding + information about local conventions: Makefile fragments. + +* Menu: + +* Build variables:: Variable-spaghetti made simple +* Build directories:: Build directories described well +* Makefile generation:: To build a Makefile +* config.guess:: Be vewwy quiet, I'm hunting system information +* config.status:: To rebuild a Makefile + + +File: configure.info, Node: Build variables, Next: Build directories, Up: What configure really does + +Build variables +--------------- + + There are several variables in the build process which you can +control through build programs such as `make'. These include machine +definitions, local conventions, installation locations, locations for +temporary files, etc. This data is accessible through certain +variables which are configurable in the build process; we refer to them +as "build variables". + + For lists of build variables which you can affect by using +`configure', see *Note Variables available to `configure.in': configure +variables, and *Note Full descriptions of all installation directories: +Install details. + + Generally, build variables, which are used by the `Makefile' to +determine various aspects of the build and installation processes, are +changeable with command-line options to `configure'. In most large +suites of programs, like the Cygnus Support Developer's Kit, the +individual programs reside in several subdirectories of a single source +code "tree". All of these subdirectories need to be configured with +information relative to the "build directory", which is not known until +`configure' is run. Unless specified otherwise, `configure' +recursively configures every subdirectory in the source tree. + + Build variables are passed from `configure' directly into the +`Makefile', and use the same names (except that dashes are transformed +into underbars; for example, when you specify the option +`--exec-prefix' on the command line, the `Makefile' variable +`exec_prefix' is set). In other words, if you specify + + eg$ ./configure --prefix=/usr/gnu/local ... HOSTTYPE + +on the command line, `configure' sets an variable called `prefix' to +`/usr/gnu/local', and passes this into the `Makefile' in the same +manner. After this command, each `Makefile' generated by `configure' +will contain a line that reads: + + prefix = /usr/gnu/local + + For a list of the `Makefile' variables `configure' can change, and +instructions on how to change them, see *Note Variables available to +`configure.in': configure variables, and *Note Invoking `configure': +Invoking configure. + + +File: configure.info, Node: Build directories, Next: Makefile generation, Prev: Build variables, Up: What configure really does + +Build directories +----------------- + + By default, `configure' builds a `Makefile' and symbolic links in the +same directory as the source files. This default works for many cases, +but it has limitations. For instance, using this approach, you can +only build object code for one host at a time. + + We refer to each directory where `configure' builds a `Makefile' as +a "build directory". + + The build directory for any given build is always the directory from +which you call `configure', or `.' relative to your prompt. The default +"source directory", the place `configure' looks to find source code, is +also `.'. For instance, if we have a directory `/gnu-stuff/src/' that +is the top branch of a tree of GNU source code we wish to configure, +then the program we will use to configure this code is +`/gnu-stuff/src/configure', as follows. (Assume for the sake of +argument that our machine is a sun4.) + + eg$ cd /gnu-stuff/src + eg$ ./configure sun4 + Created "Makefile" in /gnu-stuff/src + eg$ + + We just configured the code in `/gnu-stuff/src' to run on a Sun +SPARCstation using SunOS 4.x by creating a `Makefile' in +`/gnu-stuff/src'. By default, we also specified that when this code is +built, the object code should reside in the same directory, +`/gnu-stuff/src'. + + However, if we wanted to build this code for more than one host, we +would be in trouble, because the new configuration would write over the +old one, destroying it in the process. What we can do is to make a new +"build directory" and configure from there. Running `configure' from +the new directory will place a correct `Makefile' and a `config.status' +in this new file. That is all `configure' does; we must run `make' to +generate any object code. + + The new `Makefile' in `/gnu-stuff/sun4-obj', created from the +template file `/gnu-stuff/src/Makefile.in', contains all the information +needed to build the program. + + eg$ mkdir /gnu-stuff/sun4-obj + eg$ cd /gnu-stuff/sun4-obj + eg$ ../src/configure --srcdir=../src sun4 + Created "Makefile" in /gnu-stuff/sun4-obj + eg$ ls + Makefile config.status + eg$ make all info install install-info clean + COMPILATION MESSAGES... + eg$ mkdir /gnu-stuff/solaris2 + eg$ cd /gnu-stuff/solaris2 + eg$ ../src/configure --srcdir=../src sol2 + Created "Makefile" in /gnu-stuff/solaris2 + eg$ ls + Makefile config.status + eg$ make all info install install-info clean + COMPILATION MESSAGES... + + We can repeat this for other configurations of the same software +simply by making a new build directory and reconfiguring from inside +it. If you do not specify the HOSTTYPE argument, `configure' will +attempt to figure out what kind of machine and operating system you +happen to be using. *Note Determining system information: +config.guess. Of course, this may not always be the configuration you +wish to build. + + *Caution:* If you build more than one configuration for a single +program, remember that you must also specify a different `--prefix' for +each configuration at configure-time. Otherwise, both configurations +will be installed in the same default location (`/usr/local'); the +configuration to be installed last would overwrite previously installed +configurations. + + +File: configure.info, Node: Makefile generation, Next: config.guess, Prev: Build directories, Up: What configure really does + +`Makefile' generation +--------------------- + + Cygnus `configure' creates a file called `Makefile' in the build +directory which can be used with `make' to automatically build a given +program or package. `configure' also builds a `Makefile' for each +relevant subdirectory for a given program or package (irrelevant +subdirectories would be those which contain no code which needs +configuring, and which therefore have no `configure' input file +`configure.in' and no `Makefile' template `Makefile.in'). *Note `make' +Invocation: (make)Running, for details on using `make' to compile your +source code. + + Each `Makefile' contains variables which have been configured for a +specific build. These build variables are determined when `configure' +is run. All build variables have defaults. By default, `configure' +generates a `Makefile' which specifies: + + * a "native" build, which is to occur + + * in the current directory, and which will be installed + + * in the default installation directory (`/usr/local') when the code + is compiled with `make'. + +Variables are changeable through command-line options to `configure' +(*note Invoking `configure': Invoking configure.). + + If you are porting a new program and intend to use `configure', see +*Note Porting with `configure': Porting, as well as *Note Writing +Makefiles: (make)Makefiles, and *Note Makefile Conventions: +(standards)Makefiles. + + +File: configure.info, Node: config.guess, Next: config.status, Prev: Makefile generation, Up: What configure really does + +Determining system information +------------------------------ + + The shell script `config.guess' is called when you do not specify a +HOSTTYPE on the command line to `configure'. `config.guess' acquires +available system information from your local machine through the shell +command `uname'. It compares this information to a database and +attempts to determine a usable three-part system identifier (known as a +"triple") to use as your HOSTTYPE. *Note What `configure' really does: +What configure really does, to see how this information is used. + + *Note:* If you do not specify a HOSTTYPE on the command line, +`configure' will attempt to configure your software to run on the +machine you happen to be using. This may not be the configuration you +desire. + + +File: configure.info, Node: config.status, Prev: config.guess, Up: What configure really does + +`config.status' +--------------- + + The final step in configuring a directory is to create an executable +shell script, `config.status'. The main purpose of this file is to +allow the `Makefile' for the current directory to rebuild itself, if +necessary. It is usually run from within the `Makefile'. *Note +Extensions to the GNU coding standards: Makefile extensions. + + `config.status' also contains a record of the `configure' session +which created it. + + +File: configure.info, Node: configure.in, Next: Install locations, Prev: What configure really does, Up: Using configure + +The `configure.in' input file +============================= + + A `configure.in' file for Cygnus `configure' consists of a +"per-invocation" section, followed by a "per-host" section, followed by +a "per-target" section, optionally followed by a "post-target" section. +Each section is a shell script fragment, which is executed by the +`configure' shell script at an appropriate time. Values are passed +among `configure' and the shell fragments through a set of shell +variables. When each section is being interpreted by the shell, the +shell's current directory is the build directory, and any files created +by the section (or referred to by the section) will be relative to the +build directory. To reference files in other places (such as the +source directory), prepend a shell variable such as `$(srcdir)/' to the +desired file name. + + The beginning of the `configure.in' file begins the "per-invocation" +section. + + A line beginning with `# per-host:' begins the "per-host" section. + + A line beginning with `# per-target:' begins the "per-target" +section. + + If it exists, the "post-target" section begins with `# post-target:'. + +* Menu: + +* configure variables:: Variables available to configure.in +* Minimal:: A minimal configure.in +* Declarations:: For each invocation +* per-host:: Host-specific instructions +* per-target:: Target-specific instructions +* post-target:: Instructions to be executed after target info +* Example:: An example configure.in + + +File: configure.info, Node: configure variables, Next: Minimal, Up: configure.in + +Variables available to `configure.in' +------------------------------------- + + The following variables pass information between the standard parts +of `configure' and the shell-script fragments in `configure.in': + +`srctrigger' + Contains the name of a source file that is expected to live in the + source directory. You must usually set this in the + "per-invocation" section of `configure.in'. `configure' tests to + see that this file exists. If the file does not exist, + `configure' prints an error message. This is used as a sanity + check that `configure.in' matches the source directory. + +`srcname' + Contains the name of the source collection contained in the source + directory. You must usually set this in the "per-invocation" + section of `configure.in'. If the file named in `srctrigger' does + not exist, `configure' uses the value of `srcname' when it prints + the error message. + +`configdirs' + Contains the names of any subdirectories in which `configure' + should recurse. You must usually set this in the "per-invocation" + section of `configure.in'. If `Makefile.in' contains a line + starting with `SUBDIRS =', then it will be replaced with an + assignment to `SUBDIRS' using the value of `configdirs' (if + `subdirs' is empty). This can be used to determine which + directories to configure and build depending on the host and + target configurations. Use `configdirs' (instead of the `subdirs' + variable described below) if you want to be able to partition the + subdirectories, or use independent `Makefile' fragments. Each + subdirectory can be independent, and independently reconfigured. + +`subdirs' + Contains the names of any subdirectories where `configure' should + create a `Makefile' (in addition to the current directory), + *without* recursively running `configure'. Use `subdirs' (instead + of the `configdirs' variable described above) if you want to + configure all of the directories as a unit. Since there is a + single invocation of `configure' that configures many directories, + all the directories can use the same `Makefile' fragments, and the + same `configure.in'. + +`host' + Contains the full configuration name for the host (generated by + the script `config.sub' from the name that you entered). This is + a three-part name (commonly referred to as a "triple") of the form + CPU-VENDOR-OS. + + There are separate variables `host_cpu', `host_vendor', and + `host_os' that you can use to test each of the three parts; this + variable is useful, however, for error messages, and for testing + combinations of the three components. + +`host_cpu' + Contains the first element of the canonical triple representing + the host as returned by `config.sub'. This is occasionally used to + distinguish between minor variations of a particular vendor's + operating system and sometimes to determine variations in binary + format between the host and the target. + +`host_vendor' + Contains the second element of the canonical triple representing + the host as returned by `config.sub'. This is usually used to + distinguish among the numerous variations of *common* operating + systems. + +`host_os' + Contains the the third element of the canonical triple + representing the host as returned by `config.sub'. + +`target' + Contains the full configuration name (generated by the script + `config.sub' from the name that you entered) for the target. Like + the host, this is a three-part name of the form CPU-VENDOR-OS. + + There are separate variables `target_cpu', `target_vendor', and + `target_os' that you can use to test each of the three parts; this + variable is useful, however, for error messages, and for testing + combinations of the three components. + +`target_cpu' + Contains the first element of the canonical triple representing + the target as returned by `config.sub'. This variable is used + heavily by programs which are involved in building other programs, + like the compiler, assembler, linker, etc. Most programs will not + need the `target' variables at all, but this one could conceivably + be used to build a program, for instance, that operated on binary + data files whose byte order or alignment differ from the system + where the program is running. + +`target_vendor' + Contains the second element of the canonical triple representing + the target as returned by `config.sub'. This is usually used to + distinguish among the numerous variations of *common* operating + systems or object file formats. It is sometimes used to switch + between different flavors of user interfaces. + +`target_os' + Contains the the third element of the canonical triple + representing the target as returned by `config.sub'. This + variable is used by development tools to distinguish between + subtle variations in object file formats that some vendors use + across operating system releases. It might also be use to decide + which libraries to build or what user interface the tool should + provide. + +`floating_point' + Set to `no' if you invoked `configure' with the `--nfp' + command-line option, otherwise it is empty. This is a request to + target machines with "no floating point" unit, even if the targets + ordinarily have floating point units available. + +`gas' + Set to `true' if you invoked `configure' with the `--with-gnu-as' + command line option, otherwise it is empty. This is a request to + assume that the specified HOSTTYPE machine has GNU `as' available + even if it ordinarily does not. + +`srcdir' + Set to the name of the directory containing the source for this + program. This will be different from `.' if you have specified the + `--srcdir=DIR' option. `srcdir' can indicate either an absolute + path or a path relative to the build directory. + +`package_makefile_frag' + If set in `configure.in', this variable should be the name a file + relative to `srcdir' to be included in the resulting `Makefile'. + If the named file does not exist, `configure' will print a warning + message. This variable is not set by `configure'. + +`host_makefile_frag' + If set in `configure.in', this variable should be the name a file + relative to `srcdir' to be included in the resulting `Makefile'. + If the named file does not exist, `configure' will print a warning + message. This variable is not set by `configure'. + +`target_makefile_frag' + If set in `configure.in', this variable should be the name of a + file, relative to `srcdir', to be included in the resulting + `Makefile'. If the named file does not exist, `configure' will + print a warning message. This variable is not set by `configure'. + +`site_makefile_frag' + Set to a file name representing to the default `Makefile' fragment + for this host. It may be set in `configure.in' to override this + default. Normally `site_makefile_frag' is empty, but will have a + value if you specify `--site=SITE' on the command line. + +`Makefile' + Set to the name of the generated `Makefile'. Normally this value + is precisely `Makefile', but some programs may want something else. + +`removing' + Normally empty but will be set to some non-null value if you + specified `--rm' on the command line. That is, if `removing' is + not empty, then `configure' is *removing* a configuration rather + than creating one. + +`files' + If this variable is not empty following the "per-target" section, + then each word in its value will be the target of a symbolic link + named in the corresponding word from the `links' variable. + +`links' + If the `files' variable is not empty following the "per-target" + section, then `configure' creates symbolic links with the first + word of `links' pointing to the first word of `files', the second + word of `links' pointing to the second word of `files', and so on. + + +File: configure.info, Node: Minimal, Next: Declarations, Prev: configure variables, Up: configure.in + +A minimal `configure.in' +------------------------ + + A minimal `configure.in' consists of four lines. + + srctrigger=foo.c + srcname="source for the foo program" + # per-host: + # per-target: + + The `# per-host:' and `# per-target:' lines divide the file into the +three required sections. The `srctrigger' line names a file. +`configure' checks to see that this file exists in the source directory +before configuring. If the `srctrigger' file does not exist, +`configure' uses the value of `srcname' to print an error message about +not finding the source. + + This particular example uses no links, and only the default host, +target, and site-specific `Makefile' fragments if they exist. + + +File: configure.info, Node: Declarations, Next: per-host, Prev: Minimal, Up: configure.in + +For each invocation +------------------- + + `configure' invokes the entire shell script fragment from the start +of `configure.in' up to a line beginning with `# per-host:' immediately +after parsing command line arguments. The variables `srctrigger' and +`srcname' *must* be set here. + + You might also want to set the variables `configdirs' and +`package_makefile_frag' here. + + +File: configure.info, Node: per-host, Next: per-target, Prev: Declarations, Up: configure.in + +Host-specific instructions +-------------------------- + + The "per-host" section of `configure.in' starts with the line that +begins with `# per-host:' and ends before a line beginning with +`# per-target:'. `configure' invokes the commands in the "per-host" +section when determining host-specific information. + + This section usually contains a big `case' statement using the +variable `host' to determine appropriate values for +`host_makefile_frag' and `files', although `files' is not usually set +here. Usually, it is set at the end of the "per-target" section after +determining the names of the target specific configuration files. + + +File: configure.info, Node: per-target, Next: post-target, Prev: per-host, Up: configure.in + +Target-specific instructions +---------------------------- + + The "per-target" section of `configure.in' starts with the line that +begins with `# per-target:' and ends before the line that begins with +`# post-target:', if there is such a line. Otherwise the "per-target" +section extends to the end of the file. `configure' invokes the +commands in the "per-target" section when determining target-specific +information, and before building any files, directories, or links. + + This section usually contains a big `case' statement using the +variable `target' to determine appropriate values for +`target_makefile_frag' and `files'. The last lines in the "per-target" +section normally set the variables `files' and `links'. + + +File: configure.info, Node: post-target, Next: Example, Prev: per-target, Up: configure.in + +Instructions to be executed after target info +--------------------------------------------- + + The "post-target" section is optional. If it exists, the +`post-target' section starts with a line beginning with +`# Post-target:' and extends to the end of the file. If it exists, +`configure' invokes this section once for each target after building +all files, directories, or links. + + This section is seldom needed, but you can use it to edit the +`Makefile' generated by `configure'. + + +File: configure.info, Node: Example, Prev: post-target, Up: configure.in + +An example `configure.in' +------------------------- + + Here is a small example of a `configure.in' file. + + # This file is a collection of shell script fragments + # used to tailor a template configure script as + # appropriate for this directory. For more information, + # see configure.texi. + + configdirs= + srctrigger=warshall.c + srcname="bison" + + # per-host: + case "${host}" in + m88k-motorola-*) + host_makefile_frag=config/mh-delta88 + ;; + esac + + # per-target: + files="bison_in.hairy" + links="bison.hairy" + + # post-target: + + +File: configure.info, Node: Install locations, Next: Host, Prev: configure.in, Up: Using configure + +Install locations +================= + + Using the default configuration, `make install' creates a single +tree of files, some of which are programs. The location of this tree +is determined by the value of the variable `prefix'. The default value +of `prefix' is `/usr/local'. This is often correct for native tools +installed on only one host. + +* Menu: + +* prefix:: Changing the default install directory +* exec_prefix:: How to separate host independent files + from host dependent files when + installing for multiple hosts +* Install details:: Full descriptions of all installation subdirectories + + +File: configure.info, Node: prefix, Next: exec_prefix, Up: Install locations + +Changing the default install directory +-------------------------------------- + + In the default configuration, all files are installed in +subdirectories of `/usr/local'. The location is determined by the +value of the `configure' variable `prefix'; in turn, this determines the +value of the `Makefile' variable of the same name (`prefix'). + + You can also set the value of the `Makefile' variable `prefix' +explicitly each time you invoke `make' if you are so inclined. However, +because many programs have this location compiled in, you must specify +the `prefix' value consistently on each invocation of `make', or you +will end up with a broken installation. + + To make this easier, the value of the `configure' variable `prefix' +can be set on the command line to `configure' using the option +`--prefix='. + + +File: configure.info, Node: exec_prefix, Next: Install details, Prev: prefix, Up: Install locations + +Installing for multiple hosts +----------------------------- + + By default, host dependent files are installed in subdirectories of +`$(exec_prefix)'. The location is determined by the value of the +`configure' variable `exec_prefix', which determines the value of the +`Makefile' variable `exec_prefix'. This makes it easier to install for +a single host, and simplifies changing the default location for the +install tree. The default doesn't allow for multiple hosts to +effectively share host independent files, however. + + To configure so that multiple hosts can share common files, use +something like: + + configure HOST1 -prefix=/usr/gnu -exec_prefix=/usr/gnu/H-host1 + make all info install install-info clean + + configure HOST2 -prefix=/usr/gnu -exec_prefix=/usr/gnu/H-host2 + make all info install install-info + + The first line configures the source for HOST1 to place host-specific +programs in subdirectories of `/usr/gnu/H-HOST1'. + + The second line builds and installs all programs for HOST1, +including both host-independent and host-specific files, as well as +removing the host-specific object files from of the build directory. + + The third line reconfigures the source for HOST2 to place host +specific programs in subdirectories of `/usr/gnu/H-HOST2'. + + The fourth line builds and installs all programs for HOST2. Host +specific files are installed in new directories, but the host +independent files are installed *on top of* the host independent files +installed for HOST1. This results in a single copy of the host +independent files, suitable for use by both hosts. + + *Note Extensions to the GNU coding standards: Makefile extensions, +for more information. + + +File: configure.info, Node: Install details, Prev: exec_prefix, Up: Install locations + +Full descriptions of all installation subdirectories +---------------------------------------------------- + + During any install, a number of standard directories are created. +Their names are determined by `Makefile' variables. Some of the +defaults for `Makefile' variables can be changed at configuration time +using command line options to `configure'. For more information on the +standard directories or the `Makefile' variables, please refer to *Note +Makefile Conventions: (standards)Makefiles. See also *Note Extensions +to the GNU coding standards: Makefile extensions. + + Note that `configure' does not create the directory indicated by the +variable `srcdir' at any time. `$(srcdir)' is not an installation +directory. + + You can override all `Makefile' variables on the command line to +`make'. (*Note Overriding Variables: (make)Overriding.) If you do so, +you will need to specify the value precisely the same way for each +invocation of `make', or you risk ending up with a broken installation. +This is because many programs have the locations of other programs or +files compiled into them. If you find yourself overriding any of the +variables frequently, you should consider site dependent `Makefile' +fragments. See also *Note Adding site info: Sites. + + During `make install', a number of standard directories are created +and populated. The following `Makefile' variables define them. Those +whose defaults are set by corresponding `configure' variables are marked +"`Makefile' and `configure'". + +`prefix (`Makefile' and `configure')' + The root of the installation tree. You can set its `Makefile' + default with the `--prefix=' command line option to `configure' + (*note Invoking `configure': Invoking configure.). The default + value for `prefix' is `/usr/local'. + +`bindir' + A directory for binary programs that users can run. The default + value for `bindir' depends on `prefix'; `bindir' is normally + changed only indirectly through `prefix'. The default value for + `bindir' is `$(prefix)/bin'. + +`exec_prefix (`Makefile' and `configure')' + A directory for host dependent files. You can specify the + `Makefile' default value by using the `--exec_prefix=' option to + `configure'. (*Note Invoking `configure': Invoking configure.) + The default value for `exec_prefix' is `$(prefix)'. + +`libdir' + A directory for libraries and support programs. The default value + for `libdir' depends on `prefix'; `libdir' is normally changed only + indirectly through `prefix'. The default value for `libdir' is + `$(prefix)/lib'. + +`mandir' + A directory for `man' format documentation ("man pages"). The + default value for `mandir' depends on `prefix'; `mandir' is + normally changed only indirectly through `prefix'. The default + value for `mandir' is `$(prefix)/man'. + +`manNdir' + These are eight variables named `man1dir', `man2dir', etc. They + name the specific directories for each man page section. For + example, `man1dir' by default holds the filename `$(mandir)/man1'; + this directory contains `emacs.1' (the man page for GNU Emacs). + Similarly, `man5dir' contains the value `$(mandir)/man5', + indicating the directory which holds `rcsfile.5' (the man page + describing the `rcs' data file format). The default value for any + of the `manNdir' variables depends indirectly on `prefix', and is + normally changed only through `prefix'. The default value for + `manNdir' is `$(mandir)/manN'. + +`manNext' + *Not supported by Cygnus `configure'*. The `GNU Coding Standards' + do not call for `man1ext', `man2ext', so the intended use for + `manext' is apparently not parallel to `mandir'. Its use is not + clear. (See also *Note Extensions to the GNU coding standards: + Makefile extensions.) + +`infodir' + A directory for `info' format documentation. The default value for + `infodir' depends indirectly on `prefix'; `infodir' is normally + changed only through `prefix'. The default value for `infodir' is + `$(prefix)/info'. + +`docdir' + A directory for any documentation that is in a format other than + those used by `info' or `man'. The default value for `docdir' + depends indirectly on `prefix'; `docdir' is normally changed only + through `prefix'. The default value for `docdir' is + `$(datadir)/doc'. *This variable is an extension to the GNU + coding standards*. (See also *Note Extensions to the GNU coding + standards: Makefile extensions.) + +`includedir' + A directory for the header files accompanying the libraries + installed in `libdir'. The default value for `includedir' depends + on `prefix'; `includedir' is normally changed only indirectly + through `prefix'. The default value for `includedir' is + `$(prefix)/include'. + + +File: configure.info, Node: Host, Next: Target, Prev: Install locations, Up: Using configure + +Host +==== + + The arguments to `configure' are "hosttypes". By "hosttype" we mean +the "environment" in which the source will be compiled. This need not +necessarily be the same as the physical machine involved, although it +usually is. + + For example, if some obscure machine had the GNU `POSIX' emulation +libraries available, it would be possible to configure most GNU source +for a `POSIX' system and build it on the obscure host. + + For more on this topic, see *Note On Configuring Development Tools: +(cfg-paper)Host Environments. + + +File: configure.info, Node: Target, Next: Makefile fragments, Prev: Host, Up: Using configure + +Target +====== + + For building native development tools, or most of the other GNU +tools, you need not worry about the target. The "target" of a +configuration defaults to the same as the "host". + + For building cross development tools, please see *Note On +Configuring Development Tools: (cfg-paper)Building Development +Environments. + diff --git a/gnu/usr.bin/binutils/etc/configure.info-2 b/gnu/usr.bin/binutils/etc/configure.info-2 new file mode 100644 index 00000000000..022d187f819 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/configure.info-2 @@ -0,0 +1,572 @@ +This is Info file configure.info, produced by Makeinfo-1.55 from the +input file ./configure.texi. + +START-INFO-DIR-ENTRY +* configure: (configure). Cygnus configure. +END-INFO-DIR-ENTRY + + This document describes the Cygnus Support version of `configure'. + + Copyright (C) 1991, 1992, 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. + + 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 Cygnus Support. + + +File: configure.info, Node: Makefile fragments, Next: Makefile extensions, Prev: Target, Up: Using configure + +Adding information about local conventions +========================================== + + If you find that a tool does not get configured to your liking, or if +`configure''s conventions differ from your local conventions, you should +probably consider "site-specific `Makefile' fragments". See also *Note +Adding site info: Sites. + + These are probably not the right choice for options that can be set +from the `configure' command line or for differences that are host or +target dependent. + + Cygnus `configure' uses three types of `Makefile' fragments. In a +generated `Makefile' they appear in the order: "target fragment", "host +fragment", and "site fragment". This allows host fragments to override +target fragments, and site fragments to override both. + + Host-specific `Makefile' fragments conventionally reside in the +`./config/' subdirectory with names of the form `mh-HOSTTYPE'. They +are used for hosts that require odd options to the standard compiler and +for compile time options based on the host configuration. + + Target-specific `Makefile' fragments conventionally reside in the +`./config/' subdirectory with names of the form `mt-TARGET'. They are +used for target dependent compile time options. + + Site specific `Makefile' fragments conventionally reside in the +`./config/' subdirectory with names of the form `ms-SITE'. They are +used to override host- and target-independent compile time options. +Note that you can also override these options on the `make' invocation +line. + + +File: configure.info, Node: Makefile extensions, Prev: Makefile fragments, Up: Using configure + +Extensions to the GNU coding standards +====================================== + + The following additions to the GNU coding standards are required for +Cygnus `configure' to work properly. + + * The `Makefile' must contain exactly one line starting with `####'. + This line should follow any default macro definitions but precede + any rules. Host, target, and site-specific `Makefile' fragments + will be inserted immediately after this line. If the line is + missing, the fragments will not be inserted. + + * Cygnus adds the following targets to each `Makefile'. Their + existence is not required for Cygnus `configure', but they are + documented here for completeness. + + `info' + Build all info files from texinfo source. + + `install-info' + Install all info files. + + `clean-info' + Remove all info files and any intermediate files that can be + generated from texinfo source. + + `Makefile' + Calls `./config.status' to rebuild the `Makefile' in this + directory. + + * The following `Makefile' targets have revised semantics: + + `install' + Should *not* depend on the target `all'. If the program is + not already built, `make install' should fail. This allows + you to install programs even when `make' would otherwise + determine them to be out of date. This can happen, for + example, when the result of a `make all' is transported via + tape to another machine for installation. + + `clean' + Should remove any file that can be regenerated by the + `Makefile', excepting only the `Makefile' itself, and any + links created by `configure'. That is, `make all clean' + should return all directories to their original condition. + If this is not done, then the command sequence + + configure HOST1 ; make all install clean ; + configure HOST2 ; make all install + + will fail because of intermediate files intended for HOST1. + + * Cygnus adds the following macros to all `Makefile.in' files, but + you are not required to use them to run Cygnus `configure'. + + `docdir' + The directory in which to install any documentation that is + not either a `man' page or an `info' file. For `man' pages, + see `mandir'; for `info', see `infodir'. + + `includedir' + The directory in which to install any header files that + should be made available to users. This is distinct from the + `gcc' include directory, which is intended for `gcc' only. + Files in `includedir' may be used by `cc' as well. + + * The following macros have revised semantics. Most of them describe + installation directories; see also *Note Full description of all + installation subdirectories: Install details. + + `datadir' + is used for host independent data files. + + `mandir' + The default path for `mandir' depends on `prefix'. + + `infodir' + The default path for `infodir' depends on `prefix'. + + `BISON' + is assumed to have a `yacc' calling convention. To use GNU + `bison', use `BISON=bison -y'. + + * Each Cygnus `Makefile' also conforms to one additional restriction: + + When libraries are installed, the line containing the call to + `INSTALL_DATA' should always be followed by a line containing a + call to `RANLIB' on the installed library. This is to accommodate + systems that use `ranlib'. Systems that do not use `ranlib' can + set `RANLIB' to "`echo'" in a host specific `Makefile' fragment. + + +File: configure.info, Node: Porting, Next: Variables Index, Prev: Using configure, Up: Top + +Porting with `configure' +************************ + + This section explains how to add programs, host and target +configuration names, and site-specific information to Cygnus +`configure'. + +* Menu: + +* Programs:: Adding configure to new programs +* Hosts and targets:: Adding hosts and targets +* Sites:: Adding site info + + +File: configure.info, Node: Programs, Next: Hosts and targets, Up: Porting + +Adding `configure' to new programs +================================== + + If you are writing a new program, you probably shouldn't worry about +porting or configuration issues until it is running reasonably on some +host. Then refer back to this section. + + If your program currently has a `configure' script that meets the GNU +standards (*note How Configuration Should Work: +(standards)Configuration., please do not add Cygnus `configure'. It +should be possible to add this program without change to a Cygnus +`configure' style source tree. + + If the program is not target dependent, please consider using +`autoconf' instead of Cygnus `configure'. `autoconf' is available from +the Free Software Foundation; it is a program which generates an +executable shell script called `configure' by automatically finding +information on the system to be configured on and embedding this +information in the shell script. `configure' scripts generated by +`autoconf' require no arguments, and accept the same options as Cygnus +`configure'. For detailed instructions on using `autoconf', see *Note +How to organize and produce Autoconf scripts: (autoconf)Making +configure Scripts. + + To add Cygnus `configure' to an existing program, do the following: + +*Make sure the `Makefile' conforms to the GNU standard + The coding standard for writing a GNU `Makefile' is described in + *Note Makefile Conventions: (standards)Makefiles. For technical + information on writing a `Makefile', see *Note Writing Makefiles: + (make)Makefiles. + +*Add Cygnus extensions to the `Makefile' + These are described in *Note Extensions to the GNU coding + standards: Makefile extensions. + +*Collect package specific definitions in a single file + Many packages are best configured using a common `Makefile' + fragment which is included by all of the makefiles in the + different directories of the package. In order to accomplish + this, set the variable `package_makefile_fragment' to the name of + the file. It will be inserted into the final `Makefile' before + the target-specific fragment. + +*Move host support from `Makefile' to fragments + This usually involves finding sections of the `Makefile' that say + things like "uncomment these lines for host HOSTTYPE" and moving + them to a new file called `./config/mh-HOSTTYPE'. For more + information, see *Note Adding hosts and targets: Hosts and targets. + +*Choose defaults + If the program has compile-time options that determine the way the + program should behave, choose reasonable defaults and make these + `Makefile' variables. Be sure the variables are assigned their + default values before the `####' line so that site-specific + `Makefile' fragments can override them (*note Extensions to the + GNU coding standards: Makefile extensions.). + +*Locate configuration files + If there is configuration information in header files or source + files, separate it in such a way that the files have generic + names. Then move the specific instances of those files into the + `./config/' subdirectory. + +*Separate host and target information + Some programs already have this information separated. If yours + does not, you will need to separate these two kinds of + configuration information. "Host specific" information is the + information needed to compile the program. "Target specific" + information is information on the format of data files that the + program will read or write. This information should live in + separate files in the `./config/' subdirectory with names that + reflect the configuration for which they are intended. + + At this point you might skip this step and simply move on. If you + do, you should end up with a program that can be configured only + to build "native" tools, that is, tools for which the host system + is also the target system. Later, you could attempt to build a + cross tool and separate out the target-specific information by + figuring out what went wrong. This is often simpler than combing + through all of the source code. + +*Write `configure.in' + Usually this involves writing shell script fragments to map from + canonical configuration names into the names of the configuration + files. These files will then be linked at configure time from the + specific instances of those files in `./config' to files in the + build directory with more generic names. (See also *Note Build + directories: Build directories.) The format of `configure.in' is + described in *Note The `configure.in' input file: configure.in. + +*Rename `Makefile' to `Makefile.in' + At this point you should have a program that can be configured using +Cygnus `configure'. + + +File: configure.info, Node: Hosts and targets, Next: Sites, Prev: Programs, Up: Porting + +Adding hosts and targets +======================== + + To add a host or target to a program that already uses Cygnus +`configure', do the following. + + * Make sure the new configuration name is represented in + `config.sub'. If not, add it. For more details, see the comments + in the shell script `config.sub'. + + * If you are adding a host configuration, look in `configure.in', in + the "per-host" section. Make sure that your configuration name is + represented in the mapping from host configuration names to + configuration files. If not, add it. Also see *Note The + `configure.in' input file: configure.in. + + * If you are adding a target configuration, look in `configure.in', + in the "per-target" section. Make sure that your configuration + name is represented in the mapping from target configuration names + to configuration files. If not, add it. Also see *Note The + `configure.in' input file: configure.in. + + * Look in `configure.in' for the variables `files', `links', + `host_makefile_frag', and `target_makefile_frag'. The values + assigned to these variables are the names of the configuration + files, (relative to `srcdir') that the program uses. Make sure + that copies of the files exist for your host. If not, create + them. See also *Note Variables available to `configure.in': + configure variables. + + This should be enough to `configure' for a new host or target +configuration name. Getting the program to compile and run properly +represents the hardest work of any port. + + +File: configure.info, Node: Sites, Prev: Hosts and targets, Up: Porting + +Adding site info +================ + + If some of the `Makefile' defaults are not right for your site, you +can build site-specific `Makefile' fragments. To do this, do the +following. + + * Choose a name for your site. It must currently be less than + eleven characters. + + * If the program source does not have a `./config/' subdirectory, + create it. + + * Create a file called `./config/ms-SITE' where SITE is the name of + your site. In it, set whatever `Makefile' variables you need to + override to match your site's conventions. + + * Configure the program with: + + configure ... --site=SITE + + +File: configure.info, Node: Variables Index, Next: Concept Index, Prev: Porting, Up: Top + +Variable Index +************** + +* Menu: + +* bindir: Install details. +* configdirs: configure variables. +* disable-FEATURE: Invoking configure. +* docdir: Install details. +* enable-FEATURE: Invoking configure. +* exec-prefix: Invoking configure. +* exec_prefix: exec_prefix. +* exec_prefix: Install details. +* files: configure variables. +* floating_point: configure variables. +* gas: configure variables. +* host: configure variables. +* host_cpu: configure variables. +* host_makefile_frag: configure variables. +* host_os: configure variables. +* host_vendor: configure variables. +* includedir: Install details. +* infodir: Install details. +* libdir: Install details. +* links: configure variables. +* Makefile: configure variables. +* manNdir: Install details. +* manNext: Install details. +* mandir: Install details. +* nfp: Invoking configure. +* norecursion: Invoking configure. +* package_makefile_frag: configure variables. +* prefix: prefix. +* prefix: Install details. +* prefix: Invoking configure. +* program-prefix: Invoking configure. +* removing: configure variables. +* rm: Invoking configure. +* site: Invoking configure. +* site_makefile_frag: configure variables. +* srcdir: configure variables. +* srcdir: What configure does. +* srcdir: Invoking configure. +* srcname: configure variables. +* srctrigger: configure variables. +* subdirs: configure variables. +* target: Invoking configure. +* target: configure variables. +* target_cpu: configure variables. +* target_makefile_frag: configure variables. +* target_os: configure variables. +* target_vendor: configure variables. +* tmpdir: Invoking configure. +* verbose: Invoking configure. +* with-PACKAGE: Invoking configure. +* without-PACKAGE: Invoking configure. + + +File: configure.info, Node: Concept Index, Prev: Variables Index, Up: Top + +Concept Index +************* + +* Menu: + +* -disable-FEATURE: Invoking configure. +* -enable-FEATURE: Invoking configure. +* -exec-prefix: Invoking configure. +* -help: Invoking configure. +* -nfp: Invoking configure. +* -norecursion: Invoking configure. +* -prefix: Invoking configure. +* -program-prefix: Invoking configure. +* -rm: Invoking configure. +* -site: Invoking configure. +* -srcdir: Invoking configure. +* -target: Invoking configure. +* -tmpdir: Invoking configure. +* -verbose: Invoking configure. +* -version: Invoking configure. +* -with-PACKAGE: Invoking configure. +* -without-PACKAGE: Invoking configure. +* -s: Invoking configure. +* -v: Invoking configure. +* .gdbinit: What configure does. +* autoconf: Programs. +* bindir: Install details. +* config.guess: config.guess. +* config.guess definition: What configure really does. +* config.status: config.status. +* config.status: What configure does. +* config.status definition: What configure really does. +* config.sub definition: What configure really does. +* config/ subdirectory: What configure really does. +* configdirs: configure variables. +* configure.in: configure.in. +* configure.in definition: What configure really does. +* configure back end: What configure really does. +* configure details: What configure really does. +* disable-FEATURE option: Invoking configure. +* docdir: Install details. +* enable-FEATURE option: Invoking configure. +* exec-prefix option: Invoking configure. +* exec_prefix: Install details. +* floating_point: configure variables. +* help option: Invoking configure. +* host: configure variables. +* includedir: Install details. +* infodir: Install details. +* libdir: Install details. +* Makefile.in definition: What configure really does. +* Makefile extensions: Makefile extensions. +* Makefile fragments: Makefile fragments. +* Makefile generation: Makefile generation. +* Makefile generation: What configure does. +* manNdir: Install details. +* manNext: Install details. +* mandir: Install details. +* nfp option: Invoking configure. +* nfp option: configure variables. +* norecursion option: Invoking configure. +* prefix: Install details. +* prefix option: Invoking configure. +* prefix option: prefix. +* program-prefix option: Invoking configure. +* rm option: Invoking configure. +* rm option: configure variables. +* site option: Invoking configure. +* srcdir: configure variables. +* srcdir: What configure does. +* srcdir option: Invoking configure. +* srcname: configure variables. +* srctrigger: configure variables. +* subdirs: configure variables. +* s option: Invoking configure. +* target: configure variables. +* target option: Invoking configure. +* tmpdir option: Invoking configure. +* verbose option: Invoking configure. +* v option: Invoking configure. +* with-PACKAGE option: Invoking configure. +* with-gnu-as option: configure variables. +* without-PACKAGE option: Invoking configure. +* configure.in interface: configure variables. +* host shell-script fragment: per-host. +* per-host section: per-host. +* per-host section: configure.in. +* per-invocation section: configure.in. +* per-invocation section: Declarations. +* per-target section: configure.in. +* per-target section: per-target. +* post-target section: configure.in. +* post-target section: post-target. +* Abbreviating option names: Invoking configure. +* Adding configure to new programs: Programs. +* Adding hosts and targets: Hosts and targets. +* Adding local info: Makefile fragments. +* Adding site info: Sites. +* Adding site info: Makefile fragments. +* Behind the scenes: What configure really does. +* BISON: Makefile extensions. +* Build directories: What configure does. +* Build directories: Build directories. +* Build variables: Build variables. +* Building for multiple hosts: Build directories. +* Building for multiple targets: Build directories. +* Canonical "triple": configure variables. +* Canonical "triple": configure variables. +* Changing the install directory: prefix. +* clean: Makefile extensions. +* clean-info: Makefile extensions. +* Coding standards extensions: Makefile extensions. +* configure variables: configure variables. +* Configuring for multiple hosts: exec_prefix. +* Cygnus extensions: Makefile extensions. +* Cygnus Support Developer's Kit: What configure does. +* Cygnus Support Developer's Kit: Build variables. +* datadir: Makefile extensions. +* Declarations section: Declarations. +* Default configuration: Makefile generation. +* Detailed usage: Using configure. +* docdir: Makefile extensions. +* Example configure.in: Example. +* Example session: Build directories. +* Example session: Build directories. +* Example session: exec_prefix. +* Example session: Build variables. +* Example session: Makefile extensions. +* Example session: What configure really does. +* Example session: Sites. +* Example session: Invoking configure. +* Example session: Invoking configure. +* For each invocation: Declarations. +* Host: Host. +* Host-specific instructions: per-host. +* Hosts and targets: Hosts and targets. +* includedir: Makefile extensions. +* info: Makefile extensions. +* infodir: Makefile extensions. +* install: Makefile extensions. +* Install details: Install details. +* Install locations: Install locations. +* install-info: Makefile extensions. +* Installation subdirectories: Install details. +* Installing host-independent files: exec_prefix. +* Introduction: What configure does. +* Invoking configure: Invoking configure. +* Local conventions: Makefile fragments. +* Makefile: Makefile extensions. +* mandir: Makefile extensions. +* Minimal configure.in example: Minimal. +* Object directories: Build directories. +* Other files: What configure really does. +* Overview: What configure does. +* Porting with configure: Porting. +* Post-target shell-script fragment: post-target. +* Recursion: What configure does. +* Sample configure.in: Example. +* Sharing host-independent files: exec_prefix. +* Sites: Sites. +* Subdirectories: Install details. +* Symbolic links: What configure does. +* Symbolic links: configure variables. +* Symbolic links: configure variables. +* Target: Target. +* target shell-script fragment: per-target. +* Target-specific instructions: per-target. +* The exec_prefix directory: exec_prefix. +* Truncating option names: Invoking configure. +* Usage: Invoking configure. +* Usage: Invoking configure. +* Usage: detailed: Using configure. +* Using configure: Using configure. +* Variables: Build variables. +* Verbose Output: Invoking configure. +* version: Invoking configure. +* version: Invoking configure. +* What configure does: What configure does. +* What configure really does: What configure really does. +* Where to install: Install locations. + + diff --git a/gnu/usr.bin/binutils/etc/configure.man b/gnu/usr.bin/binutils/etc/configure.man new file mode 100644 index 00000000000..0761854dc43 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/configure.man @@ -0,0 +1,166 @@ +.\" -*- nroff -*- +.\" Copyright (c) 1991, 1992 Cygnus Support +.\" written by K. Richard Pixley +.TH configure 1 "2 February 1993" "cygnus support" "Cygnus Support" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +configure \(em\& prepare source code to be built + +.SH SYNOPSIS +configure HOST [--target=TARGET] [--srcdir=DIR] [--rm] + [--site=SITE] [--prefix=DIR] [--exec_prefix=DIR] + [--program_prefix=DIR] [--tmpdir=DIR] + [--with-PACKAGE[=YES/NO]] [--without-PACKAGE] + [--enable-FEATURE[=YES/NO]] [--disable-FEATURE] + [--norecursion] [--nfp] [-s] [-v] [-V | --version] [--help] + +.SH DESCRIPTION +.I configure +is a program used to prepare souce code to be built. It does this by +generating Makefiles and .gdbinit files, creating symlinks, recursing +in subdirectories, and some other miscellaneous file editing. + +.SH OPTIONS +.I configure +accepts the following options: + +.TP +.I \--target=TARGET +Requests that the sources be configured to target the +.I TARGET +machine. If no target is specified explicitly, the target is assumed +to be the same as the host. + +.TP +.I \--srcdir=DIR +tells configure to find the source in +.I DIR. +Object code is always built in the current directory, +.I `.'. + +.TP +.I \--rm +asks configure to remove a configuration rather than create one. + +.TP +.I \--site=SITE +asks configure to use any site-specific Makefile fragments for +.I SITE +when building Makefiles. + +.TP +.I \--prefix=DIR +sets the location in which to install files to +.I DIR. +The default is "/usr/local". + +.TP +.I \--exec_prefix=DIR +sets the root directory for host-dependent files to +.I DIR. +The default location is the value of +.I prefix. + +.TP +.I \--program_prefix=DIR +configures the source to install programs which have the same names as +common Unix programs, such as "make", in +.I DIR. +Also applies to programs which might be used for cross-compilation. + +.TP +.I \--tmpdir=DIR +sets the directory in which configure creates temporary files to +.I DIR. + +.TP +.I \--with-PACKAGE[=YES/NO] +sets a flag for the build to recognize that +.I PACKAGE +is explicitly present or not present. If +.I \=YES/NO +is nonexistent, the default is +.I YES. +.I \--without-PACKAGE +is equivalent to +.IR \--with-PACKAGE=no . + +.TP +.I \--enable-FEATURE[=YES/NO] +sets a flag for the build to recognize that +.I FEATURE +should be included or not included. If +.I \=YES/NO +is nonexistent, the default is +.I YES. +.I \--disable-FEATURE +is equivalent to +.IR --enable-FEATURE=no . + +.TP +.I \--norecursion +asks that only the current directory be configured. Normally +.I configure +recurs on subdirectories. + +.TP +.I \-nfp +Notifies +.I configure +that all of the specified hosts have +.I no floating point +units. + +.TP +.I \-s +used internally by configure to supress status messages on +subdirectory recursions. Override with +.I \-v + +.TP +.I \-v +verbose output. Asks that configure print status lines for each +directory configured. Normally, only the status lines for the current +directory are printed. + +.TP +.I \--version +.I \-V +prints +.I configure +version number. + +.TP +.I \-help +displays a brief usage summary. + + +.SH FILES +configure.in for each directory's individual needs +.br +Makefile.in Makefile template +.br +config.sub for parsing configuration names +.br +config.guess for guessing HOST when not specified +.br +config.status non-recursively rebuilds current directory + +.SH FILES +.ta \w'gmon.sum 'u +a.out the namelist and text space. +.br +gmon.out dynamic call graph and profile. +.br +gmon.sum summarized dynamic call graph and profile. + +.SH "SEE ALSO" +.RB "`\|" configure "\|'" +entry in +.B +info. diff --git a/gnu/usr.bin/binutils/etc/configure.texi b/gnu/usr.bin/binutils/etc/configure.texi new file mode 100644 index 00000000000..445777491fb --- /dev/null +++ b/gnu/usr.bin/binutils/etc/configure.texi @@ -0,0 +1,1830 @@ +\input texinfo @c -*-texinfo-*- +@setfilename configure.info +@settitle Cygnus configure + +@synindex ky cp + +@setchapternewpage odd + +@ifinfo +@format +START-INFO-DIR-ENTRY +* configure: (configure). Cygnus configure. +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@ifinfo +This document describes the Cygnus Support version of @code{configure}. + +Copyright (C) 1991, 1992, 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 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 Cygnus Support. +@end ifinfo + +@c We should not distribute texinfo files with smallbook enabled. +@c @smallbook +@finalout +@titlepage +@title Cygnus configure +@author K. Richard Pixley +@author Cygnus Support +@page +@cindex copyleft + +@vskip 0pt plus 1filll +Edited January, 1993, by Jeffrey Osier, Cygnus Support. + +Copyright @copyright{} 1991, 1992, 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. + +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 Cygnus Support. +@end titlepage + +@c --------------------------------------------------------------------- +@ifinfo +@node Top +@top Cygnus configure + +This file documents the configuration system used and distributed by +Cygnus Support. + +@menu +* What configure does:: What configure does +* Invoking configure:: Invoking configure---basic usage +* Using configure:: More than you ever wanted to know +* Porting:: How to use configure with new programs +* Variables Index:: +* Concept Index:: +@end menu +@end ifinfo + +@c --------------------------------------------------------------------- +@node What configure does +@chapter What @code{configure} does +@cindex Introduction +@cindex Overview +@cindex What @code{configure} does +@kindex Cygnus Support Developer's Kit + +This manual documents Cygnus @code{configure}, a program which helps to +automate much of the setup activity associated with building large suites of +programs, such the Cygnus Support Developer's Kit. This manual is therefore +geared toward readers who are likely to face the problem of configuring +software in source form before compiling and installing it. We assume you are +an experienced programmer or system administrator. +@ifinfo +For further background on this topic, see @ref{Some Basic Terms, , Apologia +Configure, cfg-paper, On Configuring Development Tools}, by K. Richard +Pixley. +@end ifinfo +@iftex +For further background on this topic, see @cite{On Configuring Development +Tools} by K. Richard Pixley. +@end iftex + +When @code{configure} runs, it does the following things: + +@table @emph +@item @bullet{} creates build directories +@vindex srcdir +@cindex @code{srcdir} +@cindex Build directories +When you run @code{configure} with the @samp{--srcdir} option, it uses the +current directory as the @dfn{build directory}, creating under it a directory +tree that parallels the directory structure of the source directory. If you +don't specify a @samp{srcdir}, @code{configure} first assumes that the source +code you wish to configure is in your current directory; if it finds no +@file{configure.in} input file there, it searches in the directory +@code{configure} itself lies in. (For details, see @ref{Build directories, , +Build directories}.) + +@item @bullet{} generates @file{Makefile} +@cindex @code{Makefile} generation +A @file{Makefile} template from the source directory, usually called +@file{Makefile.in}, is copied to an output file in the build directory which is +most often named @file{Makefile}. @code{configure} places definitions for a +number of standard @file{Makefile} macros at the beginning of the output file. +If @w{@samp{--prefix=@var{dir}}} or @w{@samp{--exec_prefix=@var{dir}}} are +specified on the @code{configure} command line, corresponding @file{Makefile} +variables are set accordingly. If host, target, or site-specific +@file{Makefile} fragments exist, these are inserted into the output file. (For +details, see @ref{Makefile generation, , @code{Makefile} generation}.) + +@item @bullet{} generates @file{.gdbinit} +@cindex @code{.gdbinit} +If the source directory contains a @file{.gdbinit} file and the build directory +is not the same as the source directory, a @file{.gdbinit} file is created in +the build directory. This @file{.gdbinit} file contains commands which allow +the source directory to be read when debugging with the @sc{gnu} debugger, +@code{gdb}. (@xref{Command Files, , Command Files, gdb, Debugging With GDB}.) + +@item @bullet{} makes symbolic links +@cindex Symbolic links +Most build directories require that some symbolic links with generic names are +built pointing to specific files in the source directory. If the system where +@code{configure} runs cannot support symbolic links, hard links are used +instead. (For details, see @ref{configure.in, , The @code{configure.in} input +file}.) + +@item @bullet{} generates @file{config.status} +@cindex @code{config.status} +@code{configure} creates a shell script named @file{config.status} in the build +directory. This shell script, when run from the build directory (usually from +within a @file{Makefile}), will reconfigure the build directory (but not its +subdirectories). This is most often used to have a @file{Makefile} update +itself automatically if a new source directory is available. + +@item @bullet{} calls itself recursively +@cindex Recursion +If the source directory has subdirectories that should also be configured, +@code{configure} is called for each. +@end table + +@c --------------------------------------------------------------------- +@node Invoking configure +@chapter Invoking @code{configure} +@cindex Invoking @code{configure} +@cindex Usage + +Cygnus @code{configure} is a shell script which resides in a source tree. The +usual way to invoke @code{configure} is from the shell, as follows: + +@cindex Example session +@example +eg$ ./configure @var{hosttype} +@end example + +@noindent +This prepares the source in the current directory (@file{.}) to be +compiled for a @var{hosttype} environment. It assumes that you wish to +build programs and files in the default @dfn{build directory} (also the +current directory, @file{.}). If you do not specify a value for +@var{hosttype}, Cygnus @code{configure} will attempt to discover this +information by itself (@pxref{config.guess, , Determining system +information}). For information on @var{hosttype} environments, +@xref{Host, , Host}. + +All @sc{gnu} software is packaged with one or more @code{configure} script(s) +(@pxref{Configuration, , How Configuration Should Work, standards, GNU Coding +Standards}). By using @code{configure} you prepare the source for your +specific environment by selecting and using @file{Makefile} fragments and +fragments of shell scripts, which are prepared in advance and stored with the +source. + +@code{configure}'s command-line options also allow you to specify other aspects +of the source configuration: + +@smallexample + configure @var{hosttype} [--target=@var{target}] [--srcdir=@var{dir}] [--rm] + [--site=@var{site}] [--prefix=@var{dir}] [--exec-prefix=@var{dir}] + [--program-prefix=@var{string}] [--tmpdir=@var{dir}] + [--with-@var{package}[=@var{yes/no}]] [--without-@var{package}] + [--enable-@var{feature}[=@var{yes/no}]] [--disable-@var{feature}] + [--norecursion] [--nfp] [-s] [-v] [-V | --version] [--help] +@end smallexample + +@table @code +@item --target=@var{target} +@cindex @code{--target} +@cindex @code{target} option +@vindex target +Requests that the sources be configured to target the @var{target} machine. If +no target is specified explicitly, the target is assumed to be the same as the +host (i.e., a @dfn{native} configuration). @xref{Host, , Host}, and +@ref{Target, , Target}, for +discussions of each. + +@item --srcdir=@var{dir} +@cindex @code{--srcdir} +@cindex @code{srcdir} option +@vindex srcdir +Direct each generated @file{Makefile} to use the sources located in directory +@var{dir}. Use this option whenever you wish the object code to reside in a +different place from the source code. The @dfn{build directory} is always +assumed to be the directory you call @code{configure} from. See @ref{Build +directories, , Build directories}, for an example. If the source directory is +not specified, @code{configure} assumes that the source is in your current +directory. If @code{configure} finds no @file{configure.in} there, it searches +in the same directory that the @code{configure} script itself lies in. +Pathnames specified (Values for @var{dir}) can be either absolute relative to +the @emph{build} directory. + +@item --rm +@cindex @code{--rm} +@cindex @code{rm} option +@vindex rm +@emph{Remove} the configuration specified by @var{hosttype} and the other +command-line options, rather than create it. + +@c FIXME: check @ref +@quotation +@emph{Note:} We recommend that you use @samp{make distclean} rather than +use this option; see @ref{Invoking make,,Invoking @code{make},make,GNU +Make}, for details on @samp{make distclean}. +@end quotation + +@item --site=@var{site} +@cindex @code{--site} +@cindex @code{site} option +@vindex site +Generate the @file{Makefile} using site-specific @file{Makefile} fragments for +@var{site}. @xref{Makefile fragments, , Adding information about local +conventions}. + +@item --prefix=@var{dir} +@cindex @code{--prefix} +@cindex @code{prefix} option +@vindex prefix +Configure the source to install programs and files under directory @var{dir}. + +This option sets the variable @samp{prefix}. Each generated @file{Makefile} +will have its @samp{prefix} variables set to this value. (@xref{What configure +really does, , What @code{configure} really does}.) + +@item --exec-prefix=@var{dir} +@cindex @code{--exec-prefix} +@cindex @code{exec-prefix} option +@vindex exec-prefix +Configure the source to install @dfn{host dependent} files in @var{dir}. + +This option sets the variable @samp{exec_prefix}. Each generated +@file{Makefile} will have its @samp{exec_prefix} variables set to this value. +(@xref{What configure really does, , What @code{configure} really does}.) + +@item --program-prefix=@var{string} +@cindex @code{--program-prefix} +@cindex @code{program-prefix} option +@vindex program-prefix +Configure the source to install certain programs using @var{string} as a +prefix. This applies to programs which might be used for cross-compilation, +such as the compiler and the binary utilities, and also to programs which have +the same names as common Unix programs, such as @code{make}. + +This option sets the variable @samp{program_prefix}. Each generated +@file{Makefile} will have its @samp{program_prefix} variables set to this +value. (@xref{What configure really does, , What @code{configure} really +does}.) + +@item --tmpdir=@var{tmpdir} +@cindex @code{--tmpdir} +@cindex @code{tmpdir} option +@vindex tmpdir +Use the directory @var{tmpdir} for @code{configure}'s temporary files. The +default is the value of the environment variable @w{@code{TMPDIR}}, or +@file{/tmp} if the environment variable is not set. + +@item --with-@var{package}[=@var{yes/no}] +@itemx --without-@var{package} +@cindex @code{--with-@var{package}} +@cindex @code{with-@var{package}} option +@vindex with-@var{package} +@cindex @code{--without-@var{package}} +@cindex @code{without-@var{package}} option +@vindex without-@var{package} +Indicate that @var{package} is present, or not present, depending on +@var{yes/no}. If @var{yes/no} is nonexistent, its value is assumed to be +@code{yes}. @samp{--without-@var{package}} is equivalent to +@samp{--with-@var{package}=no}. + +For example, if you wish to configure the program @code{gcc} for a Sun +SPARCstation running SunOS 4.x, and you want @code{gcc} to use the +@sc{gnu} linker @code{ld}, you can configure @code{gcc} using + +@cindex Example session +@smallexample +eg$ configure --with-gnu-ld sun4 +@end smallexample + +@noindent +@xref{What configure really does, , What @code{configure} really does}, for +details. See the installation or release notes for your particular package for +details on which other @var{package} options are recognized. +@c FIXME - need to include info about --with-* in other dox! + +@item --enable-@var{feature}[=@var{yes/no}] +@itemx --disable-@var{feature} +@cindex @code{--enable-@var{feature}} +@cindex @code{enable-@var{feature}} option +@vindex enable-@var{feature} +@cindex @code{--disable-@var{feature}} +@cindex @code{disable-@var{feature}} option +@vindex disable-@var{feature} +Include @var{feature}, or not, depending on @var{yes/no}. If @var{yes/no} is +nonexistent, its value is assumed to be @code{yes}. +@samp{--disable-@var{feature}} is equivalent to +@samp{--enable-@var{feature}=no}. + +@noindent +@xref{What configure really does, , What @code{configure} really does}, for +details. See the installation or release notes for your particular package for +details on which other @var{feature} options are recognized. +@c FIXME - need to include info about --enable-* in other dox! + +@item --norecursion +@cindex @code{--norecursion} +@cindex @code{norecursion} option +@vindex norecursion +Configure only this directory; ignore any subdirectories. This is used by the +executable shell script @file{config.status} to reconfigure only the current +directory; it is most often used non-interactively, when @code{make} is +invoked. (@xref{config.status, , @code{config.status}}.) + +@item --nfp +@cindex @code{--nfp} +@cindex @code{nfp} option +@vindex nfp +Assume that the intended @var{hosttype} has no floating point unit. + +@item -s +@cindex @code{-s} +@cindex @code{s} option +Suppress status output. This option is used internally by +@code{configure} when calling itself recursively in subdirectories. You +can override this option with the @code{--verbose} option. + +@item -v +@itemx --verbose +@cindex @code{-v} +@cindex @code{--verbose} +@cindex @code{v} option +@cindex @code{verbose} option +@cindex Verbose Output +@vindex verbose +Print status lines for each directory configured. Normally, only the +status lines for the initial working directory are printed. + +@item --version +@itemx -V +@cindex version +@cindex @code{--version} +@cindex version +Print the @code{configure} version number. + +@item --help +@cindex Usage +@cindex @code{--help} +@cindex @code{help} option +Print a short summary of how to invoke @code{configure}. +@end table + +@cindex Abbreviating option names +@cindex Truncating option names +@cartouche +@emph{Note:} You may introduce options with a single dash, @samp{-}, rather +than two dashes, @samp{--}. However, you may not be able to truncate long +option names when using a single dash. When using two dashes, options may be +abbreviated as long as each option can be uniquely identified. For example, +@smallexample +eg$ configure --s=/u/me/src @var{hosttype} +@end smallexample +@noindent +is ambiguous, as @w{@samp{--s}} could refer to either @w{@samp{--site}} or +@w{@samp{--srcdir}}. However, +@smallexample +eg$ configure --src=/u/me/src @var{hosttype} +@end smallexample +@noindent +is a valid abbreviation. +@end cartouche + + +@c ======================================================================== +@node Using configure +@chapter Using @code{configure} +@cindex Using @code{configure} +@cindex Detailed usage +@cindex Usage: detailed + +@code{configure} prepares source directories for building programs in +them. ``Configuring'' is the process of preparing software to compile +correctly on a given @dfn{host}, for a given @dfn{target}. + +@code{configure} subsequently writes a configured @file{Makefile} from a +pre-built template; @code{configure} uses variables that have been set in the +configuring process to determine the values of some variables in the +@file{Makefile}. Because of this we will refer to both @code{configure} +variables and @file{Makefile} variables. This convention allows us to +determine where the variable should be set initially, in either +@file{configure.in} or @file{Makefile.in}. + +@menu +* What configure really does:: What configure really does +* configure.in:: The configure.in input file +* Install locations:: Where to install things once they are built +* Host:: Telling configure what will source will be built +* Target:: Telling configure what the source will target +* Makefile fragments:: Adding information about local conventions +* Makefile extensions:: Extensions to the GNU coding standards +@end menu + +@c --------------------------------------------------------------------- +@node What configure really does +@section What @code{configure} really does +@cindex What @code{configure} really does +@cindex Behind the scenes +@cindex @code{configure} back end +@cindex @code{configure} details + +Cygnus @code{configure} is a shell script that sets up an environment in +which your programs will compile correctly for your machine and +operating system, and will install in proper places. @code{configure} +accomplishes this task by doing the following: + +@itemize @bullet +@item +it generates a @file{Makefile} from a custom template called +@file{Makefile.in} in each relevant source directory; + +@item +it customizes the build process to your specifications; you set certain +variables for @code{configure}, either on the command line or in the +file @file{configure.in}, which subsequently sets variables in each +generated @file{Makefile} to be used by @code{make} when actually +building the software; + +@item +it creates @dfn{build directories}, places for your code to be compiled +in before being installed; + +@item +it generates a @file{.gdbinit} in the build directory, if needed, to +communicate to @code{gdb} where to find the program's source code; + +@item +it generates a shell script called @file{config.status} +which is used most often by the @file{Makefile} to reconfigure itself; + +@item +it recurses in subdirectories, setting up entire trees so that they build +correctly; if @code{configure} finds another @code{configure} script +further down in a given source tree, it knows to use this script and not +recur. +@end itemize + +For the sake of safety (i.e., in order to prevent broken installations), the +@sc{gnu} coding standards call for software to be @dfn{configured} in such a +way that an end user trying to build a given package will be able to do so by +affecting a finite number of variables. All @sc{gnu} software comes with an +executable @code{configure} shell script which sets up an environment within a +build directory which will correctly compile your new package for your host +(or, alternatively, whatever host you specify to @code{configure}). +@ifinfo +For further background on this topic, see @ref{Some Basic Terms, , Apologia +Configure, cfg-paper, On Configuring Development Tools}, by K. Richard +Pixley. +@end ifinfo +@iftex +For further background on this topic, see @cite{On Configuring Development +Tools} by K. Richard Pixley. +@end iftex + +Use @code{configure} to set for the build process: + +@itemize @bullet +@item +correct values for certain variables; + +@item +which type of host you wish to configure a given package for +(@pxref{Host, , Host}); + +@item +where you want to install this package (by using @samp{prefix}, +@samp{exec-prefix} and @samp{program-prefix}; @pxref{Install details, , +Full descriptions of all installation directories}); + +@item +optionally, which type of machine you wish to @dfn{target} this +package's output to (@pxref{Target, , Target}); + +@item +which other @sc{gnu} packages are already installed and available to +this particular build (by using the @samp{--with-@var{package}} option; +@pxref{Invoking configure, , Invoking @code{configure}}); + +@item +where to place temporary files (by using the @samp{--tmpdir=@var{dir}} +option; @pxref{Invoking configure, , Invoking @code{configure}}); + +@item whether to recur in subdirectories (changeable through the +@w{@samp{--norecursion}} option; @pxref{Invoking configure, , Invoking +@code{configure}}). +@end itemize + +@code{configure} uses a few other files to complete its tasks. These are +discussed in detail where noted. + +@table @code +@cindex Other files +@item configure.in +@cindex @code{configure.in} definition +Input file for @code{configure}. Shell script fragments reside here. +@xref{configure.in, , The @code{configure.in} input file}. + +@item Makefile.in +@cindex @code{Makefile.in} definition +Template which @code{configure} uses to build a file called @file{Makefile} in +the @dfn{build directory}. @xref{Makefile generation, , @code{Makefile} +generation}. + +@item config.sub +@cindex @code{config.sub} definition +Shell script used by @code{configure} to expand referents to the +@var{hosttype} argument into a single specification of the form +@w{@var{cpu-vendor-os}}. For instance, on the command line you can +specify + +@cindex Example session +@example +eg$ ./configure sun4 +@end example + +@noindent +to configure for a Sun SPARCstation running SunOS 4.x. @code{configure} +consults @code{config.sub} to find that the three-part specification for this +is + +@example +sparc-sun-sunos4.1.1 +@end example + +@noindent +which notes the @var{cpu} as @samp{sparc}, the @var{manufacturer} as @samp{sun} +(Sun Microsystems), and the @var{os} (operating system) as @samp{sunos4.1.1}, +the SunOS 4.1.1 release. @xref{configure variables, , Variables available to @code{configure}}. + +@item config.guess +@cindex @code{config.guess} definition +If you do not put the @var{hosttype} argument on the command line, +@code{configure} uses the @code{config.guess} shell script to make an +analysis of your machine (it assumes that you wish to configure your +software for the type of machine on which you are running). The output +of @code{config.guess} is a three-part identifier as described above. + +@item config.status +@cindex @code{config.status} definition +The final step in configuring a directory is to create a shell script, +@code{config.status}. The main purpose of this file is to allow the +@file{Makefile} for the current directory to rebuild itself, if +necessary. @xref{config.status, , @code{config.status}}. + +@item config/* +@cindex @code{config/} subdirectory +@code{configure} uses three types of @file{Makefile} @dfn{fragments}, which +reside in the directory @file{@var{srcdir}/config/}. @xref{Makefile fragments, +, Adding information about local conventions}. +@end table + +@menu +* Build variables:: Variable-spaghetti made simple +* Build directories:: Build directories described well +* Makefile generation:: To build a Makefile +* config.guess:: Be vewwy quiet, I'm hunting system information +* config.status:: To rebuild a Makefile +@end menu + +@c --------------------------------------------------------------------- +@node Build variables +@subsection Build variables +@cindex Build variables +@cindex Cygnus Support Developer's Kit +@cindex Variables + +There are several variables in the build process which you can control through +build programs such as @code{make}. These include machine definitions, local +conventions, installation locations, locations for temporary files, etc. This +data is accessible through certain variables which are configurable in the +build process; we refer to them as @dfn{build variables}. + +For lists of build variables which you can affect by using @code{configure}, +see @ref{configure variables, , Variables available to @code{configure.in}}, +and @ref{Install details, , Full descriptions of all installation directories}. + +Generally, build variables, which are used by the @file{Makefile} to +determine various aspects of the build and installation processes, are +changeable with command-line options to @code{configure}. In most large +suites of programs, like the Cygnus Support Developer's Kit, the +individual programs reside in several subdirectories of a single source +code ``tree''. All of these subdirectories need to be configured with +information relative to the @dfn{build directory}, which is not known +until @code{configure} is run. Unless specified otherwise, +@code{configure} recursively configures every subdirectory in the source +tree. + +Build variables are passed from @code{configure} directly into the +@file{Makefile}, and use the same names (except that dashes are +transformed into underbars; for example, when you specify the option +@samp{--exec-prefix} on the command line, the @file{Makefile} variable +@samp{exec_prefix} is set). In other words, if you specify + +@cindex Example session +@example +eg$ ./configure --prefix=/usr/gnu/local @dots{} @var{hosttype} +@end example + +@noindent +on the command line, @code{configure} sets an variable called @samp{prefix} to +@samp{/usr/gnu/local}, and passes this into the @file{Makefile} in the same +manner. After this command, each @file{Makefile} generated by @code{configure} +will contain a line that reads: + +@example +prefix = /usr/gnu/local +@end example + +For a list of the @file{Makefile} variables @code{configure} can change, and +instructions on how to change them, see @ref{configure variables, , Variables +available to @code{configure.in}}, and @ref{Invoking configure, , Invoking +@code{configure}}. + +@c --------------------------------------------------------------------- +@node Build directories +@subsection Build directories +@cindex Build directories +@cindex Object directories +@cindex Building for multiple hosts +@cindex Building for multiple targets + +By default, @code{configure} builds a @file{Makefile} and symbolic links in the +same directory as the source files. This default works for many cases, but it +has limitations. For instance, using this approach, you can only build object +code for one host at a time. + +We refer to each directory where @code{configure} builds a @file{Makefile} as +a @dfn{build directory}. + +The build directory for any given build is always the directory from which you +call @code{configure}, or @file{.} relative to your prompt. The default +@dfn{source directory}, the place @code{configure} looks to find source code, +is also @file{.}. For instance, if we have a directory @file{/gnu-stuff/src/} +that is the top branch of a tree of @sc{gnu} source code we wish to configure, +then the program we will use to configure this code is +@file{/gnu-stuff/src/configure}, as follows. (Assume for the sake of argument +that our machine is a sun4.) + +@cindex Example session +@smallexample +@group +eg$ cd /gnu-stuff/src +eg$ ./configure sun4 +Created "Makefile" in /gnu-stuff/src +eg$ +@end group +@end smallexample + +We just configured the code in @file{/gnu-stuff/src} to run on a Sun +SPARCstation using SunOS 4.x by creating a @file{Makefile} in +@file{/gnu-stuff/src}. By default, we also specified that when this code is +built, the object code should reside in the same directory, +@file{/gnu-stuff/src}. + +However, if we wanted to build this code for more than one host, we would be in +trouble, because the new configuration would write over the old one, destroying +it in the process. What we can do is to make a new @dfn{build directory} and +configure from there. Running @code{configure} from the new directory will +place a correct @file{Makefile} and a @file{config.status} in this new file. +That is all @code{configure} does; we must run @code{make} to generate any +object code. + +The new @file{Makefile} in @file{/gnu-stuff/sun4-obj}, created from the +template file @file{/gnu-stuff/src/Makefile.in}, contains all the information +needed to build the program. + +@cindex Example session +@smallexample +@group +eg$ mkdir /gnu-stuff/sun4-obj +eg$ cd /gnu-stuff/sun4-obj +eg$ ../src/configure --srcdir=../src sun4 +Created "Makefile" in /gnu-stuff/sun4-obj +eg$ ls +Makefile config.status +eg$ make all info install install-info clean +@var{compilation messages@dots{}} +eg$ mkdir /gnu-stuff/solaris2 +eg$ cd /gnu-stuff/solaris2 +eg$ ../src/configure --srcdir=../src sol2 +Created "Makefile" in /gnu-stuff/solaris2 +eg$ ls +Makefile config.status +eg$ make all info install install-info clean +@var{compilation messages@dots{}} +@end group +@end smallexample + +We can repeat this for other configurations of the same software simply +by making a new build directory and reconfiguring from inside it. If +you do not specify the @var{hosttype} argument, @code{configure} +will attempt to figure out what kind of machine and operating system you +happen to be using. @xref{config.guess, , Determining system +information}. Of course, this may not always be the configuration you +wish to build. + +@emph{Caution:} If you build more than one configuration for a single program, +remember that you must also specify a different @samp{--prefix} for each +configuration at configure-time. Otherwise, both configurations will be +installed in the same default location (@file{/usr/local}); the configuration +to be installed last would overwrite previously installed configurations. + +@c --------------------------------------------------------------------- +@node Makefile generation +@subsection @code{Makefile} generation +@cindex @code{Makefile} generation + +Cygnus @code{configure} creates a file called @file{Makefile} in the build +directory which can be used with @code{make} to automatically build a given +program or package. @code{configure} also builds a @file{Makefile} for each +relevant subdirectory for a given program or package (irrelevant subdirectories +would be those which contain no code which needs configuring, and which +therefore have no @code{configure} input file @file{configure.in} and no +@file{Makefile} template @file{Makefile.in}). @xref{Running, @code{make} +Invocation, How to Run @code{make}, make, GNU Make}, for details on using +@code{make} to compile your source code. + +Each @file{Makefile} contains variables which have been configured for a +specific build. These build variables are determined when @code{configure} is +run. All build variables have defaults. By default, @code{configure} +generates a @file{Makefile} which specifies: + +@cindex Default configuration +@itemize @bullet +@item a @dfn{native} build, which is to occur + +@item in the current directory, and which will be installed + +@item in the default installation directory (@file{/usr/local}) when the code +is compiled with @code{make}. +@end itemize + +@noindent +Variables are changeable through command-line options to @code{configure} +(@pxref{Invoking configure, , Invoking @code{configure}}). + +If you are porting a new program and intend to use @code{configure}, see +@ref{Porting, , Porting with @code{configure}}, as well as @ref{Makefiles, , +Writing Makefiles, make, GNU Make}, and @ref{Makefiles, , Makefile Conventions, +standards, GNU Coding Standards}. + +@c --------------------------------------------------------------------- +@node config.guess +@subsection Determining system information +@cindex @code{config.guess} + +The shell script @code{config.guess} is called when you do not specify a +@var{hosttype} on the command line to @code{configure}. @code{config.guess} +acquires available system information from your local machine through the shell +command @code{uname}. It compares this information to a database and attempts +to determine a usable three-part system identifier (known as a @dfn{triple}) to +use as your @var{hosttype}. @xref{What configure really does, , What +@code{configure} really does}, to see how this information is used. + +@emph{Note:} If you do not specify a @var{hosttype} on the command line, +@code{configure} will attempt to configure your software to run on the machine +you happen to be using. This may not be the configuration you desire. + +@c --------------------------------------------------------------------- +@node config.status +@subsection @code{config.status} +@cindex @code{config.status} + +The final step in configuring a directory is to create an executable shell +script, @file{config.status}. The main purpose of this file is to allow the +@file{Makefile} for the current directory to rebuild itself, if necessary. It +is usually run from within the @file{Makefile}. @xref{Makefile extensions, , +Extensions to the @sc{gnu} coding standards}. + +@file{config.status} also contains a record of the @code{configure} session +which created it. + +@c --------------------------------------------------------------------- +@node configure.in +@section The @code{configure.in} input file +@cindex @code{configure.in} + +A @file{configure.in} file for Cygnus @code{configure} consists of a +@dfn{per-invocation} section, followed by a @dfn{per-host} section, followed by +a @dfn{per-target} section, optionally followed by a @dfn{post-target} section. +Each section is a shell script fragment, which is executed by the +@code{configure} shell script at an appropriate time. Values are passed among +@code{configure} and the shell fragments through a set of shell variables. +When each section is being interpreted by the shell, the shell's current +directory is the build directory, and any files created by the section (or +referred to by the section) will be relative to the build directory. To +reference files in other places (such as the source directory), prepend a shell +variable such as @samp{$(srcdir)/} to the desired file name. + +@cindex @i{per-invocation} section +The beginning of the @file{configure.in} file begins the @dfn{per-invocation} +section. + +@cindex @i{per-host} section +A line beginning with @samp{# per-host:} begins the @dfn{per-host} section. + +@cindex @i{per-target} section +A line beginning with @samp{# per-target:} begins the @dfn{per-target} section. + +@cindex @i{post-target} section +If it exists, the @dfn{post-target} section begins with @samp{# post-target:}. + +@menu +* configure variables:: Variables available to configure.in +* Minimal:: A minimal configure.in +* Declarations:: For each invocation +* per-host:: Host-specific instructions +* per-target:: Target-specific instructions +* post-target:: Instructions to be executed after target info +* Example:: An example configure.in +@end menu + +@c --------------------------------------------------------------------- +@node configure variables +@subsection Variables available to @code{configure.in} +@cindex @file{configure.in} interface +@cindex configure variables + +The following variables pass information between the standard parts of +@code{configure} and the shell-script fragments in @file{configure.in}: + +@table @code +@item srctrigger +@cindex @code{srctrigger} +@vindex srctrigger +Contains the name of a source file that is expected to live in the source +directory. You must usually set this in the @dfn{per-invocation} section of +@file{configure.in}. @code{configure} tests to see that this file exists. If +the file does not exist, @code{configure} prints an error message. This is +used as a sanity check that @file{configure.in} matches the source directory. + +@item srcname +@cindex @code{srcname} +@vindex srcname +Contains the name of the source collection contained in the source directory. +You must usually set this in the @dfn{per-invocation} section of +@file{configure.in}. If the file named in @samp{srctrigger} does not exist, +@code{configure} uses the value of @samp{srcname} when it prints the error +message. + +@item configdirs +@cindex @code{configdirs} +@vindex configdirs +Contains the names of any subdirectories in which @code{configure} should +recurse. You must usually set this in the @dfn{per-invocation} section of +@file{configure.in}. +If @file{Makefile.in} contains a line starting with @samp{SUBDIRS =}, +then it will be replaced with an assignment to @samp{SUBDIRS} using +the value of @samp{configdirs} (if @samp{subdirs} is empty). This can +be used to determine which directories to configure and build depending +on the host and target configurations. +@c Most other matching makefile/config vars use the same name. Why not +@c this? (FIXME). +@c Can we get rid of SUBDIRS-substitution? It doesn't work well with subdirs. +Use @samp{configdirs} (instead of the @samp{subdirs} variable +described below) if you want to be able to partition the +subdirectories, or use independent @file{Makefile} fragments. +Each subdirectory can be independent, and independently reconfigured. + +@item subdirs +@cindex @code{subdirs} +@vindex subdirs +Contains the names of any subdirectories where @code{configure} should create a +@file{Makefile} (in addition to the current directory), @emph{without} +recursively running @code{configure}. Use @samp{subdirs} (instead of the +@samp{configdirs} variable described above) if you want to configure all of the +directories as a unit. Since there is a single invocation of @code{configure} +that configures many directories, all the directories can use the same +@file{Makefile} fragments, and the same @code{configure.in}. + +@item host +@cindex @code{host} +@cindex Canonical ``triple'' +@vindex host +Contains the full configuration name for the host (generated by the script +@file{config.sub} from the name that you entered). This is a three-part +name (commonly referred to as a @dfn{triple}) of the form +@var{cpu}-@var{vendor}-@var{os}. + +There are separate variables @samp{host_cpu}, @samp{host_vendor}, and +@samp{host_os} that you can use to test each of the three parts; this variable +is useful, however, for error messages, and for testing combinations of the +three components. + +@item host_cpu +@vindex host_cpu +Contains the first element of the canonical triple representing the host +as returned by @file{config.sub}. This is occasionally used to +distinguish between minor variations of a particular vendor's operating +system and sometimes to determine variations in binary format between +the host and the target. + +@item host_vendor +@vindex host_vendor +Contains the second element of the canonical triple representing the host as +returned by @file{config.sub}. This is usually used to distinguish among the +numerous variations of @emph{common} operating systems. +@c "@emph{common} OS" doesn't convey much to me. Is this meant to cover +@c cases like Unix, widespread but with many variations? + +@item host_os +@vindex host_os +Contains the the third element of the canonical triple representing the +host as returned by @file{config.sub}. + +@item target +@cindex @code{target} +@cindex Canonical ``triple'' +@vindex target +Contains the full configuration name (generated by the script @file{config.sub} +from the name that you entered) for the target. Like the host, this is a +three-part name of the form @var{cpu}-@var{vendor}-@var{os}. + +There are separate variables @samp{target_cpu}, @samp{target_vendor}, and +@samp{target_os} that you can use to test each of the three parts; this +variable is useful, however, for error messages, and for testing combinations +of the three components. + +@item target_cpu +@vindex target_cpu +Contains the first element of the canonical triple representing the target as +returned by @file{config.sub}. This variable is used heavily by programs which +are involved in building other programs, like the compiler, assembler, linker, +etc. Most programs will not need the @samp{target} variables at all, but this +one could conceivably be used to build a program, for instance, that operated +on binary data files whose byte order or alignment differ from the system where +the program is running. + +@item target_vendor +@vindex target_vendor +Contains the second element of the canonical triple representing the target as +returned by @file{config.sub}. This is usually used to distinguish among the +numerous variations of @emph{common} operating systems or object file +formats. It is sometimes used to switch between different flavors of user +interfaces. +@c above query re "@emph{common} OS" applies here too + +@item target_os +@vindex target_os +Contains the the third element of the canonical triple representing the +target as returned by @file{config.sub}. This variable is used by +development tools to distinguish between subtle variations in object +file formats that some vendors use across operating system releases. It +might also be use to decide which libraries to build or what user +interface the tool should provide. + +@item floating_point +@cindex @code{floating_point} +@cindex @code{nfp} option +@vindex floating_point +Set to @samp{no} if you invoked @code{configure} with the @samp{--nfp} +command-line option, otherwise it is empty. This is a request to target +machines with @dfn{no floating point} unit, even if the targets ordinarily have +floating point units available. + +@item gas +@cindex @code{with-gnu-as} option +@vindex gas +Set to @samp{true} if you invoked @code{configure} with the +@w{@samp{--with-gnu-as}} command line option, otherwise it is empty. This is a +request to assume that the specified @var{hosttype} machine has @sc{gnu} @code{as} +available even if it ordinarily does not. + +@item srcdir +@cindex @code{srcdir} +@vindex srcdir +Set to the name of the directory containing the source for this program. +This will be different from @file{.} if you have specified the +@samp{--srcdir=@var{dir}} option. @samp{srcdir} can indicate either an +absolute path or a path relative to the build directory. + +@item package_makefile_frag +@vindex package_makefile_frag +If set in @file{configure.in}, this variable should be the name a file relative +to @samp{srcdir} to be included in the resulting @file{Makefile}. If the named +file does not exist, @code{configure} will print a warning message. This +variable is not set by @code{configure}. + +@item host_makefile_frag +@vindex host_makefile_frag +If set in @file{configure.in}, this variable should be the name a file relative +to @samp{srcdir} to be included in the resulting @file{Makefile}. If the named +file does not exist, @code{configure} will print a warning message. This +variable is not set by @code{configure}. + +@item target_makefile_frag +@vindex target_makefile_frag +If set in @file{configure.in}, this variable should be the name of a file, +relative to @samp{srcdir}, to be included in the resulting @file{Makefile}. If +the named file does not exist, @code{configure} will print a warning message. +This variable is not set by @code{configure}. + +@item site_makefile_frag +@vindex site_makefile_frag +Set to a file name representing to the default @file{Makefile} fragment for +this host. It may be set in @file{configure.in} to override this default. +Normally @samp{site_makefile_frag} is empty, but will have a value if you +specify @samp{--site=@var{site}} on the command line. +@ignore -- this doesn't fit +It is probably not a good idea to override this variable from +@file{configure.in}, since that may defeat the @code{configure} user's +intentions. +@end ignore + +@item Makefile +@vindex Makefile +Set to the name of the generated @file{Makefile}. Normally this value is +precisely @file{Makefile}, but some programs may want something else. + +@item removing +@cindex @code{rm} option +@vindex removing +Normally empty but will be set to some non-null value if you specified +@samp{--rm} on the command line. That is, if @samp{removing} is not empty, +then @code{configure} is @emph{removing} a configuration rather than creating +one. + +@item files +@cindex Symbolic links +@vindex files +If this variable is not empty following the @dfn{per-target} section, +then each word in its value will be the target of a symbolic link named +in the corresponding word from the @samp{links} variable. + +@item links +@cindex Symbolic links +@vindex links +If the @samp{files} variable is not empty following the @dfn{per-target} +section, then @code{configure} creates symbolic links with the first word of +@samp{links} pointing to the first word of @samp{files}, the second word of +@samp{links} pointing to the second word of @samp{files}, and so on. +@end table + +@c --------------------------------------------------------------------- +@node Minimal +@subsection A minimal @code{configure.in} +@cindex Minimal @file{configure.in} example + +A minimal @file{configure.in} consists of four lines. + +@example +srctrigger=foo.c +srcname="source for the foo program" +# per-host: +# per-target: +@end example + +The @samp{# per-host:} and @samp{# per-target:} lines divide the file into the +three required sections. The @samp{srctrigger} line names a file. +@code{configure} checks to see that this file exists in the source directory +before configuring. If the @samp{srctrigger} file does not exist, +@code{configure} uses the value of @samp{srcname} to print an error message +about not finding the source. + +This particular example uses no links, and only the default host, +target, and site-specific @file{Makefile} fragments if they exist. + +@c --------------------------------------------------------------------- +@node Declarations +@subsection For each invocation +@cindex For each invocation +@cindex Declarations section +@cindex @i{per-invocation} section + +@code{configure} invokes the entire shell script fragment from the start of +@file{configure.in} up to a line beginning with @w{@samp{# per-host:}} +immediately after parsing command line arguments. The variables +@samp{srctrigger} and @samp{srcname} @emph{must} be set here. + +You might also want to set the variables @samp{configdirs} and +@samp{package_makefile_frag} here. + +@c --------------------------------------------------------------------- +@node per-host +@subsection Host-specific instructions +@cindex Host-specific instructions +@cindex @i{host} shell-script fragment +@cindex @i{per-host} section + +The @dfn{per-host} section of @file{configure.in} starts with the line that +begins with @w{@samp{# per-host:}} and ends before a line beginning with +@w{@samp{# per-target:}}. @code{configure} invokes the commands in the +@dfn{per-host} section when determining host-specific information. + +This section usually contains a big @code{case} statement using the variable +@samp{host} to determine appropriate values for @samp{host_makefile_frag} and +@samp{files}, although @samp{files} is not usually set here. Usually, it is +set at the end of the @dfn{per-target} section after determining the names of +the target specific configuration files. + +@c --------------------------------------------------------------------- +@node per-target +@subsection Target-specific instructions +@cindex Target-specific instructions +@cindex target shell-script fragment +@cindex @i{per-target} section + +The @dfn{per-target} section of @file{configure.in} starts with the line that +begins with @w{@samp{# per-target:}} and ends before the line that begins with +@w{@samp{# post-target:}}, if there is such a line. Otherwise the +@dfn{per-target} section extends to the end of the file. @code{configure} +invokes the commands in the @dfn{per-target} section when determining +target-specific information, and before building any files, directories, or +links. + +This section usually contains a big @code{case} statement using the variable +@samp{target} to determine appropriate values for @samp{target_makefile_frag} +and @samp{files}. The last lines in the @dfn{per-target} section normally set +the variables @samp{files} and @samp{links}. + +@c --------------------------------------------------------------------- +@node post-target +@subsection Instructions to be executed after target info +@cindex Post-target shell-script fragment +@cindex @i{post-target} section + +The @dfn{post-target} section is optional. If it exists, the +@samp{post-target} section starts with a line beginning with @w{@samp{# +Post-target:}} and extends to the end of the file. If it exists, +@code{configure} invokes this section once for each target after +building all files, directories, or links. + +This section is seldom needed, but you can use it to edit the @file{Makefile} +generated by @code{configure}. + +@c --------------------------------------------------------------------- +@node Example +@subsection An example @code{configure.in} +@cindex Example @file{configure.in} +@cindex Sample @file{configure.in} +@c @cindex @code{bison} @file{configure.in} +@c this won't be the bison configure.in for long.. need better example + +Here is a small example of a @file{configure.in} file. + +@cartouche +@example +@group +# This file is a collection of shell script fragments +# used to tailor a template configure script as +# appropriate for this directory. For more information, +# see configure.texi. + +configdirs= +srctrigger=warshall.c +srcname="bison" + +# per-host: +case "$@{host@}" in +m88k-motorola-*) + host_makefile_frag=config/mh-delta88 + ;; +esac + +# per-target: +files="bison_in.hairy" +links="bison.hairy" + +# post-target: +@end group +@end example +@end cartouche + +@c --------------------------------------------------------------------- +@node Install locations +@section Install locations +@cindex Where to install +@cindex Install locations + +Using the default configuration, @samp{make install} creates a single tree of +files, some of which are programs. The location of this tree is determined by +the value of the variable @samp{prefix}. The default value of @samp{prefix} is +@samp{/usr/local}. This is often correct for native tools installed on only +one host. + +@menu +* prefix:: Changing the default install directory +* exec_prefix:: How to separate host independent files + from host dependent files when + installing for multiple hosts +* Install details:: Full descriptions of all installation subdirectories +@end menu + +@c --------------------------------------------------------------------- +@node prefix +@subsection Changing the default install directory +@cindex Changing the install directory +@cindex @code{prefix} option +@vindex prefix + +In the default configuration, all files are installed in subdirectories +of @file{/usr/local}. The location is determined by the value of +the @code{configure} variable @samp{prefix}; in turn, this determines the +value of the @file{Makefile} variable of the same name (@samp{prefix}). + +You can also set the value of the @file{Makefile} variable @samp{prefix} +explicitly each time you invoke @code{make} if you are so inclined. However, +because many programs have this location compiled in, you must specify the +@samp{prefix} value consistently on each invocation of @code{make}, or you will +end up with a broken installation. + +To make this easier, the value of the @code{configure} variable +@samp{prefix} can be set on the command line to @code{configure} +using the option @samp{--prefix=}. + +@c --------------------------------------------------------------------- +@node exec_prefix +@subsection Installing for multiple hosts +@cindex Configuring for multiple hosts +@cindex Sharing host-independent files +@cindex Installing host-independent files +@cindex The @code{exec_prefix} directory +@vindex exec_prefix + +By default, host dependent files are installed in subdirectories of +@file{$(exec_prefix)}. The location is determined by the value of the +@code{configure} variable @samp{exec_prefix}, which determines the value of the +@file{Makefile} variable @samp{exec_prefix}. This makes it easier to install +for a single host, and simplifies changing the default location for the install +tree. The default doesn't allow for multiple hosts to effectively share +host independent files, however. + +To configure so that multiple hosts can share common files, use something like: + +@cindex Example session +@smallexample +configure @var{host1} -prefix=/usr/gnu -exec_prefix=/usr/gnu/H-host1 +make all info install install-info clean + +configure @var{host2} -prefix=/usr/gnu -exec_prefix=/usr/gnu/H-host2 +make all info install install-info +@end smallexample + +The first line configures the source for @var{host1} to place host-specific +programs in subdirectories of @file{/usr/gnu/H-@var{host1}}. + +The second line builds and installs all programs for @var{host1}, +including both host-independent and host-specific files, as well as removing +the host-specific object files from of the build directory. + +The third line reconfigures the source for @var{host2} to place host +specific programs in subdirectories of @file{/usr/gnu/H-@var{host2}}. + +The fourth line builds and installs all programs for @var{host2}. Host +specific files are installed in new directories, but the host +independent files are installed @emph{on top of} the host +independent files installed for @var{host1}. This results in a single +copy of the host independent files, suitable for use by both hosts. + +@xref{Makefile extensions, , Extensions to the @sc{gnu} coding standards}, for +more information. + +@c --------------------------------------------------------------------- +@node Install details +@subsection Full descriptions of all installation subdirectories +@cindex Install details +@cindex Installation subdirectories +@cindex Subdirectories + +During any install, a number of standard directories are created. Their names +are determined by @file{Makefile} variables. Some of the defaults for +@file{Makefile} variables can be changed at configuration time using command +line options to @code{configure}. For more information on the standard +directories or the @file{Makefile} variables, please refer to @ref{Makefiles, , +Makefile Conventions, standards, GNU Coding Standards}. See also @ref{Makefile +extensions, , Extensions to the @sc{gnu} coding standards}. + +Note that @code{configure} does not create the directory indicated by the +variable @samp{srcdir} at any time. @code{$(srcdir)} is not an installation +directory. + +You can override all @file{Makefile} variables on the command line to +@code{make}. (@xref{Overriding, , Overriding Variables, make, GNU Make}.) If +you do so, you will need to specify the value precisely the same way for each +invocation of @code{make}, or you risk ending up with a broken installation. +This is because many programs have the locations of other programs or files +compiled into them. If you find yourself overriding any of the variables +frequently, you should consider site dependent @file{Makefile} fragments. See +also @ref{Sites, , Adding site info}. + +During @samp{make install}, a number of standard directories are created and +populated. The following @file{Makefile} variables define them. Those whose +defaults are set by corresponding @code{configure} variables are marked +``@code{Makefile} and @code{configure}''. + +@table @code +@item prefix (@code{Makefile} and @code{configure}) +@cindex @code{prefix} +@vindex prefix +The root of the installation tree. You can set its @file{Makefile} default +with the @samp{--prefix=} command line option to @code{configure} +(@pxref{Invoking configure, , Invoking @code{configure}}). The default value +for @samp{prefix} is @samp{/usr/local}. + +@item bindir +@cindex @code{bindir} +@vindex bindir +A directory for binary programs that users can run. The default value for +@samp{bindir} depends on @samp{prefix}; @samp{bindir} is normally changed only +indirectly through @samp{prefix}. The default value for @samp{bindir} is +@samp{$(prefix)/bin}. + +@item exec_prefix (@code{Makefile} and @code{configure}) +@cindex @code{exec_prefix} +@vindex exec_prefix +A directory for host dependent files. You can specify the @file{Makefile} +default value by using the @samp{--exec_prefix=} option to @code{configure}. +(@xref{Invoking configure, , Invoking @code{configure}}.) The default value +for @samp{exec_prefix} is @samp{$(prefix)}. + +@item libdir +@cindex @code{libdir} +@vindex libdir +A directory for libraries and support programs. The default value for +@samp{libdir} depends on @samp{prefix}; @samp{libdir} is normally changed only +indirectly through @samp{prefix}. The default value for @samp{libdir} is +@samp{$(prefix)/lib}. + +@item mandir +@cindex @code{mandir} +@vindex mandir +A directory for @code{man} format documentation (``man pages''). The default +value for @samp{mandir} depends on @samp{prefix}; @samp{mandir} is normally +changed only indirectly through @samp{prefix}. The default value for +@samp{mandir} is @samp{$(prefix)/man}. + +@item man@var{N}dir +@cindex @code{man@var{N}dir} +@vindex man@var{N}dir +These are eight variables named @samp{man1dir}, @samp{man2dir}, etc. They name +the specific directories for each man page section. For example, +@samp{man1dir} by default holds the filename @file{$(mandir)/man1}; this +directory contains @file{emacs.1} (the man page for @sc{gnu} Emacs). +Similarly, @samp{man5dir} contains the value @file{$(mandir)/man5}, indicating +the directory which holds @file{rcsfile.5} (the man page describing the +@code{rcs} data file format). The default value for any of the +@samp{man@var{N}dir} variables depends indirectly on @samp{prefix}, and is +normally changed only through @samp{prefix}. The default value for +@samp{man@var{N}dir} is @samp{$(mandir)/man@var{N}}. + +@item man@var{N}ext +@cindex @code{man@var{N}ext} +@vindex man@var{N}ext +@emph{Not supported by Cygnus @code{configure}}. The @cite{@sc{gnu} Coding +Standards} do not call for @samp{man1ext}, @samp{man2ext}, so the intended use +for @code{manext} is apparently not parallel to @samp{mandir}. Its use is not +clear. (See also @ref{Makefile extensions, , Extensions to the @sc{gnu} coding +standards}.) + +@item infodir +@cindex @code{infodir} +@vindex infodir +A directory for @code{info} format documentation. The default value for +@samp{infodir} depends indirectly on @samp{prefix}; @samp{infodir} is +normally changed only through @samp{prefix}. The default value for +@samp{infodir} is @samp{$(prefix)/info}. + +@item docdir +@cindex @code{docdir} +@vindex docdir +A directory for any documentation that is in a format other than those used by +@code{info} or @code{man}. The default value for @samp{docdir} depends +indirectly on @samp{prefix}; @samp{docdir} is normally changed only through +@samp{prefix}. The default value for @samp{docdir} is @samp{$(datadir)/doc}. +@emph{This variable is an extension to the @sc{gnu} coding standards}. (See +also @ref{Makefile extensions, , Extensions to the @sc{gnu} coding standards}.) + +@item includedir +@cindex @code{includedir} +@vindex includedir +A directory for the header files accompanying the libraries installed in +@samp{libdir}. The default value for @samp{includedir} depends on +@samp{prefix}; @samp{includedir} is normally changed only indirectly +through @samp{prefix}. The default value for @samp{includedir} is +@samp{$(prefix)/include}. +@end table + +@c --------------------------------------------------------------------- +@node Host +@section Host +@cindex Host + +The arguments to @code{configure} are @dfn{hosttypes}. By +@dfn{hosttype} we mean the @dfn{environment} in which the source will be +compiled. This need not necessarily be the same as the physical machine +involved, although it usually is. + +For example, if some obscure machine had the @sc{gnu} @code{POSIX} emulation +libraries available, it would be possible to configure most @sc{gnu} source for +a @code{POSIX} system and build it on the obscure host. + +For more on this topic, see @ref{Host Environments, On Configuring Development +Tools, Host Environments, cfg-paper, On Configuring Development Tools}. + +@c --------------------------------------------------------------------- +@node Target +@section Target +@cindex Target + +For building native development tools, or most of the other @sc{gnu} +tools, you need not worry about the target. The @dfn{target} of a +configuration defaults to the same as the @dfn{host}. + +For building cross development tools, please see @ref{Building Development +Environments, On Configuring Development Tools, Building Development +Environments, cfg-paper, On Configuring Development Tools}. + +@c --------------------------------------------------------------------- +@node Makefile fragments +@section Adding information about local conventions +@cindex @code{Makefile} fragments +@cindex Local conventions +@cindex Adding local info +@cindex Adding site info + +If you find that a tool does not get configured to your liking, or if +@code{configure}'s conventions differ from your local conventions, you should +probably consider @dfn{site-specific @file{Makefile} fragments}. See also +@ref{Sites, , Adding site info}. + +These are probably not the right choice for options that can be set from +the @code{configure} command line or for differences that are host or +target dependent. + +Cygnus @code{configure} uses three types of @file{Makefile} fragments. In a +generated @file{Makefile} they appear in the order: @dfn{target fragment}, +@dfn{host fragment}, and @dfn{site fragment}. This allows host fragments to +override target fragments, and site fragments to override both. + +Host-specific @file{Makefile} fragments conventionally reside in the +@file{./config/} subdirectory with names of the form @file{mh-@var{hosttype}}. +They are used for hosts that require odd options to the standard compiler and +for compile time options based on the host configuration. + +Target-specific @file{Makefile} fragments conventionally reside in the +@file{./config/} subdirectory with names of the form @file{mt-@var{target}}. +They are used for target dependent compile time options. + +Site specific @file{Makefile} fragments conventionally reside in the +@file{./config/} subdirectory with names of the form @file{ms-@var{site}}. +They are used to override host- and target-independent compile time options. +Note that you can also override these options on the @code{make} invocation +line. + +@c --------------------------------------------------------------------- +@node Makefile extensions +@section Extensions to the @sc{gnu} coding standards +@cindex @code{Makefile} extensions +@cindex Cygnus extensions +@cindex Coding standards extensions + +The following additions to the @sc{gnu} coding standards are required for +Cygnus @code{configure} to work properly. + +@itemize @bullet +@item +The @file{Makefile} must contain exactly one line starting with @samp{####}. +This line should follow any default macro definitions but precede any rules. +Host, target, and site-specific @file{Makefile} fragments will be inserted +immediately after this line. If the line is missing, the fragments will not be +inserted. + +@item +Cygnus adds the following targets to each @file{Makefile}. Their existence is +not required for Cygnus @code{configure}, but they are documented here for +completeness. + +@table @code +@kindex info +@item info +Build all info files from texinfo source. + +@kindex install-info +@item install-info +Install all info files. + +@kindex clean-info +@item clean-info +Remove all info files and any intermediate files that can be generated +from texinfo source. + +@kindex Makefile +@item Makefile +Calls @code{./config.status} to rebuild the @file{Makefile} in this directory. +@end table + +@item +The following @file{Makefile} targets have revised semantics: + +@table @code +@kindex install +@item install +Should @emph{not} depend on the target @samp{all}. If the program is not +already built, @samp{make install} should fail. This allows you to install +programs even when @code{make} would otherwise determine them to be out of +date. This can happen, for example, when the result of a @samp{make all} is +transported via tape to another machine for installation. + +@kindex clean +@item clean +Should remove any file that can be regenerated by the @file{Makefile}, +excepting only the @file{Makefile} itself, and any links created by +@code{configure}. That is, @code{make all clean} should return all directories +to their original condition. If this is not done, then the command sequence + +@cindex Example session +@example +configure @var{host1} ; make all install clean ; +configure @var{host2} ; make all install +@end example + +@noindent +will fail because of intermediate files intended for @var{host1}. +@end table + +@item +Cygnus adds the following macros to all @file{Makefile.in} files, but +you are not required to use them to run Cygnus @code{configure}. + +@table @code +@kindex docdir +@item docdir +The directory in which to install any documentation that is not either a +@code{man} page or an @code{info} file. For @code{man} pages, see +@samp{mandir}; for @code{info}, see @samp{infodir}. + +@kindex includedir +@item includedir +The directory in which to install any header files that should be made +available to users. This is distinct from the @code{gcc} include directory, +which is intended for @code{gcc} only. Files in @samp{includedir} may be used +by @code{cc} as well. +@end table + +@item +The following macros have revised semantics. Most of them describe +installation directories; see also @ref{Install details, , Full description of +all installation subdirectories}. + +@table @code +@kindex datadir +@item datadir +is used for host independent data files. + +@kindex mandir +@item mandir +The default path for @samp{mandir} depends on @samp{prefix}. + +@kindex infodir +@item infodir +The default path for @samp{infodir} depends on @samp{prefix}. + +@kindex BISON +@item BISON +is assumed to have a @code{yacc} calling convention. To use @sc{gnu} +@code{bison}, use @samp{BISON=bison -y}. +@end table + +@item +Each Cygnus @file{Makefile} also conforms to one additional restriction: + +When libraries are installed, the line containing the call to +@samp{INSTALL_DATA} should always be followed by a line containing a call to +@samp{RANLIB} on the installed library. This is to accommodate systems that +use @code{ranlib}. Systems that do not use @code{ranlib} can set @samp{RANLIB} +to ``@code{echo}'' in a host specific @file{Makefile} fragment. +@end itemize + +@c ======================================================================== +@node Porting +@chapter Porting with @code{configure} +@cindex Porting with @code{configure} + +This section explains how to add programs, host and target configuration +names, and site-specific information to Cygnus @code{configure}. + +@menu +* Programs:: Adding configure to new programs +* Hosts and targets:: Adding hosts and targets +* Sites:: Adding site info +@end menu + +@c --------------------------------------------------------------------- +@node Programs +@section Adding @code{configure} to new programs +@cindex Adding @code{configure} to new programs + +If you are writing a new program, you probably shouldn't worry about porting or +configuration issues until it is running reasonably on some host. Then refer +back to this section. + +If your program currently has a @code{configure} script that meets the @sc{gnu} +standards (@pxref{Configuration, , How Configuration Should Work, standards, +GNU Coding Standards}, please do not add Cygnus @code{configure}. It should be +possible to add this program without change to a Cygnus @code{configure} style +source tree. + +@cindex @code{autoconf} +If the program is not target dependent, please consider using @code{autoconf} +instead of Cygnus @code{configure}. @code{autoconf} is available from the Free +Software Foundation; it is a program which generates an executable shell script +called @file{configure} by automatically finding information on the system to +be configured on and embedding this information in the shell script. +@file{configure} scripts generated by @code{autoconf} require no arguments, and +accept the same options as Cygnus @code{configure}. For detailed instructions +on using @code{autoconf}, see @ref{Making configure Scripts, , How to organize +and produce Autoconf scripts, autoconf, Autoconf}. + + +To add Cygnus @code{configure} to an existing program, do the following: + +@table @bullet +@item Make sure the @file{Makefile} conforms to the @sc{gnu} standard +The coding standard for writing a @sc{gnu} @file{Makefile} is described in +@ref{Makefiles, , Makefile Conventions, standards, GNU Coding Standards}. For +technical information on writing a @file{Makefile}, see @ref{Makefiles, , +Writing Makefiles, make, GNU Make}. + +@item Add Cygnus extensions to the @file{Makefile} +These are described in @ref{Makefile extensions, , Extensions to the @sc{gnu} +coding standards}. + +@item Collect package specific definitions in a single file +Many packages are best configured using a common @file{Makefile} fragment which +is included by all of the makefiles in the different directories of the +package. In order to accomplish this, set the variable +@samp{package_makefile_fragment} to the name of the file. It will be inserted +into the final @file{Makefile} before the target-specific fragment. + +@item Move host support from @file{Makefile} to fragments +This usually involves finding sections of the @file{Makefile} that say things +like ``uncomment these lines for host @var{hosttype}'' and moving them to a new +file called @file{./config/mh-@var{hosttype}}. For more information, see @ref{Hosts +and targets, , Adding hosts and targets}. + +@item Choose defaults +If the program has compile-time options that determine the way the program +should behave, choose reasonable defaults and make these @file{Makefile} +variables. Be sure the variables are assigned their default values before the +@samp{####} line so that site-specific @file{Makefile} fragments can override +them (@pxref{Makefile extensions, , Extensions to the @sc{gnu} coding +standards}). + +@item Locate configuration files +If there is configuration information in header files or source files, separate +it in such a way that the files have generic names. Then move the specific +instances of those files into the @file{./config/} subdirectory. + +@item Separate host and target information +Some programs already have this information separated. If yours does not, you +will need to separate these two kinds of configuration information. @dfn{Host +specific} information is the information needed to compile the program. +@dfn{Target specific} information is information on the format of data files +that the program will read or write. This information should live in separate +files in the @file{./config/} subdirectory with names that reflect the +configuration for which they are intended. + +At this point you might skip this step and simply move on. If you do, you +should end up with a program that can be configured only to build @dfn{native} +tools, that is, tools for which the host system is also the target system. +Later, you could attempt to build a cross tool and separate out the +target-specific information by figuring out what went wrong. This is often +simpler than combing through all of the source code. + +@item Write @code{configure.in} +Usually this involves writing shell script fragments to map from canonical +configuration names into the names of the configuration files. These files +will then be linked at configure time from the specific instances of those +files in @file{./config} to files in the build directory with more generic +names. (See also @ref{Build directories, , Build directories}.) The format of +@file{configure.in} is described in @ref{configure.in, , The +@code{configure.in} input file}. + +@item Rename @file{Makefile} to @file{Makefile.in} +@end table + +At this point you should have a program that can be configured using +Cygnus @code{configure}. + +@c --------------------------------------------------------------------- +@node Hosts and targets +@section Adding hosts and targets +@cindex Adding hosts and targets +@cindex Hosts and targets + +To add a host or target to a program that already uses Cygnus @code{configure}, +do the following. + +@itemize @bullet + +@item +Make sure the new configuration name is represented in @file{config.sub}. If +not, add it. For more details, see the comments in the shell script +@file{config.sub}. + +@item +If you are adding a host configuration, look in @file{configure.in}, in the +@dfn{per-host} section. Make sure that your configuration name is represented +in the mapping from host configuration names to configuration files. If not, +add it. Also see @ref{configure.in, , The @code{configure.in} input file}. + +@item +If you are adding a target configuration, look in @file{configure.in}, in the +@dfn{per-target} section. Make sure that your configuration name is +represented in the mapping from target configuration names to configuration +files. If not, add it. Also see @ref{configure.in, , The @code{configure.in} +input file}. + +@item +Look in @file{configure.in} for the variables @samp{files}, @samp{links}, +@samp{host_makefile_frag}, and @samp{target_makefile_frag}. The values +assigned to these variables are the names of the configuration files, (relative +to @samp{srcdir}) that the program uses. Make sure that copies of the files +exist for your host. If not, create them. See also @ref{configure variables, +, Variables available to @code{configure.in}}. +@end itemize + +This should be enough to @code{configure} for a new host or target +configuration name. Getting the program to compile and run properly represents +the hardest work of any port. + +@c --------------------------------------------------------------------- +@node Sites +@section Adding site info +@cindex Sites +@cindex Adding site info + +If some of the @file{Makefile} defaults are not right for your site, you can +build site-specific @file{Makefile} fragments. To do this, do the following. + +@itemize @bullet + +@item +Choose a name for your site. It must currently be less than eleven characters. + +@item +If the program source does not have a @file{./config/} subdirectory, create it. + +@item +Create a file called @file{./config/ms-@var{site}} where @var{site} is the name +of your site. In it, set whatever @file{Makefile} variables you need to +override to match your site's conventions. + +@item +Configure the program with: + +@cindex Example session +@example +configure @dots{} --site=@var{site} +@end example + +@end itemize + +@c --------------------------------------------------------------------- +@node Variables Index +@unnumbered Variable Index + +@printindex vr + +@page +@c --------------------------------------------------------------------- +@node Concept Index +@unnumbered Concept Index + +@printindex cp +@contents +@bye + +@c Local Variables: +@c fill-column: 79 +@c outline-regexp: "@chap" +@c End: +@c (setq outline-regexp "@chapt\\\|@unnum\\\|@setf\\\|@conte\\\|@sectio\\\|@subsect\\\|@itemize\\\|@defvar{") + diff --git a/gnu/usr.bin/binutils/etc/make-stds.texi b/gnu/usr.bin/binutils/etc/make-stds.texi new file mode 100644 index 00000000000..4b4ff7ef953 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/make-stds.texi @@ -0,0 +1,528 @@ +@comment This file is included by both standards.texi and make.texinfo. +@comment It was broken out of standards.texi on 1/6/93 by roland. + +@node Makefile Conventions +@chapter Makefile Conventions +@comment standards.texi does not print an index, but make.texinfo does. +@cindex makefile, conventions for +@cindex conventions for makefiles +@cindex standards for makefiles + +This chapter describes conventions for writing the Makefiles for GNU programs. + +@menu +* Makefile Basics:: +* Utilities in Makefiles:: +* Standard Targets:: +* Command Variables:: +* Directory Variables:: +@end menu + +@node Makefile Basics +@section General Conventions for Makefiles + +Every Makefile should contain this line: + +@example +SHELL = /bin/sh +@end example + +@noindent +to avoid trouble on systems where the @code{SHELL} variable might be +inherited from the environment. (This is never a problem with GNU +@code{make}.) + +Don't assume that @file{.} is in the path for command execution. When +you need to run programs that are a part of your package during the +make, please make sure that it uses @file{./} if the program is built as +part of the make or @file{$(srcdir)/} if the file is an unchanging part +of the source code. Without one of these prefixes, the current search +path is used. + +The distinction between @file{./} and @file{$(srcdir)/} is important +when using the @samp{--srcdir} option to @file{configure}. A rule of +the form: + +@smallexample +foo.1 : foo.man sedscript + sed -e sedscript foo.man > foo.1 +@end smallexample + +@noindent +will fail when the current directory is not the source directory, +because @file{foo.man} and @file{sedscript} are not in the current +directory. + +When using GNU @code{make}, relying on @samp{VPATH} to find the source +file will work in the case where there is a single dependency file, +since the @file{make} automatic variable @samp{$<} will represent the +source file wherever it is. (Many versions of @code{make} set @samp{$<} +only in implicit rules.) A makefile target like + +@smallexample +foo.o : bar.c + $(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.o +@end smallexample + +@noindent +should instead be written as + +@smallexample +foo.o : bar.c + $(CC) $(CFLAGS) $< -o $@@ +@end smallexample + +@noindent +in order to allow @samp{VPATH} to work correctly. When the target has +multiple dependencies, using an explicit @samp{$(srcdir)} is the easiest +way to make the rule work well. For example, the target above for +@file{foo.1} is best written as: + +@smallexample +foo.1 : foo.man sedscript + sed -s $(srcdir)/sedscript $(srcdir)/foo.man > foo.1 +@end smallexample + +@node Utilities in Makefiles +@section Utilities in Makefiles + +Write the Makefile commands (and any shell scripts, such as +@code{configure}) to run in @code{sh}, not in @code{csh}. Don't use any +special features of @code{ksh} or @code{bash}. + +The @code{configure} script and the Makefile rules for building and +installation should not use any utilities directly except these: + +@example +cat cmp cp echo egrep expr grep +ln mkdir mv pwd rm rmdir sed test touch +@end example + +Stick to the generally supported options for these programs. For +example, don't use @samp{mkdir -p}, convenient as it may be, because +most systems don't support it. + +The Makefile rules for building and installation can also use compilers +and related programs, but should do so via @code{make} variables so that the +user can substitute alternatives. Here are some of the programs we +mean: + +@example +ar bison cc flex install ld lex +make makeinfo ranlib texi2dvi yacc +@end example + +When you use @code{ranlib}, you should test whether it exists, and run +it only if it exists, so that the distribution will work on systems that +don't have @code{ranlib}. + +If you use symbolic links, you should implement a fallback for systems +that don't have symbolic links. + +It is ok to use other utilities in Makefile portions (or scripts) +intended only for particular systems where you know those utilities to +exist. + +@node Standard Targets +@section Standard Targets for Users + +All GNU programs should have the following targets in their Makefiles: + +@table @samp +@item all +Compile the entire program. This should be the default target. This +target need not rebuild any documentation files; Info files should +normally be included in the distribution, and DVI files should be made +only when explicitly asked for. + +@item install +Compile the program and copy the executables, libraries, and so on to +the file names where they should reside for actual use. If there is a +simple test to verify that a program is properly installed, this target +should run that test. + +The commands should create all the directories in which files are to be +installed, if they don't already exist. This includes the directories +specified as the values of the variables @code{prefix} and +@code{exec_prefix}, as well as all subdirectories that are needed. +One way to do this is by means of an @code{installdirs} target +as described below. + +Use @samp{-} before any command for installing a man page, so that +@code{make} will ignore any errors. This is in case there are systems +that don't have the Unix man page documentation system installed. + +The way to install Info files is to copy them into @file{$(infodir)} +with @code{$(INSTALL_DATA)} (@pxref{Command Variables}), and then run +the @code{install-info} program if it is present. @code{install-info} +is a script that edits the Info @file{dir} file to add or update the +menu entry for the given Info file; it will be part of the Texinfo package. +Here is a sample rule to install an Info file: + +@comment This example has been carefully formatted for the Make manual. +@comment Please do not reformat it without talking to roland@gnu.ai.mit.edu. +@smallexample +$(infodir)/foo.info: foo.info +# There may be a newer info file in . than in srcdir. + -if test -f foo.info; then d=.; \ + else d=$(srcdir); fi; \ + $(INSTALL_DATA) $$d/foo.info $@@; \ +# Run install-info only if it exists. +# Use `if' instead of just prepending `-' to the +# line so we notice real errors from install-info. +# We use `$(SHELL) -c' because some shells do not +# fail gracefully when there is an unknown command. + if $(SHELL) -c 'install-info --version' \ + >/dev/null 2>&1; then \ + install-info --infodir=$(infodir) $$d/foo.info; \ + else true; fi +@end smallexample + +@item uninstall +Delete all the installed files that the @samp{install} target would +create (but not the noninstalled files such as @samp{make all} would +create). + +@comment The gratuitous blank line here is to make the table look better +@comment in the printed Make manual. Please leave it in. +@item clean + +Delete all files from the current directory that are normally created by +building the program. Don't delete the files that record the +configuration. Also preserve files that could be made by building, but +normally aren't because the distribution comes with them. + +Delete @file{.dvi} files here if they are not part of the distribution. + +@item distclean +Delete all files from the current directory that are created by +configuring or building the program. If you have unpacked the source +and built the program without creating any other files, @samp{make +distclean} should leave only the files that were in the distribution. + +@item mostlyclean +Like @samp{clean}, but may refrain from deleting a few files that people +normally don't want to recompile. For example, the @samp{mostlyclean} +target for GCC does not delete @file{libgcc.a}, because recompiling it +is rarely necessary and takes a lot of time. + +@item realclean +Delete everything from the current directory that can be reconstructed +with this Makefile. This typically includes everything deleted by +@code{distclean}, plus more: C source files produced by Bison, tags tables, +Info files, and so on. + +One exception, however: @samp{make realclean} should not delete +@file{configure} even if @file{configure} can be remade using a rule in +the Makefile. More generally, @samp{make realclean} should not delete +anything that needs to exist in order to run @file{configure} +and then begin to build the program. + +@item TAGS +Update a tags table for this program. + +@item info +Generate any Info files needed. The best way to write the rules is as +follows: + +@smallexample +info: foo.info + +foo.info: foo.texi chap1.texi chap2.texi + $(MAKEINFO) $(srcdir)/foo.texi +@end smallexample + +@noindent +You must define the variable @code{MAKEINFO} in the Makefile. It should +run the @code{makeinfo} program, which is part of the Texinfo +distribution. + +@item dvi +Generate DVI files for all TeXinfo documentation. +For example: + +@smallexample +dvi: foo.dvi + +foo.dvi: foo.texi chap1.texi chap2.texi + $(TEXI2DVI) $(srcdir)/foo.texi +@end smallexample + +@noindent +You must define the variable @code{TEXI2DVI} in the Makefile. It should +run the program @code{texi2dvi}, which is part of the Texinfo +distribution. Alternatively, write just the dependencies, and allow GNU +Make to provide the command. + +@item dist +Create a distribution tar file for this program. The tar file should be +set up so that the file names in the tar file start with a subdirectory +name which is the name of the package it is a distribution for. This +name can include the version number. + +For example, the distribution tar file of GCC version 1.40 unpacks into +a subdirectory named @file{gcc-1.40}. + +The easiest way to do this is to create a subdirectory appropriately +named, use @code{ln} or @code{cp} to install the proper files in it, and +then @code{tar} that subdirectory. + +The @code{dist} target should explicitly depend on all non-source files +that are in the distribution, to make sure they are up to date in the +distribution. +@xref{Releases, , Making Releases, standards, GNU Coding Standards}. + +@item check +Perform self-tests (if any). The user must build the program before +running the tests, but need not install the program; you should write +the self-tests so that they work when the program is built but not +installed. +@end table + +The following targets are suggested as conventional names, for programs +in which they are useful. + +@table @code +@item installcheck +Perform installation tests (if any). The user must build and install +the program before running the tests. You should not assume that +@file{$(bindir)} is in the search path. + +@item installdirs +It's useful to add a target named @samp{installdirs} to create the +directories where files are installed, and their parent directories. +There is a script called @file{mkinstalldirs} which is convenient for +this; find it in the Texinfo package.@c It's in /gd/gnu/lib/mkinstalldirs. +You can use a rule like this: + +@comment This has been carefully formatted to look decent in the Make manual. +@comment Please be sure not to make it extend any further to the right.--roland +@smallexample +# Make sure all installation directories (e.g. $(bindir)) +# actually exist by making them if necessary. +installdirs: mkinstalldirs + $(srcdir)/mkinstalldirs $(bindir) $(datadir) \ + $(libdir) $(infodir) \ + $(mandir) +@end smallexample +@end table + +@node Command Variables +@section Variables for Specifying Commands + +Makefiles should provide variables for overriding certain commands, options, +and so on. + +In particular, you should run most utility programs via variables. +Thus, if you use Bison, have a variable named @code{BISON} whose default +value is set with @samp{BISON = bison}, and refer to it with +@code{$(BISON)} whenever you need to use Bison. + +File management utilities such as @code{ln}, @code{rm}, @code{mv}, and +so on, need not be referred to through variables in this way, since users +don't need to replace them with other programs. + +Each program-name variable should come with an options variable that is +used to supply options to the program. Append @samp{FLAGS} to the +program-name variable name to get the options variable name---for +example, @code{BISONFLAGS}. (The name @code{CFLAGS} is an exception to +this rule, but we keep it because it is standard.) Use @code{CPPFLAGS} +in any compilation command that runs the preprocessor, and use +@code{LDFLAGS} in any compilation command that does linking as well as +in any direct use of @code{ld}. + +If there are C compiler options that @emph{must} be used for proper +compilation of certain files, do not include them in @code{CFLAGS}. +Users expect to be able to specify @code{CFLAGS} freely themselves. +Instead, arrange to pass the necessary options to the C compiler +independently of @code{CFLAGS}, by writing them explicitly in the +compilation commands or by defining an implicit rule, like this: + +@smallexample +CFLAGS = -g +ALL_CFLAGS = -I. $(CFLAGS) +.c.o: + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< +@end smallexample + +Do include the @samp{-g} option in @code{CFLAGS}, because that is not +@emph{required} for proper compilation. You can consider it a default +that is only recommended. If the package is set up so that it is +compiled with GCC by default, then you might as well include @samp{-O} +in the default value of @code{CFLAGS} as well. + +Put @code{CFLAGS} last in the compilation command, after other variables +containing compiler options, so the user can use @code{CFLAGS} to +override the others. + +Every Makefile should define the variable @code{INSTALL}, which is the +basic command for installing a file into the system. + +Every Makefile should also define the variables @code{INSTALL_PROGRAM} +and @code{INSTALL_DATA}. (The default for each of these should be +@code{$(INSTALL)}.) Then it should use those variables as the commands +for actual installation, for executables and nonexecutables +respectively. Use these variables as follows: + +@example +$(INSTALL_PROGRAM) foo $(bindir)/foo +$(INSTALL_DATA) libfoo.a $(libdir)/libfoo.a +@end example + +@noindent +Always use a file name, not a directory name, as the second argument of +the installation commands. Use a separate command for each file to be +installed. + +@node Directory Variables +@section Variables for Installation Directories + +Installation directories should always be named by variables, so it is +easy to install in a nonstandard place. The standard names for these +variables are: + +@table @samp +@item prefix +A prefix used in constructing the default values of the variables listed +below. The default value of @code{prefix} should be @file{/usr/local} +(at least for now). + +@item exec_prefix +A prefix used in constructing the default values of some of the +variables listed below. The default value of @code{exec_prefix} should +be @code{$(prefix)}. + +Generally, @code{$(exec_prefix)} is used for directories that contain +machine-specific files (such as executables and subroutine libraries), +while @code{$(prefix)} is used directly for other directories. + +@item bindir +The directory for installing executable programs that users can run. +This should normally be @file{/usr/local/bin}, but write it as +@file{$(exec_prefix)/bin}. + +@item libdir +The directory for installing executable files to be run by the program +rather than by users. Object files and libraries of object code should +also go in this directory. The idea is that this directory is used for +files that pertain to a specific machine architecture, but need not be +in the path for commands. The value of @code{libdir} should normally be +@file{/usr/local/lib}, but write it as @file{$(exec_prefix)/lib}. + +@item datadir +The directory for installing read-only data files which the programs +refer to while they run. This directory is used for files which are +independent of the type of machine being used. This should normally be +@file{/usr/local/lib}, but write it as @file{$(prefix)/lib}. + +@item statedir +The directory for installing data files which the programs modify while +they run. These files should be independent of the type of machine +being used, and it should be possible to share them among machines at a +network installation. This should normally be @file{/usr/local/lib}, +but write it as @file{$(prefix)/lib}. + +@item includedir +@c rewritten to avoid overfull hbox --roland +The directory for installing header files to be included by user +programs with the C @samp{#include} preprocessor directive. This +should normally be @file{/usr/local/include}, but write it as +@file{$(prefix)/include}. + +Most compilers other than GCC do not look for header files in +@file{/usr/local/include}. So installing the header files this way is +only useful with GCC. Sometimes this is not a problem because some +libraries are only really intended to work with GCC. But some libraries +are intended to work with other compilers. They should install their +header files in two places, one specified by @code{includedir} and one +specified by @code{oldincludedir}. + +@item oldincludedir +The directory for installing @samp{#include} header files for use with +compilers other than GCC. This should normally be @file{/usr/include}. + +The Makefile commands should check whether the value of +@code{oldincludedir} is empty. If it is, they should not try to use +it; they should cancel the second installation of the header files. + +A package should not replace an existing header in this directory unless +the header came from the same package. Thus, if your Foo package +provides a header file @file{foo.h}, then it should install the header +file in the @code{oldincludedir} directory if either (1) there is no +@file{foo.h} there or (2) the @file{foo.h} that exists came from the Foo +package. + +To tell whether @file{foo.h} came from the Foo package, put a magic +string in the file---part of a comment---and grep for that string. + +@item mandir +The directory for installing the man pages (if any) for this package. +It should include the suffix for the proper section of the +manual---usually @samp{1} for a utility. It will normally be +@file{/usr/local/man/man1}, but you should write it as +@file{$(prefix)/man/man1}. + +@item man1dir +The directory for installing section 1 man pages. +@item man2dir +The directory for installing section 2 man pages. +@item @dots{} +Use these names instead of @samp{mandir} if the package needs to install man +pages in more than one section of the manual. + +@strong{Don't make the primary documentation for any GNU software be a +man page. Write a manual in Texinfo instead. Man pages are just for +the sake of people running GNU software on Unix, which is a secondary +application only.} + +@item manext +The file name extension for the installed man page. This should contain +a period followed by the appropriate digit; it should normally be @samp{.1}. + +@item man1ext +The file name extension for installed section 1 man pages. +@item man2ext +The file name extension for installed section 2 man pages. +@item @dots{} +Use these names instead of @samp{manext} if the package needs to install man +pages in more than one section of the manual. + +@item infodir +The directory for installing the Info files for this package. By +default, it should be @file{/usr/local/info}, but it should be written +as @file{$(prefix)/info}. + +@item srcdir +The directory for the sources being compiled. The value of this +variable is normally inserted by the @code{configure} shell script. +@end table + +For example: + +@smallexample +@c I have changed some of the comments here slightly to fix an overfull +@c hbox, so the make manual can format correctly. --roland +# Common prefix for installation directories. +# NOTE: This directory must exist when you start the install. +prefix = /usr/local +exec_prefix = $(prefix) +# Where to put the executable for the command `gcc'. +bindir = $(exec_prefix)/bin +# Where to put the directories used by the compiler. +libdir = $(exec_prefix)/lib +# Where to put the Info files. +infodir = $(prefix)/info +@end smallexample + +If your program installs a large number of files into one of the +standard user-specified directories, it might be useful to group them +into a subdirectory particular to that program. If you do this, you +should write the @code{install} rule to create these subdirectories. + +Do not expect the user to include the subdirectory name in the value of +any of the variables listed above. The idea of having a uniform set of +variable names for installation directories is to enable the user to +specify the exact same values for several different GNU packages. In +order for this to be useful, all the packages must be designed so that +they will work sensibly when the user does so. + diff --git a/gnu/usr.bin/binutils/etc/standards.info b/gnu/usr.bin/binutils/etc/standards.info new file mode 100644 index 00000000000..92b0dc90c04 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/standards.info @@ -0,0 +1,59 @@ +This is Info file standards.info, produced by Makeinfo-1.55 from the +input file ./standards.texi. + +START-INFO-DIR-ENTRY +* Standards: (standards). GNU coding standards. +END-INFO-DIR-ENTRY + + GNU Coding Standards Copyright (C) 1992, 1993, 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. + + 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 Free Software Foundation. + + +Indirect: +standards.info-1: 950 +standards.info-2: 49237 + +Tag Table: +(Indirect) +Node: Top950 +Node: Reading Non-Free Code2051 +Node: Contributions3777 +Node: Change Logs5375 +Node: Compatibility9091 +Node: Makefile Conventions10730 +Node: Makefile Basics11087 +Node: Utilities in Makefiles12978 +Node: Standard Targets14414 +Node: Command Variables21523 +Node: Directory Variables24353 +Node: Configuration30825 +Node: Source Language37849 +Node: Formatting38979 +Node: Comments42269 +Node: Syntactic Conventions45055 +Node: Names47947 +Node: Using Extensions49237 +Node: System Functions50978 +Node: Semantics55781 +Node: Errors58747 +Node: Libraries59950 +Node: Portability61174 +Node: User Interfaces64461 +Node: Documentation79291 +Node: Releases83225 + +End Tag Table diff --git a/gnu/usr.bin/binutils/etc/standards.info-1 b/gnu/usr.bin/binutils/etc/standards.info-1 new file mode 100644 index 00000000000..38184e4a1bb --- /dev/null +++ b/gnu/usr.bin/binutils/etc/standards.info-1 @@ -0,0 +1,1225 @@ +This is Info file standards.info, produced by Makeinfo-1.55 from the +input file ./standards.texi. + +START-INFO-DIR-ENTRY +* Standards: (standards). GNU coding standards. +END-INFO-DIR-ENTRY + + GNU Coding Standards Copyright (C) 1992, 1993, 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. + + 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 Free Software Foundation. + + +File: standards.info, Node: Top, Next: Reading Non-Free Code, Prev: (dir), Up: (dir) + +Version +******* + + Last updated 28 March 1994. + +* Menu: + +* Reading Non-Free Code:: Referring to Proprietary Programs +* Contributions:: Accepting Contributions +* Change Logs:: Recording Changes +* Compatibility:: Compatibility with Other Implementations +* Makefile Conventions:: Makefile Conventions +* Configuration:: How Configuration Should Work +* Source Language:: Using Languages Other Than C +* Formatting:: Formatting Your Source Code +* Comments:: Commenting Your Work +* Syntactic Conventions:: Clean Use of C Constructs +* Names:: Naming Variables and Functions +* Using Extensions:: Using Non-standard Features +* System Functions:: Portability and "standard" library functions +* Semantics:: Program Behavior for All Programs +* Errors:: Formatting Error Messages +* Libraries:: Library Behavior +* Portability:: Portability As It Applies to GNU +* User Interfaces:: Standards for Command Line Interfaces +* Documentation:: Documenting Programs +* Releases:: Making Releases + + +File: standards.info, Node: Reading Non-Free Code, Next: Contributions, Prev: Top, Up: Top + +Referring to Proprietary Programs +********************************* + + Don't in any circumstances refer to Unix source code for or during +your work on GNU! (Or to any other proprietary programs.) + + If you have a vague recollection of the internals of a Unix program, +this does not absolutely mean you can't write an imitation of it, but +do try to organize the imitation internally along different lines, +because this is likely to make the details of the Unix version +irrelevant and dissimilar to your results. + + For example, Unix utilities were generally optimized to minimize +memory use; if you go for speed instead, your program will be very +different. You could keep the entire input file in core and scan it +there instead of using stdio. Use a smarter algorithm discovered more +recently than the Unix program. Eliminate use of temporary files. Do +it in one pass instead of two (we did this in the assembler). + + Or, on the contrary, emphasize simplicity instead of speed. For some +applications, the speed of today's computers makes simpler algorithms +adequate. + + Or go for generality. For example, Unix programs often have static +tables or fixed-size strings, which make for arbitrary limits; use +dynamic allocation instead. Make sure your program handles NULs and +other funny characters in the input files. Add a programming language +for extensibility and write part of the program in that language. + + Or turn some parts of the program into independently usable +libraries. Or use a simple garbage collector instead of tracking +precisely when to free memory, or use a new GNU facility such as +obstacks. + + +File: standards.info, Node: Contributions, Next: Change Logs, Prev: Reading Non-Free Code, Up: Top + +Accepting Contributions +*********************** + + If someone else sends you a piece of code to add to the program you +are working on, we need legal papers to use it--the same sort of legal +papers we will need to get from you. *Each* significant contributor to +a program must sign some sort of legal papers in order for us to have +clear title to the program. The main author alone is not enough. + + So, before adding in any contributions from other people, tell us so +we can arrange to get the papers. Then wait until we tell you that we +have received the signed papers, before you actually use the +contribution. + + This applies both before you release the program and afterward. If +you receive diffs to fix a bug, and they make significant change, we +need legal papers for it. + + You don't need papers for changes of a few lines here or there, since +they are not significant for copyright purposes. Also, you don't need +papers if all you get from the suggestion is some ideas, not actual code +which you use. For example, if you write a different solution to the +problem, you don't need to get papers. + + I know this is frustrating; it's frustrating for us as well. But if +you don't wait, you are going out on a limb--for example, what if the +contributor's employer won't sign a disclaimer? You might have to take +that code out again! + + The very worst thing is if you forget to tell us about the other +contributor. We could be very embarrassed in court some day as a +result. + + +File: standards.info, Node: Change Logs, Next: Compatibility, Prev: Contributions, Up: Top + +Change Logs +*********** + + Keep a change log for each directory, describing the changes made to +source files in that directory. The purpose of this is so that people +investigating bugs in the future will know about the changes that might +have introduced the bug. Often a new bug can be found by looking at +what was recently changed. More importantly, change logs can help +eliminate conceptual inconsistencies between different parts of a +program; they can give you a history of how the conflicting concepts +arose. + + Use the Emacs command `M-x add-change' to start a new entry in the +change log. An entry should have an asterisk, the name of the changed +file, and then in parentheses the name of the changed functions, +variables or whatever, followed by a colon. Then describe the changes +you made to that function or variable. + + Separate unrelated entries with blank lines. When two entries +represent parts of the same change, so that they work together, then +don't put blank lines between them. Then you can omit the file name +and the asterisk when successive entries are in the same file. + + Here are some examples: + + * register.el (insert-register): Return nil. + (jump-to-register): Likewise. + + * sort.el (sort-subr): Return nil. + + * tex-mode.el (tex-bibtex-file, tex-file, tex-region): + Restart the tex shell if process is gone or stopped. + (tex-shell-running): New function. + + * expr.c (store_one_arg): Round size up for move_block_to_reg. + (expand_call): Round up when emitting USE insns. + * stmt.c (assign_parms): Round size up for move_block_from_reg. + + It's important to name the changed function or variable in full. +Don't abbreviate them; don't combine them. Subsequent maintainers will +often search for a function name to find all the change log entries that +pertain to it; if you abbreviate the name, they won't find it when they +search. For example, some people are tempted to abbreviate groups of +function names by writing `* register.el ({insert,jump-to}-register)'; +this is not a good idea, since searching for `jump-to-register' or +`insert-register' would not find the entry. + + There's no need to describe the full purpose of the changes or how +they work together. It is better to put such explanations in comments +in the code. That's why just "New function" is enough; there is a +comment with the function in the source to explain what it does. + + However, sometimes it is useful to write one line to describe the +overall purpose of a large batch of changes. + + You can think of the change log as a conceptual "undo list" which +explains how earlier versions were different from the current version. +People can see the current version; they don't need the change log to +tell them what is in it. What they want from a change log is a clear +explanation of how the earlier version differed. + + When you change the calling sequence of a function in a simple +fashion, and you change all the callers of the function, there is no +need to make individual entries for all the callers. Just write in the +entry for the function being called, "All callers changed." + + When you change just comments or doc strings, it is enough to write +an entry for the file, without mentioning the functions. Write just, +"Doc fix." There's no need to keep a change log for documentation +files. This is because documentation is not susceptible to bugs that +are hard to fix. Documentation does not consist of parts that must +interact in a precisely engineered fashion; to correct an error, you +need not know the history of the erroneous passage. + + +File: standards.info, Node: Compatibility, Next: Makefile Conventions, Prev: Change Logs, Up: Top + +Compatibility with Other Implementations +**************************************** + + With certain exceptions, utility programs and libraries for GNU +should be upward compatible with those in Berkeley Unix, and upward +compatible with ANSI C if ANSI C specifies their behavior, and upward +compatible with POSIX if POSIX specifies their behavior. + + When these standards conflict, it is useful to offer compatibility +modes for each of them. + + ANSI C and POSIX prohibit many kinds of extensions. Feel free to +make the extensions anyway, and include a `--ansi' or `--compatible' +option to turn them off. However, if the extension has a significant +chance of breaking any real programs or scripts, then it is not really +upward compatible. Try to redesign its interface. + + Many GNU programs suppress extensions that conflict with POSIX if the +environment variable `POSIXLY_CORRECT' is defined (even if it is +defined with a null value). Please make your program recognize this +variable if appropriate. + + When a feature is used only by users (not by programs or command +files), and it is done poorly in Unix, feel free to replace it +completely with something totally different and better. (For example, +vi is replaced with Emacs.) But it is nice to offer a compatible +feature as well. (There is a free vi clone, so we offer it.) + + Additional useful features not in Berkeley Unix are welcome. +Additional programs with no counterpart in Unix may be useful, but our +first priority is usually to duplicate what Unix already has. + + +File: standards.info, Node: Makefile Conventions, Next: Configuration, Prev: Compatibility, Up: Top + +Makefile Conventions +******************** + + This chapter describes conventions for writing the Makefiles for GNU +programs. + +* Menu: + +* Makefile Basics:: +* Utilities in Makefiles:: +* Standard Targets:: +* Command Variables:: +* Directory Variables:: + + +File: standards.info, Node: Makefile Basics, Next: Utilities in Makefiles, Up: Makefile Conventions + +General Conventions for Makefiles +================================= + + Every Makefile should contain this line: + + SHELL = /bin/sh + +to avoid trouble on systems where the `SHELL' variable might be +inherited from the environment. (This is never a problem with GNU +`make'.) + + Don't assume that `.' is in the path for command execution. When +you need to run programs that are a part of your package during the +make, please make sure that it uses `./' if the program is built as +part of the make or `$(srcdir)/' if the file is an unchanging part of +the source code. Without one of these prefixes, the current search +path is used. + + The distinction between `./' and `$(srcdir)/' is important when +using the `--srcdir' option to `configure'. A rule of the form: + + foo.1 : foo.man sedscript + sed -e sedscript foo.man > foo.1 + +will fail when the current directory is not the source directory, +because `foo.man' and `sedscript' are not in the current directory. + + When using GNU `make', relying on `VPATH' to find the source file +will work in the case where there is a single dependency file, since +the `make' automatic variable `$<' will represent the source file +wherever it is. (Many versions of `make' set `$<' only in implicit +rules.) A makefile target like + + foo.o : bar.c + $(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.o + +should instead be written as + + foo.o : bar.c + $(CC) $(CFLAGS) $< -o $@ + +in order to allow `VPATH' to work correctly. When the target has +multiple dependencies, using an explicit `$(srcdir)' is the easiest way +to make the rule work well. For example, the target above for `foo.1' +is best written as: + + foo.1 : foo.man sedscript + sed -s $(srcdir)/sedscript $(srcdir)/foo.man > foo.1 + + +File: standards.info, Node: Utilities in Makefiles, Next: Standard Targets, Prev: Makefile Basics, Up: Makefile Conventions + +Utilities in Makefiles +====================== + + Write the Makefile commands (and any shell scripts, such as +`configure') to run in `sh', not in `csh'. Don't use any special +features of `ksh' or `bash'. + + The `configure' script and the Makefile rules for building and +installation should not use any utilities directly except these: + + cat cmp cp echo egrep expr grep + ln mkdir mv pwd rm rmdir sed test touch + + Stick to the generally supported options for these programs. For +example, don't use `mkdir -p', convenient as it may be, because most +systems don't support it. + + The Makefile rules for building and installation can also use +compilers and related programs, but should do so via `make' variables +so that the user can substitute alternatives. Here are some of the +programs we mean: + + ar bison cc flex install ld lex + make makeinfo ranlib texi2dvi yacc + + When you use `ranlib', you should test whether it exists, and run it +only if it exists, so that the distribution will work on systems that +don't have `ranlib'. + + If you use symbolic links, you should implement a fallback for +systems that don't have symbolic links. + + It is ok to use other utilities in Makefile portions (or scripts) +intended only for particular systems where you know those utilities to +exist. + + +File: standards.info, Node: Standard Targets, Next: Command Variables, Prev: Utilities in Makefiles, Up: Makefile Conventions + +Standard Targets for Users +========================== + + All GNU programs should have the following targets in their +Makefiles: + +`all' + Compile the entire program. This should be the default target. + This target need not rebuild any documentation files; Info files + should normally be included in the distribution, and DVI files + should be made only when explicitly asked for. + +`install' + Compile the program and copy the executables, libraries, and so on + to the file names where they should reside for actual use. If + there is a simple test to verify that a program is properly + installed, this target should run that test. + + The commands should create all the directories in which files are + to be installed, if they don't already exist. This includes the + directories specified as the values of the variables `prefix' and + `exec_prefix', as well as all subdirectories that are needed. One + way to do this is by means of an `installdirs' target as described + below. + + Use `-' before any command for installing a man page, so that + `make' will ignore any errors. This is in case there are systems + that don't have the Unix man page documentation system installed. + + The way to install Info files is to copy them into `$(infodir)' + with `$(INSTALL_DATA)' (*note Command Variables::.), and then run + the `install-info' program if it is present. `install-info' is a + script that edits the Info `dir' file to add or update the menu + entry for the given Info file; it will be part of the Texinfo + package. Here is a sample rule to install an Info file: + + $(infodir)/foo.info: foo.info + # There may be a newer info file in . than in srcdir. + -if test -f foo.info; then d=.; \ + else d=$(srcdir); fi; \ + $(INSTALL_DATA) $$d/foo.info $@; \ + # Run install-info only if it exists. + # Use `if' instead of just prepending `-' to the + # line so we notice real errors from install-info. + # We use `$(SHELL) -c' because some shells do not + # fail gracefully when there is an unknown command. + if $(SHELL) -c 'install-info --version' \ + >/dev/null 2>&1; then \ + install-info --infodir=$(infodir) $$d/foo.info; \ + else true; fi + +`uninstall' + Delete all the installed files that the `install' target would + create (but not the noninstalled files such as `make all' would + create). + +`clean' + Delete all files from the current directory that are normally + created by building the program. Don't delete the files that + record the configuration. Also preserve files that could be made + by building, but normally aren't because the distribution comes + with them. + + Delete `.dvi' files here if they are not part of the distribution. + +`distclean' + Delete all files from the current directory that are created by + configuring or building the program. If you have unpacked the + source and built the program without creating any other files, + `make distclean' should leave only the files that were in the + distribution. + +`mostlyclean' + Like `clean', but may refrain from deleting a few files that people + normally don't want to recompile. For example, the `mostlyclean' + target for GCC does not delete `libgcc.a', because recompiling it + is rarely necessary and takes a lot of time. + +`realclean' + Delete everything from the current directory that can be + reconstructed with this Makefile. This typically includes + everything deleted by `distclean', plus more: C source files + produced by Bison, tags tables, Info files, and so on. + + One exception, however: `make realclean' should not delete + `configure' even if `configure' can be remade using a rule in the + Makefile. More generally, `make realclean' should not delete + anything that needs to exist in order to run `configure' and then + begin to build the program. + +`TAGS' + Update a tags table for this program. + +`info' + Generate any Info files needed. The best way to write the rules + is as follows: + + info: foo.info + + foo.info: foo.texi chap1.texi chap2.texi + $(MAKEINFO) $(srcdir)/foo.texi + + You must define the variable `MAKEINFO' in the Makefile. It should + run the `makeinfo' program, which is part of the Texinfo + distribution. + +`dvi' + Generate DVI files for all TeXinfo documentation. For example: + + dvi: foo.dvi + + foo.dvi: foo.texi chap1.texi chap2.texi + $(TEXI2DVI) $(srcdir)/foo.texi + + You must define the variable `TEXI2DVI' in the Makefile. It should + run the program `texi2dvi', which is part of the Texinfo + distribution. Alternatively, write just the dependencies, and + allow GNU Make to provide the command. + +`dist' + Create a distribution tar file for this program. The tar file + should be set up so that the file names in the tar file start with + a subdirectory name which is the name of the package it is a + distribution for. This name can include the version number. + + For example, the distribution tar file of GCC version 1.40 unpacks + into a subdirectory named `gcc-1.40'. + + The easiest way to do this is to create a subdirectory + appropriately named, use `ln' or `cp' to install the proper files + in it, and then `tar' that subdirectory. + + The `dist' target should explicitly depend on all non-source files + that are in the distribution, to make sure they are up to date in + the distribution. *Note Making Releases: (standards)Releases. + +`check' + Perform self-tests (if any). The user must build the program + before running the tests, but need not install the program; you + should write the self-tests so that they work when the program is + built but not installed. + + The following targets are suggested as conventional names, for +programs in which they are useful. + +`installcheck' + Perform installation tests (if any). The user must build and + install the program before running the tests. You should not + assume that `$(bindir)' is in the search path. + +`installdirs' + It's useful to add a target named `installdirs' to create the + directories where files are installed, and their parent + directories. There is a script called `mkinstalldirs' which is + convenient for this; find it in the Texinfo package.You can use a + rule like this: + + # Make sure all installation directories (e.g. $(bindir)) + # actually exist by making them if necessary. + installdirs: mkinstalldirs + $(srcdir)/mkinstalldirs $(bindir) $(datadir) \ + $(libdir) $(infodir) \ + $(mandir) + + +File: standards.info, Node: Command Variables, Next: Directory Variables, Prev: Standard Targets, Up: Makefile Conventions + +Variables for Specifying Commands +================================= + + Makefiles should provide variables for overriding certain commands, +options, and so on. + + In particular, you should run most utility programs via variables. +Thus, if you use Bison, have a variable named `BISON' whose default +value is set with `BISON = bison', and refer to it with `$(BISON)' +whenever you need to use Bison. + + File management utilities such as `ln', `rm', `mv', and so on, need +not be referred to through variables in this way, since users don't +need to replace them with other programs. + + Each program-name variable should come with an options variable that +is used to supply options to the program. Append `FLAGS' to the +program-name variable name to get the options variable name--for +example, `BISONFLAGS'. (The name `CFLAGS' is an exception to this +rule, but we keep it because it is standard.) Use `CPPFLAGS' in any +compilation command that runs the preprocessor, and use `LDFLAGS' in +any compilation command that does linking as well as in any direct use +of `ld'. + + If there are C compiler options that *must* be used for proper +compilation of certain files, do not include them in `CFLAGS'. Users +expect to be able to specify `CFLAGS' freely themselves. Instead, +arrange to pass the necessary options to the C compiler independently +of `CFLAGS', by writing them explicitly in the compilation commands or +by defining an implicit rule, like this: + + CFLAGS = -g + ALL_CFLAGS = -I. $(CFLAGS) + .c.o: + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< + + Do include the `-g' option in `CFLAGS', because that is not +*required* for proper compilation. You can consider it a default that +is only recommended. If the package is set up so that it is compiled +with GCC by default, then you might as well include `-O' in the default +value of `CFLAGS' as well. + + Put `CFLAGS' last in the compilation command, after other variables +containing compiler options, so the user can use `CFLAGS' to override +the others. + + Every Makefile should define the variable `INSTALL', which is the +basic command for installing a file into the system. + + Every Makefile should also define the variables `INSTALL_PROGRAM' +and `INSTALL_DATA'. (The default for each of these should be +`$(INSTALL)'.) Then it should use those variables as the commands for +actual installation, for executables and nonexecutables respectively. +Use these variables as follows: + + $(INSTALL_PROGRAM) foo $(bindir)/foo + $(INSTALL_DATA) libfoo.a $(libdir)/libfoo.a + +Always use a file name, not a directory name, as the second argument of +the installation commands. Use a separate command for each file to be +installed. + + +File: standards.info, Node: Directory Variables, Prev: Command Variables, Up: Makefile Conventions + +Variables for Installation Directories +====================================== + + Installation directories should always be named by variables, so it +is easy to install in a nonstandard place. The standard names for these +variables are: + +`prefix' + A prefix used in constructing the default values of the variables + listed below. The default value of `prefix' should be `/usr/local' + (at least for now). + +`exec_prefix' + A prefix used in constructing the default values of some of the + variables listed below. The default value of `exec_prefix' should + be `$(prefix)'. + + Generally, `$(exec_prefix)' is used for directories that contain + machine-specific files (such as executables and subroutine + libraries), while `$(prefix)' is used directly for other + directories. + +`bindir' + The directory for installing executable programs that users can + run. This should normally be `/usr/local/bin', but write it as + `$(exec_prefix)/bin'. + +`libdir' + The directory for installing executable files to be run by the + program rather than by users. Object files and libraries of + object code should also go in this directory. The idea is that + this directory is used for files that pertain to a specific + machine architecture, but need not be in the path for commands. + The value of `libdir' should normally be `/usr/local/lib', but + write it as `$(exec_prefix)/lib'. + +`datadir' + The directory for installing read-only data files which the + programs refer to while they run. This directory is used for + files which are independent of the type of machine being used. + This should normally be `/usr/local/lib', but write it as + `$(prefix)/lib'. + +`statedir' + The directory for installing data files which the programs modify + while they run. These files should be independent of the type of + machine being used, and it should be possible to share them among + machines at a network installation. This should normally be + `/usr/local/lib', but write it as `$(prefix)/lib'. + +`includedir' + The directory for installing header files to be included by user + programs with the C `#include' preprocessor directive. This + should normally be `/usr/local/include', but write it as + `$(prefix)/include'. + + Most compilers other than GCC do not look for header files in + `/usr/local/include'. So installing the header files this way is + only useful with GCC. Sometimes this is not a problem because some + libraries are only really intended to work with GCC. But some + libraries are intended to work with other compilers. They should + install their header files in two places, one specified by + `includedir' and one specified by `oldincludedir'. + +`oldincludedir' + The directory for installing `#include' header files for use with + compilers other than GCC. This should normally be `/usr/include'. + + The Makefile commands should check whether the value of + `oldincludedir' is empty. If it is, they should not try to use + it; they should cancel the second installation of the header files. + + A package should not replace an existing header in this directory + unless the header came from the same package. Thus, if your Foo + package provides a header file `foo.h', then it should install the + header file in the `oldincludedir' directory if either (1) there + is no `foo.h' there or (2) the `foo.h' that exists came from the + Foo package. + + To tell whether `foo.h' came from the Foo package, put a magic + string in the file--part of a comment--and grep for that string. + +`mandir' + The directory for installing the man pages (if any) for this + package. It should include the suffix for the proper section of + the manual--usually `1' for a utility. It will normally be + `/usr/local/man/man1', but you should write it as + `$(prefix)/man/man1'. + +`man1dir' + The directory for installing section 1 man pages. + +`man2dir' + The directory for installing section 2 man pages. + +`...' + Use these names instead of `mandir' if the package needs to + install man pages in more than one section of the manual. + + *Don't make the primary documentation for any GNU software be a + man page. Write a manual in Texinfo instead. Man pages are just + for the sake of people running GNU software on Unix, which is a + secondary application only.* + +`manext' + The file name extension for the installed man page. This should + contain a period followed by the appropriate digit; it should + normally be `.1'. + +`man1ext' + The file name extension for installed section 1 man pages. + +`man2ext' + The file name extension for installed section 2 man pages. + +`...' + Use these names instead of `manext' if the package needs to + install man pages in more than one section of the manual. + +`infodir' + The directory for installing the Info files for this package. By + default, it should be `/usr/local/info', but it should be written + as `$(prefix)/info'. + +`srcdir' + The directory for the sources being compiled. The value of this + variable is normally inserted by the `configure' shell script. + + For example: + + # Common prefix for installation directories. + # NOTE: This directory must exist when you start the install. + prefix = /usr/local + exec_prefix = $(prefix) + # Where to put the executable for the command `gcc'. + bindir = $(exec_prefix)/bin + # Where to put the directories used by the compiler. + libdir = $(exec_prefix)/lib + # Where to put the Info files. + infodir = $(prefix)/info + + If your program installs a large number of files into one of the +standard user-specified directories, it might be useful to group them +into a subdirectory particular to that program. If you do this, you +should write the `install' rule to create these subdirectories. + + Do not expect the user to include the subdirectory name in the value +of any of the variables listed above. The idea of having a uniform set +of variable names for installation directories is to enable the user to +specify the exact same values for several different GNU packages. In +order for this to be useful, all the packages must be designed so that +they will work sensibly when the user does so. + + +File: standards.info, Node: Configuration, Next: Source Language, Prev: Makefile Conventions, Up: Top + +How Configuration Should Work +***************************** + + Each GNU distribution should come with a shell script named +`configure'. This script is given arguments which describe the kind of +machine and system you want to compile the program for. + + The `configure' script must record the configuration options so that +they affect compilation. + + One way to do this is to make a link from a standard name such as +`config.h' to the proper configuration file for the chosen system. If +you use this technique, the distribution should *not* contain a file +named `config.h'. This is so that people won't be able to build the +program without configuring it first. + + Another thing that `configure' can do is to edit the Makefile. If +you do this, the distribution should *not* contain a file named +`Makefile'. Instead, include a file `Makefile.in' which contains the +input used for editing. Once again, this is so that people won't be +able to build the program without configuring it first. + + If `configure' does write the `Makefile', then `Makefile' should +have a target named `Makefile' which causes `configure' to be rerun, +setting up the same configuration that was set up last time. The files +that `configure' reads should be listed as dependencies of `Makefile'. + + All the files which are output from the `configure' script should +have comments at the beginning explaining that they were generated +automatically using `configure'. This is so that users won't think of +trying to edit them by hand. + + The `configure' script should write a file named `config.status' +which describes which configuration options were specified when the +program was last configured. This file should be a shell script which, +if run, will recreate the same configuration. + + The `configure' script should accept an option of the form +`--srcdir=DIRNAME' to specify the directory where sources are found (if +it is not the current directory). This makes it possible to build the +program in a separate directory, so that the actual source directory is +not modified. + + If the user does not specify `--srcdir', then `configure' should +check both `.' and `..' to see if it can find the sources. If it finds +the sources in one of these places, it should use them from there. +Otherwise, it should report that it cannot find the sources, and should +exit with nonzero status. + + Usually the easy way to support `--srcdir' is by editing a +definition of `VPATH' into the Makefile. Some rules may need to refer +explicitly to the specified source directory. To make this possible, +`configure' can add to the Makefile a variable named `srcdir' whose +value is precisely the specified directory. + + The `configure' script should also take an argument which specifies +the type of system to build the program for. This argument should look +like this: + + CPU-COMPANY-SYSTEM + + For example, a Sun 3 might be `m68k-sun-sunos4.1'. + + The `configure' script needs to be able to decode all plausible +alternatives for how to describe a machine. Thus, `sun3-sunos4.1' +would be a valid alias. So would `sun3-bsd4.2', since SunOS is +basically BSD and no other BSD system is used on a Sun. For many +programs, `vax-dec-ultrix' would be an alias for `vax-dec-bsd', simply +because the differences between Ultrix and BSD are rarely noticeable, +but a few programs might need to distinguish them. + + There is a shell script called `config.sub' that you can use as a +subroutine to validate system types and canonicalize aliases. + + Other options are permitted to specify in more detail the software +or hardware present on the machine, and include or exclude optional +parts of the package: + +`--enable-FEATURE[=PARAMETER]' + Configure the package to build and install an optional user-level + facility called FEATURE. This allows users to choose which + optional features to include. Giving an optional PARAMETER of + `no' should omit FEATURE, if it is built by default. + + No `--enable' option should *ever* cause one feature to replace + another. No `--enable' option should ever substitute one useful + behavior for another useful behavior. The only proper use for + `--enable' is for questions of whether to build part of the program + or exclude it. + +`--with-PACKAGE' + The package PACKAGE will be installed, so configure this package + to work with PACKAGE. + + Possible values of PACKAGE include `x', `x-toolkit', `gnu-as' (or + `gas'), `gnu-ld', `gnu-libc', and `gdb'. + + Do not use a `--with' option to specify the file name to use to + find certain files. That is outside the scope of what `--with' + options are for. + +`--nfp' + The target machine has no floating point processor. + +`--gas' + The target machine assembler is GAS, the GNU assembler. This is + obsolete; users should use `--with-gnu-as' instead. + +`--x' + The target machine has the X Window System installed. This is + obsolete; users should use `--with-x' instead. + + All `configure' scripts should accept all of these "detail" options, +whether or not they make any difference to the particular package at +hand. In particular, they should accept any option that starts with +`--with-' or `--enable-'. This is so users will be able to configure +an entire GNU source tree at once with a single set of options. + + You will note that the categories `--with-' and `--enable-' are +narrow: they *do not* provide a place for any sort of option you might +think of. That is deliberate. We want to limit the possible +configuration options in GNU software. We do not want GNU programs to +have idiosyncratic configuration options. + + Packages that perform part of compilation may support +cross-compilation. In such a case, the host and target machines for +the program may be different. The `configure' script should normally +treat the specified type of system as both the host and the target, +thus producing a program which works for the same type of machine that +it runs on. + + The way to build a cross-compiler, cross-assembler, or what have +you, is to specify the option `--host=HOSTTYPE' when running +`configure'. This specifies the host system without changing the type +of target system. The syntax for HOSTTYPE is the same as described +above. + + Bootstrapping a cross-compiler requires compiling it on a machine +other than the host it will run on. Compilation packages accept a +configuration option `--build=HOSTTYPE' for specifying the +configuration on which you will compile them, in case that is different +from the host. + + Programs for which cross-operation is not meaningful need not accept +the `--host' option, because configuring an entire operating system for +cross-operation is not a meaningful thing. + + Some programs have ways of configuring themselves automatically. If +your program is set up to do this, your `configure' script can simply +ignore most of its arguments. + + +File: standards.info, Node: Source Language, Next: Formatting, Prev: Configuration, Up: Top + +Using Languages Other Than C +**************************** + + Using a language other than C is like using a non-standard feature: +it will cause trouble for users. Even if GCC supports the other +language, users may find it inconvenient to have to install the +compiler for that other language in order to build your program. So +please write in C. + + There are three exceptions for this rule: + + * It is okay to use a special language if the same program contains + an interpreter for that language. + + Thus, it is not a problem that GNU Emacs contains code written in + Emacs Lisp, because it comes with a Lisp interpreter. + + * It is okay to use another language in a tool specifically intended + for use with that language. + + This is okay because the only people who want to build the tool + will be those who have installed the other language anyway. + + * If an application is not of extremely widespread interest, then + perhaps it's not important if the application is inconvenient to + install. + + +File: standards.info, Node: Formatting, Next: Comments, Prev: Source Language, Up: Top + +Formatting Your Source Code +*************************** + + It is important to put the open-brace that starts the body of a C +function in column zero, and avoid putting any other open-brace or +open-parenthesis or open-bracket in column zero. Several tools look +for open-braces in column zero to find the beginnings of C functions. +These tools will not work on code not formatted that way. + + It is also important for function definitions to start the name of +the function in column zero. This helps people to search for function +definitions, and may also help certain tools recognize them. Thus, the +proper format is this: + + static char * + concat (s1, s2) /* Name starts in column zero here */ + char *s1, *s2; + { /* Open brace in column zero here */ + ... + } + +or, if you want to use ANSI C, format the definition like this: + + static char * + concat (char *s1, char *s2) + { + ... + } + + In ANSI C, if the arguments don't fit nicely on one line, split it +like this: + + int + lots_of_args (int an_integer, long a_long, short a_short, + double a_double, float a_float) + ... + + For the body of the function, we prefer code formatted like this: + + if (x < foo (y, z)) + haha = bar[4] + 5; + else + { + while (z) + { + haha += foo (z, z); + z--; + } + return ++x + bar (); + } + + We find it easier to read a program when it has spaces before the +open-parentheses and after the commas. Especially after the commas. + + When you split an expression into multiple lines, split it before an +operator, not after one. Here is the right way: + + if (foo_this_is_long && bar > win (x, y, z) + && remaining_condition) + + Try to avoid having two operators of different precedence at the same +level of indentation. For example, don't write this: + + mode = (inmode[j] == VOIDmode + || GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j]) + ? outmode[j] : inmode[j]); + + Instead, use extra parentheses so that the indentation shows the +nesting: + + mode = ((inmode[j] == VOIDmode + || (GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j]))) + ? outmode[j] : inmode[j]); + + Insert extra parentheses so that Emacs will indent the code properly. +For example, the following indentation looks nice if you do it by hand, +but Emacs would mess it up: + + v = rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000 + + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000; + + But adding a set of parentheses solves the problem: + + v = (rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000 + + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000); + + Format do-while statements like this: + + do + { + a = foo (a); + } + while (a > 0); + + Please use formfeed characters (control-L) to divide the program into +pages at logical places (but not within a function). It does not matter +just how long the pages are, since they do not have to fit on a printed +page. The formfeeds should appear alone on lines by themselves. + + +File: standards.info, Node: Comments, Next: Syntactic Conventions, Prev: Formatting, Up: Top + +Commenting Your Work +******************** + + Every program should start with a comment saying briefly what it is +for. Example: `fmt - filter for simple filling of text'. + + Please put a comment on each function saying what the function does, +what sorts of arguments it gets, and what the possible values of +arguments mean and are used for. It is not necessary to duplicate in +words the meaning of the C argument declarations, if a C type is being +used in its customary fashion. If there is anything nonstandard about +its use (such as an argument of type `char *' which is really the +address of the second character of a string, not the first), or any +possible values that would not work the way one would expect (such as, +that strings containing newlines are not guaranteed to work), be sure +to say so. + + Also explain the significance of the return value, if there is one. + + Please put two spaces after the end of a sentence in your comments, +so that the Emacs sentence commands will work. Also, please write +complete sentences and capitalize the first word. If a lower-case +identifer comes at the beginning of a sentence, don't capitalize it! +Changing the spelling makes it a different identifier. If you don't +like starting a sentence with a lower case letter, write the sentence +differently (e.g., "The identifier lower-case is ..."). + + The comment on a function is much clearer if you use the argument +names to speak about the argument values. The variable name itself +should be lower case, but write it in upper case when you are speaking +about the value rather than the variable itself. Thus, "the inode +number NODE_NUM" rather than "an inode". + + There is usually no purpose in restating the name of the function in +the comment before it, because the reader can see that for himself. +There might be an exception when the comment is so long that the +function itself would be off the bottom of the screen. + + There should be a comment on each static variable as well, like this: + + /* Nonzero means truncate lines in the display; + zero means continue them. */ + int truncate_lines; + + Every `#endif' should have a comment, except in the case of short +conditionals (just a few lines) that are not nested. The comment should +state the condition of the conditional that is ending, *including its +sense*. `#else' should have a comment describing the condition *and +sense* of the code that follows. For example: + + #ifdef foo + ... + #else /* not foo */ + ... + #endif /* not foo */ + +but, by contrast, write the comments this way for a `#ifndef': + + #ifndef foo + ... + #else /* foo */ + ... + #endif /* foo */ + + +File: standards.info, Node: Syntactic Conventions, Next: Names, Prev: Comments, Up: Top + +Clean Use of C Constructs +************************* + + Please explicitly declare all arguments to functions. Don't omit +them just because they are `int's. + + Declarations of external functions and functions to appear later in +the source file should all go in one place near the beginning of the +file (somewhere before the first function definition in the file), or +else should go in a header file. Don't put `extern' declarations inside +functions. + + It used to be common practice to use the same local variables (with +names like `tem') over and over for different values within one +function. Instead of doing this, it is better declare a separate local +variable for each distinct purpose, and give it a name which is +meaningful. This not only makes programs easier to understand, it also +facilitates optimization by good compilers. You can also move the +declaration of each local variable into the smallest scope that includes +all its uses. This makes the program even cleaner. + + Don't use local variables or parameters that shadow global +identifiers. + + Don't declare multiple variables in one declaration that spans lines. +Start a new declaration on each line, instead. For example, instead of +this: + + int foo, + bar; + +write either this: + + int foo, bar; + +or this: + + int foo; + int bar; + +(If they are global variables, each should have a comment preceding it +anyway.) + + When you have an `if'-`else' statement nested in another `if' +statement, always put braces around the `if'-`else'. Thus, never write +like this: + + if (foo) + if (bar) + win (); + else + lose (); + +always like this: + + if (foo) + { + if (bar) + win (); + else + lose (); + } + + If you have an `if' statement nested inside of an `else' statement, +either write `else if' on one line, like this, + + if (foo) + ... + else if (bar) + ... + +with its `then'-part indented like the preceding `then'-part, or write +the nested `if' within braces like this: + + if (foo) + ... + else + { + if (bar) + ... + } + + Don't declare both a structure tag and variables or typedefs in the +same declaration. Instead, declare the structure tag separately and +then use it to declare the variables or typedefs. + + Try to avoid assignments inside `if'-conditions. For example, don't +write this: + + if ((foo = (char *) malloc (sizeof *foo)) == 0) + fatal ("virtual memory exhausted"); + +instead, write this: + + foo = (char *) malloc (sizeof *foo); + if (foo == 0) + fatal ("virtual memory exhausted"); + + Don't make the program ugly to placate `lint'. Please don't insert +any casts to `void'. Zero without a cast is perfectly fine as a null +pointer constant. + + +File: standards.info, Node: Names, Next: Using Extensions, Prev: Syntactic Conventions, Up: Top + +Naming Variables and Functions +****************************** + + Please use underscores to separate words in a name, so that the Emacs +word commands can be useful within them. Stick to lower case; reserve +upper case for macros and `enum' constants, and for name-prefixes that +follow a uniform convention. + + For example, you should use names like `ignore_space_change_flag'; +don't use names like `iCantReadThis'. + + Variables that indicate whether command-line options have been +specified should be named after the meaning of the option, not after +the option-letter. A comment should state both the exact meaning of +the option and its letter. For example, + + /* Ignore changes in horizontal whitespace (-b). */ + int ignore_space_change_flag; + + When you want to define names with constant integer values, use +`enum' rather than `#define'. GDB knows about enumeration constants. + + Use file names of 14 characters or less, to avoid creating gratuitous +problems on System V. You can use the program `doschk' to test for +this. `doschk' also tests for potential name conflicts if the files +were loaded onto an MS-DOS file system--something you may or may not +care about. + diff --git a/gnu/usr.bin/binutils/etc/standards.info-2 b/gnu/usr.bin/binutils/etc/standards.info-2 new file mode 100644 index 00000000000..119f28149f4 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/standards.info-2 @@ -0,0 +1,1462 @@ +This is Info file standards.info, produced by Makeinfo-1.55 from the +input file ./standards.texi. + +START-INFO-DIR-ENTRY +* Standards: (standards). GNU coding standards. +END-INFO-DIR-ENTRY + + GNU Coding Standards Copyright (C) 1992, 1993, 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. + + 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 Free Software Foundation. + + +File: standards.info, Node: Using Extensions, Next: System Functions, Prev: Names, Up: Top + +Using Non-standard Features +*************************** + + Many GNU facilities that already exist support a number of convenient +extensions over the comparable Unix facilities. Whether to use these +extensions in implementing your program is a difficult question. + + On the one hand, using the extensions can make a cleaner program. +On the other hand, people will not be able to build the program unless +the other GNU tools are available. This might cause the program to +work on fewer kinds of machines. + + With some extensions, it might be easy to provide both alternatives. +For example, you can define functions with a "keyword" `INLINE' and +define that as a macro to expand into either `inline' or nothing, +depending on the compiler. + + In general, perhaps it is best not to use the extensions if you can +straightforwardly do without them, but to use the extensions if they +are a big improvement. + + An exception to this rule are the large, established programs (such +as Emacs) which run on a great variety of systems. Such programs would +be broken by use of GNU extensions. + + Another exception is for programs that are used as part of +compilation: anything that must be compiled with other compilers in +order to bootstrap the GNU compilation facilities. If these require +the GNU compiler, then no one can compile them without having them +installed already. That would be no good. + + Since most computer systems do not yet implement ANSI C, using the +ANSI C features is effectively using a GNU extension, so the same +considerations apply. (Except for ANSI features that we discourage, +such as trigraphs--don't ever use them.) + + +File: standards.info, Node: System Functions, Next: Semantics, Prev: Using Extensions, Up: Top + +Calling System Functions +************************ + + C implementations differ substantially. ANSI C reduces but does not +eliminate the incompatibilities; meanwhile, many users wish to compile +GNU software with pre-ANSI compilers. This chapter gives +recommendations for how to use the more or less standard C library +functions to avoid unnecessary loss of portability. + + * Don't use the value of `sprintf'. It returns the number of + characters written on some systems, but not on all systems. + + * Don't declare system functions explicitly. + + Almost any declaration for a system function is wrong on some + system. To minimize conflicts, leave it to the system header + files to declare system functions. If the headers don't declare a + function, let it remain undeclared. + + While it may seem unclean to use a function without declaring it, + in practice this works fine for most system library functions on + the systems where this really happens. The problem is only + theoretical. By contrast, actual declarations have frequently + caused actual conflicts. + + * If you must declare a system function, don't specify the argument + types. Use an old-style declaration, not an ANSI prototype. The + more you specify about the function, the more likely a conflict. + + * In particular, don't unconditionally declare `malloc' or `realloc'. + + Most GNU programs use those functions just once, in functions + conventionally named `xmalloc' and `xrealloc'. These functions + call `malloc' and `realloc', respectively, and check the results. + + Because `xmalloc' and `xrealloc' are defined in your program, you + can declare them in other files without any risk of type conflict. + + On most systems, `int' is the same length as a pointer; thus, the + calls to `malloc' and `realloc' work fine. For the few + exceptional systems (mostly 64-bit machines), you can use + *conditionalized* declarations of `malloc' and `realloc'--or put + these declarations in configuration files specific to those + systems. + + * The string functions require special treatment. Some Unix systems + have a header file `string.h'; other have `strings.h'. Neither + file name is portable. There are two things you can do: use + Autoconf to figure out which file to include, or don't include + either file. + + * If you don't include either strings file, you can't get + declarations for the string functions from the header file in the + usual way. + + That causes less of a problem than you might think. The newer ANSI + string functions are off-limits anyway because many systems still + don't support them. The string functions you can use are these: + + strcpy strncpy strcat strncat + strlen strcmp strncmp + strchr strrchr + + The copy and concatenate functions work fine without a declaration + as long as you don't use their values. Using their values without + a declaration fails on systems where the width of a pointer + differs from the width of `int', and perhaps in other cases. It + is trivial to avoid using their values, so do that. + + The compare functions and `strlen' work fine without a declaration + on most systems, possibly all the ones that GNU software runs on. + You may find it necessary to declare them *conditionally* on a few + systems. + + The search functions must be declared to return `char *'. Luckily, + there is no variation in the data type they return. But there is + variation in their names. Some systems give these functions the + names `index' and `rindex'; other systems use the names `strchr' + and `strrchr'. Some systems support both pairs of names, but + neither pair works on all systems. + + You should pick a single pair of names and use it throughout your + program. (Nowadays, it is better to choose `strchr' and + `strrchr'.) Declare both of those names as functions returning + `char *'. On systems which don't support those names, define them + as macros in terms of the other pair. For example, here is what + to put at the beginning of your file (or in a header) if you want + to use the names `strchr' and `strrchr' throughout: + + #ifndef HAVE_STRCHR + #define strchr index + #endif + #ifndef HAVE_STRRCHR + #define strrchr rindex + #endif + + char *strchr (); + char *strrchr (); + + Here we assume that `HAVE_STRCHR' and `HAVE_STRRCHR' are macros +defined in systems where the corresponding functions exist. One way to +get them properly defined is to use Autoconf. + + +File: standards.info, Node: Semantics, Next: Errors, Prev: System Functions, Up: Top + +Program Behavior for All Programs +********************************* + + Avoid arbitrary limits on the length or number of *any* data +structure, including filenames, lines, files, and symbols, by allocating +all data structures dynamically. In most Unix utilities, "long lines +are silently truncated". This is not acceptable in a GNU utility. + + Utilities reading files should not drop NUL characters, or any other +nonprinting characters *including those with codes above 0177*. The +only sensible exceptions would be utilities specifically intended for +interface to certain types of printers that can't handle those +characters. + + Check every system call for an error return, unless you know you +wish to ignore errors. Include the system error text (from `perror' or +equivalent) in *every* error message resulting from a failing system +call, as well as the name of the file if any and the name of the +utility. Just "cannot open foo.c" or "stat failed" is not sufficient. + + Check every call to `malloc' or `realloc' to see if it returned +zero. Check `realloc' even if you are making the block smaller; in a +system that rounds block sizes to a power of 2, `realloc' may get a +different block if you ask for less space. + + In Unix, `realloc' can destroy the storage block if it returns zero. +GNU `realloc' does not have this bug: if it fails, the original block +is unchanged. Feel free to assume the bug is fixed. If you wish to +run your program on Unix, and wish to avoid lossage in this case, you +can use the GNU `malloc'. + + You must expect `free' to alter the contents of the block that was +freed. Anything you want to fetch from the block, you must fetch before +calling `free'. + + Use `getopt_long' to decode arguments, unless the argument syntax +makes this unreasonable. + + When static storage is to be written in during program execution, use +explicit C code to initialize it. Reserve C initialized declarations +for data that will not be changed. + + Try to avoid low-level interfaces to obscure Unix data structures +(such as file directories, utmp, or the layout of kernel memory), since +these are less likely to work compatibly. If you need to find all the +files in a directory, use `readdir' or some other high-level interface. +These will be supported compatibly by GNU. + + By default, the GNU system will provide the signal handling +functions of BSD and of POSIX. So GNU software should be written to use +these. + + In error checks that detect "impossible" conditions, just abort. +There is usually no point in printing any message. These checks +indicate the existence of bugs. Whoever wants to fix the bugs will have +to read the source code and run a debugger. So explain the problem with +comments in the source. The relevant data will be in variables, which +are easy to examine with the debugger, so there is no point moving them +elsewhere. + + +File: standards.info, Node: Errors, Next: Libraries, Prev: Semantics, Up: Top + +Formatting Error Messages +************************* + + Error messages from compilers should look like this: + + SOURCE-FILE-NAME:LINENO: MESSAGE + + Error messages from other noninteractive programs should look like +this: + + PROGRAM:SOURCE-FILE-NAME:LINENO: MESSAGE + +when there is an appropriate source file, or like this: + + PROGRAM: MESSAGE + +when there is no relevant source file. + + In an interactive program (one that is reading commands from a +terminal), it is better not to include the program name in an error +message. The place to indicate which program is running is in the +prompt or with the screen layout. (When the same program runs with +input from a source other than a terminal, it is not interactive and +would do best to print error messages using the noninteractive style.) + + The string MESSAGE should not begin with a capital letter when it +follows a program name and/or filename. Also, it should not end with a +period. + + Error messages from interactive programs, and other messages such as +usage messages, should start with a capital letter. But they should not +end with a period. + + +File: standards.info, Node: Libraries, Next: Portability, Prev: Errors, Up: Top + +Library Behavior +**************** + + Try to make library functions reentrant. If they need to do dynamic +storage allocation, at least try to avoid any nonreentrancy aside from +that of `malloc' itself. + + Here are certain name conventions for libraries, to avoid name +conflicts. + + Choose a name prefix for the library, more than two characters long. +All external function and variable names should start with this prefix. +In addition, there should only be one of these in any given library +member. This usually means putting each one in a separate source file. + + An exception can be made when two external symbols are always used +together, so that no reasonable program could use one without the +other; then they can both go in the same file. + + External symbols that are not documented entry points for the user +should have names beginning with `_'. They should also contain the +chosen name prefix for the library, to prevent collisions with other +libraries. These can go in the same files with user entry points if +you like. + + Static functions and variables can be used as you like and need not +fit any naming convention. + + +File: standards.info, Node: Portability, Next: User Interfaces, Prev: Libraries, Up: Top + +Portability As It Applies to GNU +******************************** + + Much of what is called "portability" in the Unix world refers to +porting to different Unix versions. This is a secondary consideration +for GNU software, because its primary purpose is to run on top of one +and only one kernel, the GNU kernel, compiled with one and only one C +compiler, the GNU C compiler. The amount and kinds of variation among +GNU systems on different cpu's will be like the variation among Berkeley +4.3 systems on different cpu's. + + All users today run GNU software on non-GNU systems. So supporting a +variety of non-GNU systems is desirable; simply not paramount. The +easiest way to achieve portability to a reasonable range of systems is +to use Autoconf. It's unlikely that your program needs to know more +information about the host machine than Autoconf can provide, simply +because most of the programs that need such knowledge have already been +written. + + It is difficult to be sure exactly what facilities the GNU kernel +will provide, since it isn't finished yet. Therefore, assume you can +use anything in 4.3; just avoid using the format of semi-internal data +bases (e.g., directories) when there is a higher-level alternative +(`readdir'). + + You can freely assume any reasonably standard facilities in the C +language, libraries or kernel, because we will find it necessary to +support these facilities in the full GNU system, whether or not we have +already done so. The fact that there may exist kernels or C compilers +that lack these facilities is irrelevant as long as the GNU kernel and +C compiler support them. + + It remains necessary to worry about differences among cpu types, such +as the difference in byte ordering and alignment restrictions. It's +unlikely that 16-bit machines will ever be supported by GNU, so there +is no point in spending any time to consider the possibility that an +int will be less than 32 bits. + + You can assume that all pointers have the same format, regardless of +the type they point to, and that this is really an integer. There are +some weird machines where this isn't true, but they aren't important; +don't waste time catering to them. Besides, eventually we will put +function prototypes into all GNU programs, and that will probably make +your program work even on weird machines. + + Since some important machines (including the 68000) are big-endian, +it is important not to assume that the address of an `int' object is +also the address of its least-significant byte. Thus, don't make the +following mistake: + + int c; + ... + while ((c = getchar()) != EOF) + write(file_descriptor, &c, 1); + + You can assume that it is reasonable to use a meg of memory. Don't +strain to reduce memory usage unless it can get to that level. If your +program creates complicated data structures, just make them in core and +give a fatal error if malloc returns zero. + + If a program works by lines and could be applied to arbitrary +user-supplied input files, it should keep only a line in memory, because +this is not very hard and users will want to be able to operate on input +files that are bigger than will fit in core all at once. + + +File: standards.info, Node: User Interfaces, Next: Documentation, Prev: Portability, Up: Top + +Standards for Command Line Interfaces +************************************* + + Please don't make the behavior of a utility depend on the name used +to invoke it. It is useful sometimes to make a link to a utility with +a different name, and that should not change what it does. + + Instead, use a run time option or a compilation switch or both to +select among the alternate behaviors. + + Likewise, please don't make the behavior of the program depend on the +type of output device it is used with. Device independence is an +important principle of the system's design; do not compromise it merely +to save someone from typing an option now and then. + + If you think one behavior is most useful when the output is to a +terminal, and another is most useful when the output is a file or a +pipe, then it is usually best to make the default behavior the one that +is useful with output to a terminal, and have an option for the other +behavior. + + Compatibility requires certain programs to depend on the type of +output device. It would be disastrous if `ls' or `sh' did not do so in +the way all users expect. In some of these cases, we supplement the +program with a preferred alternate version that does not depend on the +output device type. For example, we provide a `dir' program much like +`ls' except that its default output format is always multi-column +format. + + It is a good idea to follow the POSIX guidelines for the +command-line options of a program. The easiest way to do this is to use +`getopt' to parse them. Note that the GNU version of `getopt' will +normally permit options anywhere among the arguments unless the special +argument `--' is used. This is not what POSIX specifies; it is a GNU +extension. + + Please define long-named options that are equivalent to the +single-letter Unix-style options. We hope to make GNU more user +friendly this way. This is easy to do with the GNU function +`getopt_long'. + + One of the advantages of long-named options is that they can be +consistent from program to program. For example, users should be able +to expect the "verbose" option of any GNU program which has one, to be +spelled precisely `--verbose'. To achieve this uniformity, look at the +table of common long-option names when you choose the option names for +your program. The table appears below. + + If you use names not already in the table, please send +`gnu@prep.ai.mit.edu' a list of them, with their meanings, so we can +update the table. + + It is usually a good idea for file names given as ordinary arguments +to be input files only; any output files would be specified using +options (preferably `-o'). Even if you allow an output file name as an +ordinary argument for compatibility, try to provide a suitable option +as well. This will lead to more consistency among GNU utilities, so +that there are fewer idiosyncracies for users to remember. + + Programs should support an option `--version' which prints the +program's version number on standard output and exits successfully, and +an option `--help' which prints option usage information on standard +output and exits successfully. These options should inhibit the normal +function of the command; they should do nothing except print the +requested information. + +`auto-check' + `-a' in `recode'. + +`auto-reference' + `-A' in `ptx'. + +`after-date' + `-N' in `tar'. + +`all' + `-a' in `du', `ls', `nm', `stty', `uname', and `unexpand'. + +`all-text' + `-a' in `diff'. + +`almost-all' + `-A' in `ls'. + +`append' + `-a' in `etags', `tee', `time'; `-r' in `tar'. + +`archive' + `-a' in `cp'. + +`arglength' + `-l' in `m4'. + +`ascii' + `-a' in `diff'. + +`assume-new' + `-W' in Make. + +`assume-old' + `-o' in Make. + +`backward-search' + `-B' in etags. + +`batch' + Used in GDB. + +`baud' + Used in GDB. + +`before' + `-b' in `tac'. + +`binary' + `-b' in `cpio' and `diff'. + +`block-size' + Used in `cpio' and `tar'. + +`blocks' + `-b' in `head' and `tail'. + +`break-file' + `-b' in `ptx'. + +`brief' + Used in various programs to make output shorter. + +`bytes' + `-c' in `head', `split', and `tail'. + +`c++' + `-C' in `etags'. + +`catenate' + `-A' in `tar'. + +`cd' + Used in various programs to specify the directory to use. + +`changes' + `-c' in `chgrp' and `chown'. + +`classify' + `-F' in `ls'. + +`colons' + `-c' in `recode'. + +`command' + `-c' in `su'; `-x' in GDB. + +`compare' + `-d' in `tar'. + +`compress' + `-Z' in `tar'. + +`concatenate' + `-A' in `tar'. + +`confirmation' + `-w' in `tar'. + +`context' + Used in `diff'. + +`copyright' + `-C' in `ptx' and `recode'. + +`core' + Used in GDB. + +`count' + `-q' in `who'. + +`count-links' + `-l' in `du'. + +`create' + Used in `tar' and `cpio'. + +`cxref' + `-x' in `etags'. + +`date' + `-d' in `touch'. + +`debug' + `-d' in Make and `m4'; `-t' in Bison. + +`define' + `-D' in `m4'. + +`defines' + `-d' in Bison and `etags'. + +`delete' + `-D' in `tar'. + +`dereference' + `-L' in `chgrp', `chown', `cpio', `du', `ls', and `tar'. + +`dereference-args' + `-D' in `du'. + +`diacritics' + `-d' in `recode'. + +`dictionary-order' + `-d' in `look'. + +`diff' + `-d' in `tar'. + +`digits' + `-n' in `csplit'. + +`directory' + Specify the directory to use, in various programs. In `ls', it + means to show directories themselves rather than their contents. + In `rm' and `ln', it means to not treat links to directories + specially. + +`discard-all' + `-x' in `strip'. + +`discard-locals' + `-X' in `strip'. + +`diversions' + `-N' in `m4'. + +`dry-run' + `-n' in Make. + +`ed' + `-e' in `diff'. + +`elide-empty-files' + `-z' in `csplit'. + +`entire-new-file' + `-N' in `diff'. + +`environment-overrides' + `-e' in Make. + +`eof' + `-e' in `xargs'. + +`epoch' + Used in GDB. + +`error-limit' + Used in Makeinfo. + +`error-output' + `-o' in `m4'. + +`escape' + `-b' in `ls'. + +`exclude-from' + `-X' in `tar'. + +`exec' + Used in GDB. + +`exit' + `-x' in `xargs'. + +`expand-tabs' + `-t' in `diff'. + +`expression' + `-e' in `sed'. + +`extern-only' + `-g' in `nm'. + +`extract' + `-i' in `cpio'; `-x' in `tar'. + +`faces' + `-f' in `finger'. + +`fast' + `-f' in `su'. + +`file' + `-f' in `info', Make, `mt', and `tar'; `-n' in `sed'; `-r' in + `touch'. + +`file-prefix' + `-b' in Bison. + +`file-type' + `-F' in `ls'. + +`files-from' + `-T' in `tar'. + +`fill-column' + Used in Makeinfo. + +`flag-truncation' + `-F' in `ptx'. + +`fixed-output-files' + `-y' in Bison. + +`follow' + `-f' in `tail'. + +`footnote-style' + Used in Makeinfo. + +`force' + `-f' in `cp', `ln', `mv', and `rm'. + +`format' + Used in `ls', `time', and `ptx'. + +`forward-search' + `-F' in `etags'. + +`fullname' + Used in GDB. + +`gap-size' + `-g' in `ptx'. + +`get' + `-x' in `tar'. + +`graphic' + `-i' in `ul'. + +`graphics' + `-g' in `recode'. + +`group' + `-g' in `install'. + +`gzip' + `-z' in `tar'. + +`hashsize' + `-H' in `m4'. + +`header' + `-h' in `objdump' and `recode' + +`heading' + `-H' in `who'. + +`help' + Used to ask for brief usage information. + +`hide-control-chars' + `-q' in `ls'. + +`idle' + `-u' in `who'. + +`ifdef' + `-D' in `diff'. + +`ignore' + `-I' in `ls'; `-x' in `recode'. + +`ignore-all-space' + `-w' in `diff'. + +`ignore-backups' + `-B' in `ls'. + +`ignore-blank-lines' + `-B' in `diff'. + +`ignore-case' + `-f' in `look' and `ptx'; `-i' in `diff'. + +`ignore-errors' + `-i' in Make. + +`ignore-file' + `-i' in `ptx'. + +`ignore-indentation' + `-S' in `etags'. + +`ignore-init-file' + `-f' in Oleo. + +`ignore-interrupts' + `-i' in `tee'. + +`ignore-matching-lines' + `-I' in `diff'. + +`ignore-space-change' + `-b' in `diff'. + +`ignore-zeros' + `-i' in `tar'. + +`include' + `-i' in `etags'; `-I' in `m4'. + +`include-dir' + `-I' in Make. + +`incremental' + `-G' in `tar'. + +`info' + `-i', `-l', and `-m' in Finger. + +`initial' + `-i' in `expand'. + +`initial-tab' + `-T' in `diff'. + +`inode' + `-i' in `ls'. + +`interactive' + `-i' in `cp', `ln', `mv', `rm'; `-e' in `m4'; `-p' in `xargs'; + `-w' in `tar'. + +`jobs' + `-j' in Make. + +`just-print' + `-n' in Make. + +`keep-going' + `-k' in Make. + +`keep-files' + `-k' in `csplit'. + +`kilobytes' + `-k' in `du' and `ls'. + +`line-bytes' + `-C' in `split'. + +`lines' + Used in `split', `head', and `tail'. + +`link' + `-l' in `cpio'. + +`list' + `-t' in `cpio'; `-l' in `recode'. + +`list' + `-t' in `tar'. + +`literal' + `-N' in `ls'. + +`load-average' + `-l' in Make. + +`login' + Used in `su'. + +`machine' + No listing of which programs already use this; someone should + check to see if any actually do and tell `gnu@prep.ai.mit.edu'. + +`macro-name' + `-M' in `ptx'. + +`mail' + `-m' in `hello' and `uname'. + +`make-directories' + `-d' in `cpio'. + +`makefile' + `-f' in Make. + +`mapped' + Used in GDB. + +`max-args' + `-n' in `xargs'. + +`max-chars' + `-n' in `xargs'. + +`max-lines' + `-l' in `xargs'. + +`max-load' + `-l' in Make. + +`max-procs' + `-P' in `xargs'. + +`mesg' + `-T' in `who'. + +`message' + `-T' in `who'. + +`minimal' + `-d' in `diff'. + +`mode' + `-m' in `install', `mkdir', and `mkfifo'. + +`modification-time' + `-m' in `tar'. + +`multi-volume' + `-M' in `tar'. + +`name-prefix' + `-a' in Bison. + +`new-file' + `-W' in Make. + +`no-builtin-rules' + `-r' in Make. + +`no-create' + `-c' in `touch'. + +`no-defines' + `-D' in `etags'. + +`no-dereference' + `-d' in `cp'. + +`no-keep-going' + `-S' in Make. + +`no-lines' + `-l' in Bison. + +`no-prof' + `-e' in `gprof'. + +`no-sort' + `-p' in `nm'. + +`no-split' + Used in Makeinfo. + +`no-static' + `-a' in `gprof'. + +`no-time' + `-E' in `gprof'. + +`no-validate' + Used in Makeinfo. + +`no-warn' + Used in various programs to inhibit warnings. + +`node' + `-n' in `info'. + +`nodename' + `-n' in `uname'. + +`nonmatching' + `-f' in `cpio'. + +`nstuff' + `-n' in `objdump'. + +`null' + `-0' in `xargs'. + +`number' + `-n' in `cat'. + +`number-nonblank' + `-b' in `cat'. + +`numeric-sort' + `-n' in `nm'. + +`numeric-uid-gid' + `-n' in `cpio' and `ls'. + +`nx' + Used in GDB. + +`old-archive' + `-o' in `tar'. + +`old-file' + `-o' in Make. + +`one-file-system' + `-l' in `tar', `cp', and `du'. + +`only-file' + `-o' in `ptx'. + +`only-prof' + `-f' in `gprof'. + +`only-time' + `-F' in `gprof'. + +`output' + In various programs, specify the output file name. + +`override' + `-o' in `rm'. + +`owner' + `-o' in `install'. + +`paginate' + `-l' in `diff'. + +`paragraph-indent' + Used in Makeinfo. + +`parents' + `-p' in `mkdir' and `rmdir'. + +`pass-all' + `-p' in `ul'. + +`pass-through' + `-p' in `cpio'. + +`port' + `-P' in `finger'. + +`portability' + `-c' in `cpio' and `tar'. + +`prefix-builtins' + `-P' in `m4'. + +`prefix' + `-f' in `csplit'. + +`preserve' + Used in `tar' and `cp'. + +`preserve-environment' + `-p' in `su'. + +`preserve-modification-time' + `-m' in `cpio'. + +`preserve-order' + `-s' in `tar'. + +`preserve-permissions' + `-p' in `tar'. + +`print' + `-l' in `diff'. + +`print-chars' + `-L' in `cmp'. + +`print-data-base' + `-p' in Make. + +`print-directory' + `-w' in Make. + +`print-file-name' + `-o' in `nm'. + +`print-symdefs' + `-s' in `nm'. + +`question' + `-q' in Make. + +`quiet' + Used in many programs to inhibit the usual output. *Note:* every + program accepting `--quiet' should accept `--silent' as a synonym. + +`quote-name' + `-Q' in `ls'. + +`rcs' + `-n' in `diff'. + +`read-full-blocks' + `-B' in `tar'. + +`readnow' + Used in GDB. + +`recon' + `-n' in Make. + +`record-number' + `-R' in `tar'. + +`recursive' + Used in `chgrp', `chown', `cp', `ls', `diff', and `rm'. + +`reference-limit' + Used in Makeinfo. + +`references' + `-r' in `ptx'. + +`regex' + `-r' in `tac'. + +`release' + `-r' in `uname'. + +`relocation' + `-r' in `objdump'. + +`rename' + `-r' in `cpio'. + +`replace' + `-i' in `xargs'. + +`report-identical-files' + `-s' in `diff'. + +`reset-access-time' + `-a' in `cpio'. + +`reverse' + `-r' in `ls' and `nm'. + +`reversed-ed' + `-f' in `diff'. + +`right-side-defs' + `-R' in `ptx'. + +`same-order' + `-s' in `tar'. + +`same-permissions' + `-p' in `tar'. + +`save' + `-g' in `stty'. + +`se' + Used in GDB. + +`sentence-regexp' + `-S' in `ptx'. + +`separate-dirs' + `-S' in `du'. + +`separator' + `-s' in `tac'. + +`sequence' + Used by `recode' to chose files or pipes for sequencing passes. + +`shell' + `-s' in `su'. + +`show-all' + `-A' in `cat'. + +`show-c-function' + `-p' in `diff'. + +`show-ends' + `-E' in `cat'. + +`show-function-line' + `-F' in `diff'. + +`show-tabs' + `-T' in `cat'. + +`silent' + Used in many programs to inhibit the usual output. *Note:* every + program accepting `--silent' should accept `--quiet' as a synonym. + +`size' + `-s' in `ls'. + +`sort' + Used in `ls'. + +`sparse' + `-S' in `tar'. + +`speed-large-files' + `-H' in `diff'. + +`squeeze-blank' + `-s' in `cat'. + +`starting-file' + Used in `tar' and `diff' to specify which file within a directory + to start processing with. + +`stop' + `-S' in Make. + +`strict' + `-s' in `recode'. + +`strip' + `-s' in `install'. + +`strip-all' + `-s' in `strip'. + +`strip-debug' + `-S' in `strip'. + +`suffix' + `-S' in `cp', `ln', `mv'. + +`suffix-format' + `-b' in `csplit'. + +`sum' + `-s' in `gprof'. + +`summarize' + `-s' in `du'. + +`symbolic' + `-s' in `ln'. + +`symbols' + Used in GDB and `objdump'. + +`synclines' + `-s' in `m4'. + +`sysname' + `-s' in `uname'. + +`tabs' + `-t' in `expand' and `unexpand'. + +`tabsize' + `-T' in `ls'. + +`terminal' + `-T' in `tput' and `ul'. + +`text' + `-a' in `diff'. + +`time' + Used in `ls' and `touch'. + +`to-stdout' + `-O' in `tar'. + +`total' + `-c' in `du'. + +`touch' + `-t' in Make, `ranlib', and `recode'. + +`trace' + `-t' in `m4'. + +`traditional' + `-t' in `hello'; `-G' in `m4' and `ptx'. + +`tty' + Used in GDB. + +`typedefs' + `-t' in `etags'. + +`typedefs-and-c++' + `-T' in `etags'. + +`typeset-mode' + `-t' in `ptx'. + +`uncompress' + `-z' in `tar'. + +`unconditional' + `-u' in `cpio'. + +`undefine' + `-U' in `m4'. + +`undefined-only' + `-u' in `nm'. + +`update' + `-u' in `cp', `etags', `mv', `tar'. + +`verbose' + Print more information about progress. Many programs support this. + +`verify' + `-W' in `tar'. + +`version' + Print the version number. + +`version-control' + `-V' in `cp', `ln', `mv'. + +`vgrind' + `-v' in `etags'. + +`volume' + `-V' in `tar'. + +`what-if' + `-W' in Make. + +`width' + `-w' in `ls' and `ptx'. + +`word-regexp' + `-W' in `ptx'. + +`writable' + `-T' in `who'. + +`zeros' + `-z' in `gprof'. + + +File: standards.info, Node: Documentation, Next: Releases, Prev: User Interfaces, Up: Top + +Documenting Programs +******************** + + Please use Texinfo for documenting GNU programs. See the Texinfo +manual, either the hardcopy or the version in the GNU Emacs Info +subsystem (`C-h i'). See existing GNU Texinfo files (e.g., those under +the `man/' directory in the GNU Emacs distribution) for examples. + + The title page of the manual should state the version of the program +which the manual applies to. The Top node of the manual should also +contain this information. If the manual is changing more frequently +than or independent of the program, also state a version number for the +manual in both of these places. + + The manual should document all command-line arguments and all +commands. It should give examples of their use. But don't organize +the manual as a list of features. Instead, organize it by the concepts +a user will have before reaching that point in the manual. Address the +goals that a user will have in mind, and explain how to accomplish +them. Don't use Unix man pages as a model for how to write GNU +documentation; they are a bad example to follow. + + The manual should have a node named `PROGRAM Invocation' or +`Invoking PROGRAM', where PROGRAM stands for the name of the program +being described, as you would type it in the shell to run the program. +This node (together with its subnodes, if any) should describe the +program's command line arguments and how to run it (the sort of +information people would look in a man page for). Start with an +`@example' containing a template for all the options and arguments that +the program uses. + + Alternatively, put a menu item in some menu whose item name fits one +of the above patterns. This identifies the node which that item points +to as the node for this purpose, regardless of the node's actual name. + + There will be automatic features for specifying a program name and +quickly reading just this part of its manual. + + If one manual describes several programs, it should have such a node +for each program described. + + In addition to its manual, the package should have a file named +`NEWS' which contains a list of user-visible changes worth mentioning. +In each new release, add items to the front of the file and identify +the version they pertain to. Don't discard old items; leave them in +the file after the newer items. This way, a user upgrading from any +previous version can see what is new. + + If the `NEWS' file gets very long, move some of the older items into +a file named `ONEWS' and put a note at the end referring the user to +that file. + + Please do not use the term "pathname" that is used in Unix +documentation; use "file name" (two words) instead. We use the term +"path" only for search paths, which are lists of file names. + + It is ok to supply a man page for the program as well as a Texinfo +manual if you wish to. But keep in mind that supporting a man page +requires continual effort, each time the program is changed. Any time +you spend on the man page is time taken away from more useful things you +could contribute. + + Thus, even if a user volunteers to donate a man page, you may find +this gift costly to accept. Unless you have time on your hands, it may +be better to refuse the man page unless the same volunteer agrees to +take full responsibility for maintaining it--so that you can wash your +hands of it entirely. If the volunteer ceases to do the job, then +don't feel obliged to pick it up yourself; it may be better to withdraw +the man page until another volunteer offers to carry on with it. + + Alternatively, if you expect the discrepancies to be small enough +that the man page remains useful, put a prominent note near the +beginning of the man page explaining that you don't maintain it and +that the Texinfo manual is more authoritative, and describing how to +access the Texinfo documentation. + + +File: standards.info, Node: Releases, Prev: Documentation, Up: Top + +Making Releases +*************** + + Package the distribution of Foo version 69.96 in a gzipped tar file +named `foo-69.96.tar.gz'. It should unpack into a subdirectory named +`foo-69.96'. + + Building and installing the program should never modify any of the +files contained in the distribution. This means that all the files +that form part of the program in any way must be classified into "source +files" and "non-source files". Source files are written by humans and +never changed automatically; non-source files are produced from source +files by programs under the control of the Makefile. + + Naturally, all the source files must be in the distribution. It is +okay to include non-source files in the distribution, provided they are +up-to-date and machine-independent, so that building the distribution +normally will never modify them. We commonly include non-source files +produced by Bison, Lex, TeX, and Makeinfo; this helps avoid unnecessary +dependencies between our distributions, so that users can install +whichever packages they want to install. + + Non-source files that might actually be modified by building and +installing the program should *never* be included in the distribution. +So if you do distribute non-source files, always make sure they are up +to date when you make a new distribution. + + Make sure that the directory into which the distribution unpacks (as +well as any subdirectories) are all world-writable (octal mode 777). +This is so that old versions of `tar' which preserve the ownership and +permissions of the files from the tar archive will be able to extract +all the files even if the user is unprivileged. + + Make sure that all the files in the distribution are world-readable. + + Make sure that no file name in the distribution is more than 14 +characters long. Likewise, no file created by building the program +should have a name longer than 14 characters. The reason for this is +that some systems adhere to a foolish interpretation of the POSIX +standard, and refuse to open a longer name, rather than truncating as +they did in the past. + + Don't include any symbolic links in the distribution itself. If the +tar file contains symbolic links, then people cannot even unpack it on +systems that don't support symbolic links. Also, don't use multiple +names for one file in different directories, because certain file +systems cannot handle this and that prevents unpacking the distribution. + + Try to make sure that all the file names will be unique on MS-DOG. A +name on MS-DOG consists of up to 8 characters, optionally followed by a +period and up to three characters. MS-DOG will truncate extra +characters both before and after the period. Thus, `foobarhacker.c' +and `foobarhacker.o' are not ambiguous; they are truncated to +`foobarha.c' and `foobarha.o', which are distinct. + + Include in your distribution a copy of the `texinfo.tex' you used to +test print any `*.texinfo' files. + + Likewise, if your program uses small GNU software packages like +regex, getopt, obstack, or termcap, include them in the distribution +file. Leaving them out would make the distribution file a little +smaller at the expense of possible inconvenience to a user who doesn't +know what other files to get. + + diff --git a/gnu/usr.bin/binutils/etc/standards.texi b/gnu/usr.bin/binutils/etc/standards.texi new file mode 100644 index 00000000000..13908d65fe4 --- /dev/null +++ b/gnu/usr.bin/binutils/etc/standards.texi @@ -0,0 +1,2295 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename standards.info +@settitle GNU Coding Standards +@c UPDATE THIS DATE WHENEVER YOU MAKE CHANGES! +@set lastupdate 28 March 1994 +@c %**end of header + +@ifinfo +@format +START-INFO-DIR-ENTRY +* Standards: (standards). GNU coding standards. +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@setchapternewpage off + +@ifinfo +GNU Coding Standards +Copyright (C) 1992, 1993, 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 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 Free Software Foundation. +@end ifinfo + +@titlepage +@title GNU Coding Standards +@author Richard Stallman +@author last updated @value{lastupdate} +@page + +@vskip 0pt plus 1filll +Copyright @copyright{} 1992, 1993 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. + +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 Free Software Foundation. +@end titlepage + +@ifinfo +@node Top, Reading Non-Free Code, (dir), (dir) +@top Version + +Last updated @value{lastupdate}. +@end ifinfo + +@menu +* Reading Non-Free Code:: Referring to Proprietary Programs +* Contributions:: Accepting Contributions +* Change Logs:: Recording Changes +* Compatibility:: Compatibility with Other Implementations +* Makefile Conventions:: Makefile Conventions +* Configuration:: How Configuration Should Work +* Source Language:: Using Languages Other Than C +* Formatting:: Formatting Your Source Code +* Comments:: Commenting Your Work +* Syntactic Conventions:: Clean Use of C Constructs +* Names:: Naming Variables and Functions +* Using Extensions:: Using Non-standard Features +* System Functions:: Portability and ``standard'' library functions +* Semantics:: Program Behavior for All Programs +* Errors:: Formatting Error Messages +* Libraries:: Library Behavior +* Portability:: Portability As It Applies to GNU +* User Interfaces:: Standards for Command Line Interfaces +* Documentation:: Documenting Programs +* Releases:: Making Releases +@end menu + +@node Reading Non-Free Code +@chapter Referring to Proprietary Programs + +Don't in any circumstances refer to Unix source code for or during +your work on GNU! (Or to any other proprietary programs.) + +If you have a vague recollection of the internals of a Unix program, +this does not absolutely mean you can't write an imitation of it, but +do try to organize the imitation internally along different lines, +because this is likely to make the details of the Unix version +irrelevant and dissimilar to your results. + +For example, Unix utilities were generally optimized to minimize +memory use; if you go for speed instead, your program will be very +different. You could keep the entire input file in core and scan it +there instead of using stdio. Use a smarter algorithm discovered more +recently than the Unix program. Eliminate use of temporary files. Do +it in one pass instead of two (we did this in the assembler). + +Or, on the contrary, emphasize simplicity instead of speed. For some +applications, the speed of today's computers makes simpler algorithms +adequate. + +Or go for generality. For example, Unix programs often have static +tables or fixed-size strings, which make for arbitrary limits; use +dynamic allocation instead. Make sure your program handles NULs and +other funny characters in the input files. Add a programming language +for extensibility and write part of the program in that language. + +Or turn some parts of the program into independently usable libraries. +Or use a simple garbage collector instead of tracking precisely when +to free memory, or use a new GNU facility such as obstacks. + + +@node Contributions +@chapter Accepting Contributions + +If someone else sends you a piece of code to add to the program you are +working on, we need legal papers to use it---the same sort of legal +papers we will need to get from you. @emph{Each} significant +contributor to a program must sign some sort of legal papers in order +for us to have clear title to the program. The main author alone is not +enough. + +So, before adding in any contributions from other people, tell us +so we can arrange to get the papers. Then wait until we tell you +that we have received the signed papers, before you actually use the +contribution. + +This applies both before you release the program and afterward. If +you receive diffs to fix a bug, and they make significant change, we +need legal papers for it. + +You don't need papers for changes of a few lines here or there, since +they are not significant for copyright purposes. Also, you don't need +papers if all you get from the suggestion is some ideas, not actual code +which you use. For example, if you write a different solution to the +problem, you don't need to get papers. + +I know this is frustrating; it's frustrating for us as well. But if +you don't wait, you are going out on a limb---for example, what if the +contributor's employer won't sign a disclaimer? You might have to take +that code out again! + +The very worst thing is if you forget to tell us about the other +contributor. We could be very embarrassed in court some day as a +result. + +@node Change Logs +@chapter Change Logs + +Keep a change log for each directory, describing the changes made to +source files in that directory. The purpose of this is so that people +investigating bugs in the future will know about the changes that +might have introduced the bug. Often a new bug can be found by +looking at what was recently changed. More importantly, change logs +can help eliminate conceptual inconsistencies between different parts +of a program; they can give you a history of how the conflicting +concepts arose. + +Use the Emacs command @kbd{M-x add-change} to start a new entry in the +change log. An entry should have an asterisk, the name of the changed +file, and then in parentheses the name of the changed functions, +variables or whatever, followed by a colon. Then describe the changes +you made to that function or variable. + +Separate unrelated entries with blank lines. When two entries +represent parts of the same change, so that they work together, then +don't put blank lines between them. Then you can omit the file name +and the asterisk when successive entries are in the same file. + +Here are some examples: + +@example +* register.el (insert-register): Return nil. +(jump-to-register): Likewise. + +* sort.el (sort-subr): Return nil. + +* tex-mode.el (tex-bibtex-file, tex-file, tex-region): +Restart the tex shell if process is gone or stopped. +(tex-shell-running): New function. + +* expr.c (store_one_arg): Round size up for move_block_to_reg. +(expand_call): Round up when emitting USE insns. +* stmt.c (assign_parms): Round size up for move_block_from_reg. +@end example + +It's important to name the changed function or variable in full. Don't +abbreviate them; don't combine them. Subsequent maintainers will often +search for a function name to find all the change log entries that +pertain to it; if you abbreviate the name, they won't find it when they +search. For example, some people are tempted to abbreviate groups of +function names by writing @samp{* register.el +(@{insert,jump-to@}-register)}; this is not a good idea, since searching +for @code{jump-to-register} or @code{insert-register} would not find the +entry. + +There's no need to describe the full purpose of the changes or how they +work together. It is better to put such explanations in comments in the +code. That's why just ``New function'' is enough; there is a comment +with the function in the source to explain what it does. + +However, sometimes it is useful to write one line to describe the +overall purpose of a large batch of changes. + +You can think of the change log as a conceptual ``undo list'' which +explains how earlier versions were different from the current version. +People can see the current version; they don't need the change log +to tell them what is in it. What they want from a change log is a +clear explanation of how the earlier version differed. + +When you change the calling sequence of a function in a simple +fashion, and you change all the callers of the function, there is no +need to make individual entries for all the callers. Just write in +the entry for the function being called, ``All callers changed.'' + +When you change just comments or doc strings, it is enough to write an +entry for the file, without mentioning the functions. Write just, +``Doc fix.'' There's no need to keep a change log for documentation +files. This is because documentation is not susceptible to bugs that +are hard to fix. Documentation does not consist of parts that must +interact in a precisely engineered fashion; to correct an error, you +need not know the history of the erroneous passage. + + +@node Compatibility +@chapter Compatibility with Other Implementations + +With certain exceptions, utility programs and libraries for GNU should +be upward compatible with those in Berkeley Unix, and upward compatible +with @sc{ANSI} C if @sc{ANSI} C specifies their behavior, and upward +compatible with @sc{POSIX} if @sc{POSIX} specifies their behavior. + +When these standards conflict, it is useful to offer compatibility +modes for each of them. + +@sc{ANSI} C and @sc{POSIX} prohibit many kinds of extensions. Feel +free to make the extensions anyway, and include a @samp{--ansi} or +@samp{--compatible} option to turn them off. However, if the extension +has a significant chance of breaking any real programs or scripts, +then it is not really upward compatible. Try to redesign its +interface. + +Many GNU programs suppress extensions that conflict with POSIX if the +environment variable @code{POSIXLY_CORRECT} is defined (even if it is +defined with a null value). Please make your program recognize this +variable if appropriate. + +When a feature is used only by users (not by programs or command +files), and it is done poorly in Unix, feel free to replace it +completely with something totally different and better. (For example, +vi is replaced with Emacs.) But it is nice to offer a compatible +feature as well. (There is a free vi clone, so we offer it.) + +Additional useful features not in Berkeley Unix are welcome. +Additional programs with no counterpart in Unix may be useful, +but our first priority is usually to duplicate what Unix already +has. + +@comment The makefile standards are in a separate file that is also +@comment included by make.texinfo. Done by roland@gnu.ai.mit.edu on 1/6/93. +@include make-stds.texi + +@node Configuration +@chapter How Configuration Should Work + +Each GNU distribution should come with a shell script named +@code{configure}. This script is given arguments which describe the +kind of machine and system you want to compile the program for. + +The @code{configure} script must record the configuration options so +that they affect compilation. + +One way to do this is to make a link from a standard name such as +@file{config.h} to the proper configuration file for the chosen system. +If you use this technique, the distribution should @emph{not} contain a +file named @file{config.h}. This is so that people won't be able to +build the program without configuring it first. + +Another thing that @code{configure} can do is to edit the Makefile. If +you do this, the distribution should @emph{not} contain a file named +@file{Makefile}. Instead, include a file @file{Makefile.in} which +contains the input used for editing. Once again, this is so that people +won't be able to build the program without configuring it first. + +If @code{configure} does write the @file{Makefile}, then @file{Makefile} +should have a target named @file{Makefile} which causes @code{configure} +to be rerun, setting up the same configuration that was set up last +time. The files that @code{configure} reads should be listed as +dependencies of @file{Makefile}. + +All the files which are output from the @code{configure} script should +have comments at the beginning explaining that they were generated +automatically using @code{configure}. This is so that users won't think +of trying to edit them by hand. + +The @code{configure} script should write a file named @file{config.status} +which describes which configuration options were specified when the +program was last configured. This file should be a shell script which, +if run, will recreate the same configuration. + +The @code{configure} script should accept an option of the form +@samp{--srcdir=@var{dirname}} to specify the directory where sources are found +(if it is not the current directory). This makes it possible to build +the program in a separate directory, so that the actual source directory +is not modified. + +If the user does not specify @samp{--srcdir}, then @code{configure} should +check both @file{.} and @file{..} to see if it can find the sources. If +it finds the sources in one of these places, it should use them from +there. Otherwise, it should report that it cannot find the sources, and +should exit with nonzero status. + +Usually the easy way to support @samp{--srcdir} is by editing a +definition of @code{VPATH} into the Makefile. Some rules may need to +refer explicitly to the specified source directory. To make this +possible, @code{configure} can add to the Makefile a variable named +@code{srcdir} whose value is precisely the specified directory. + +The @code{configure} script should also take an argument which specifies the +type of system to build the program for. This argument should look like +this: + +@example +@var{cpu}-@var{company}-@var{system} +@end example + +For example, a Sun 3 might be @samp{m68k-sun-sunos4.1}. + +The @code{configure} script needs to be able to decode all plausible +alternatives for how to describe a machine. Thus, @samp{sun3-sunos4.1} +would be a valid alias. So would @samp{sun3-bsd4.2}, since SunOS is +basically @sc{BSD} and no other @sc{BSD} system is used on a Sun. For many +programs, @samp{vax-dec-ultrix} would be an alias for +@samp{vax-dec-bsd}, simply because the differences between Ultrix and +@sc{BSD} are rarely noticeable, but a few programs might need to distinguish +them. + +There is a shell script called @file{config.sub} that you can use +as a subroutine to validate system types and canonicalize aliases. + +Other options are permitted to specify in more detail the software +or hardware present on the machine, and include or exclude optional +parts of the package: + +@table @samp +@item --enable-@var{feature}@r{[}=@var{parameter}@r{]} +Configure the package to build and install an optional user-level +facility called @var{feature}. This allows users to choose which +optional features to include. Giving an optional @var{parameter} of +@samp{no} should omit @var{feature}, if it is built by default. + +No @samp{--enable} option should @strong{ever} cause one feature to +replace another. No @samp{--enable} option should ever substitute one +useful behavior for another useful behavior. The only proper use for +@samp{--enable} is for questions of whether to build part of the program +or exclude it. + +@item --with-@var{package} +@c @r{[}=@var{parameter}@r{]} +The package @var{package} will be installed, so configure this package +to work with @var{package}. + +@c Giving an optional @var{parameter} of +@c @samp{no} should omit @var{package}, if it is used by default. + +Possible values of @var{package} include @samp{x}, @samp{x-toolkit}, +@samp{gnu-as} (or @samp{gas}), @samp{gnu-ld}, @samp{gnu-libc}, and +@samp{gdb}. + +Do not use a @samp{--with} option to specify the file name to use to +find certain files. That is outside the scope of what @samp{--with} +options are for. + +@item --nfp +The target machine has no floating point processor. + +@item --gas +The target machine assembler is GAS, the GNU assembler. +This is obsolete; users should use @samp{--with-gnu-as} instead. + +@item --x +The target machine has the X Window System installed. +This is obsolete; users should use @samp{--with-x} instead. +@end table + +All @code{configure} scripts should accept all of these ``detail'' +options, whether or not they make any difference to the particular +package at hand. In particular, they should accept any option that +starts with @samp{--with-} or @samp{--enable-}. This is so users will +be able to configure an entire GNU source tree at once with a single set +of options. + +You will note that the categories @samp{--with-} and @samp{--enable-} +are narrow: they @strong{do not} provide a place for any sort of option +you might think of. That is deliberate. We want to limit the possible +configuration options in GNU software. We do not want GNU programs to +have idiosyncratic configuration options. + +Packages that perform part of compilation may support cross-compilation. +In such a case, the host and target machines for the program may be +different. The @code{configure} script should normally treat the +specified type of system as both the host and the target, thus producing +a program which works for the same type of machine that it runs on. + +The way to build a cross-compiler, cross-assembler, or what have you, is +to specify the option @samp{--host=@var{hosttype}} when running +@code{configure}. This specifies the host system without changing the +type of target system. The syntax for @var{hosttype} is the same as +described above. + +Bootstrapping a cross-compiler requires compiling it on a machine other +than the host it will run on. Compilation packages accept a +configuration option @samp{--build=@var{hosttype}} for specifying the +configuration on which you will compile them, in case that is different +from the host. + +Programs for which cross-operation is not meaningful need not accept the +@samp{--host} option, because configuring an entire operating system for +cross-operation is not a meaningful thing. + +Some programs have ways of configuring themselves automatically. If +your program is set up to do this, your @code{configure} script can simply +ignore most of its arguments. + + +@node Source Language +@chapter Using Languages Other Than C + +Using a language other than C is like using a non-standard feature: it +will cause trouble for users. Even if GCC supports the other language, +users may find it inconvenient to have to install the compiler for that +other language in order to build your program. So please write in C. + +There are three exceptions for this rule: + +@itemize @bullet +@item +It is okay to use a special language if the same program contains an +interpreter for that language. + +Thus, it is not a problem that GNU Emacs contains code written in Emacs +Lisp, because it comes with a Lisp interpreter. + +@item +It is okay to use another language in a tool specifically intended for +use with that language. + +This is okay because the only people who want to build the tool will be +those who have installed the other language anyway. + +@item +If an application is not of extremely widespread interest, then perhaps +it's not important if the application is inconvenient to install. +@end itemize + +@node Formatting +@chapter Formatting Your Source Code + +It is important to put the open-brace that starts the body of a C +function in column zero, and avoid putting any other open-brace or +open-parenthesis or open-bracket in column zero. Several tools look +for open-braces in column zero to find the beginnings of C functions. +These tools will not work on code not formatted that way. + +It is also important for function definitions to start the name of the +function in column zero. This helps people to search for function +definitions, and may also help certain tools recognize them. Thus, +the proper format is this: + +@example +static char * +concat (s1, s2) /* Name starts in column zero here */ + char *s1, *s2; +@{ /* Open brace in column zero here */ + @dots{} +@} +@end example + +@noindent +or, if you want to use @sc{ANSI} C, format the definition like this: + +@example +static char * +concat (char *s1, char *s2) +@{ + @dots{} +@} +@end example + +In @sc{ANSI} C, if the arguments don't fit nicely on one line, +split it like this: + +@example +int +lots_of_args (int an_integer, long a_long, short a_short, + double a_double, float a_float) +@dots{} +@end example + +For the body of the function, we prefer code formatted like this: + +@example +if (x < foo (y, z)) + haha = bar[4] + 5; +else + @{ + while (z) + @{ + haha += foo (z, z); + z--; + @} + return ++x + bar (); + @} +@end example + +We find it easier to read a program when it has spaces before the +open-parentheses and after the commas. Especially after the commas. + +When you split an expression into multiple lines, split it +before an operator, not after one. Here is the right way: + +@example +if (foo_this_is_long && bar > win (x, y, z) + && remaining_condition) +@end example + +Try to avoid having two operators of different precedence at the same +level of indentation. For example, don't write this: + +@example +mode = (inmode[j] == VOIDmode + || GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j]) + ? outmode[j] : inmode[j]); +@end example + +Instead, use extra parentheses so that the indentation shows the nesting: + +@example +mode = ((inmode[j] == VOIDmode + || (GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j]))) + ? outmode[j] : inmode[j]); +@end example + +Insert extra parentheses so that Emacs will indent the code properly. +For example, the following indentation looks nice if you do it by hand, +but Emacs would mess it up: + +@example +v = rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000 + + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000; +@end example + +But adding a set of parentheses solves the problem: + +@example +v = (rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000 + + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000); +@end example + +Format do-while statements like this: + +@example +do + @{ + a = foo (a); + @} +while (a > 0); +@end example + +Please use formfeed characters (control-L) to divide the program into +pages at logical places (but not within a function). It does not matter +just how long the pages are, since they do not have to fit on a printed +page. The formfeeds should appear alone on lines by themselves. + + +@node Comments +@chapter Commenting Your Work + +Every program should start with a comment saying briefly what it is for. +Example: @samp{fmt - filter for simple filling of text}. + +Please put a comment on each function saying what the function does, +what sorts of arguments it gets, and what the possible values of +arguments mean and are used for. It is not necessary to duplicate in +words the meaning of the C argument declarations, if a C type is being +used in its customary fashion. If there is anything nonstandard about +its use (such as an argument of type @code{char *} which is really the +address of the second character of a string, not the first), or any +possible values that would not work the way one would expect (such as, +that strings containing newlines are not guaranteed to work), be sure +to say so. + +Also explain the significance of the return value, if there is one. + +Please put two spaces after the end of a sentence in your comments, so +that the Emacs sentence commands will work. Also, please write +complete sentences and capitalize the first word. If a lower-case +identifer comes at the beginning of a sentence, don't capitalize it! +Changing the spelling makes it a different identifier. If you don't +like starting a sentence with a lower case letter, write the sentence +differently (e.g., ``The identifier lower-case is @dots{}''). + +The comment on a function is much clearer if you use the argument +names to speak about the argument values. The variable name itself +should be lower case, but write it in upper case when you are speaking +about the value rather than the variable itself. Thus, ``the inode +number NODE_NUM'' rather than ``an inode''. + +There is usually no purpose in restating the name of the function in +the comment before it, because the reader can see that for himself. +There might be an exception when the comment is so long that the function +itself would be off the bottom of the screen. + +There should be a comment on each static variable as well, like this: + +@example +/* Nonzero means truncate lines in the display; + zero means continue them. */ +int truncate_lines; +@end example + +Every @samp{#endif} should have a comment, except in the case of short +conditionals (just a few lines) that are not nested. The comment should +state the condition of the conditional that is ending, @emph{including +its sense}. @samp{#else} should have a comment describing the condition +@emph{and sense} of the code that follows. For example: + +@example +#ifdef foo + @dots{} +#else /* not foo */ + @dots{} +#endif /* not foo */ +@end example + +@noindent +but, by contrast, write the comments this way for a @samp{#ifndef}: + +@example +#ifndef foo + @dots{} +#else /* foo */ + @dots{} +#endif /* foo */ +@end example + + +@node Syntactic Conventions +@chapter Clean Use of C Constructs + +Please explicitly declare all arguments to functions. +Don't omit them just because they are @code{int}s. + +Declarations of external functions and functions to appear later in the +source file should all go in one place near the beginning of the file +(somewhere before the first function definition in the file), or else +should go in a header file. Don't put @code{extern} declarations inside +functions. + +It used to be common practice to use the same local variables (with +names like @code{tem}) over and over for different values within one +function. Instead of doing this, it is better declare a separate local +variable for each distinct purpose, and give it a name which is +meaningful. This not only makes programs easier to understand, it also +facilitates optimization by good compilers. You can also move the +declaration of each local variable into the smallest scope that includes +all its uses. This makes the program even cleaner. + +Don't use local variables or parameters that shadow global identifiers. + +Don't declare multiple variables in one declaration that spans lines. +Start a new declaration on each line, instead. For example, instead +of this: + +@example +int foo, + bar; +@end example + +@noindent +write either this: + +@example +int foo, bar; +@end example + +@noindent +or this: + +@example +int foo; +int bar; +@end example + +@noindent +(If they are global variables, each should have a comment preceding it +anyway.) + +When you have an @code{if}-@code{else} statement nested in another +@code{if} statement, always put braces around the @code{if}-@code{else}. +Thus, never write like this: + +@example +if (foo) + if (bar) + win (); + else + lose (); +@end example + +@noindent +always like this: + +@example +if (foo) + @{ + if (bar) + win (); + else + lose (); + @} +@end example + +If you have an @code{if} statement nested inside of an @code{else} +statement, either write @code{else if} on one line, like this, + +@example +if (foo) + @dots{} +else if (bar) + @dots{} +@end example + +@noindent +with its @code{then}-part indented like the preceding @code{then}-part, +or write the nested @code{if} within braces like this: + +@example +if (foo) + @dots{} +else + @{ + if (bar) + @dots{} + @} +@end example + +Don't declare both a structure tag and variables or typedefs in the +same declaration. Instead, declare the structure tag separately +and then use it to declare the variables or typedefs. + +Try to avoid assignments inside @code{if}-conditions. For example, +don't write this: + +@example +if ((foo = (char *) malloc (sizeof *foo)) == 0) + fatal ("virtual memory exhausted"); +@end example + +@noindent +instead, write this: + +@example +foo = (char *) malloc (sizeof *foo); +if (foo == 0) + fatal ("virtual memory exhausted"); +@end example + +Don't make the program ugly to placate @code{lint}. Please don't insert any +casts to @code{void}. Zero without a cast is perfectly fine as a null +pointer constant. + +@node Names +@chapter Naming Variables and Functions + +Please use underscores to separate words in a name, so that the Emacs +word commands can be useful within them. Stick to lower case; reserve +upper case for macros and @code{enum} constants, and for name-prefixes +that follow a uniform convention. + +For example, you should use names like @code{ignore_space_change_flag}; +don't use names like @code{iCantReadThis}. + +Variables that indicate whether command-line options have been +specified should be named after the meaning of the option, not after +the option-letter. A comment should state both the exact meaning of +the option and its letter. For example, + +@example +/* Ignore changes in horizontal whitespace (-b). */ +int ignore_space_change_flag; +@end example + +When you want to define names with constant integer values, use +@code{enum} rather than @samp{#define}. GDB knows about enumeration +constants. + +Use file names of 14 characters or less, to avoid creating gratuitous +problems on System V. You can use the program @code{doschk} to test for +this. @code{doschk} also tests for potential name conflicts if the +files were loaded onto an MS-DOS file system---something you may or may +not care about. + + +@node Using Extensions +@chapter Using Non-standard Features + +Many GNU facilities that already exist support a number of convenient +extensions over the comparable Unix facilities. Whether to use these +extensions in implementing your program is a difficult question. + +On the one hand, using the extensions can make a cleaner program. +On the other hand, people will not be able to build the program +unless the other GNU tools are available. This might cause the +program to work on fewer kinds of machines. + +With some extensions, it might be easy to provide both alternatives. +For example, you can define functions with a ``keyword'' @code{INLINE} +and define that as a macro to expand into either @code{inline} or +nothing, depending on the compiler. + +In general, perhaps it is best not to use the extensions if you can +straightforwardly do without them, but to use the extensions if they +are a big improvement. + +An exception to this rule are the large, established programs (such as +Emacs) which run on a great variety of systems. Such programs would +be broken by use of GNU extensions. + +Another exception is for programs that are used as part of +compilation: anything that must be compiled with other compilers in +order to bootstrap the GNU compilation facilities. If these require +the GNU compiler, then no one can compile them without having them +installed already. That would be no good. + +Since most computer systems do not yet implement @sc{ANSI} C, using the +@sc{ANSI} C features is effectively using a GNU extension, so the +same considerations apply. (Except for @sc{ANSI} features that we +discourage, such as trigraphs---don't ever use them.) + + +@node System Functions +@chapter Calling System Functions + +C implementations differ substantially. ANSI C reduces but does not +eliminate the incompatibilities; meanwhile, many users wish to compile +GNU software with pre-ANSI compilers. This chapter gives +recommendations for how to use the more or less standard C library +functions to avoid unnecessary loss of portability. + +@itemize @bullet +@item +Don't use the value of @code{sprintf}. It returns the number of +characters written on some systems, but not on all systems. + +@item +Don't declare system functions explicitly. + +Almost any declaration for a system function is wrong on some system. +To minimize conflicts, leave it to the system header files to declare +system functions. If the headers don't declare a function, let it +remain undeclared. + +While it may seem unclean to use a function without declaring it, in +practice this works fine for most system library functions on the +systems where this really happens. The problem is only theoretical. By +contrast, actual declarations have frequently caused actual conflicts. + +@item +If you must declare a system function, don't specify the argument types. +Use an old-style declaration, not an ANSI prototype. The more you +specify about the function, the more likely a conflict. + +@item +In particular, don't unconditionally declare @code{malloc} or +@code{realloc}. + +Most GNU programs use those functions just once, in functions +conventionally named @code{xmalloc} and @code{xrealloc}. These +functions call @code{malloc} and @code{realloc}, respectively, and +check the results. + +Because @code{xmalloc} and @code{xrealloc} are defined in your program, +you can declare them in other files without any risk of type conflict. + +On most systems, @code{int} is the same length as a pointer; thus, the +calls to @code{malloc} and @code{realloc} work fine. For the few +exceptional systems (mostly 64-bit machines), you can use +@strong{conditionalized} declarations of @code{malloc} and +@code{realloc}---or put these declarations in configuration files +specific to those systems. + +@item +The string functions require special treatment. Some Unix systems have +a header file @file{string.h}; other have @file{strings.h}. Neither +file name is portable. There are two things you can do: use Autoconf to +figure out which file to include, or don't include either file. + +@item +If you don't include either strings file, you can't get declarations for +the string functions from the header file in the usual way. + +That causes less of a problem than you might think. The newer ANSI +string functions are off-limits anyway because many systems still don't +support them. The string functions you can use are these: + +@example +strcpy strncpy strcat strncat +strlen strcmp strncmp +strchr strrchr +@end example + +The copy and concatenate functions work fine without a declaration as +long as you don't use their values. Using their values without a +declaration fails on systems where the width of a pointer differs from +the width of @code{int}, and perhaps in other cases. It is trivial to +avoid using their values, so do that. + +The compare functions and @code{strlen} work fine without a declaration +on most systems, possibly all the ones that GNU software runs on. +You may find it necessary to declare them @strong{conditionally} on a +few systems. + +The search functions must be declared to return @code{char *}. Luckily, +there is no variation in the data type they return. But there is +variation in their names. Some systems give these functions the names +@code{index} and @code{rindex}; other systems use the names +@code{strchr} and @code{strrchr}. Some systems support both pairs of +names, but neither pair works on all systems. + +You should pick a single pair of names and use it throughout your +program. (Nowadays, it is better to choose @code{strchr} and +@code{strrchr}.) Declare both of those names as functions returning +@code{char *}. On systems which don't support those names, define them +as macros in terms of the other pair. For example, here is what to put +at the beginning of your file (or in a header) if you want to use the +names @code{strchr} and @code{strrchr} throughout: + +@example +#ifndef HAVE_STRCHR +#define strchr index +#endif +#ifndef HAVE_STRRCHR +#define strrchr rindex +#endif + +char *strchr (); +char *strrchr (); +@end example +@end itemize + +Here we assume that @code{HAVE_STRCHR} and @code{HAVE_STRRCHR} are +macros defined in systems where the corresponding functions exist. +One way to get them properly defined is to use Autoconf. + +@node Semantics +@chapter Program Behavior for All Programs + +Avoid arbitrary limits on the length or number of @emph{any} data +structure, including filenames, lines, files, and symbols, by allocating +all data structures dynamically. In most Unix utilities, ``long lines +are silently truncated''. This is not acceptable in a GNU utility. + +Utilities reading files should not drop NUL characters, or any other +nonprinting characters @emph{including those with codes above 0177}. The +only sensible exceptions would be utilities specifically intended for +interface to certain types of printers that can't handle those characters. + +Check every system call for an error return, unless you know you wish to +ignore errors. Include the system error text (from @code{perror} or +equivalent) in @emph{every} error message resulting from a failing +system call, as well as the name of the file if any and the name of the +utility. Just ``cannot open foo.c'' or ``stat failed'' is not +sufficient. + +Check every call to @code{malloc} or @code{realloc} to see if it +returned zero. Check @code{realloc} even if you are making the block +smaller; in a system that rounds block sizes to a power of 2, +@code{realloc} may get a different block if you ask for less space. + +In Unix, @code{realloc} can destroy the storage block if it returns +zero. GNU @code{realloc} does not have this bug: if it fails, the +original block is unchanged. Feel free to assume the bug is fixed. If +you wish to run your program on Unix, and wish to avoid lossage in this +case, you can use the GNU @code{malloc}. + +You must expect @code{free} to alter the contents of the block that was +freed. Anything you want to fetch from the block, you must fetch before +calling @code{free}. + +Use @code{getopt_long} to decode arguments, unless the argument syntax +makes this unreasonable. + +When static storage is to be written in during program execution, use +explicit C code to initialize it. Reserve C initialized declarations +for data that will not be changed. + +Try to avoid low-level interfaces to obscure Unix data structures (such +as file directories, utmp, or the layout of kernel memory), since these +are less likely to work compatibly. If you need to find all the files +in a directory, use @code{readdir} or some other high-level interface. +These will be supported compatibly by GNU. + +By default, the GNU system will provide the signal handling functions of +@sc{BSD} and of @sc{POSIX}. So GNU software should be written to use +these. + +In error checks that detect ``impossible'' conditions, just abort. +There is usually no point in printing any message. These checks +indicate the existence of bugs. Whoever wants to fix the bugs will have +to read the source code and run a debugger. So explain the problem with +comments in the source. The relevant data will be in variables, which +are easy to examine with the debugger, so there is no point moving them +elsewhere. + + +@node Errors +@chapter Formatting Error Messages + +Error messages from compilers should look like this: + +@example +@var{source-file-name}:@var{lineno}: @var{message} +@end example + +Error messages from other noninteractive programs should look like this: + +@example +@var{program}:@var{source-file-name}:@var{lineno}: @var{message} +@end example + +@noindent +when there is an appropriate source file, or like this: + +@example +@var{program}: @var{message} +@end example + +@noindent +when there is no relevant source file. + +In an interactive program (one that is reading commands from a +terminal), it is better not to include the program name in an error +message. The place to indicate which program is running is in the +prompt or with the screen layout. (When the same program runs with +input from a source other than a terminal, it is not interactive and +would do best to print error messages using the noninteractive style.) + +The string @var{message} should not begin with a capital letter when +it follows a program name and/or filename. Also, it should not end +with a period. + +Error messages from interactive programs, and other messages such as +usage messages, should start with a capital letter. But they should not +end with a period. + + +@node Libraries +@chapter Library Behavior + +Try to make library functions reentrant. If they need to do dynamic +storage allocation, at least try to avoid any nonreentrancy aside from +that of @code{malloc} itself. + +Here are certain name conventions for libraries, to avoid name +conflicts. + +Choose a name prefix for the library, more than two characters long. +All external function and variable names should start with this +prefix. In addition, there should only be one of these in any given +library member. This usually means putting each one in a separate +source file. + +An exception can be made when two external symbols are always used +together, so that no reasonable program could use one without the +other; then they can both go in the same file. + +External symbols that are not documented entry points for the user +should have names beginning with @samp{_}. They should also contain +the chosen name prefix for the library, to prevent collisions with +other libraries. These can go in the same files with user entry +points if you like. + +Static functions and variables can be used as you like and need not +fit any naming convention. + + +@node Portability +@chapter Portability As It Applies to GNU + +Much of what is called ``portability'' in the Unix world refers to +porting to different Unix versions. This is a secondary consideration +for GNU software, because its primary purpose is to run on top of one +and only one kernel, the GNU kernel, compiled with one and only one C +compiler, the GNU C compiler. The amount and kinds of variation among +GNU systems on different cpu's will be like the variation among Berkeley +4.3 systems on different cpu's. + +All users today run GNU software on non-GNU systems. So supporting a +variety of non-GNU systems is desirable; simply not paramount. +The easiest way to achieve portability to a reasonable range of systems +is to use Autoconf. It's unlikely that your program needs to know more +information about the host machine than Autoconf can provide, simply +because most of the programs that need such knowledge have already been +written. + +It is difficult to be sure exactly what facilities the GNU kernel +will provide, since it isn't finished yet. Therefore, assume you can +use anything in 4.3; just avoid using the format of semi-internal data +bases (e.g., directories) when there is a higher-level alternative +(@code{readdir}). + +You can freely assume any reasonably standard facilities in the C +language, libraries or kernel, because we will find it necessary to +support these facilities in the full GNU system, whether or not we +have already done so. The fact that there may exist kernels or C +compilers that lack these facilities is irrelevant as long as the GNU +kernel and C compiler support them. + +It remains necessary to worry about differences among cpu types, such +as the difference in byte ordering and alignment restrictions. It's +unlikely that 16-bit machines will ever be supported by GNU, so there +is no point in spending any time to consider the possibility that an +int will be less than 32 bits. + +You can assume that all pointers have the same format, regardless +of the type they point to, and that this is really an integer. +There are some weird machines where this isn't true, but they aren't +important; don't waste time catering to them. Besides, eventually +we will put function prototypes into all GNU programs, and that will +probably make your program work even on weird machines. + +Since some important machines (including the 68000) are big-endian, +it is important not to assume that the address of an @code{int} object +is also the address of its least-significant byte. Thus, don't +make the following mistake: + +@example +int c; +@dots{} +while ((c = getchar()) != EOF) + write(file_descriptor, &c, 1); +@end example + +You can assume that it is reasonable to use a meg of memory. Don't +strain to reduce memory usage unless it can get to that level. If +your program creates complicated data structures, just make them in +core and give a fatal error if malloc returns zero. + +If a program works by lines and could be applied to arbitrary +user-supplied input files, it should keep only a line in memory, because +this is not very hard and users will want to be able to operate on input +files that are bigger than will fit in core all at once. + + +@node User Interfaces +@chapter Standards for Command Line Interfaces + +Please don't make the behavior of a utility depend on the name used +to invoke it. It is useful sometimes to make a link to a utility +with a different name, and that should not change what it does. + +Instead, use a run time option or a compilation switch or both +to select among the alternate behaviors. + +Likewise, please don't make the behavior of the program depend on the +type of output device it is used with. Device independence is an +important principle of the system's design; do not compromise it +merely to save someone from typing an option now and then. + +If you think one behavior is most useful when the output is to a +terminal, and another is most useful when the output is a file or a +pipe, then it is usually best to make the default behavior the one that +is useful with output to a terminal, and have an option for the other +behavior. + +Compatibility requires certain programs to depend on the type of output +device. It would be disastrous if @code{ls} or @code{sh} did not do so +in the way all users expect. In some of these cases, we supplement the +program with a preferred alternate version that does not depend on the +output device type. For example, we provide a @code{dir} program much +like @code{ls} except that its default output format is always +multi-column format. + +It is a good idea to follow the @sc{POSIX} guidelines for the +command-line options of a program. The easiest way to do this is to use +@code{getopt} to parse them. Note that the GNU version of @code{getopt} +will normally permit options anywhere among the arguments unless the +special argument @samp{--} is used. This is not what @sc{POSIX} +specifies; it is a GNU extension. + +Please define long-named options that are equivalent to the +single-letter Unix-style options. We hope to make GNU more user +friendly this way. This is easy to do with the GNU function +@code{getopt_long}. + +One of the advantages of long-named options is that they can be +consistent from program to program. For example, users should be able +to expect the ``verbose'' option of any GNU program which has one, to be +spelled precisely @samp{--verbose}. To achieve this uniformity, look at +the table of common long-option names when you choose the option names +for your program. The table appears below. + +If you use names not already in the table, please send +@samp{gnu@@prep.ai.mit.edu} a list of them, with their meanings, so we +can update the table. + +It is usually a good idea for file names given as ordinary arguments +to be input files only; any output files would be specified using +options (preferably @samp{-o}). Even if you allow an output file name +as an ordinary argument for compatibility, try to provide a suitable +option as well. This will lead to more consistency among GNU +utilities, so that there are fewer idiosyncracies for users to +remember. + +Programs should support an option @samp{--version} which prints the +program's version number on standard output and exits successfully, and +an option @samp{--help} which prints option usage information on +standard output and exits successfully. These options should inhibit +the normal function of the command; they should do nothing except print +the requested information. + +@c Please leave newlines between items in this table; it's much easier +@c to update when it isn't completely squashed together and unreadable. +@c When there is more than one short option for a long option name, put +@c a semicolon between the lists of the programs that use them, not a +@c period. --friedman + +@table @samp + +@item auto-check +@samp{-a} in @code{recode}. + +@item auto-reference +@samp{-A} in @code{ptx}. + +@item after-date +@samp{-N} in @code{tar}. + +@item all +@samp{-a} in @code{du}, @code{ls}, @code{nm}, @code{stty}, @code{uname}, +and @code{unexpand}. + +@item all-text +@samp{-a} in @code{diff}. + +@item almost-all +@samp{-A} in @code{ls}. + +@item append +@samp{-a} in @code{etags}, @code{tee}, @code{time}; +@samp{-r} in @code{tar}. + +@item archive +@samp{-a} in @code{cp}. + +@item arglength +@samp{-l} in @code{m4}. + +@item ascii +@samp{-a} in @code{diff}. + +@item assume-new +@samp{-W} in Make. + +@item assume-old +@samp{-o} in Make. + +@item backward-search +@samp{-B} in etags. + +@item batch +Used in GDB. + +@item baud +Used in GDB. + +@item before +@samp{-b} in @code{tac}. + +@item binary +@samp{-b} in @code{cpio} and @code{diff}. + +@item block-size +Used in @code{cpio} and @code{tar}. + +@item blocks +@samp{-b} in @code{head} and @code{tail}. + +@item break-file +@samp{-b} in @code{ptx}. + +@item brief +Used in various programs to make output shorter. + +@item bytes +@samp{-c} in @code{head}, @code{split}, and @code{tail}. + +@item c++ +@samp{-C} in @code{etags}. + +@item catenate +@samp{-A} in @code{tar}. + +@item cd +Used in various programs to specify the directory to use. + +@item changes +@samp{-c} in @code{chgrp} and @code{chown}. + +@item classify +@samp{-F} in @code{ls}. + +@item colons +@samp{-c} in @code{recode}. + +@item command +@samp{-c} in @code{su}; +@samp{-x} in GDB. + +@item compare +@samp{-d} in @code{tar}. + +@item compress +@samp{-Z} in @code{tar}. + +@item concatenate +@samp{-A} in @code{tar}. + +@item confirmation +@samp{-w} in @code{tar}. + +@item context +Used in @code{diff}. + +@item copyright +@samp{-C} in @code{ptx} and @code{recode}. + +@item core +Used in GDB. + +@item count +@samp{-q} in @code{who}. + +@item count-links +@samp{-l} in @code{du}. + +@item create +Used in @code{tar} and @code{cpio}. + +@item cxref +@samp{-x} in @code{etags}. + +@item date +@samp{-d} in @code{touch}. + +@item debug +@samp{-d} in Make and @code{m4}; +@samp{-t} in Bison. + +@item define +@samp{-D} in @code{m4}. + +@item defines +@samp{-d} in Bison and @code{etags}. + +@item delete +@samp{-D} in @code{tar}. + +@item dereference +@samp{-L} in @code{chgrp}, @code{chown}, @code{cpio}, @code{du}, +@code{ls}, and @code{tar}. + +@item dereference-args +@samp{-D} in @code{du}. + +@item diacritics +@samp{-d} in @code{recode}. + +@item dictionary-order +@samp{-d} in @code{look}. + +@item diff +@samp{-d} in @code{tar}. + +@item digits +@samp{-n} in @code{csplit}. + +@item directory +Specify the directory to use, in various programs. In @code{ls}, it +means to show directories themselves rather than their contents. In +@code{rm} and @code{ln}, it means to not treat links to directories +specially. + +@item discard-all +@samp{-x} in @code{strip}. + +@item discard-locals +@samp{-X} in @code{strip}. + +@item diversions +@samp{-N} in @code{m4}. + +@item dry-run +@samp{-n} in Make. + +@item ed +@samp{-e} in @code{diff}. + +@item elide-empty-files +@samp{-z} in @code{csplit}. + +@item entire-new-file +@samp{-N} in @code{diff}. + +@item environment-overrides +@samp{-e} in Make. + +@item eof +@samp{-e} in @code{xargs}. + +@item epoch +Used in GDB. + +@item error-limit +Used in Makeinfo. + +@item error-output +@samp{-o} in @code{m4}. + +@item escape +@samp{-b} in @code{ls}. + +@item exclude-from +@samp{-X} in @code{tar}. + +@item exec +Used in GDB. + +@item exit +@samp{-x} in @code{xargs}. + +@item expand-tabs +@samp{-t} in @code{diff}. + +@item expression +@samp{-e} in @code{sed}. + +@item extern-only +@samp{-g} in @code{nm}. + +@item extract +@samp{-i} in @code{cpio}; +@samp{-x} in @code{tar}. + +@item faces +@samp{-f} in @code{finger}. + +@item fast +@samp{-f} in @code{su}. + +@item file +@samp{-f} in @code{info}, Make, @code{mt}, and @code{tar}; +@samp{-n} in @code{sed}; +@samp{-r} in @code{touch}. + +@item file-prefix +@samp{-b} in Bison. + +@item file-type +@samp{-F} in @code{ls}. + +@item files-from +@samp{-T} in @code{tar}. + +@item fill-column +Used in Makeinfo. + +@item flag-truncation +@samp{-F} in @code{ptx}. + +@item fixed-output-files +@samp{-y} in Bison. + +@item follow +@samp{-f} in @code{tail}. + +@item footnote-style +Used in Makeinfo. + +@item force +@samp{-f} in @code{cp}, @code{ln}, @code{mv}, and @code{rm}. + +@item format +Used in @code{ls}, @code{time}, and @code{ptx}. + +@item forward-search +@samp{-F} in @code{etags}. + +@item fullname +Used in GDB. + +@item gap-size +@samp{-g} in @code{ptx}. + +@item get +@samp{-x} in @code{tar}. + +@item graphic +@samp{-i} in @code{ul}. + +@item graphics +@samp{-g} in @code{recode}. + +@item group +@samp{-g} in @code{install}. + +@item gzip +@samp{-z} in @code{tar}. + +@item hashsize +@samp{-H} in @code{m4}. + +@item header +@samp{-h} in @code{objdump} and @code{recode} + +@item heading +@samp{-H} in @code{who}. + +@item help +Used to ask for brief usage information. + +@item hide-control-chars +@samp{-q} in @code{ls}. + +@item idle +@samp{-u} in @code{who}. + +@item ifdef +@samp{-D} in @code{diff}. + +@item ignore +@samp{-I} in @code{ls}; +@samp{-x} in @code{recode}. + +@item ignore-all-space +@samp{-w} in @code{diff}. + +@item ignore-backups +@samp{-B} in @code{ls}. + +@item ignore-blank-lines +@samp{-B} in @code{diff}. + +@item ignore-case +@samp{-f} in @code{look} and @code{ptx}; +@samp{-i} in @code{diff}. + +@item ignore-errors +@samp{-i} in Make. + +@item ignore-file +@samp{-i} in @code{ptx}. + +@item ignore-indentation +@samp{-S} in @code{etags}. + +@item ignore-init-file +@samp{-f} in Oleo. + +@item ignore-interrupts +@samp{-i} in @code{tee}. + +@item ignore-matching-lines +@samp{-I} in @code{diff}. + +@item ignore-space-change +@samp{-b} in @code{diff}. + +@item ignore-zeros +@samp{-i} in @code{tar}. + +@item include +@samp{-i} in @code{etags}; +@samp{-I} in @code{m4}. + +@item include-dir +@samp{-I} in Make. + +@item incremental +@samp{-G} in @code{tar}. + +@item info +@samp{-i}, @samp{-l}, and @samp{-m} in Finger. + +@item initial +@samp{-i} in @code{expand}. + +@item initial-tab +@samp{-T} in @code{diff}. + +@item inode +@samp{-i} in @code{ls}. + +@item interactive +@samp{-i} in @code{cp}, @code{ln}, @code{mv}, @code{rm}; +@samp{-e} in @code{m4}; +@samp{-p} in @code{xargs}; +@samp{-w} in @code{tar}. + +@item jobs +@samp{-j} in Make. + +@item just-print +@samp{-n} in Make. + +@item keep-going +@samp{-k} in Make. + +@item keep-files +@samp{-k} in @code{csplit}. + +@item kilobytes +@samp{-k} in @code{du} and @code{ls}. + +@item line-bytes +@samp{-C} in @code{split}. + +@item lines +Used in @code{split}, @code{head}, and @code{tail}. + +@item link +@samp{-l} in @code{cpio}. + +@item list +@samp{-t} in @code{cpio}; +@samp{-l} in @code{recode}. + +@item list +@samp{-t} in @code{tar}. + +@item literal +@samp{-N} in @code{ls}. + +@item load-average +@samp{-l} in Make. + +@item login +Used in @code{su}. + +@item machine +No listing of which programs already use this; +someone should check to +see if any actually do and tell @code{gnu@@prep.ai.mit.edu}. + +@item macro-name +@samp{-M} in @code{ptx}. + +@item mail +@samp{-m} in @code{hello} and @code{uname}. + +@item make-directories +@samp{-d} in @code{cpio}. + +@item makefile +@samp{-f} in Make. + +@item mapped +Used in GDB. + +@item max-args +@samp{-n} in @code{xargs}. + +@item max-chars +@samp{-n} in @code{xargs}. + +@item max-lines +@samp{-l} in @code{xargs}. + +@item max-load +@samp{-l} in Make. + +@item max-procs +@samp{-P} in @code{xargs}. + +@item mesg +@samp{-T} in @code{who}. + +@item message +@samp{-T} in @code{who}. + +@item minimal +@samp{-d} in @code{diff}. + +@item mode +@samp{-m} in @code{install}, @code{mkdir}, and @code{mkfifo}. + +@item modification-time +@samp{-m} in @code{tar}. + +@item multi-volume +@samp{-M} in @code{tar}. + +@item name-prefix +@samp{-a} in Bison. + +@item new-file +@samp{-W} in Make. + +@item no-builtin-rules +@samp{-r} in Make. + +@item no-create +@samp{-c} in @code{touch}. + +@item no-defines +@samp{-D} in @code{etags}. + +@item no-dereference +@samp{-d} in @code{cp}. + +@item no-keep-going +@samp{-S} in Make. + +@item no-lines +@samp{-l} in Bison. + +@item no-prof +@samp{-e} in @code{gprof}. + +@item no-sort +@samp{-p} in @code{nm}. + +@item no-split +Used in Makeinfo. + +@item no-static +@samp{-a} in @code{gprof}. + +@item no-time +@samp{-E} in @code{gprof}. + +@item no-validate +Used in Makeinfo. + +@item no-warn +Used in various programs to inhibit warnings. + +@item node +@samp{-n} in @code{info}. + +@item nodename +@samp{-n} in @code{uname}. + +@item nonmatching +@samp{-f} in @code{cpio}. + +@item nstuff +@samp{-n} in @code{objdump}. + +@item null +@samp{-0} in @code{xargs}. + +@item number +@samp{-n} in @code{cat}. + +@item number-nonblank +@samp{-b} in @code{cat}. + +@item numeric-sort +@samp{-n} in @code{nm}. + +@item numeric-uid-gid +@samp{-n} in @code{cpio} and @code{ls}. + +@item nx +Used in GDB. + +@item old-archive +@samp{-o} in @code{tar}. + +@item old-file +@samp{-o} in Make. + +@item one-file-system +@samp{-l} in @code{tar}, @code{cp}, and @code{du}. + +@item only-file +@samp{-o} in @code{ptx}. + +@item only-prof +@samp{-f} in @code{gprof}. + +@item only-time +@samp{-F} in @code{gprof}. + +@item output +In various programs, specify the output file name. + +@item override +@samp{-o} in @code{rm}. + +@item owner +@samp{-o} in @code{install}. + +@item paginate +@samp{-l} in @code{diff}. + +@item paragraph-indent +Used in Makeinfo. + +@item parents +@samp{-p} in @code{mkdir} and @code{rmdir}. + +@item pass-all +@samp{-p} in @code{ul}. + +@item pass-through +@samp{-p} in @code{cpio}. + +@item port +@samp{-P} in @code{finger}. + +@item portability +@samp{-c} in @code{cpio} and @code{tar}. + +@item prefix-builtins +@samp{-P} in @code{m4}. + +@item prefix +@samp{-f} in @code{csplit}. + +@item preserve +Used in @code{tar} and @code{cp}. + +@item preserve-environment +@samp{-p} in @code{su}. + +@item preserve-modification-time +@samp{-m} in @code{cpio}. + +@item preserve-order +@samp{-s} in @code{tar}. + +@item preserve-permissions +@samp{-p} in @code{tar}. + +@item print +@samp{-l} in @code{diff}. + +@item print-chars +@samp{-L} in @code{cmp}. + +@item print-data-base +@samp{-p} in Make. + +@item print-directory +@samp{-w} in Make. + +@item print-file-name +@samp{-o} in @code{nm}. + +@item print-symdefs +@samp{-s} in @code{nm}. + +@item question +@samp{-q} in Make. + +@item quiet +Used in many programs to inhibit the usual output. @strong{Note:} every +program accepting @samp{--quiet} should accept @samp{--silent} as a +synonym. + +@item quote-name +@samp{-Q} in @code{ls}. + +@item rcs +@samp{-n} in @code{diff}. + +@item read-full-blocks +@samp{-B} in @code{tar}. + +@item readnow +Used in GDB. + +@item recon +@samp{-n} in Make. + +@item record-number +@samp{-R} in @code{tar}. + +@item recursive +Used in @code{chgrp}, @code{chown}, @code{cp}, @code{ls}, @code{diff}, +and @code{rm}. + +@item reference-limit +Used in Makeinfo. + +@item references +@samp{-r} in @code{ptx}. + +@item regex +@samp{-r} in @code{tac}. + +@item release +@samp{-r} in @code{uname}. + +@item relocation +@samp{-r} in @code{objdump}. + +@item rename +@samp{-r} in @code{cpio}. + +@item replace +@samp{-i} in @code{xargs}. + +@item report-identical-files +@samp{-s} in @code{diff}. + +@item reset-access-time +@samp{-a} in @code{cpio}. + +@item reverse +@samp{-r} in @code{ls} and @code{nm}. + +@item reversed-ed +@samp{-f} in @code{diff}. + +@item right-side-defs +@samp{-R} in @code{ptx}. + +@item same-order +@samp{-s} in @code{tar}. + +@item same-permissions +@samp{-p} in @code{tar}. + +@item save +@samp{-g} in @code{stty}. + +@item se +Used in GDB. + +@item sentence-regexp +@samp{-S} in @code{ptx}. + +@item separate-dirs +@samp{-S} in @code{du}. + +@item separator +@samp{-s} in @code{tac}. + +@item sequence +Used by @code{recode} to chose files or pipes for sequencing passes. + +@item shell +@samp{-s} in @code{su}. + +@item show-all +@samp{-A} in @code{cat}. + +@item show-c-function +@samp{-p} in @code{diff}. + +@item show-ends +@samp{-E} in @code{cat}. + +@item show-function-line +@samp{-F} in @code{diff}. + +@item show-tabs +@samp{-T} in @code{cat}. + +@item silent +Used in many programs to inhibit the usual output. +@strong{Note:} every program accepting +@samp{--silent} should accept @samp{--quiet} as a synonym. + +@item size +@samp{-s} in @code{ls}. + +@item sort +Used in @code{ls}. + +@item sparse +@samp{-S} in @code{tar}. + +@item speed-large-files +@samp{-H} in @code{diff}. + +@item squeeze-blank +@samp{-s} in @code{cat}. + +@item starting-file +Used in @code{tar} and @code{diff} to specify which file within +a directory to start processing with. + +@item stop +@samp{-S} in Make. + +@item strict +@samp{-s} in @code{recode}. + +@item strip +@samp{-s} in @code{install}. + +@item strip-all +@samp{-s} in @code{strip}. + +@item strip-debug +@samp{-S} in @code{strip}. + +@item suffix +@samp{-S} in @code{cp}, @code{ln}, @code{mv}. + +@item suffix-format +@samp{-b} in @code{csplit}. + +@item sum +@samp{-s} in @code{gprof}. + +@item summarize +@samp{-s} in @code{du}. + +@item symbolic +@samp{-s} in @code{ln}. + +@item symbols +Used in GDB and @code{objdump}. + +@item synclines +@samp{-s} in @code{m4}. + +@item sysname +@samp{-s} in @code{uname}. + +@item tabs +@samp{-t} in @code{expand} and @code{unexpand}. + +@item tabsize +@samp{-T} in @code{ls}. + +@item terminal +@samp{-T} in @code{tput} and @code{ul}. + +@item text +@samp{-a} in @code{diff}. + +@item time +Used in @code{ls} and @code{touch}. + +@item to-stdout +@samp{-O} in @code{tar}. + +@item total +@samp{-c} in @code{du}. + +@item touch +@samp{-t} in Make, @code{ranlib}, and @code{recode}. + +@item trace +@samp{-t} in @code{m4}. + +@item traditional +@samp{-t} in @code{hello}; +@samp{-G} in @code{m4} and @code{ptx}. + +@item tty +Used in GDB. + +@item typedefs +@samp{-t} in @code{etags}. + +@item typedefs-and-c++ +@samp{-T} in @code{etags}. + +@item typeset-mode +@samp{-t} in @code{ptx}. + +@item uncompress +@samp{-z} in @code{tar}. + +@item unconditional +@samp{-u} in @code{cpio}. + +@item undefine +@samp{-U} in @code{m4}. + +@item undefined-only +@samp{-u} in @code{nm}. + +@item update +@samp{-u} in @code{cp}, @samp{etags}, @samp{mv}, @samp{tar}. + +@item verbose +Print more information about progress. Many programs support this. + +@item verify +@samp{-W} in @code{tar}. + +@item version +Print the version number. + +@item version-control +@samp{-V} in @code{cp}, @code{ln}, @code{mv}. + +@item vgrind +@samp{-v} in @code{etags}. + +@item volume +@samp{-V} in @code{tar}. + +@item what-if +@samp{-W} in Make. + +@item width +@samp{-w} in @code{ls} and @code{ptx}. + +@item word-regexp +@samp{-W} in @code{ptx}. + +@item writable +@samp{-T} in @code{who}. + +@item zeros +@samp{-z} in @code{gprof}. + +@end table + +@node Documentation +@chapter Documenting Programs + +Please use Texinfo for documenting GNU programs. See the Texinfo +manual, either the hardcopy or the version in the GNU Emacs Info +subsystem (@kbd{C-h i}). See existing GNU Texinfo files (e.g., those +under the @file{man/} directory in the GNU Emacs distribution) for +examples. + +The title page of the manual should state the version of the program +which the manual applies to. The Top node of the manual should also +contain this information. If the manual is changing more frequently +than or independent of the program, also state a version number for +the manual in both of these places. + +The manual should document all command-line arguments and all +commands. It should give examples of their use. But don't organize +the manual as a list of features. Instead, organize it by the +concepts a user will have before reaching that point in the manual. +Address the goals that a user will have in mind, and explain how to +accomplish them. Don't use Unix man pages as a model for how to +write GNU documentation; they are a bad example to follow. + +The manual should have a node named @samp{@var{program} Invocation} or +@samp{Invoking @var{program}}, where @var{program} stands for the name +of the program being described, as you would type it in the shell to run +the program. This node (together with its subnodes, if any) should +describe the program's command line arguments and how to run it (the +sort of information people would look in a man page for). Start with an +@samp{@@example} containing a template for all the options and arguments +that the program uses. + +Alternatively, put a menu item in some menu whose item name fits one of +the above patterns. This identifies the node which that item points to +as the node for this purpose, regardless of the node's actual name. + +There will be automatic features for specifying a program name and +quickly reading just this part of its manual. + +If one manual describes several programs, it should have such a node for +each program described. + +In addition to its manual, the package should have a file named +@file{NEWS} which contains a list of user-visible changes worth +mentioning. In each new release, add items to the front of the file and +identify the version they pertain to. Don't discard old items; leave +them in the file after the newer items. This way, a user upgrading from +any previous version can see what is new. + +If the @file{NEWS} file gets very long, move some of the older items +into a file named @file{ONEWS} and put a note at the end referring the +user to that file. + +Please do not use the term ``pathname'' that is used in Unix +documentation; use ``file name'' (two words) instead. We use the term +``path'' only for search paths, which are lists of file names. + +It is ok to supply a man page for the program as well as a Texinfo +manual if you wish to. But keep in mind that supporting a man page +requires continual effort, each time the program is changed. Any time +you spend on the man page is time taken away from more useful things you +could contribute. + +Thus, even if a user volunteers to donate a man page, you may find this +gift costly to accept. Unless you have time on your hands, it may be +better to refuse the man page unless the same volunteer agrees to take +full responsibility for maintaining it---so that you can wash your hands +of it entirely. If the volunteer ceases to do the job, then don't feel +obliged to pick it up yourself; it may be better to withdraw the man +page until another volunteer offers to carry on with it. + +Alternatively, if you expect the discrepancies to be small enough that +the man page remains useful, put a prominent note near the beginning of +the man page explaining that you don't maintain it and that the Texinfo +manual is more authoritative, and describing how to access the Texinfo +documentation. + +@node Releases +@chapter Making Releases + +Package the distribution of Foo version 69.96 in a gzipped tar file +named @file{foo-69.96.tar.gz}. It should unpack into a subdirectory +named @file{foo-69.96}. + +Building and installing the program should never modify any of the files +contained in the distribution. This means that all the files that form +part of the program in any way must be classified into @dfn{source +files} and @dfn{non-source files}. Source files are written by humans +and never changed automatically; non-source files are produced from +source files by programs under the control of the Makefile. + +Naturally, all the source files must be in the distribution. It is okay +to include non-source files in the distribution, provided they are +up-to-date and machine-independent, so that building the distribution +normally will never modify them. We commonly include non-source files +produced by Bison, Lex, @TeX{}, and Makeinfo; this helps avoid +unnecessary dependencies between our distributions, so that users can +install whichever packages they want to install. + +Non-source files that might actually be modified by building and +installing the program should @strong{never} be included in the +distribution. So if you do distribute non-source files, always make +sure they are up to date when you make a new distribution. + +Make sure that the directory into which the distribution unpacks (as +well as any subdirectories) are all world-writable (octal mode 777). +This is so that old versions of @code{tar} which preserve the +ownership and permissions of the files from the tar archive will be +able to extract all the files even if the user is unprivileged. + +Make sure that all the files in the distribution are world-readable. + +Make sure that no file name in the distribution is more than 14 +characters long. Likewise, no file created by building the program +should have a name longer than 14 characters. The reason for this is +that some systems adhere to a foolish interpretation of the POSIX +standard, and refuse to open a longer name, rather than truncating as +they did in the past. + +Don't include any symbolic links in the distribution itself. If the tar +file contains symbolic links, then people cannot even unpack it on +systems that don't support symbolic links. Also, don't use multiple +names for one file in different directories, because certain file +systems cannot handle this and that prevents unpacking the +distribution. + +Try to make sure that all the file names will be unique on MS-DOG. A +name on MS-DOG consists of up to 8 characters, optionally followed by a +period and up to three characters. MS-DOG will truncate extra +characters both before and after the period. Thus, +@file{foobarhacker.c} and @file{foobarhacker.o} are not ambiguous; they +are truncated to @file{foobarha.c} and @file{foobarha.o}, which are +distinct. + +Include in your distribution a copy of the @file{texinfo.tex} you used +to test print any @file{*.texinfo} files. + +Likewise, if your program uses small GNU software packages like regex, +getopt, obstack, or termcap, include them in the distribution file. +Leaving them out would make the distribution file a little smaller at +the expense of possible inconvenience to a user who doesn't know what +other files to get. + +@contents + +@bye diff --git a/gnu/usr.bin/binutils/gas/CONTRIBUTORS b/gnu/usr.bin/binutils/gas/CONTRIBUTORS new file mode 100644 index 00000000000..49ec2960852 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/CONTRIBUTORS @@ -0,0 +1,99 @@ +(This file is under construction.) -*- text -*- + +If you've contributed to gas and your name isn't listed here, it is +not meant as a slight. I just don't know about it. Email me, +raeburn@cygnus.com and I'll correct the situation. + +This file will eventually be deleted: The general info will go into +the documentation, and info on specific files will go into an AUTHORS +file, as requested by the FSF. + +++++++++++++++++ + +Dean Elsner wrote the original gas for vax. [more details?] + +Jay Fenlason maintained gas for a while, adding support for +gdb-specific debug information and the 68k series machines, most of +the preprocessing pass, and extensive changes in messages.c, +input-file.c, write.c. + +K. Richard Pixley maintained gas for a while, adding various +enhancements and many bug fixes, including merging support for several +processors, breaking gas up to handle multiple object file format +backends (including heavy rewrite, testing, an integration of the coff +and b.out backends), adding configuration including heavy testing and +verification of cross assemblers and file splits and renaming, +converted gas to strictly ansi C including full prototypes, added +support for m680[34]0 & cpu32, considerable work on i960 including a +coff port (including considerable amounts of reverse engineering), a +sparc opcode file rewrite, decstation, rs6000, and hp300hpux host +ports, updated "know" assertions and made them work, much other +reorganization, cleanup, and lint. + +Ken Raeburn currently maintains gas, and wrote the high-level BFD +interface code to replace most of the code in format-specific I/O +modules. + +The original Vax-VMS support was contributed by David L. Kashtan. +Eric Youngdale and Pat Rankin have done much work with it since. + +The Intel 80386 machine description was written by Eliot Dresselhaus. + +Minh Tran-Le at IntelliCorp contributed some AIX 386 support. + +The Motorola 88k machine description was contributed by Devon Bowen of +Buffalo University and Torbjorn Granlund of the Swedish Institute of +Computer Science. + +Keith Knowles at the Open Software Foundation wrote the original MIPS +back end (tc-mips.c, tc-mips.h), and contributed Rose format support +that hasn't been merged in yet. Ralph Campbell worked with the MIPS +code to support a.out format. + +Support for the Zilog Z8k and Hitachi H8/300, H8/500 and SH processors +(tc-z8k, tc-h8300, tc-h8500, tc-sh), and IEEE 695 object file format +(obj-ieee), was written by Steve Chamberlain of Cygnus Support. Steve +also modified the COFF back end (obj-coffbfd) to use BFD for some +low-level operations, for use with the Hitachi, 29k and Zilog targets. + +John Gilmore built the AMD 29000 support, added .include support, and +simplified the configuration of which versions accept which +pseudo-ops. He updated the 68k machine description so that Motorola's +opcodes always produced fixed-size instructions (e.g. jsr), while +synthetic instructions remained shrinkable (jbsr). John fixed many +bugs, including true tested cross-compilation support, and one bug in +relaxation that took a week and required the proverbial one-bit fix. + +Ian Lance Taylor of Cygnus Support merged the Motorola and MIT +syntaxes for the 68k, completed support for some COFF targets (68k, +i386 SVR3, and SCO Unix), wrote the ECOFF support based on Michael +Meissner's mips-tfile program, wrote the PowerPC and RS/6000 support, +and made a few other minor patches. + +David Edelsohn contributed fixes for the PowerPC and AIX support. + +Steve Chamberlain made gas able to generate listings. + +Support for the HP9000/300 was contributed by Glenn Engel of HP. + +Support for ELF format files has been worked on by Mark Eichin of +Cygnus Support (original, incomplete implementation), Pete Hoogenboom +at the University of Utah (HPPA mainly), Michael Meissner of the Open +Software Foundation (i386 mainly), and Ken Raeburn of Cygnus Support +(sparc, initial 64-bit support). + +Several engineers at Cygnus Support have also provided many small bug +fixes and configuration enhancements. + +The initial Alpha support was contributed by Carnegie-Mellon +University. Additional work was done by Ken Raeburn of Cygnus +Support. + +Ian Dall updated the support code for the National Semiconductor 32000 +series, and added support for Mach 3 and NetBSD running on the PC532. + + +Many others have contributed large or small bugfixes and enhancements. If +you've contributed significant work and are not mentioned on this list, and +want to be, let us know. Some of the history has been lost; we aren't +intentionally leaving anyone out. diff --git a/gnu/usr.bin/binutils/gas/COPYING b/gnu/usr.bin/binutils/gas/COPYING new file mode 100644 index 00000000000..a43ea2126fb --- /dev/null +++ b/gnu/usr.bin/binutils/gas/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. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You 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. + + , 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/gnu/usr.bin/binutils/gas/ChangeLog b/gnu/usr.bin/binutils/gas/ChangeLog new file mode 100644 index 00000000000..468e6202549 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/ChangeLog @@ -0,0 +1,480 @@ +Thu Nov 16 00:21:44 1995 Ken Raeburn + + Version 2.6 released. + * Makefile.in (VERSION): Updated to 2.6. + + * config/tc-mips.c (s_mipserr): Renamed from s_err, to avoid + conflict with read.h. + + * config/obj-coff.c (write_object_file): Change use of md_do_align + to pass a pointer rather than a fill value, to match other uses. + +Wed Nov 15 03:52:00 1995 Ken Raeburn + + * config/tc-ns32k.h (TC_FIX_TYPE): Add missing semicolon. + + * as.c (main): Move md_end call to just after call to + perform_an_assembly_pass. Delete cpu-specific code here. + * config/tc-i960.h (md_end): New macro, calls brtab_emit. + * config/tc-arm.c (md_end): Unused function deleted. + * config/tc-ns32k.c (md_end): Ditto. + + * config/tc-i386.c (i386_align_code): New function, moved here + from HANDLE_ALIGN macro. + * config/tc-i386.h (HANDLE_ALIGN): Call it. + + Mon Jul 31 14:53:19 1995 Alan Modra + + * config/tc-i386.h (md_do_align): cast fill and 0x90 to char + before comparing + + Mon May 1 10:91:49 1995 Alan Modra + + * config/tc-i386.h (md_do_align): Make ".align n,0x90" generate + multi-byte nops to avoid changing gcc. The necessary gcc change + might break old assemblers. + + Sat Apr 22 20:53:05 1995 Alan Modra + + * config/tc-i386.h (md_do_align, HANDLE_ALIGN): Add macros to + generate optimal multi-byte nop instructions for ".align n" + ".align n,0x90", and aligns requiring more than 15 bytes of + padding still generate multiple 0x90's as before. + +Mon Nov 13 17:40:21 1995 Ian Lance Taylor + + * config/tc-m68k.c (s_mri_until): Call pop_mri_control. + +Mon Nov 13 20:39:06 1995 Stan Shebs + + * configure.in (ppc-*-macos*, ppc-*-mpw*): New configurations. + * configure: Update. + * mpw-make.sed: Reorder commands to make sed happier. + * config/te-macos.h: New file. + * config/tc-ppc.h (TARGET_FORMAT): Set correctly for PowerMac. + +Sun Nov 12 21:14:56 1995 Jeffrey A Law (law@cygnus.com) + + * config/tc-hppa.c (pa_ip): Fix off-by-2 bug in length check for + conditional branches. + (md_apply_fix): Likewise. + +Thu Nov 9 16:14:01 1995 Ian Lance Taylor + + * config/tc-a29k.c (md_apply_fix): Warn if an attempt is made to + generate a reloc which the linker will not handle correctly. Fix + overflow checking--R_IREL is 18 bits, not 17. + +Wed Nov 8 19:59:36 1995 Ian Lance Taylor + + * config/obj-coff.c (fixup_segment): Don't subtract md_pcrel_from + from a PC relative reloc if TC_A29K. + + * config/tc-a29k.c (line_separator_chars): Restore '@'. Existing + code depends upon it. + + * config/tc-a29k.c (md_operand): Handle $float, $double, and + $extend. Based on code from Eric Freudenthal + . + * config/tc-a29k.h (LEX_DOLLAR): Define. + * read.c (LEX_DOLLAR): Define if not defined. + (lex_type): Use LEX_DOLLAR. + +Wed Nov 8 16:38:14 1995 Eric Freudenthal + + * configure.in (a29k-nyu-sym1): New target, just like other a29k + targets. + +Wed Nov 8 11:38:48 1995 Ian Lance Taylor + + * config/obj-coff.c (c_dot_file_symbol): Cast xmalloc return. + +Tue Nov 7 09:14:35 1995 Kim Knuttila + + * config/tc-ppc.c (md_apply_fix3): Added BFD_RELOC_RVA. Currently + used only by "dlltool.c". + +Mon Nov 6 18:51:26 1995 Ian Lance Taylor + + * config/tc-alpha.c: Undefine inline if not __GNUC__. + (md_pseudo_table): Don't define "extern". + +Sat Nov 4 00:51:21 1995 Ian Lance Taylor + + * config/tc-ppc.c (ppc_biei): Force symbol into text_section. + + * config/tc-ppc.c (md_show_usage): Put backslash at end of line. + +Fri Nov 3 13:02:59 1995 Ian Lance Taylor + + * macro.c (macro_expand_body): Don't warn about == with a + nonexistent parameter, in case it is in a comment field. + + * as.c (main): On TC_A29K, call macro_init with macro_alternate + set to 1. + * macro.c (get_any_string): Don't keep quotes if macro_strip_at is + set, even if macro_alternate is set. + (get_apost_token): If macro_strip_at, only skip kind if it is '@'. + (sub_actual): If macro_strip_at, and kind is '@', don't look up + the token unless it ended in '@'. + * config/tc-a29k.c (line_separator_chars): Remove '@'. + * doc/c-a29k.texi: Document macro usage on A29K. + +Thu Nov 2 23:07:57 1995 Ian Lance Taylor + + * config/tc-m68k.c (m68k_ip): Handle new 'W' place, meaning a + signed word. + (install_operand): Likewise. + + * config/obj-elf.c (ecoff_debug_pseudo_table): Add "extern". + +Wed Nov 1 15:17:02 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 + + * configure.in (m88k-motorola-sysv*): New target. + * configure: Rebuild. + * config/te-delta88.h: New file. + * config/obj-coff.c (write_object_file): Use md_do_align if it is + defined. + * config/tc-m88k.h (SUB_SEGMENT_ALIGN): Define. + (md_do_align): Define. + * config/tc-m88k.c: Include "subsegs.h". + (m88k_do_align): New function. + + * config/te-delta.h (STRIP_UNDERSCORE): Don't define. + (COFF_NOLOAD_PROBLEM): Define. + (LOCAL_LABELS_DOLLAR, LOCAL_LABELS_FB): Define. + +Wed Nov 1 16:07:43 1995 Ken Raeburn + + * config/tc-i386.c (md_assemble): For a jump instruction with + non-constant target, require 7 available bytes in the current + frag, not 6. + +Tue Oct 31 15:37:16 1995 Fred Fish + + * config/obj-elf.h: Include bfd/elf-bfd.h rather than + bfd/libelf.h. + +Tue Oct 31 16:34:28 1995 David Mosberger-Tang + + * configure.in (alpha-*-linux*): Use ecoff. + * configure: Rebuild. + * ecoff.c (ecoff_directive_extern): New function. + (ecoff_directive_weakext): New function. + (ecoff_build_symbols): Handle weak symbols. + (ecoff_setup_ext): Likewise. + (ecoff_frob_symbol): Warn about weak common symbols. + * ecoff.h (ecoff_directive_extern): Declare. + (ecoff_directive_weakext): Declare. + * symbols.c (S_IS_WEAK): New function. + * symbols.h (S_IS_WEAK): Declare. + * config/obj-ecoff.c (obj_pseudo_table): Add "extern" and + "weakext". + * config/tc-mips.c (mips_pseudo_table): Remove "extern". + (s_extern): Remove. + +Tue Oct 31 13:29:08 1995 Ian Lance Taylor + + * config/tc-ppc.c (ppc_lglobl): Do the right thing. + + * config/tc-ppc.c (ppc_bb): Call SF_SET_PROCESS. + (ppc_eb): Likewise. Set the storage class to C_BLOCK, not C_FCN. + (ppc_frob_symbol): Don't change C_BLOCK symbols to C_HIDEXT. + * config/obj-coff.c (coff_frob_symbol): Don't call + SA_SET_SYM_ENDNDX with the current symbol; call it with the next + one. If OBJ_XCOFF, try to figure out whether the symbol is going + to be dropped. + + * config/tc-ppc.c (md_pseudo_table): Add "bc" and "ec". + (ppc_stab_symbol): New static variable. + (ppc_change_csect): Check that ppc_toc_csect is not NULL. + (ppc_stabx): Set ppc_stab_symbol around call to symbol_make. Set + sy_tc.real_name to the stab string. + (ppc_bc, ppc_ec): New static functions. + (ppc_canonicalize_symbol_name): If ppc_stab_symbol is set, don't + do anything. + (ppc_symbol_new_hook): If ppc_stab_symbol is set, don't look for a + suffix. + (ppc_frob_symbol): Set BSF_NOT_AT_END for symbols with csect aux + entries. + + * input-scrub.c (input_scrub_push): Reset sb_index. + +Mon Oct 30 17:52:46 1995 Ian Lance Taylor + + * listing.c (listing_newline): Don't create a frag in the absolute + section. + +Sat Oct 28 01:02:05 1995 Ian Lance Taylor + + * config/tc-ppc.c (md_pseudo_table): Add "data" and "text". + (ppc_csect): Move most of the code to ppc_change_csect, and call + it. + (ppc_change_csect): New static function, taken from ppc_csect. + (ppc_section): New static function. + (ppc_saw_abs): New static varable. + (ppc_frob_symbol): Create aux entry for absolute symbols. Warn if + a symbol has no csect. + (ppc_adjust_symtab): New function. + * config/tc-ppc.h (tc_adjust_symtab): Define if OBJ_XCOFF. + (ppc_adjust_symtab): Declare if OBJ_XCOFF. + + * write.c (write_object_file): If tc_adjust_symtab is defined, + call it just before the call to obj_adjust_symtab. + + * symbols.c (symbol_find_or_make): Change name to be const. + * symbols.h (symbol_find_or_make): Update declaration. + +Thu Oct 26 19:18:27 1995 Ken Raeburn + + * doc/as.texinfo (Align): Mention SH. + * doc/c-m68k.texi (M68K-Directives, .even): Describe behavior, not + .align value. + * doc/c-z8k.texi (Z8000 Directives, global): Fix minor typo. + (Z8000 Directives, even): Don't give numeric align value, instead + explain behavior. + +Thu Oct 26 11:45:03 1995 Richard Earnshaw (rearnsha@armltd.co.uk) + + * tc-arm.c (do_ldst): Assemble ldr/str r0, [r1] as a pre-increment + instruction. + +Wed Oct 25 11:59:24 1995 Per Bothner + + * Makefile.in (diststuff): Also make info. + (maintainer-clean realclean): Also make clean-info. + +Tue Oct 24 15:21:33 1995 Jeffrey A Law (law@cygnus.com) + + * config/tc-hppa.c (md_pseudo_table): Add new ".nsubspa" opcode. + (pa_subspace): For ".nsubspa", always create a new subspace + with the given attributes, even if one already exists with the + same name. + +Tue Oct 24 14:50:38 1995 Michael Meissner + + * config/tc-ppc.h (TC_FORCE_RELOCATION_SECTION): Rename from + TC_FORCE_RELOCATION, taking an additional section argument. If + the section of the target symbol is not the same as the current + section, always force the relocation to be used. + (MD_PCREL_FROM_SECTION): New macro to call md_pcrel_from_section. + + * config/tc-ppc.c (md_pcrel_from_section): Rename from the + md_pcrel_from function, taking an additional section argument. + Invoke TC_FORCE_RELOCATION_SECTION instead of TC_FORCE_RELOCATION. + + * write.c (TC_FORCE_RELOCATION_SECTION): Define in terms of the + older TC_FORCE_RELOCATION if not defined. + (MD_PCREL_FROM_SECTION): If not defined, invoke md_pcrel_from. + (fixup_segment): Use MD_PCREL_FROM_SECTION instead of + md_pcrel_from, and TC_FORCE_RELOCATION_SECTION instead of + TC_FORCE_RELOCATION. + +Mon Oct 23 16:20:04 1995 Ken Raeburn + + * input-scrub.c (as_where): Set name to null pointer if we don't + have a file name. + * messages.c (identify): Only print filename if non-null. + (as_show_where): Ditto, for line number too. + (as_warn_internal, as_bad_internal): Ditto. + + * input-file.c (input_file_open): If the input file can't be + opened, consider it an error. + +Mon Oct 23 11:15:44 1995 James G. Smith + + * config/tc-mips.c: Added mips_4100 control, and support for + accepting the 4100 as a MIPS architecture variant (md_begin, + macro_build, mips_ip, md_parse_option). Adding suitable + command-line OPTIONs, and updating the help text (md_show_usage). + +Wed Oct 18 13:20:32 1995 Ken Raeburn + + * subsegs.c (subseg_begin): Only set absolute_frchain.fix_* when + BFD_ASSEMBLER is defined. + + * Use one active frag and one obstack per frag chain: + * frags.c (frags): Variable deleted. + (frag_alloc): New function. + (frag_grow, frag_more, frag_variant, frag_now_fix, + frag_append_1_char): Refer to frchain_now->frch_obstack instead of + frags variable. + (frag_new): Ditto. Verify that frch_last and frag_now match on + entry and exit, and that old frag_now has non-zero type. Replace + "know" uses with "assert". Use frag_alloc instead of mucking with + obstack alignment. + * frags.h (frags): Declaration deleted. + * subsegs.h (struct frchain): Add new field frch_frag_now. + * subsegs.c (frchains, dummy_frag, absolute_frchain): New static + variables. + (subsegs_begin): Initialize frchains obstack. Under gcc, don't + give it any stricter alignment than frchainS structures need. Do + not initialize frags obstack. Set frag_now to point to + dummy_obstack. Initialize absolute_frchain. + (subseg_set_rest): Save and restore frag_now in frch_frag_now + field of frchainS. Don't create new frags on section switch, and + use frag_alloc when creating a new frag chain. For absolute + section, set frchain_now to absolute_frchain. Verify that + frch_last and frag_now match on entry and exit. Initialize + per-chain obstack, and under gcc, set required alignment to that + needed by fragS structure. + + * write.c (chain_frchains_together_1): Verify fr_type is nonzero. + + * stabs.c (get_stab_string_offset): Only copy input string if a + fresh copy is needed, not if the section already exists. + (s_stab_generic): Cache stab section name to bypass lookups, since + usually it will match. Could be made faster still by changing the + memory allocation rules. + (s_xstab): Cache section name to bypass repeated string + allocation. + + * frags.c (frag_new): Deleted register declarations. + + * listing.c (frag_now): Don't declare. + + * as.c (chunksize): New variable. + (debug_memory): New variable. + (main): If debug_memory is set, reduce chunksize and + _bfd_chunksize. + * as.h (chunksize): Declare it. + * read.c (read_begin): Use it. + + * config/tc-alpha.c (md_shortopts): Include 'g'. + (md_parse_option): Ignore it. + + * Makefile.in (distclean): Remove Makefile and config.status from + testsuite directory. + (clean-here): Don't delete testsuite. Instead, delete only the + files within it that would be generated by running tests. + + * config/tc-hppa.c (hppa_elf_mark_end_of_function): Call + frag_now_fix instead of accessing obstack info directly. + * config/tc-arm.c (s_ltorg): Ditto. + (md_assemble): Ditto. + + * config/tc-i386.c (md_assemble): Call frag_grow instead of + obstack_room. + +Wed Oct 18 12:22:59 1995 Ken Raeburn + + * stabs.c (aout_process_stab): Insert debug symbol into symbol + chain after parsing value expression, if any, to avoid separating + continued .stabs lines. + +Mon Oct 16 10:56:41 1995 Ian Lance Taylor + + * config/tc-mips.c (mips_elf_pseudo_table): Remove. + (mips_pop_insert): Don't call pop_insert on mips_elf_pseudo_table. + +Mon Oct 16 07:07:37 1995 Michael Meissner + + * config/tc-ppc.c (md_begin): Use new flags PPC_OPCODE_COMMON for + -mcom support and PPC_OPCODE_ANY for -many. + (md_parse_option): Ditto. + (ppc_arch): Ditto. + (md_begin): For duplicate instructions, print all duplicates + before aborting. + +Sun Oct 15 22:06:14 1995 Michael Meissner + + * config/tc-ppc.c (md_parse_option): Support for -mcom to turn on + common mode operation. + (md_show_usage): Add -mcom to usage message. + +Fri Oct 13 13:32:45 1995 steve chamberlain + + * expr.c (op_rank): Add O_symbol_rva. + * expr.h (operatorT): Add O_symbol_rva. + * read.c (cons_worker): Set O_symbol_rva when necessary. + * write.c (fix_new_exp): Understand O_symbol_rva. + +Tue Oct 10 11:34:14 1995 Ian Lance Taylor + + * config/tc-mips.c: Correct s_cons arguments. From Michael + Joosten . + +Mon Oct 9 19:59:53 1995 Ian Lance Taylor + + * config/tc-ppc.c (ppc_macro): Make count unsigned. + (ppc_biei): Set segment to now_seg and value to coff_n_line_nos. + (ppc_frob_symbol): Handle C_BINCL and C_EINCL symbols by setting + the fix_line field. + * config/obj-coff.c (coff_n_line_nos): Rename from n_line_nos, and + make non-static. Change all users. + * config/obj-coff.h (coff_n_line_nos): Declare. + +Fri Oct 6 16:24:27 1995 Ken Raeburn + + Mon Sep 25 22:49:32 1995 Andreas Schwab + + * configure.in (AC_ARG_WITH(bfd-assembler)): Fix help message. + + * config/obj-elf.c (obj_elf_common): Convert specified byte + alignment to power of two. Set size of local bss symbol. + + * config/tc-m68k.c (tc_gen_reloc): Fix typo in variable name. + +Fri Oct 6 15:22:25 1995 Ian Lance Taylor + + * sb.c, macro.c: Decide whether to include or + just as as.h does. + +Fri Oct 6 09:55:33 1995 Doug Evans + + * Makefile.in (site.exp): Fix setting of $srcdir. + + * config/tc-arm.c (md_atof): Fix little-endian output. + * config/tc-arm.h (ARM_BI_ENDIAN): Move definition so defined for + all coff targets. + +Thu Oct 5 20:17:30 1995 Ken Raeburn + + * doc/as.texinfo: Split out the NS32k family documentation, + despite its being commented out for now. + * doc/c-ns32k.texi: New file. + + * sb.c, macro.c: Include string.h. + + * Makefile.in (comparison): Only check *.o; we don't care if + timestamps inserted by the native linker differ. + + * config/tc-alpha.c (alpha_align): Only fill with a no-op pattern + if alignment stricter than 4 bytes is requested; in that case, + align to a 4-byte boundary first. + + Thu Sep 28 19:35:27 1995 Pat Rankin + + * config/obj-vms.c (VMS_RSYM_Parse): eliminate "might be used + uninitialized" warning for `Max_Source_Offset'. + +Wed Oct 4 16:17:02 1995 Kim Knuttila + + * config/tc-ppc.c (parse_toc_entry): New function to parse [toc] + qualifiers and detect errors if present. + (md_assemble): Add call to parse_toc_entry. Also added some support + for the [tocv] qualifier. + (ppc_pe_tocd): New function to support data in the toc section. + +Wed Oct 4 14:03:39 1995 Ian Lance Taylor + + * config/tc-ppc.c (ppc_frob_symbol): Don't create an aux entry for + an absolute symbol. + +Tue Oct 3 12:18:19 1995 Ian Lance Taylor + + * config/tc-m68k.c (isword): Accept all values from -65536 to + +65535, so ~VAL will not be rejected. + + * cond.c (s_endif): Call demand_empty_rest_of_line. In MRI mode, + skip characters after the pseudo-op. + (s_else): Likewise. + * read.c (get_line_sb): Don't look past buffer_limit. + (s_include): In MRI mode, skip characters after the file name. + +Mon Oct 2 16:15:27 1995 Ian Lance Taylor + + * config/m68k-parse.y (m68k_reg_parse): In MRI mode, permit + periods in register names. + +For older changes see ChangeLog.1. diff --git a/gnu/usr.bin/binutils/gas/ChangeLog.1 b/gnu/usr.bin/binutils/gas/ChangeLog.1 new file mode 100644 index 00000000000..86c6d18d01b --- /dev/null +++ b/gnu/usr.bin/binutils/gas/ChangeLog.1 @@ -0,0 +1,12409 @@ +Sat Sep 30 23:03:31 1995 Jeff Law (law@hurl.cygnus.com) + + * config/tc-hppa.c (hppa_fix_adjustable): DP relative relocs + are not adjustable in SOM to avoid confusing the optimizing + linker. + +Fri Sep 29 15:18:08 1995 Ian Lance Taylor + + Add some support for i960 MRI compatibility mode. + * config/tc-i960.c (md_pseudo_table): Add endian. + (get_args): Don't discard a space between alphanumeric characters. + (get_cdisp): Change text_section to now_seg. + (s_endian): New static function. + * config/tc-i960.h (MRI_MODE_NEEDS_PSEUDO_DOT): Define. + * expr.h (operatorT): Add O_logical_not, O_logical_and, and + O_logical_or. + * expr.c (operand): Treat '!' as logical not operator. If + TC_I960, in MRI mode permit `sizeof secname' and `startof + secname'. + (op_rank): Bump values by 2 to make room for && and ||. Add + entries for !, &&, and ||. + (expr_begin): Only do MRI changes if TC_M68K. + (operator): Recognize || and &&. + (expr): Handle new operatorT values. + * symbols.c (resolve_symbol_value): Handle new operatorT values. + (print_expr_1): Likewise. + * read.c (potable): Add debug, err, irep, irepc, print, purgem, + and rep. + (read_a_source_file): Handle MRI_MODE_NEEDS_PSEUDO_DOT. + (mri_comment_field): Only handle weird comments if TC_M68K. + (s_err): New function. + (s_org): Only punt in MRI mode if TC_M68K. + (s_mri_sect): Write TC_I960 version. + (s_print, s_purgem): New functions. + * read.h (s_err, s_print, s_purgem): Declare. + * cond.c (s_ifeqs): Implement. + (ignore_input): Handle MRI_MODE_NEEDS_PSEUDO_DOT. + * macro.c (macro_strip_at): New static variable. + (macro_init): Add strip_at parameter. + (do_formals): If macro_strip_at, change NARG to $NARG. + (define_macro): Skip a comma after the macro name. + (get_apost_token): Skip character if macro_strip_at, even if + macro_mri. + (macro_expand_body): If macro_strip_at, don't recognize parameters + in strings unless they are preceded by an '@'. If macro_strip_at, + pass '@' as strip character to sub_actual. If macro_strip_at, + strip '@' characters. + (macro_expand): If macro_strip_at, change NARG to $NARG. + (delete_macro): New function. + (expand_irp): Skip leading and trailing '"' characters if irpc. + * macro.h (macro_init): Mention new strip_at parameter. + (delete_macro): Declare. + * as.c (main): If TC_I960, pass flag_mri to macro_init as + strip_at; otherwise, pass 0. + * gasp.c (process_pseudo_op): Pass 0 to macro_init as strip_at. + (main): Likewise. + * doc/as.texinfo: Document i960 MRI mode. + + * as.c (show_usage): Mention --defsym. + +Thu Sep 28 19:25:04 1995 Stan Shebs + + * mpw-config.in: Translate "powerpc" into "ppc", remove gen of + VERSION, move gen of "conf" here from makefile. + * mpw-make.sed: New file, sed commands to translate Unix makefile + into MPW syntax. + * mpw-make.in: Remove. + * mac-as.r: New file, Mac resource file. + * as.h (inline): Don't decide about defining if __MWERKS__, + remove redundant conditional and definition. + + * stabs.c (s_stab_generic): Fix syntax for OBJ_PROCESS_STAB. + +Thu Sep 28 15:43:15 1995 Kim Knuttila + + * config/tc-ppc.c (md_apply_fix3): Removed some TE_PE specific + manipulations, since I can't prove they're needed. + (md_begin): Removed init_regtable, insert_reg, and the call points. + (register_name): New function. Parses a register name, if appropriate. + (md_assemble): Added call to register_name to handle symbolic names. + (ppc_pe_section): Removed all duplicate IMAGE defines, and include + coff/pe.h instead. + +Thu Sep 28 12:09:19 1995 Ian Lance Taylor + + * config/tc-ppc.h (tc_fix_adjustable): Define. + (ppc_pe_fix_adjustable): Declare. + * config/tc-ppc.c (ppc_pe_fix_adjustable): New function. + +Thu Sep 28 01:11:58 1995 Doug Evans + + * config/tc-arm.h (TARGET_FORMAT): Define for arm-coff. + +Wed Sep 27 12:53:58 1995 Ian Lance Taylor + + * symbols.c (S_IS_LOCAL): All symbols in reg_section are local. + + * config/tc-ppc.h (OBJ_XCOFF): Define if OBJ_COFF and not TE_PE. + Change OBJ_COFF checks to check OBJ_XCOFF instead. + (TARGET_FORMAT): Fully parenthesize. + (LEX_QM): Define if TE_PE. + * config/tc-ppc.c: Replace OBJ_COFF by OBJ_XCOFF throughout. + Remove checks of TE_PE within #ifdef OBJ_XCOFF sections. + (init_regtable): Make i unsigned. + (ppc_set_current_section): Rename from setCurrentSection. Change + all callers. + (ppc_arch): Return after as_fatal to avoid gcc warning. + (md_assemble): Only declare reloc if OBJ_ELF. Add default to + switch on fixups[i].reloc to avoid gcc warning. + (IMAGE_SGN_LNK_OTHER): Fix nested comment. + (ppc_pe_function): Don't call ppc_canonicalize_symbol_name. + (ppc_frob_symbol): Remove TE_PE section checks. + (md_estimate_size_before_relax): Return after abort to avoid gcc + warning. + (md_apply_fix3): Add BFD_RELOC_16_GOT_PCREL to switch. + * read.c (LEX_QM): Define as 0 if not defined. + (lex_type): Use LEX_QM for '?'. + + * configure.in: No need to check whether ${cpu_type} is powerpc; + it never will be. + * configure: Rebuild. + +Wed Sep 27 11:33:38 1995 Michael Meissner + + * config/tc-ppc.c (md_apply_fix3): Remove Sep 26 changes to this + function, keeping other Sep. 26 changes. + +Wed Sep 27 10:29:13 1995 Kim Knuttila + + * configure (emulations): Added support for ppcle-*-[pe|winnt] + (target_frag): Removed an extraneous PPC definition. + * configure.in (emulations): Same + * config/tc-ppc.h: + * config/tc-ppc.c (md_pseudo_table): Base support for new or altered + pseudo ops - There will be more. + (pre_defined_registers): Predefined reg table to name registers, etc + (md_begin): Setup reg table initialization + (md_assemble): Initial [toc]x(rtoc) support + (ppc_frob_label): Removed some xcoff specific processing from TE_PE + (ppc_frob_symbol): Removed some xcoff specific processing from TE_PE + Added support for more predefined sections + (ppc_frob_section): Removed some xcoff specific processing from TE_PE + (ppc_fix_adjustable): Removed from TE_PE mainline + (md_apply_fix3): For TE_PE toc entries, we don't need to mess + with fx_addnumber. Removed for the time being. + (lots): Put back missing assignments to ppc_current_csect. + +Tue Sep 26 14:57:59 1995 Michael Meissner + + * config/tc-ppc.c (ppc_elf_suffix): Support all of the V.4 + relocations. + (ppc_elf_cons): Remove restriction that @ suffixes must be done + with .long. Add error if relocation does not fit in the number of + bytes provided. + (md_assemble): For absolute branches, map PC relative relocations + back into an equivalent absolute relocation. + (md_pcrel_from): If TC_FORCE_RELOCATION is true, relocation offset + is 0, not segment start. + (md_apply_fix3): Don't bother writing addend into the instruction, + since it is ignored, given that we use RELA relocations for ELF. + + * config/tc-ppc.h (TC_FORCE_RELOCATION): Define to force all + branch prediction relocations to always be emitted. + +Mon Sep 25 16:08:43 1995 Michael Meissner + + * config/tc-ppc.c (ppc_elf_suffix): Lower case reloc before + testing. + (md_assemble): Be more robust in terms of relocations. + (md_apply_fix3): Allow 14 bit relocs to be emitted for external + symbols in addition to 26 bit relocs. Properly insert 26/14 bit + reloc value fields into the instruction stream. + +Mon Sep 25 00:23:16 1995 Ian Lance Taylor + + * config/tc-arm.c (md_atof): Output little endian constants in + little endian mode. + + * config/obj-coff.c (obj_coff_section): Pass &type, not type, + s_mri_sect. + + * configure.in: Fix typo: fmt-elf to fmt=elf. + +Fri Sep 22 16:34:46 1995 Michael Meissner + + * config/tc-ppc.c (ppc_elf_suffix): Rewrite to use a table of + strings and relocations they represent. Add @br{,n}taken for + branch taken/not taken support. + (md_apply_fix3): Add BFD_RELOC_PPC_B16_BR{,N}TAKEN support. + +Thu Sep 21 21:10:17 1995 Michael Meissner + + * config/tc-ppc.c (md_parse_option): -mrelocatable-lib now only + sets EF_PPC_RELOCATABLE_LIB and not also EF_PPC_RELOCATABLE. + +Thu Sep 21 16:30:56 1995 Ian Lance Taylor + + * subsegs.c (subseg_set): Permit SEG_ABSOLUTE in know expression. + * expr.c (expr): Account for new operatorT values in know + expression. + + * write.c (fixup_segment): Clear fixp->fx_subsy if the relocation + is fully resolved. + +Thu Sep 21 14:11:49 1995 Michael Meissner + + * config/tc-ppc.c (ppc_flags): New variable to hold the flag bits + to set in the ELF header. + (md_parse_option): Add support for -mrelocatable-lib. Make both + -mrelocatable and -mrelocatable-lib set ppc_flags. + (md_begin): Set ELF flags with ppc_flags. + +Wed Sep 20 13:01:52 1995 Ian Lance Taylor + + * Makefile.in (maintainer-clean): New target, synonym for + realclean. Add GNU standard maintainer-clean echos. + * doc/Makefile.in (maintainer-clean): New target, synonym for + realclean. + +Tue Sep 19 11:31:31 1995 Ian Lance Taylor + + * config/tc-m68k.c (m68k_ip): Reject immediate operands for '%'. + + * config/tc-m68k.c (m68k_ip): Reject immediate operands for '|'. + Replace 'P' with '0', '1', and '2'. + + * config/tc-m68k.c (parse_mri_control_operand): Change leftstop + and rightstop to not be const. + (parse_mri_control_expression): Likewise. + (build_mri_control_operand): Likewise. Use m68k_ip_op to examine + the operand, not m68k_reg_parse. + (s_mri_if): In MRI mode, stop at the first '*'. + (s_mri_while): Likewise. + (s_mri_else): In MRI mode, ignore trailing characters. + (s_mri_endi, s_mri_break, s_mri_next, s_mri_for): Likewise. + (s_mri_endf, s_mri_repeat, s_mri_until, s_mri_endw): Likewise. + * config/m68k-parse.y: Revert yesterday's change. + * config/m68k-parse.h: Revert yesterday's change. + +Mon Sep 18 15:22:28 1995 Ian Lance Taylor + + * config/tc-m68k.c (parse_mri_control_operand): Change leftstart + and rightstart to not be const. + (parse_mri_control_expression): Likewise. + (build_mri_control_operand): Likewise. If the left side of the + comparison is a register, and the right side is not, swap the two + sides. + * config/m68k-parse.y (m68k_reg_parse): Make globally visible. + * config/m68k-parse.h (m68k_reg_parse): Declare. + + * read.c (mri_comment_field): New function. + (mri_comment_end): New function. + (s_align_bytes): Use mri_comment_field. + (s_align_ptwo, s_comm, s_mri_common, s_fail, s_globl): Likewise. + (s_float_space, s_struct): Likewise. + (s_space): Use mri_comment_field rather than doing it by hand. + (cons_worker, equals): Likewise. + (s_end): Ignore comments starting with '*' or '!'. + * read.h (mri_comment_field): Declare. + (mri_comment_end): Declare. + * cond.c (s_if): Use mri_comment_field. + * config/tc-m68k.c (s_chip, s_reg): Likewise. + + * write.c (fixup_segment): Handle ABS-sym in -sym case rather than + sym-sym case. + * config/obj-coff.c (fixup_segment): Likewise. Permit negative + symbols if TC_M68K. + * config/tc-m68k.c (tc_coff_fix2rtype): If fx_tcbit is set, return + R_RELLONG_NEG. + (tc_gen_reloc): If fx_tcbit is set, abort. + (md_apply_fix_2): For a negative reloc, move fx_subsy to fx_addsy, + and set fx_tcbit. + + * config/tc-m68k.c (s_reg): Ignore comment field in MRI mode. + +Mon Sep 18 14:44:04 1995 Arne H. Juul + + * configure.in (mips-dec-netbsd*): New target. + * configure: Rebuild. + +Sun Sep 17 22:17:43 1995 Ian Lance Taylor + + * configure.in: Set endian to little for mips-*-ultrix*. + * configure: Rebuild. + +Fri Sep 15 13:16:55 1995 Ian Lance Taylor + + * expr.c (current_location): New static function. Handle magic + symbol `.'; in absolute section, return a constant. + (operand): Call current_location for '.' and '$', instead of doing + it inline. In MRI mode, call current_location for '*'. + +Fri Sep 15 21:39:29 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-m68k.c: Change some "CONST" references to "const". + +Fri Sep 15 17:27:41 1995 Ken Raeburn + + Tue Sep 12 17:08:23 1995 Pat Rankin + + * config/obj-vms.c (VMS_stab_parse): simplify first loop; + use S_GET_NAME/modify/S_SET_NAME sequence instead of abusing + S_GET_NAME when updating symbol name. + (local_symbols_DST): first prefix/postfix typo from July 21st. + [plus comment reformatting --kr] + +Wed Sep 13 12:33:03 1995 Ian Lance Taylor + + * Makefile.in (EXPECT): New variable. + (CHECKFLAGS): Remove. + (site.exp): New target. + (check): Rewrite to invoke runtest directly, rather than recurring + down into testsuite. + (clean-here): Remove testsuite directory. + (clean, distclean): Don't recur into testsuite. + * configure.in: Don't call AC_CONFIG_SUBDIRS(testsuite). + * configure: Rebuild. + + * write.c (relax_and_size_seg): Change to the segment we are + relaxing, in case md_convert_frag, called by cvt_frag_to_fill, + wants to call fix_new. + * config/tc-m68k.c (m68k_ip): Permit PC relative code if the + segment of the symbol is the current segment, not just in + text_section. + (md_convert_frag_1): Don't call subseg_change. + (md_estimate_size_before_relax): Likewise. + +Tue Sep 12 10:36:40 1995 Doug Evans + + * config/tc-arm.c (md_atof): Fix debugging printf, and leave it + out by default. + +Mon Sep 11 11:39:11 1995 Ian Lance Taylor + + * doc/configure.in: Remove unused file. + + * app.c (do_scrub_chars): Grab all available spaces at start of + line before preserving a single space. Remove state == 0 test + which will never succeed. + * macro.c (macro_expand_body): Delete local variables from the + formal hash table. + (macro_expand): In MRI mode, stop when whitespace is seen in the + argument list. + + * sb.c: Include "libiberty.h". + * macro.c: Likewise. Also include if it exists. + +Fri Sep 8 00:27:46 1995 Ian Lance Taylor + + * app.c (do_scrub_chars): In MRI mode, keep a space before a + possible comment character. + * config/tc-m68k.c (m68k_ip): In MRI mode, ignore anything after + an instruction which takes no operands. + + * Makefile.in (install): Don't install gasp in $(tooldir). + + * config/tc-mips.c (macro): Handle a non zero base register for + M_U{L,S}{D,W,H}_A. + + * gasp.c (show_usage): Put program_name argument in first fprintf, + not second. + +Thu Sep 7 12:33:58 1995 Ian Lance Taylor + + * expr.c (operand): Handle 08 and 09 in MRI mode. + * macro.c (ISSEP): Remove duplicated `"' character. + (get_any_string): Copy some characters for which ISSEP is true: + ';', '>', '(', ')'. Otherwise we can get in an infinite loop. + * read.c (s_space): In MRI mode, the expressions stop at the first + unquoted space. + (cons_worker): In MRI mode, restore the terminating character at + the end of the function. + + * read.c (cons_worker): Don't use #elif; old compilers don't + support it. + +Wed Sep 6 21:13:06 1995 Ian Lance Taylor + + * app.c (do_scrub_chars): In MRI mode, silently end quoted strings + at newline characters. In MRI mode, always keep spaces in the + operands field. In MRI mode, treat a line comment character as a + regular comment character following a space. + * cond.c (ignore_input): Use strncasecmp rather than strncmp when + looking for special pseudo-ops. + * read.c (cons_worker): In MRI mode, the expressions stop at the + first unquoted space. + (equals): Likewise. + +Wed Sep 6 15:03:53 1995 Jim Wilson + + * config/tc-sh.c (get_specific): Delete arg_to_test. + (md_assemble): Increase operand array from 2 to 3. + +Tue Sep 5 16:47:36 1995 Stan Shebs + + * config/tc-mips.c: Remove CYGNUS LOCAL comments. + (md_begin): Use 0/1 instead of TRUE/FALSE. + (md_show_usage): Break up long format string for the benefit + of lame compilers. + * config/tc-m68k.c (md_show_usage): Ditto. + * gasp.c (show_usage): Ditto. + * macro.c (check_macro): Cast result of hash_find. + +Tue Sep 5 14:46:38 1995 Ken Raeburn + + * configure.in: When testing for a free() declaration in system + header files, cast the address to a function pointer, not to an + integer. + + * write.c (fix_new_internal): Call TC_INIT_FIX_DATA if TC_FIX_TYPE + is defined. Don't initialize fx_bsr. Verify that fx_size field + is wide enough to hold stored value. + * write.h (struct fix): Change tc_fix_data to type TC_FIX_TYPE if + that is defined, otherwise omit it. Delete fx_bsr. Change + fx_size to unsigned char. + * config/tc-i960.h (TC_FIX_TYPE, fx_bsr, TC_INIT_FIX_DATA): New + macros. + * config/tc-ns32k.h (TC_FIX_TYPE, fx_bsr, TC_INIT_FIX_DATA): New + macros. + * config/tc-hppa.h (TC_FIX_TYPE): Define as PTR. + + * config/tc-i860.c (md_apply_fix): Delete code for checking + fx_im_disp, and for handling non-zero values, since it never gets + set after being initialized to zero. + + * write.h (struct fix): Make fx_im_disp always 2 bits, since the + only tc-* files actually using it need that much. + + NS32K changes from Ian Dall: + * configure.in: Treat ns32k-pc532-ux* like ns32k-pc532-mach*, and + ns32k-pc532-lites* like ns32k-pc532-netbsd*. + * config/tc-ns32k.h (LOCAL_LABELS_FB): Define to 1. + +Fri Sep 1 17:02:15 1995 steve chamberlain + + * write.c (fixup_segment): Get TC_FORCE_RELOCATION up the + right way! + +Fri Sep 1 08:20:19 1995 James G. Smith + + * config/tc-mips.c (md_parse_option, md_begin, md_show_usage): + Add support for "-mcpu=vr4300" as processor identifier. + +Thu Aug 31 16:41:06 1995 steve chamberlain + + * write.c (fixup_segment): Remove change of 29th. + * config/tc-{i386,arm}.h (TC_FORCE_RELOCATION): Keep RVA relocs. + +Tue Aug 29 19:42:58 1995 Andreas Schwab + + * config/tc-m68k.c (m68k_ip) [case POST/PRE/BASE]: Fix typo when + looking at outer displacement. Don't set the postindex bit if the + index suppress bit is set (for memory indirect addressing mode). + +Thu Aug 31 06:49:37 1995 Doug Evans + + * config/tc-arm.c (tc_gen_reloc): Delete duplicated code. + +Wed Aug 30 23:51:57 1995 Ian Lance Taylor + + * app.c (do_scrub_chars): Free saved_input when the from buffer + exactly fills the to buffer. + +Wed Aug 30 13:46:39 1995 Doug Evans + + * config/tc-sparc.c (parse_keyword_arg, parse_const_expr_arg): New fns. + (sparc_ip): Call them for asi, membar, and prefetch parsing. + +Tue Aug 29 15:45:37 1995 Doug Evans + + * config/tc-sparc.c (membar_masks): Deleted. + (sparc_ip): Clean up ASI and membar support. + +Tue Aug 29 13:20:27 1995 steve chamberlain + + * read.c (potable): Rva is new entry. + (cons_worker): New, split from cons. Handles rva. + (cons, s_rva): Call cons_worker. + * read.h (s_rva): New declaration. + * write.c (fixup_segment): Don't throw away rva relocs. + * config/tc-arm.c (md_apply_fix, tc_gen_reloc): Handle RVA. + * config/tc-i386.c (tc_coff_fix2type): Handle RVA. + * config/tc-i386.h (TC_COUNT_RELOC): Remember RVAs. + (TC_RVA_RELOC): New definition. + +Sun Aug 27 17:41:05 1995 Doug Evans + + * config/tc-arm.c (do_swi): Allow optional leading '#'. + +Sat Aug 26 17:24:20 1995 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-m68k.c (comment_chars): If TE_DELTA is defined, + include '#'. + * config/tc-m68k.h (NO_PSEUDO_DOT): Define if TE_DELTA is + defined. + + * config/te-delta.h: Include obj-format.h. + * config/te-sco386.h: Likewise. + * config/te-sysv32.h: Likewise. + + * app.c (scrub_file): Remove. + (scrub_from_file, scrub_to_file): Remove. + (scrub_string, scrub_last_string): Remove. + (scrub_from_string, scrub_to_string): Remove. + (saved_input, saved_input_len): New static variables. + (struct app_saved): Remove scrub_string, scrub_last_string, and + scrub_file fields. Add saved_input and saved_input_len fields. + (app_push): Adjust saved fields for changes in struct app_save. + Initialize state and saved_input. + (app_pop): Adjust saved fields for changes in struct app_save. + (do_scrub_chars): Rename from do_scrub_next_char and rewrite to + process a buffer at a time rather than a character at a time. + (main, as_warn): Remove obsolete testing code. + * as.h (do_scrub_next_char): Don't declare. + (do_scrub_chars): Declare. + (scrub_from_file, scrub_from_string): Don't declare. + (scrub_to_file, scrub_to_string): Don't declare. + * input-file.c (input_file_get): New static function. + (input_file_give_next_buffer): Call do_scrub_chars rather than + do_scrub_next_char. + * read.c (scrub_string, scrub_string_end): New static variables. + (scrub_from_string): New static function. + (read_a_source_file): Call do_scrub_chars rather than + do_scrub_next_char. + +Thu Aug 24 18:50:19 1995 Ian Lance Taylor (ian@cygnus.com) + + * gasp.c (as_abort): New function. + * sb.c (sb_build): Revert yesterday's patch. + + * Makefile.in (gasp.new): Depend upon ../libiberty/libiberty.a. + Just link against libiberty, not against $(LIBS). + +Wed Aug 23 15:18:20 1995 Ian Lance Taylor (ian@cygnus.com) + + * sb.c (sb_build): Undefine abort before calling it, since gasp + does not provide as_abort. + +Wed Aug 23 10:40:41 1995 Michael Meissner + + * config/tc-ppc.c (set_target_endian): New static to say whether + we've initialized target_big_endian or not. + (md_parse_option): Set set_target_endian if we set the variable + target_big_endian. + (md_begin): Only set target_big_endian if !set_target_endian. + +Tue Aug 22 03:00:33 1995 Ken Raeburn + + Sat Aug 19 18:08:16 1995 Pat Rankin + + * config/obj-vms.h (DST_S_C_SRC_SETREC_W, DST_S_C_SRC_DEFLINES_B): + New macros. + * config/obj-vms.c (VMS_TBT_Line_PC_Correlation, + VMS_TBT_Source_Lines): Make traceback info be robust enough to + handle huge source files. + (VMS_TBT_Source_File): Reorganize the native- vs cross-assembly + support so that actual object file output is clearer. + (VMS_TBT_Source_File: Fab, Nam, Date_Xab, File_Header_Xab): + Replace static variables with automatic ones. + + Sat Aug 12 20:18:15 1995 Pat Rankin + + * config/obj-vms.c (Module_Name): new file scope variable. + (VMS_TBT_Module_Begin): use it instead of local variable. + (Write_VMS_MHD_Records): ditto; assign its value here. + (Write_VMS_EOM_Record): second argument has type valueT. + (VMS_Initialized_Data_Size): simplify search loop; return + type is offsetT; second argument is unsigned. + + Sat Jun 17 19:05:25 1995 Pat Rankin (rankin@eql.caltech.edu) + + * messages.c (as_perror): Use xstrerror instead of strerror. + +Mon Aug 21 13:57:20 1995 Ian Lance Taylor + + * as.c (parse_args): Accept --defsym SYM=VALUE. + * doc/as.texinfo, doc/as.1: Document --defsym. + + * read.c (read_a_source_file): In MRI mode, don't end the + statement inside a quotation. + (s_space): Don't warn about a zero repeat count in MRI mode. + * config/tc-m68k.c (crack_operand): In MRI mode, don't count + parentheses inside quotes. + (md_assemble): In MRI mode, anything after the operands field is a + comment. + (parse_mri_control_operand): Adjust start and stop to remove + spaces. + (s_mri_for): Likewise. + + * cond.c (s_ifdef): Restore the character after the symbol name, + in case it is a newline. + (s_if): If ignoring the current tree, don't try to parse the + expression. + + * app.c (do_scrub_next_char): If LEX_IS_STRINGQUOTE or + LEX_IS_ONECHAR_QUOTE is seen in state 10, preserve one space. + + * doc/as.texinfo: Document irp, irpc, macro, and rept. MRI mode + now supports macros, ifc, ifnc, irp, irpc, rept, and endr, without + using gasp. + + Add support for macros. + * as.c: Include sb.h and macro.h. + (max_macro_next): New global variable. + (main): Call macro_init. + (macro_expr): New static function. + * as.h (max_macro_nest): Declare. + * read.c (line_label): Rename from mri_line_label. Change all + uses. + (potable): Add exitm, irp, irpc, macro, mexit, rept. + (read_a_source_file): Always clear line_label at the start of a + line, not just when flag_mri or LABELS_WITHOUT_COLONS. Fix + MRI/LABELS_WITHOUT_COLONS handling. In MRI mode, permit label: + equ val. Set line_label when calling colon. In MRI mode, a + leading '.' does not imply a pseudo-op. Check for macro expansion + before calling md_assemble. + (s_irp): New function. + (get_line_sb): New static function. + (s_macro): New function. + (s_mexit): New function. + (s_rept): New function. + * read.h (line_label): Rename from mri_line_label. + (s_irp, s_rept): Declare. + (s_macro, s_mexit): Declare. + * input-scrub.c: Include sb.h. + (sb_index, from_sb): New static variables. + (macro_nest): New static variable. + (struct input_save): Add sb_index and from_sb fields. Change + next_saved_file field to be struct input_save *. + (next_saved_file): Changed to be struct input_save *. + (input_scrub_push): Change to return type struct input_save *. + Save sb_index and from_sb. + (input_scrub_pop): Change parameter type to struct input_save *. + Restore sb_index and from_sb. + (input_scrub_include_sb): New function. + (input_scrub_next_buffer): Handle reading from from_sb. + (bump_line_counters): Only increment lines if not using from_sb. + * config/tc-m68k.c (opt_table): Add nest. + (opt_nest): New static function. + * gasp.c: Include sb.h and macro.h. Move all sb related functions + and definitions to sb.h and sb.c. Move all macro related + functions and definitions to macro.h and macro.c. + * sb.h, sb.c: New files, extracted from gasp.c. + * macro.h, macro.c: Likewise. + * Makefile.in (OBJS): Add sb.o and macro.o + (GASPOBJS): Define. + (gasp.new): Depend upon $(GASPOBJS). Use $(GASPOBJS) to link. + (TARG_CPU_DEP_m68k): Depend upon subsegs.h. + (gasp.o): Depend upon sb.h and macro.h. + (sb.o): New target. + (macro.o): New target. + (as.o): Depend upon sb.h and macro.h. + (input-scrub.o): Depend upon sb.h. + (read.o): Depend upon sb.h and macro.h. + + * cond.c (get_mri_string): New static function. + (s_ifc): New function. + * read.c (potable): Add ifc and ifnc. + * read.h (s_ifc): Declare. + + * app.c (do_scrub_begin): In MRI mode, set lex of ' to + LEX_IS_STRINGQUOTE. + +Mon Aug 21 13:41:33 1995 Michael Meissner + + * config/tc-ppc.c (md_assemble): Allow @HA, @L, and @H suffixes on + constant expressions. + +Sun Aug 20 15:54:37 1995 Jim Wilson + + * config/tc-arm.c (md_reloc_size): Add const to declaration. + +Fri Aug 18 10:58:09 1995 Ian Lance Taylor + + * read.c (s_include): In MRI mode, don't expect quotes around the + file name. + * listing.c (listing_title): Don't require the title to be quoted. + + * gasp.c (include_print_where_line): Always subtract 1 from + linecount before printing it. + (process_file): In MRI mode, lines beginning with '*' or '!' are + comments. + (do_reg): In MRI mode, don't require parentheses. + (do_include): In MRI mode, don't requires quotes. If the file can + not be found in the include path, try opening it in the current + directory. Print the file name correctly in the error message. + (chartype_init): In MRI mode, set FIRSTBIT for '.'. + (main): Set comment_char to ';' when entering MRI mode. + + * config/tc-m68k.c: Include subsegs.h. + (m68k_ip): Pass 64 rather than -1 to add_Fix in 'B' 'B' case. + (md_pcrel_from): If fx_pcrel_adjust is 64, use -1 instead. + + * config/tc-sparc.h (tc_fix_adjustable): For OBJ_AOUT case, adjust + BFD_RELOC_16 and BFD_RELOC_32 relocs. + +Wed Aug 16 14:48:44 1995 Ken Raeburn + + * as.h (alloca): Use void* declaration on HP/UX. + +Wed Aug 16 12:49:17 1995 Ian Lance Taylor + + * config/tc-sparc.c (tc_gen_reloc): If PIC, only change PCREL_S2 + to WPLT30 for an undefined or external symbol. Don't consider + PC10 or PC22 to be a PC relative reloc when choosing between + fx_addnumber and fx_offset. + + * config/tc-z8k.c (md_number_to_chars): Don't do it here, call + number_to_chars_bigendian. + * config/tc-z8k.h (TARGET_BYTES_BIG_ENDIAN): Define. + + * expr.c (operand): Add support for .startof. and .sizeof. by + using magic symbol names which the linker will recognize + specially. + * doc/as.texinfo: Take out note that .startof. and .sizeof. are + not supported. + +Tue Aug 15 15:08:49 1995 Ian Lance Taylor + + * config/tc-m68k.c (md_pseudo_table): Add MRI structured control + directives: if, if.b, if.w, if.l, else, else.s, else.l, endi, + break, break.s, break.l, next, next.s, next.l, for, for.b, for.w, + for.l, endf, repeat, until, until.b, until.w, until.l, while, + while.b, while.w, while.l, endw. + (enum mri_control_type): Define. + (struct mri_control_info): Define. + (mri_control_stack): New static variable. + (mri_control_index): New static variable. + (mri_control_label): New static function. + (push_mri_control, pop_mri_control): New static functions. + (parse_mri_condition): New static function. + (parse_mri_control_operand): New static function. + (swap_mri_condition, reverse_mri_condition): New static functions. + (build_mri_control_operand): New static function. + (parse_mri_control_expression): New static function. + (s_mri_if, s_mri_else, s_mri_endi): New static functions. + (s_mri_break, s_mri_next): New static functions. + (s_mri_for, s_mri_endf): New static functions. + (s_mri_repeat, s_mri_until): New static functions. + (s_mri_while, s_mri_endw): New static functions. + * gasp.c (mrikinfo): Remove IF. + * expr.c (get_symbol_end): Accept \001 as part of a name. + + * symbols.c (colon): Change parameter to const char *. + * symbols.h (colon): Update declaration. + +Mon Aug 14 20:51:56 1995 Ken Raeburn + + * write.c (write_contents): Always do it the BFD_FAST_SECTION_FILL + way. Reformat and reindent that code to GNU standards. + (BFD_FAST_SECTION_FILL): Don't define. + +Mon Aug 14 14:08:07 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_apply_fix): Don't try to apply BEGIN_BRTAB + or END_BRTAB fixups. + +Mon Aug 14 15:45:07 1995 Ian Lance Taylor + + * gasp.c (do_align, get_any_string): Mark as static. + (do_assigna, do_assignc, new_file): Likewise. + + * config/tc-m68k.c (s_reg): Rename local op to rop to avoid + confusion with macro op. + + * gasp.c (strip_comments): Comment out; it's not used. + (do_end): Add parameter. In MRI mode, print it out. + (do_irp): New static function. + (sub_actual): Change parameter m to formal_hash, changing type + from macro_entryh * to hash_table *. + (macro_expand_body): New static function, broken out of + macro_expand. + (macro_expand): Call macro_expand_body. + (K_*): Fully parenthesize. + (K_IRP, K_IRPC): Define. + (mrikinfo): Add IRP and IRPC. + (process_pseudo_op): In MRI mode, print out END pseudo-op. Pass + line to do_end. Handle K_IRP and K_IRPC. + + * config/tc-m68k.c (s_opt): Reset *input_line_pointer even if we + don't do anything with the option. + +Sun Aug 13 17:03:58 1995 Ian Lance Taylor + + * frags.c (frag_align): Handle absolute_section. + * write.c (record_alignment): Likewise. + + * config/tc-mips.c (macro_build): Skip insns with an inappropriate + ISA level. + +Sun Aug 13 00:35:02 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_pseudo_table): Add entries for + "begin_brtab" and "end_brtab" pseudo-ops. + (pa_brtab): New function. + (tc_gen_reloc, SOM version): Handle R_BEGIN_BRTAB and R_END_BRTAB. + (hppa_force_relocation): Force relocations for BRTAB fixups + when OBJ_SOM is defined. + +Fri Aug 11 20:34:05 1995 Ken Raeburn + + * Makefile.in (TE_OBJS): Add empty definition. + +Fri Aug 11 19:16:08 1995 Ian Lance Taylor + + * gasp.c (change_base): Don't treat ' specially in MRI mode. + (process_file): Don't warn about missing END in MRI mode. + (do_if): New static function. + (get_mri_string, do_ifc): New static functions. + (buffer_and_nest): Treat MRI mode like alternate syntax mode. + (do_aendr): Change error message in MRI mode. + (do_arepeat): Use REPT/ENDR in MRI mode. + (do_formals): In MRI mode, add special NARG formal. + (macro_expand): Various changes for MRI mode: permit a qualifier + on the macro name; set special NARG formal; permit unnamed + positional arguments; use && to concatenate named parameters; + permit \d to specify an unnamed parameter; permit named parameters + to not start with \; use == to see if a parameter exists. + (getstring): In MRI mode, allow <> to quote a string. + (K_IFEQ, K_IFNE, K_IFLT, K_IFLE, K_IFGE, K_IFGT): Define. + (K_IFC, K_IFNC): Define. + (struct keyword): Name structure used in kinfo array. + (mrikinfo): New static array. + (process_pseudo_op): Don't require leading '.' in MRI mode. + Handle new MRI pseudo-op definitions. + (add_keyword): New static function, broken out of process_init. + (process_init): Use add_keyword. In MRI mode, add mrikinfo table. + (long_options): Add "mri". + (show_usage): Mention -M/--mri. + (main): Call process_init after processing arguments. Handle -M. + * doc/gasp.texi: Document -M/--mri. + + * gasp.c: Include ansidecl.h. Make all local functions static. + Add prototypes for all static functions. + (mri): New global variable. + (sb_add_char): Change parameter c from char to int. + (sb_add_string): Make parameter s into a const pointer. + (sb_add_buffer): Likewise. + (checkconst): Change parameter op from char to int. + (exp_get_abs): Make parameter emsg into a const pointer. + (do_res): Change parameter type from char to int. + (buffer_and_nest): Make parameters from and to into const + pointers. + (do_sdata): Change parameter type from char to int. + (new_file): Make parameter name into a const pointer. + (do_define): Make parameter string into a const pointer. + + * config/tc-h8300.c (md_number_to_chars): Don't do it here, call + number_to_chars_bigendian. + * config/tc-h8300.h (TARGET_BYTES_BIG_ENDIAN): Define. + +Fri Aug 11 13:23:56 1995 Michael Meissner + + * write.h (struct fix): Add new field fx_no_overflow. + + * write.c (fixup_segment): If fx_no_overflow is non-zero, don't + complain if the addend is too large. + + * config/tc-ppc.c (md_assemble): Set fx_no_overflow if the half + word relocations BFD_RELOC_{LO16,HI16,HI16_S}. + +Thu Aug 10 20:56:38 1995 Ken Raeburn + + * read.c (s_mri_sect) [BFD_ASSEMBLER]: Fix typos in choosing and + setting section flags. + +Thu Aug 10 00:38:11 1995 Ian Lance Taylor + + * doc/as.texinfo: Add documentation for MRI compatibility mode. + * doc/as.1: Likewise. + + * config/tc-m68k.c (m68k_ip): When recognizing '#', use isbyte and + iword rather than expr8 and expr16. When recognizing 'M', use + issbyte rather than expr8. When recognizing 'Q' and 't', just + check for O_constant rather than using expr8. + * config/m68k-parse.h (expr8, expr16): Don't define. + * Makefile.in (m68k-parse.o): Depend upon m68k-parse.h, not + m68k-parse.y. + + * read.c (potable): Add spc, ttl, xcom, xref. + (s_mri_sect): New function. + * read.h (s_mri_sect): Declare. + * config/obj-coff.c (obj_coff_section) (both versions): In MRI + mode, call s_mri_sect. + (obj_pseudo_table): Add sect.s and section.s. Move sect outside + of ifndef BFD_ASSEMBLER. + * config/obj-elf.c (elf_pseudo_table): Add section.s, sect, + sect.s. + (obj_elf_section): In MRI mode, call s_mri_sect. + * config/tc-m68k.c (md_pseudo_table): Add restore, save. + (struct save_opts): Define. + (save_stack): New static variable. + (s_save, s_restore): New static functions. + + * read.c (s_set): Remove unused local ptr. + (hex_float): Check target_big_endian. + (equals): Remove unused local p. + + * config/tc-a29k.h (TARGET_BYTES_BIG_ENDIAN): Define. + * config/tc-h8500.h (TARGET_BYTES_BIG_ENDIAN): Define. + * config/tc-hppa.h (TARGET_BYTES_BIG_ENDIAN): Define. + * config/tc-i860.h (TARGET_BYTES_BIG_ENDIAN): Define. + * config/tc-m68k.h (TARGET_BYTES_BIG_ENDIAN): Define. + * config/tc-m88k.h (TARGET_BYTES_BIG_ENDIAN): Define. + * config/tc-tahoe.h (TARGET_BYTES_BIG_ENDIAN): Define. + * config/tc-sh.c (little): Set target_big_endian. + (md_begin): Likewise. + (md_parse_option): Likewise. + (build_relax): Check target_big_endian rather than shl. + (build_Mytes, md_atof): Likewise. + (md_convert_frag, md_apply_fix): Likewise. + (md_number_to_chars): Likewise. + +Wed Aug 9 10:51:48 1995 Ian Lance Taylor + + * config/tc-m68k.c (m68k_abspcadd): New static variable. + (m68k_quick): New static variable. + (m68k_rel32): New static variable. + (md_pseudo_table): Add opt and reg. + (m68k_ip): Permit absolute symbols in 'l'/'L' recognition. Check + m68k_quick in 'M' and 'Q' recognition. Check m68k_abspcadd in + DISP handling. Check m68k_rel32 in BASE/POST/PRE handling. + (md_begin): In MRI mode, initialize m68k_abspcadd and m68k_rel32. + In MRI mode, change unsized branch aliases to be variable sized. + (struct opt_action): Define. + (opt_table): Define. + (s_opt): New static function. + (skip_to_comma): New static function. + (opt_chip): New static function. + (opt_list): New static function. + (opt_list_symbols): New static function. + (s_reg): New static function. + * as.h (flag_keep_locals): Change from unsigned char to int. + (flag_no_warnings): Likewise. + + * read.c (mri_line_label): Make non-static. + (potable): Add nopage, page, plen. + (s_org): Error if in MRI mode. + * read.h (mri_line_label): Declare. + * listing.c (listing_nopage): New function. + * listing.h (listing_nopage): Declare. + + * symbols.c (symbol_begin): Set sy_frag of abs_symbol to + &zero_address_frag. + + * write.c (adjust_reloc_syms): Check that symbol is not NULL + before checking sy_mri_common. + (fixup_segment): Likewise. + * config/obj-coff.c (fixup_segment): Likewise. + + * read.c (abs_section_offset): New global variable. + (potable): Add offset, struct. + (do_org): New static function; handle changing the origin in the + absolute section. + (s_org): Use do_org. + (s_set): Likewise. + (equals): Likewise. + (s_space): In absolute_section, just increase abs_section_offset. + (s_struct): New function. + (emit_expr): Handle absolute_section specially. + * read.h (abs_section_offset): Declare. + (s_struct): Declare. + * frags.c (frag_more): Warn if in absolute_section. + (frag_now_fix): In absolute_section, return abs_section_offset. + * subsegs.c (subseg_change): If switching to absolute_section, + just set now_seg and now_subseg. + (subseg_set_rest): Special handling when switching to or from + absolute_section. + + * config/tc-m68k.c (m68k_float_copnum): New static variable. + (md_pseudo_table): Add fopt and mask2. + (m68k_ip): Use m68k_float_copnum, not COPNUM, when setting + coprocessor register to use. In case 'I' when checking operands, + correct coprocessor register numbers. In case 'I' when setting + operands, don't add 1. + (s_fopt): New static function. + * config/m68k-parse.h (COPNUM): Don't define. + + * read.c (potable): Add ifeq, ifge, ifgt, ifle, iflt, ifne. + Change if to pass O_ne to s_if. + (read_a_source_file): Don't define an label without a colon if + ignore_input returns true. + * cond.c (s_if): Treat argument as an operatorT describing how to + compare the argument against zero. + (ignore_input): Don't require an initial dot in MRI mode, or if + NO_PSEUDO_DOT is defined. + + * read.c (potable): Add dcb, dcb.b, dcb.d, dcb.l, dcb.s, dcb.w, + dcb.x, ds.d, ds.p, ds.s, ds.x, elsec, endc, fail, format, llen, + noformat. + (read_a_source_file): If pseudo-op handler is s_end, quit + immediately. + (s_end): New function. + (s_fail): New function. + (s_float_space): New function. + (hex_float): New static function. + (float_cons): Use hex_float. + * read.h (s_fail): Declare. + (s_float_space): Declare. + * cond.c (s_end): Remove. + * listing.c (listing_psize): Treat argument as indicating whether + a height is expected. + + * read.c (mri_pending_align): New static variable. + (read_a_source_file): Handle mri_pending_align. + (cons): Set mri_pending_align if appropriate. + + * configure.in: Move random special target handling before + possible break. + * configure: Rebuild. + +Tue Aug 8 23:41:25 1995 Alan Modra + + * configure.in: Consistently use ${target_cpu_type} rather than + ${cpu_type} after the loop. + * configure: Rebuild. + * Makefile.in (targ-cpu.o): Use @target_cpu_type@ rather than + @cpu_type@. + +Tue Aug 8 17:27:17 1995 Ken Raeburn + + * expr.h (operatorT): Remove comma after last enumerator value. + + * config/obj-vms.c: Some whitespace cleanup from Pat Rankin. + + * as.h (alloca): If __STDC__, declare void* instead of char*. + + Wed Aug 2 18:54:37 1995 Pat Rankin + + * config/obj-vms.c (Flush_VMS_Object_Record_Buffer, + Close_VMS_Object_File): Reorganize the `#if !VMS' cross-assmebler + support code. + (Close_VMS_Object_File): Call Set_VMS_Object_File_Record to flush + output buffer--just in case--before closing the file. + +Tue Aug 8 13:07:05 1995 Ian Lance Taylor + + * config/tc-m68k.c (archs): Add 68ec000, 68hc000, 68hc001, + 68ec020, 68ec030, 68ec040, and 68330. + (md_pseudo_table): Add chip and comline. + (m68k_init_after_args): Use strcasecmp when comparing default_cpu + against architectures. + (mri_chip, s_chip): New static functions. + + * struc-symbol.h (struct symbol): Add sy_mri_common bit. + * read.h (mri_comon_symbol): Declare. + (s_mri_common): Declare. + * read.c (mri_line_label): New static variable. + (mri_common_symbol): New global variable. + (potable): Add "common" and "common.s". + (read_a_source_file): In MRI mode, set mri_line_label for a label + at the start of a line. + (s_mri_common): New function. + (s_space): Handle mri_common_symbol. + * symbols.c (colon): Change return value from void to symbolS *, + and return new symbol. If mri_common_symbol is set, attach the + new symbol to it. + (resolve_symbol_value): Handle an sy_mri_common symbol. + * symbols.h (colon): Change return value in declaration. + * subsegs.c (subseg_set_rest): Clear mri_common_symbol. + (subseg_set (both versions)): Likewise. + * frags.c (frag_more): Warn if mri_common_symbol is not NULL. + * write.c (adjust_reloc_syms): Skip sy_mri_common symbols. + (write_object_file): Discard sy_mri_common symbols. + (fixup_segment): Change relocations against sy_mri_common symbols + to be against the common symbol itself. + * config/obj-coff.c (yank_symbols): Discard sy_mri_common symbols. + (fixup_segment): Change relocations against sy_mri_common symbols + to be against the common symbol itself. + * config/obj-aout.c (obj_crawl_symbol_chain): Discard + sy_mri_common symbols. + + * doc/c-m68k.texi: Add documentation for CPU specific options, and + for Motorola syntax. + + * config/m68k-parse.y (motorola_operand): For (%pc), set mode to + DISP, not BASE. + +Tue Aug 8 02:31:38 1995 Ken Raeburn + + * write.c (relax_align): Add extra padding for linkrelax only if + LINKER_RELAXING_SHRINKS_ONLY is defined. + * config/tc-i960.h (LINKER_RELAXING_SHRINKS_ONLY): Define it. + * doc/internals.texi (Relaxation): Write up some stuff on linker + relaxing and LINKER_RELAXING_SHRINKS_ONLY. + +Mon Aug 7 17:18:10 1995 Ian Lance Taylor + + * config/m68k-parse.y: New file: bison grammar for m68k operands, + including support for Motorola syntax. + * config/m68k-parse.h: New file; definitions shared between + m68k-parse.y and tc-m68k.c. + * config/tc-m68k.c: Include m68k-parse.h. + (enum operand_type): Move to m68k-parse.h, where it is named + m68k_operand_type. Rename all uses. Rearrange somewhat. Add + FPREG. Rename AOFF to DISP. Rename AINDX to BASE. Rename APODX + to POST. Rename APRDX to PRE. Remove AMIND. Rename MSCR to + CONTROL. Remove DINDR. + (struct m68k_exp): Move to m68k-parse.h. Remove e_beg, e_end and + e_seg fields. Rename e_exp to exp. Rename e_siz to size, and + change type to enum m68k_size. Change all uses. + (enum _register): Move to m68k-parse.h, where it is named + m68k_register. Rename all uses. Add ZDATA0-7 and ZADDR0-7. + (struct m68k_op): Move to m68k-parse.h. Change all fields. + (seg): Don't define. + (add_exp): Remove. + (FAIL, OK): Remove. + (m68k_reg_parse): Move to m68k-parse.y, and rewrite. + (SKIP_WHITE, SKIP_W): Remove. + (try_moto_index, try_index): Remove. + (m68k_ip_op): Move to m68k-parse.y, and rewrite to use grammar. + (main): Remove obsolete test function. + (m68k_ip): Extensive changes to use new grammar. + (get_regs): Remove. + (crack_operand): m68k_ip_op now returns 0 on success. + (init_table): Add ssp, zd0-7 and za0-7. + (md_assemble): Make er const. Correct loop over operands when + looking for error message. + (md_begin): Set alt_notend_table for '(' and '@'. + (get_num): Expression is already parsed. Don't set seg. + * configure.in: If cpu_type is m68k, put m68k-parse.o in + extra-objects. + * configure: Rebuild. + * Makefile.in (DISTSTUFF): Add m68k-parse.c. + (BISON): Use ../bison/bison if it exists. + (BISONFLAGS): Define as empty. + (TARG_CPU_DEP_m68k): Depend upon $(srcdir)/config/m68k-parse.h. + (m68k-parse.c, m68k-parse.o): New targets. + +Fri Aug 4 12:29:21 1995 Ian Lance Taylor + + * expr.c (op_encoding): Make non-const. Don't set '"' to + O_bit_not. + (expr_begin): Set op_encoding['"'] in MRI mode. + +Wed Aug 2 18:39:43 1995 Ian Lance Taylor + + * config/tc-m68k.c: Remove BREAK_UP_BIG_DECL stuff. + (struct m68k_incant): Change m_operands field to be const. + (struct m68k_it): Change args field to be const. + (m68k_ip): Change local variable s to be const. + (opcode_ptr): Remove. + (md_begin): Use m68k_numopcodes, not numopcodes. Use + m68k_opcodes, not removed opcode_ptr. Use m68k_numaliases, not + numaliases. + +Tue Aug 1 17:35:26 1995 Ian Lance Taylor + + * config/tc-m68k.c (init_table): Add "control", "status", "iaddr", + "sfcr", and "dfcr" as synonyms for existing entries. + (md_begin): In MRI mode, force flag_reg_prefix_optional to 1. + (md_parse_option): Removed unused locals i and arch. Change type + of arch (another one) to unsigned long. + (tc_coff_sizemachdep): Add return after abort to avoid warning. + + Initial support for MRI style labels and expressions. + * as.h (flag_mri): Declare/define. + * as.c (show_usage): Mention -M and its synonym --mri. + (parse_args): Add 'M' to std_shortopts. Add "mri" to + std_longopts. Set flag_mri if -M is seen. + (main): Call parse_args before input_scrub_begin. Call + expr_begin. + * app.c (do_scrub_begin): Don't set lex for '"' or '\'' in MRI + mode. Do set lex for ';', '*', and '!' in MRI mode. + (do_scrub_next_char): Remove MRI ifdef in LEX_IS_WHITESPACE case. + In MRI mode, keep spaces between labels and colons. Remove MRI + ifndef around LEX_IS_ONECHAR_QUOTE case. In MRI mode, don't use + '!' or '*' as comment characters even if they are in + comment_chars. + * read.h (lex_type): No longer const. + * read.c: Include libiberty.h. + (lex_type): No longer const. + (read_begin): In MRI mode, set lex_type of '?' to 3. + (potable): Add dc, dc.b, dc.d, dc.l, dc.s, dc.w, dc.x, ds, ds.b, + ds.l, ds.w, and xdef. + (read_a_source_file): Change LABELS_WITHOUT_COLON ifdef to check + for MRI mode at runtime rather than compile time. Handle the EQU + pseudo-op in MRI mode. Remove bogus MRI ifdef around done_pseudo. + Change NO_PSEUDO_DOT ifdef to also take effect for MRI mode at + runtime. + (cons): In MRI mode, always call parse_mri_cons rather than + TC_PARSE_CONS_EXPRESSION. + (parse_mri_cons): Always compile, not just when MRI is defined. + Call TC_PARSE_CONS_EXPRESSION, not expression, when the input is + not a string constant. Handle A and E modifiers. + (float_cons): Accept :xxxx, where the x's are hex digits. + * expr.h (operatorT): Add O_eq, O_ne, O_lt, O_le, O_ge, O_gt. + (expr_begin): Declare. + * expr.c (integer_constant): In MRI mode, if the base was not + specified, look for a suffix on the number to set the base. + (mri_char_constant): New static function. + (operand): Remove MRI ifdef. In MRI mode, do various things: Pass + 0 as the base when calling integer_constant if there was no + prefix. Check for a hex constant suffix if when a leading '0' is + seen. Don't accept 0x or 0b as a prefix. Check for E'chars' and + A'chars'. Handle MRI character constants. Treat '"' as the + unary bitwise not operator. Treat $ as the program counter, or as + the prefix for a hex constant. Treat % as the prefix for a binary + constant and @ as the prefix for an octal constant. Treat : as + the prefix for a hex constant. + (op_encoding): Set '"' to O_bit_not, '<' to O_lt, and '>' to O_gt. + (op_rank): No longer const. Change rank values. + (expr_begin): New function. + (operator): New static function. + (expr): Use operator. Don't bother to mention the operator in + warnings. Remove bogus #if 0 code. Handle new operatorT values. + * atof-generic.c (atof_generic): In MRI mode, accept underscores + around the exponent in floating point numbers. + * symbols.h (symbols_case_sensitive): Declare. + * symbols.c (symbols_case_sensitive): New global variable. + (symbol_create): Check symbols_case_sensitive. + (symbol_find_base): Likewise. + (resolve_symbol_value): Handle new operatorT values. + (print_expr_1): Likewise. + (S_IS_LOCAL): In MRI mode, names beginning with two '?' characters + are local. + +Tue Aug 1 11:35:18 1995 steve chamberlain + + * tc-sh.c (md_convert_frag): Make some error messages more + explict. + +Mon Jul 31 21:40:47 1995 Ken Raeburn + + Sat Jul 29 18:55:23 1995 Pat Rankin + + * config/obj-vms.c (COPY_SHORT, COPY_LONG, PUT_SHORT, PUT_LONG): + Make expansion be safe for use in expressions. + (PUT_COUNTED_STRING): Bracket expansion with `do {...} while (0)' + rather than just `{...}'. + +Mon Jul 31 18:19:26 1995 steve chamberlain + + * gasp.c (main): Parse -I option. + (do_include): Look through include list. + * gasp.c (change_base): Don't modify numbers in strings. + +Mon Jul 31 12:16:21 1995 Ian Lance Taylor + + * config/tc-ppc.h (SUB_SEGMENT_ALIGN): Define. From Niclas + Andersson . + +Thu Jul 27 20:47:12 1995 Ken Raeburn + + * config/obj-coff.c (fixup_segment): Don't do further pcrel + processing after converting difference of two symbols in the + same segment. From Jim Wilson. + + * configure.in (i386-*-linuxoldld): Add as synonym for + i386-*-linux*aout*. From Fred Fish. + * configure: Regenerated. + +Thu Jul 27 16:14:56 1995 Pat Rankin + + * config/obj-vms.c (enum ps_type {ps_TEXT,ps_DATA,ps_COMMON, + ps_CONST}): New constants. + (VMS_Psect_Spec): Use them instead of literal strings. + (vms_write_object_file, global_symbol_directory): Adjust callers. + +Wed Jul 26 18:31:35 1995 Pat Rankin + + * config/obj-vms.c (const_flag): Change from char to unsigned char. + * config/obj-vms.h (const_flag): Ditto. + (struct nlist): Replace union n_un and n_un.{n_name,n_next,n_strx} + fields with just n_name; delete field n_value; change n_other from + char to unsigned char and n_desc from short to int; insert explicit + padding for alignment. + +Mon Jul 24 20:06:17 1995 Ken Raeburn + + * subsegs.h (struct seg_info_trash): Make bitfield types valid. + + * config/obj-coff.c (fixup_segment): Local add_number should not + be declared register since its address is taken for + MD_APPLY_FIX3. + + Fri Jul 21 15:28:18 1995 Pat Rankin + + Split huge vms_write_object_file routine into managable pieces. + + * config/obj-vms.c (vms_fixup_text_section, synthesize_data_segment, + vms_fixup_data_section, global_symbol_directory, local_symbols_DST, + vms_build_DST): New routines. + (vms_write_object_file): Call them. + (struct vms_obj_state): New file scope variable used by the above. + +Mon Jul 24 14:10:24 1995 Ian Lance Taylor + + * config/tc-sh.c (md_pseudo_table): Add "uses". + (s_uses): New static function. + (sh_coff_frob_file): New function. + (md_convert_frag): Call subseg_change before calling fix_new. + (sh_handle_align): New function. + (SWITCH_TABLE): Define. + (sh_force_relocation): New function. + (md_apply_fix): Handle R_SH_USES, R_SH_COUNT and R_SH_ALIGN. + (sh_coff_reloc_mangle): Likewise. Also handle switch table + entries. + * config/tc-sh.h (HANDLE_ALIGN): Define. + (sh_handle_align): Declare. + (TC_FORCE_RELOCATION): Define. + (sh_force_relocation): Declare. + (TC_COUNT_RELOC): Simplify; rely on TC_FORCE_RELOCATION instead. + (tc_frob_file): Define. + (sh_coff_frob_file): Declare. + * config/obj-coff.c (write_object_file): Call tc_frob_file if it + is defined. + (fixup_mdeps): Call HANDLE_ALIGN if it is defined. + (TC_FORCE_RELOCATION): Define if not defined. + (fixup_segment): Use TC_FORCE_RELOCATION to decide whether to + clear the symbol fields of fixP. + +Fri Jul 21 22:38:00 1995 Michael Meissner + + * config/tc-ppc.c (ppc_elf_suffix): Add support for R_PPC_SDAREL + relocation. + (md_apply_fix3): Ditto. + +Thu Jul 20 13:00:56 1995 Ken Raeburn + + * config/tc-m68k.c (md_convert_frag): Rename argument seg to sec, + since seg is a macro name in this file. + + * configure.in (arm-*-riscix*): Don't set emulation. + +Wed Jul 19 16:08:29 1995 Doug Evans + + * config/obj-coff.h (TE_PE): Delete. + * config/tc-arm.h (BYTE_ORDER): Delete. + (TARGET_FORMAT): Provide value for OBJ_COFF and TE_PE. + (ARM_BI_ENDIAN): Define if OBJ_COFF and TE_PE. + * config/tc-arm.c (byte_order): Delete. + (md_number_to_chars): Reference target_big_endian, not byte_order. + (md_chars_to_number): Likewise. + (md_longopts): Add -EB/-EL if ARM_BI_ENDIAN. + (md_parse_options): Recognize -EB/-EL. + (md_show_usage): List -EB/-EL. + +Wed Jul 19 11:49:25 1995 Ian Lance Taylor + + * gasp.c (process_assigns): Use toupper before comparing against + upper case letter. + (whatcond): Likewise. + + * config/tc-sh.c (sh_relax): Rename from relax, and make global. + Renamed all uses. + (insert): Pass a size of 2, not 4. + (build_relax): Remove unused len variable. + (md_show_usage): Mention -little option. + (md_convert_frag): Add segT argument. Rewrite to generate relocs + rather than to generate complete instructions here. + (md_apply_fix): Adjust and clarify R_SH_PCRELIMM8BY4 case for + changes in insert and md_pcrel_from. Add cases for R_SH_PCDISP + and R_SH_PCDISP8BY2. + (md_pcrel_from): Don't subtract 1, add 2. + (tc_coff_fix2rtype): Remove. + (sh_coff_reloc_mangle): New function. + * config/tc-sh.h (TC_COFF_FIX2RTYPE): Just return fx_r_type. + (sh_relax): Declare. + (TC_COUNT_RELOC): If relaxing, count PC relative relocs. + (TC_RELOC_MANGLE): Define. + (sh_coff_reloc_mangle): Declare. + (tc_coff_sizemachdep): Declare. + * tc.h (md_convert_frag): Add segT parameter to non BFD_ASSEMBLER + declaration. + * write.c (cvt_frag_to_fill): Add sec argument to non + BFD_ASSEMBLER version. Pass it to md_convert_frag. + (write_object_file): Pass SEG_TEXT to cvs_frag_to_fill. + * config/obj-coff.c (do_relocs_for): Pass segment info to + TC_RELOC_MANGLE. + (fixup_mdeps): Pass segment type to md_convert_frag. + * config/tc-a29k.c (md_convert_frag): Add segT argument. + * config/tc-h8300.c (md_convert_frag): Likewise. + * config/tc-h8500.c (md_convert_frag): Likewise. + * config/tc-i386.c (md_convert_frag): Likewise. + * config/tc-i860.c (md_convert_frag): Likewise. + * config/tc-i960.c (md_convert_frag): Likewise. + * config/tc-m68k.c (md_convert_frag): Likewise. + * config/tc-m88k.h (md_convert_frag): Likewise. + * config/tc-ns32k.c (md_convert_frag): Likewise. + * config/tc-rce.c (md_convert_frag): Likewise. + * config/tc-tahoe.c (md_convert_frag): Likewise. + * config/tc-vax.c (md_convert_frag): Likewise. + * config/tc-w65.c (md_convert_frag): Likewise. + * config/tc-z8k.c (md_convert_frag): Likewise. + * config/tc-h8300.h (TC_RELOC_MANGLE): Add segment argument. + * config/tc-h8500.h (TC_RELOC_MANGLE): Likewise. + * config/tc-rce.h (TC_RELOC_MANGLE): Likewise. + * config/tc-w65.h (TC_RELOC_MANGLE): Likewise. + * config/tc-z8k.h (TC_RELOC_MANGLE): Likewise. + +Mon Jul 17 15:02:54 1995 Pat Rankin + + * config/obj-vms.c (Current_Routine, Text_Psect): Delete as file + scope variables. + (Define_Routine, Define_Local_Symbols): Take Current_Routine and + Text_Psect as arguments. + (VMS_DBG_Define_Routine): Delete. + (VMS_TBT_Block_End): Change `Size' argument from int to valueT. + (vms_write_object_file: text and data fixup loops): Difference + of two symbols has type offsetT rather than int; convert with + md_number_to_chars before passing to VMS_Store_Immediate_Data. + (vms_write_object_file: debug symbol loop): Call Define_Routine + instead of VMS_DBG_Define_Routine. + +Sat Jul 15 00:01:35 1995 Michael Meissner + + * config/tc-ppc.c (ppc_elf_suffix): Add @fixup so that the + compiler can mark which relocs not to complain about with + -mrelocatable. + (ppc_elf_validate_fix): Add .fixup to sections not to complain + about, and also don't complain for BFD_RELOC_CTOR relocations in + writable non-code segments. + (md_apply_fix): Treat BFD_RELOC_CTOR just like BFD_RELOC_32. + +Fri Jul 14 19:54:28 1995 Ian Lance Taylor + + Add support for SPARC SunOS PIC: + * config/tc-sparc.h (sparc_pic_code): Always declare, not just + when OBJ_ELF. + (TC_RELOC_RTSYM_LOC_FIXUP): Define when OBJ_AOUT. + (tc_fix_adjustable): New definition for OBJ_AOUT. + * config/tc-sparc.c (sparc_pic_code): Always define, not just when + OBJ_ELF. + (md_apply_fix): Adjust reloc addend for OBJ_AOUT and PIC. In + BFD_RELOC_32_PCREL_S2 case, don't increment val for an external + symbol when PIC. + (tc_gen_reloc): Generate different PIC relocs when OBJ_AOUT, as + well as when OBJ_ELF. + (md_shortopts): If OBJ_AOUT, include `k'. + (md_parse_option): If OBJ_AOUT, handle 'k'. + (md_show_usage): Mention -k if OBJ_AOUT, and -KPIC if OBJ_ELF. + (md_pcrel_from): Don't add in size for an external symbol when + PIC. + + +Thu Jul 13 21:16:43 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.h (UNDEFINED_DIFFERENCE_OK): Define for SOM. + * write.c (adjust_reloc_syms): Set sy_used_in_reloc for both + symbols in a fixup where a defined symbol is subtracted from an + undefined symbol (when UNDEFINED_DIFFERENCE_OK is defined). + (fixup_segment): Do nothing for the difference of two symbols if + UNDEFINED_DIFFERENCE_OK is defined. + +Wed Jul 12 23:33:40 1995 Ian Lance Taylor + + * config/obj-coff.c (fixup_segment): Support MD_APPLY_FIX3. + +Wed Jul 12 01:12:12 1995 Ken Raeburn + + * write.c (fix_new): Use int, not short int, for argument type. + (fix_new_exp): Ditto. + + * configure.in (arm-*-riscix*): Don't set emulations. + + * config/tc-mips.c (NO_ECOFF_DEBUGGING): Define if ECOFF_DEBUGGING + wasn't previously defined. + (s_extern): Don't set ecoff_extern_size if NO_ECOFF_DEBUGGING. + (nopic_need_relax): Don't check it if NO_ECOFF_DEBUGGING. + (macro_build) [!USE_STDARG]: Don't use variadic prototype. + (mips_local_label) [NO_ECOFF_DEBUGGING]: Don't preserve potential + ECOFF debugging symbols. + + * emul.h (struct emulation): Use unsigned, not unsigned char, for + bitfields. + * obj.h (struct format_ops): Likewise. + + * config/tc-arm.c (symbol_make_empty) [BFD_ASSEMBLER]: Set + udata.p, not udata. + +Tue Jul 11 14:30:19 1995 Ian Lance Taylor + + * doc/c-mips.texi: Document -m4010 and -mno-4010. + +Tue Jul 11 14:28:55 1995 Jeff Spiegel + + * config/tc-mips.c (mips_4010): New static variable. + (interlocks): New static variable. + (md_begin): Check for a cpu of "r4010". Set mips_4010 correctly. + If mips_4650 or mips_4010, set interlocks. + (append_insn): Check interlocks, not mips_4650. + (mips_emit_delays): Likewise. + (mips_ip): Only permit INSN_4010 instructions if mips_4010. + (md_longopts): Add "m4010" and "no-m4010". + (md_parse_option): Accept -mcpu=r4010. Handle -m4010 and + -no-m4010. + (md_show_usage): Document -m4010 and -no-m4010. + +Tue Jul 11 13:22:50 1995 Ian Lance Taylor + + * ecoff.c (struct efdr): Add new field fake. + (init_file): Initialize fake. + (add_file): Add new parameter fake. Change all callers. + (ecoff_build_debug): Don't warn about a missing .end for a fake + file. + +Mon Jul 10 16:01:31 1995 Ken Raeburn + + * doc/as.texinfo: Split out most cpu chapters... + * doc/c-*.texi: ...to here. + + * read.c (po_hash): Now static. + +Mon Jul 10 13:47:22 1995 Ian Lance Taylor + + Based on patches from H.J. Lu : + * config/tc-i386.c (md_apply_fix3): Rename from md_apply_fix1. + Accept pointer to value and segment. Fix OBJ_ELF PCREL case to + handle global defined symbols correctly. + (md_apply_fix): Remove both versions. + * config/tc-i386.h (MD_APPLY_FIX3): Define. + + * configure.in: When switching on ${cpu}, use ${cpu}, not + $[target_cpu}, in default case. + * configure: Rebuild. + +Sat Jul 8 13:27:55 1995 Ian Lance Taylor + + * write.c (fixup_segment): Call resolve_symbol_value on + sub_symbolP, in case it isn't in the symbol table. + +Fri Jul 7 11:17:27 1995 Ian Lance Taylor + + * read.c (s_lcomm): For .lcomm 1, set align to 0, not 1. + + * config/obj-coff.c (coff_frob_symbol): If SF_GET_FUNCTION, set + BSF_FUNCTION. + (symbol_globalP, symbol_global_lastP): New global variables. + (yank_symbols): Sort defined global symbols to the end, just + before the undefined symbols. + (glue_symbols): Add two arguments, and use them instead of + referring directly to global variables. + (crawl_symbols): Call glue_symbols twice, once for defined globals + and once for undefined. Add corresponding know calls. + + * app.c (do_scrub_next_char): Always accept \v. Don't make it + conditional on BACKSLASH_V. + * read.c (next_char_of_string): Likewise. + * config/obj-bout.h (BACKSLASH_V): Don't define. + * config/tc-mips.h (BACKSLASH_V): Don't define. + + Add SPARC ELF PIC support. + * write.c (fixup_segment): Pass fixP to TC_RELOC_RTSYM_LOC_FIXUP, + not fixP->fx_r_type. + * config/tc-sparc.c (sparc_pic_code): New global variable. + (md_apply_fix): If generating PIC, adjust fx_addnumber for any non + PC relative reloc. + (tc_gen_reloc): If generating PIC, adjust various reloc types. + Remove fx_pcrel assert, since it is no longer true. + (md_parse_option): Handle -K PIC. + * config/tc-sparc.h (sparc_pic_code): Declare if OBJ_ELF. + (TC_RELOC_RTSYM_LOC_FIXUP): Define if OBJ_ELF. + (tc_fix_adjustable): Don't adjust PC relative relocs if PIC. + * config/tc-i386.h (TC_RELOC_RTSYM_LOC_FIXUP): Take a fixp, not a + reloc type. + + * Makefile.in (Makefile): Add dependency on conf.in, so that conf + is rebuilt when conf.in changes. + +Thu Jul 6 16:49:38 1995 Ken Raeburn + + * All files: Updated FSF address. + +Thu Jul 6 16:30:34 1995 Jim Wilson + + * ecoff.c (add_file): Don't collapse multiple .file commands into + a single file structure. + (ecoff_build_lineno): Set ilineBase to sum of previous file's + ilineBase and cline. + +Thu Jul 6 12:54:27 1995 Ian Lance Taylor + + Patches from Jerry Blakely : + * as.c (listing_filename): New static variable. + (show_usage): Mention -a=file. + (parse_args): Support = option of -a to set name of listing file. + (main): Pass listing_filename to listing_print. + * listing.c (list_file): New static variable. + (various): Replace printf with fprintf to list_file. + (listing_print): If name argument is not NULL, open it as + list_file. + * doc/as.texinfo, doc/as.1: Document -a=file. + + * config/tc-sparc.c (s_reserve): Don't permit redefinition, even + if the symbol was already in bss_section. Fix warning message. + + * listing.c (struct file_info_struct): Rename end_pending field to + at_end. + (file_info): Initialize at_end, not end_pending. + (buffer_line): If at_end set, just return immediately. Don't + worry about end_pending cases. Set at_end when EOF is read. + (print_source): Check at_end, not end_pending. + (listing_listing): Likewise. + + * config/tc-alpha.h (alpha_do_align): Don't declare. + (md_do_align): Don't define. + (tc_frob_label): Define. + (alpha_define_label): Declare. + (md_flush_pending_output): Define. + (alpha_flush_pending_output): Declare. + * config/tc-alpha.c (insn_label): New static variable. + (auto_align): New static variable. + (md_pseudo_table): Add cases for .text, .data, .align, .byte, + .hword, .int, .long, .octa, .quad, .short, .word, .double, .float, + and .single. Change .t_floating, .s_floating, .f_floating, + .g_floating, and .d_floating to use s_alpha_float_cons rather than + float_cons. + (s_alpha_text, s_alpha_data): New static functions. + (s_rdata, s_sdata): Clear insn_label and set auto_align. + (s_gprel32): If auto_align, align. Clear insn_label. + (emit_insn): Clear insn_label. + (s_alpha_align): New static function. + (alpha_align): Make static. Take label argument. + (alpha_flush_pending_output): New static function. + (s_alpha_cons, s_alpha_float_cons): New static functions. + (alpha_define_label): New function. + +Wed Jul 5 22:49:31 1995 Ken Raeburn + + * conf.in: Regenerate with autoreconf. + + Mon Jul 3 19:47:53 1995 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.h (vms_resolve_symbol_redef): Use full prototype. + (vms_check_for_special_label, tc_frob_label): Move them to group + with other prototypes. + [WANT_VMS_OBJ_DEFS]: Only define the many OBJ_x, DBG_x, and DST_x + macros when this is defined. + * config/obj-vms.c: Fully prototype all local functions. + [symbolS, fragS]: Use consistently instead of their struct tags. + [WANT_VMS_OBJ_DEFS]: Define this. + (s_const): Make definition correctly match actual usage. + (VMS_stab_parse): Make `expected_type' arg be int rather than char. + (get_VMS_time_on_unix): Define as `static void'. + (hash_string): Make definition match actual usage; argument is + `char const *' rather than `unsigned char *'. + (VMS_Case_Hack_Symbol, VMS_Modify_Psect_Attributes, VMS_Psect_Spec, + VMS_Global_Symbol_Spec): Declare string args as `const char *'. + [IS_GXX_VTABLE]: New macro. + (vms_write_object_file: GSD loop): Use it. + (vms_write_object_file: data segment): Reorganize `fill' loop. + +Wed Jul 5 12:01:49 1995 Ian Lance Taylor + + * config/tc-sparc.c (md_shortopts): Add "K:" if OBJ_ELF. + (md_parse_option): If OBJ_ELF, check for -K. Die if -K PIC, since + PIC code is not currently supported. + + * as.c (parse_args): Change std_shortopts to be an array rather + than a constant string. Only include 'K' if WORKING_DOT_WORD is + not defined. Only check for 'K' in that case as well. + * as.h (flag_warn_displacement): Only declare if WORKING_DOT_WORD + is not defined. + + * conf.in: Add undef of HAVE_SBRK. + + * config/obj-coff.c (obj_coff_line): Call listing_source_line, in + both BFD_ASSEMBLER and non BFD_ASSEMBLER versions of the function. + + * symbols.c (S_SET_EXTERNAL): Warn if symbol is weak. + (S_CLEAR_EXTERNAL): Likewise. + (S_SET_WEAK): Warn if symbol is global. + + * config/obj-aout.c (obj_aout_frob_symbol): Warn about an attempt + to put an undefined symbol into a set. + + * Makefile.in: Remove @configure_input@; it's not needed in + files named Makefile. + + * config/tc-m88k.c (md_pseudo_table): Add ".set" so that the + explicit pseudo-op works, while continuing to treat "set" as an + instruction. + + * ecoff.c (ecoff_debugging_seen): New global variable. + (ecoff_directive_def): Set ecoff_debugging_seen. + (ecoff_stab): Likewise. + * ecoff.h: Make idempotent. + (ecoff_debugging_seen): Declare. + * config/tc-mips.c: Include ecoff.h. + (mips_debug): New static variable. + (s_stringer, s_mips_space): Remove unneeded declarations. + (md_parse_option): In case 'g', set mips_debug to debugging level. + (mips_local_label): New function. + * tc-mips.h (LOCAL_LABEL): Call mips_local_label. + (mips_local_label): Declare. + +Wed Jul 5 00:59:22 1995 Fred Fish (fnf@cygnus.com) + + * as.c (main): Only use sbrk when HAVE_SBRK defined. + * configure.in: Add test for sbrk. + * configure: Regenerate using autoconf 2.4. + +Mon Jul 3 15:58:16 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.h (MAX_RELOC_EXPANSION): Bump to 6. + * config/tc-hppa.c (tc_gen_reloc, SOM version): Handle + relocations for the difference of two (possibly external) + symbols. + (hppa_fix_adjustable): For SOM, reject reductions involving + the difference of two symbols. + (hppa_force_relocation): Force relocations for expressions + involving the difference of two symbols. + +Mon Jul 3 14:22:59 1995 Steve Chamberlain + + * configure[.in] (i386-*-win32): New host and target. + +Thu Jun 29 17:25:43 1995 Steve Chamberlain + + Support for long filenames non-bfd coff. + * config/obj-coff.c (filename_list_head, filename_list_tail): New. + (yank_symbols): Notice and record filenames which are too long. + (w_strings): Write out filename strings. + (c_dot_file_symbols): Put long filenames onto list. + +Wed Jun 28 17:33:13 1995 Steve Chamberlain + + * config/obj-coff.c (fixup_segment): PE doesn't use + the strange common symbol format that other 386s formats + do. + * config/tc-i386.c (md_begin): If LEX_AT defined then + '@' is in the set of identifiers. + (i386_operand): If LEX_AT, then don't look for @goto stuff. + * config/te-pe.h: Define LEX_AT. + +Wed Jun 28 17:49:59 1995 Ken Raeburn + + * doc/as.texinfo (H8/500 Floating Point): Indicate that IEEE FP + numbers are for the standard emulation code. + (SH Floating Point): Ditto. + (Overview): Describe new --emulation option for MIPS. + * doc/*.m4: Deleted. + +Thu Jun 22 19:26:25 1995 Ken Raeburn + + Sun May 7 11:53:41 MDT 1995 Bryan Ford + + * configure.in: Added i386-*-moss* target. + +Thu Jun 22 14:41:23 1995 Michael Meissner + + * write.c (write_object_file): Cast decode_local_label_name + argument to char * to avoid warning. + +Wed Jun 21 18:07:59 1995 Ken Raeburn + + Changes from Andreas Schwab : + * config/tc-m68k.c (insword): Increment the frag offsets. + (struct m68k_it): Add reloc[].pcrel_fix field to hold pc-rel + fixup. + (add_fix): Accept additional parameter, the pc-rel fixup. All + callers changed. Fix offset address if width == 'b'. + (m68k_ip) [case AINDX]: Allow explicit size spec. Don't make the + outer displacement pc-relative. + (md_pcrel_from): Make it relative to the first extension word of + the operand. + (opcode_ptr): Make it a macro if DO_BREAK_UP_BIG_DECL is + undefined. + (md_convert_frag_1): Don't reference fragP->fr_opcode[2..]. + (md_estimate_size_before_relax) [case TAB (FBRANCH, SZ_UNDEF)]: + Turn on long bit. + (m68k_ip) [case 'C']: Don't set set long bit, set it in the opcode + table. + (md_estimate_size_before_relax) [case TAB (PCINDEX, SZ_UNDEF)]: + Variable part increases by four, not six. + * write.c (fixup_segment) [TC_M68K]: Don't do further pcrel + processing after converting difference of two symbols in the + same segment. + + * write.c (fixup_segment): Don't conditionalize the pcrel fix on + TC_M68K. + + * config/tc-sparc.c (sparc_ip, case 'A'): If ASI is not a "#" + value, don't shift it an extra time. + +Wed Jun 21 14:18:37 1995 Steve Chamberlain + + * gasp.c (do_print, do_form, buffer_and_nest): Use case insensitive + string compares. + +Tue Jun 20 14:55:02 1995 Ken Raeburn + + * config/obj-coff.c (write_object_file): Cast time() argument to + time_t *. + +Tue Jun 20 12:00:53 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_build_unwind_subspace): Fix typo in last + change. + +Mon Jun 19 15:27:17 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_build_unwind_subspace): Zero out memory + from frag_more calls. + +Thu Jun 15 16:53:37 1995 Stan Shebs + + * config/obj-coff.c: Don't use "bfd/" when including libbfd.h + and libcoff.h. + (fill_section): Call PROGRESS. + * Makefile.in (INCLUDES): Add bfd srcdir. + + * mpw-config.in: Add bfd_gas flag and set for each config. + (i386-unknown-go32, m68k-unknown-coff): Recognize. + * mpw-make.in (HACK_O_RAMA, OBJ_COFF_OMIT_TIMESTAMP): Add to + config.h. + +Thu Jun 15 10:04:26 1995 Doug Evans + + * config/tc-arm.h (LOCAL_LABEL): Prepend '.' if not OBJ_AOUT. + (FAKE_LABEL_NAME): Likewise. + +Mon Jun 12 22:25:39 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_ip): Check for invalid register in single + precision fmpyadd and fmpysub instructions. + +Thu Jun 8 19:33:02 1995 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.c (myname): Delete all references. + (VMS_stab_parse, Write_VMS_MHD_Records, VMS_Case_Hack_Symbol): + Replace printf calls with as_tsktsk. + (PUT_LONG, PUT_SHORT): Use COPY_LONG, COPY_SHORT. + (VMS_Store_Immediate_Data): Move second buffer capacity check + below bottom of loop; first check at top suffices for loop itself. + (find_file): Remove redundant pointer checks in first two loops; + replace third loop with pointer to last list element determined + in first loop. + + +Tue Jun 6 13:53:06 1995 Ken Raeburn + + * config/tc-sparc.c (sparc_ip): Handle defined absolute symbols as + ASI values. + + * config/obj-vms.c (vms_write_object_file, case N_DATA): Use + strcmp against FAKE_LABEL_NAME instead of checking third + character. (Suggested by Pat Rankin.) + +Mon Jun 5 20:10:46 1995 Pat Rankin (rankin@eql.caltech.edu) + + Add support for N_ABS and N_ABS|N_EXT type symbols. + + * config/obj-vms.h (LSY_S_M_{DEF,REL}, ENV_S_M_{DEF,NESTED}): + New macros for local symbols (from and ). + * config/obj-vms.c (Current_Environment): New file-scope variable. + (VMS_Local_Environment_Setup): New routine. + (GBLSYM_LCL): New macro. + (VMS_Global_Symbol_Spec): Handle local symbols too. + (VMS_Psect_Spec): Set GLOBALVALUE_BIT for absolute symbols. + (VMS_Emit_Globalvalues): Handle local and global absolute symbols. + (VMS_Store_PIC_Symbol_Reference): Ditto. + (vms_write_object_file: GSD symbol loop): Ditto. + +Mon Jun 5 16:10:40 1995 Steve Chamberlain + + * config/tc-arm.h (LOCAL_LABELS_FB): Define. + +Mon Jun 5 02:17:58 1995 Ken Raeburn + + * configure.in (i386-*-gnu*): Always use GNU ELF config. + +Wed May 31 17:49:18 1995 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.c (obj_crawl_symbol_chain): Update *symbolPP + in `else' clause when removing a symbol. Also, revise comments + to match the code. + (vms_write_object_file (GSD symbol loop, case N_DATA)): Never + output symbol definitions for local numeric labels. + +Tue May 30 18:29:10 1995 Richard Earnshaw (rearnsha@armltd.co.uk) + + * configure.in (architecture variants, cases armeb and arm*): Remove + spaces round assignment to endian. + +Tue May 30 12:31:31 1995 Ken Raeburn + + * write.c (write_object_file): Check for undefined local dollar + and fb labels. + + * symbols.c (decode_local_label_name): Extract instance number + from the correct location. + +Sat May 27 21:28:49 1995 J.T. Conklin + + * config/te-dpx2.h: Include obj-format.h. + (COFF_MAGIC): Renamed from FILE_HEADER_MAGIC. + +Wed May 24 13:45:32 1995 Steve Chamberlain + + * configure, configure.in, config/obj-coff.c, config/obj-coff.h: + Add support for ARM pe + +Tue May 23 17:00:32 1995 Doug Evans + + * config/tc-sparc.c (tc_gen_reloc): Handle BFD_RELOC_SPARC_WDISP16 + and BFD_RELOC_SPARC_WDISP19. + +Tue May 23 19:18:33 1995 Ken Raeburn + + * as.c (parse_args) [! USE_EMULATIONS]: Always print an error + message. + + * doc/internals.texi: Document obj_app_file and + TARGET_BYTES_BIG_ENDIAN. + +Mon May 22 20:03:23 1995 Ken Raeburn + + * ecoff.c (ecoff_stab): Add extra leading argument, for 4 May + change. + * ecoff.h (ecoff_stab): Fix declaration. + * obj.h (format_ops.process_stab): Include prototype. + * config/obj-elf.h (OBJ_PROCESS_STAB): Pass through seg argument. + * config/obj-ecoff.h (OBJ_PROCESS_STAB): Ditto. + + * config/e-mipself.c (mipself): New emulation mode, doesn't change + endianness from configured default. + * config/e-mipsecoff.c (mipsecoff): Ditto. + * configure.in (mips ecoff/elf targets): Include them. + * as.c (mipself, mipsecoff): Declare. + + * as.c (emulation_name): New variable. + (select_emulation_mode): Set emulation_name. Don't change argv. + (parse_args): Handle --emulation; complain if the supplied name + isn't what select_emulation_name came up with. + + +Sun May 21 21:36:17 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c: Reverse changes from Dec. 19th which + changed the way unwinds were built for ELF. Rely on relocation + symbol reductions to avoid placing the end of function marker + symbols into the object file's symbol table. + +Sat May 20 12:31:36 1995 Ken Raeburn + + Added improved VMS support from Pat Rankin: + + Fri 19 May 16:51:40 1995 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.h (AOUT_STABS): Define. + + * config/obj-vms.c (fpush, rpush): New routines. + (push): Replaced by the above. + (find_symbol): Slight reorganization to expose tail recursion. + + Fri Mar 17 18:40:36 1995 Pat Rankin (rankin@eql.caltech.edu) + + * Makefile.in (VMS_OTHER_OBJS): delete this. + * vmsconf.sh (make-gas.com): build ../libiberty/liberty.olb + first if necessary; link gas against it. + +Fri May 19 16:37:39 1995 Richard Earnshaw (rearnsha@armltd.co.uk) + + * gasp.c (istrue): Correctly test for string inequality. + +Thu May 18 04:25:11 1995 Ken Raeburn + + Wed May 10 14:28:16 1995 Richard Earnshaw (rearnsha@armltd.co.uk) + + * config/tc-arm.c (CP_T_{Pre,UD,WB}): Define, bits in co-processor + instructions. + ([ls]fm_flags): Correct error in bitmasks. + (cp_address_required_here): Delete second parameter, FLAGS. All + callers changed. Remove all dead code referring to FLAGS. If + address is just "[Reg]" then convert into a PRE-INCREMENT UP format. + (do_fp_ldmstm): Handle full-descending and empty-ascending stack + formats explicitly. + + * config/tc-arm.c (internalError): Define. + (ARM_{1,2,250,3,6,7,7DM,ANY,2UP,ALL,3UP,6UP,LONGMUL}): Define processor + variants. + (FPU_{CORE,FPA10,FPA11,NONE,ALL,MEMMULTI}): Define floating point + variants. + ({CPU,FPU}_DEFAULT): Define. + (cpu_variant): New variable. + (asm_flg): Change more_flags to flag_bits. + Add prototypes for new functions. + (FLAG_{S,P,B,T,ED,FD,FA,EA,IB,IA,DB,DA,L}): Delete. + (s_flag[], ldst_flags[], byte_flag[], cmp_flags[], ldm_flags[], + stm_flags[], lfm_flags[], sfm_flags[], round_flags[], except_flags[], + cplong_flag[]): New variables. + (asm_opcode, insns[]): New format, add version support. + (arm_flg_hsh): Delete. + (do_mul, do_mla): Remove "Warning" from warning messages. + (do_arit): Simplify. + (do_swap): Make error message more appropriate. + (md_begin): Build hash tables starting at first entry in tables. + (md_number_to_chars): Cope with big/little-endian selection. + (md_chars_to_number): New function. + (md_apply_fix): Rewrite to make endian independent. + (tc_gen_reloc): Better error messages. + (md_assemble): Reject opcodes forbidden by the currently selected cpu + variant. Rewrite handling code for instruction flags. + (md_shortopts): Add option "m:". + (md_parse_option): Get the desired cpu/fpu variant. + + From: David Taylor (dtaylor@armltd.co.uk) + * configure.in (architecture variants): Check for "armeb" and "arm*", + set endianness accordingly. + * read.c (read_a_source_file): New hooks md_start_line_hook and + md_after_pass_hook. + * config/arm-{big,lit}.mt: New files + * config/tc-arm.h ({LITTLE,BIG}_ENDIAN, BYTE_ORDER): Define. + (TARGET_FORMAT): Select depending on endianness and emulation and + object format. + (md_after_pass_hook, md_start_line_hook): Define. + * config/tc-arm.c: Include subsegs.h, symbols.h and listing.h. + (shift[]): Add uppper case equivalents. + (CP_T_[XY], TRANS_BIT): Define. + (conds[]): Delete initial NULL entry, add "lo" entry as synonym for + "cc". + (LONGEST_FLAG, flags[]): Delete. + (arm_psr): New structure. + (psrs[]): New variable. + (PSR_ALL): Define. + (LONGEST_INST): Bump to 5. + (LITERAL_MASK, COND_MASK, OPCODE_MASK, DATA_OP_SHIFT): Define. + (OPCODE_{AND,EOR,SUB,RSB,ADD,ADC,SBC,RSC,TST,TEQ,CMP,CMN,ORR,MOV,BIC, + MVN}): Define. + (insns[]): Add smull, umull, smlal, umlal, ldfm, stfm, msr and mrs + instructions. Add nop and adr pseudo ops. + (reg_table): Add APCS register name variants. + (arm_psr_hsh): New hash table. + (md_pseudo_table): Add "ltorg", "pool", "extend", "ldouble" and + "packed". + (MAX_LITERAL_POOL_SIZE): Define. + (struct literalS): New structure. + (literals, next_literal_pool_place, lit_pool_num, current_poolP): New + variables. + (add_to_lit_pool, symbol_locate, symbol_make_empty): New functions. + (validate_immediate): Return FAIL on failure. + (s_ltorg): New function. + (psr_required_here, psrf_required_here): New functions. + (cp_address_required_here): New parameter, flag, all callers changed. + If flag is non-zero, restrict the legal addressing modes. + (do_nop, do_mrs, do_msr, do_mull): New functions. + (negate_data_op): New function. + (data_op2): accept #x,y meaning x rotated right by y, but only when + suitable constants. If immediate is not legal, try changing the + opcode. + (do_adr): New function. + (do_ldst): accept "ldr reg, =expr". Put expr in the pool if it can't + be done as an immediate. + (do_fp_ldst): Use CP_T_[XY], not immediate values. + (do_fp_ldmstm): New function. + (arm_psr_parse): New function. + (output_inst): Use INSN_SIZE in call to md_number_to_chars. + (md_assemble): Add hack so that "Label instruction" causes alignment of + the label. + (arm_after_pass_hook, arm_start_line_hook, arm_frob_symbol): New + functions. + +Wed May 17 05:25:16 1995 Michael Meissner + + * config/tc-ppc.c (md_show_usage): Add \'s at end of lines in + strings for non-GCC compilers. + +Tue May 16 19:36:00 1995 Ken Raeburn + + * config/obj-ecoff.c (ecoff_pop_insert): New function. + (ecoff_format_ops): Use it. + (obj_ecoff_frob_symbol): Now static. + +Wed May 17 00:59:12 1995 Andrew Cagney - aka Noid + + * config/tc-ppc.c (md_begin): Was assuming that an instruction was + bigendian and hence 16bit relocs withing instructions would + ALWAYS be at addresses i+2-i+3. In LE mode it is i+0-i+1. + +Tue May 16 16:29:58 1995 Ken Raeburn + + * config/obj-multi.h (obj_frob_symbol, obj_frob_file, S_GET_SIZE, + S_SET_SIZE, S_GET_ALIGN, S_SET_ALIGN, obj_copy_symbol_attributes, + OBJ_PROCESS_STAB): New macros. + * config/tc-mips.c: Protect against redefining them also when + including obj-elf.h. Test only OBJ_ELF for including elf/mips.h. + (mips_init_after_args): New function. Set byte_order here. + (md_parse_option): Not here. + (byte_order): Don't bother initializing. + * config/tc-mips.h (mips_init_after_args): Declare. + (tc_init_after_args): New macro. + + * read.c (s_lcomm): Do ELF/ECOFF test at run time, not compile + time. + +Fri May 12 14:17:47 1995 Steve Chamberlain + + Initial support for PE object files. + * configure.in, configure (i386-*-pe, i386-*-*nt): Add. + * config/obj-coff.c (fixup_segment): Cope with PE wierdness. + * config/obj-coff.h (TE_PE): New target format. + +Thu May 11 14:58:21 1995 Ken Raeburn + + * config/obj-elf.c (NEED_ECOFF_DEBUG): Define if ECOFF_DEBUGGING + was defined by header files. Test in preprocessor conditionals + instead of ECOFF_DEBUGGING. + (ecoff_debug_pseudo_table): Make empty if NEED_ECOFF_DEBUG is not + defined. + (obj_read_begin_hook, obj_symbol_new_hook, elf_frob_symbol, + elf_frob_file): Only call ecoff routines if NEED_ECOFF_DEBUG is + defined. + (elf_ecoff_set_ext, elf_get_extr, elf_set_index): Define only if + NEED_ECOFF_DEBUG is defined. + (elf_format_ops): Reference elf_ecoff_set_ext only if + NEED_ECOFF_DEBUG. + +Wed May 10 18:09:12 1995 Ken Raeburn + + * Makefile.in (OBJS): Include @extra_objects@. + (obj-elf.o, obj-ecoff.o, e-mipself.o, e-mipsecoff.o): New rules + for building these independently. + * emul-target.h, config/e-mipself.c, config/e-mipsecoff.c: New + files. + + * acconfig.h (DEFAULT_EMULATION, EMULATIONS, USE_EMULATIONS, + OBJ_MAYBE_*, I386COFF, M68KCOFF, M88KCOFF): New macros. + * aclocal.m4 (GAS_UNIQ): New macro. + + * as.c (emulations, n_emulations) [USE_EMULATIONS]: New variable. + (select_emulation_mode, default_emul_bfd_name, common_emul_init) + [USE_EMULATIONS]: New functions. + (main) [USE_EMULATIONS]: Call select_emulation_mode before other + initialization. + * emul.h: New file. + * as.h [USE_EMULATIONS]: Include it. + + * configure.in: Handle enable-targets option. Iterate over target + list, building up a list of object file formats and emulation + configurations. (Only supports emulations for MIPS CPU so far.) + If multiple formats are needed, set obj_format to multi and add + format config files to extra_files. If emulation modes are + needed, add the relevant files to extra_files. + + * configure.in: Define I386COFF, M68KCOFF, M88KCOFF for those + configurations. + + * ecoff.c (ecoff_generate_asm_lineno): Filename argument now + points to const. + * ecoff.h (ecoff_generate_asm_lineno): Updated declaration. + + * obj.h (obj_read_begin_hook): Don't declare function if it's + already a macro. + + * read.c (s_space, cons, stringer): If md_flush_pending_output is + defined, call it on entry. + * config/obj-elf.c (obj_elf_section): If md_flush_pending_output + is defined, call it on entry. If md_elf_section_change_hook is + defined, call it before returning normally. + + * read.h (target_big_endian): Declare. + + * obj.h (struct format_ops): Added new function pointer fields + ecoff_set_ext, read_begin_hook, symbol_new_hook. + (ecoff_format_ops, elf_format_ops): Declare. + * config/obj-elf.c (elf_s_get_size, elf_s_set_size, + elf_s_get_align, elf_s_set_align, elf_copy_symbol_attributes, + elf_sec_sym_ok_for_reloc): New functions. + (elf_format_ops): New variable. + (elf_frob_symbol): Now takes additional int* argument. + * config/obj-elf.h (elf_frob_symbol): Update declaration. + (elf_pop_insert): Declare. + (obj_pop_insert): Define to call elf_pop_insert. + * config/obj-ecoff.c (ecoff_sec_sym_ok_for_reloc, + obj_ecoff_frob_symbol): New functions. + (ecoff_format_ops): New variable. + + * config/te-generic.h: If OBJ_HEADER is defined, use it as the + filename to include in place of obj-format.h. + * config/te-multi.h: New file, copied from te-generic.h. + * config/obj-elf.c (OBJ_HEADER): Define it to "obj-elf.h". + * config/obj-ecoff.c (OBJ_HEADER): Define it to "obj-ecoff.h". + + * config/obj-elf.c (ECOFF_DEBUGGING): Default to 0. + (obj_read_begin_hook, obj_symbol_new_hook, elf_frob_symbol, + elf_frob_file): Test it at run time. + (obj_ecoff_set_ext, elf_get_extr, elf_set_index): Define + unconditionally. + (elf_pseudo_table): Renamed from obj_pseudo_table, now static. + (ecoff_debug_pseudo_table): Split off into separate table. Define + it unconditionally. + (elf_pop_insert): New function. + * config/obj-elf.h (elf_pop_insert): Declare. + (obj_pop_insert): New macro. + (obj_ecoff_set_ext) [!OBJ_MAYBE_ELF]: Define to elf_ecoff_set_ext. + * config/obj-ecoff.h (obj_ecoff_set_ext): Define to ecoff_set_ext. + + * config/tc-mips.h: Protect against multiple inclusions. + (mips_pop_insert): Declare. + (md_pop_insert): Call it. + + * config/tc-mips.c: If OBJ_MAYBE_ELF is defined, include + obj-elf.h, but preserve OUTPUT_FLAVOR and protect some other + macros from redefinition. + (ECOFF_DEBUGGING): Default to 0. All references changed to + run-time tests or made unconditional. + (s_stringer, s_mips_space, s_elf_section): Deleted. + (md_pseudo_table): Don't refer to them. Split table into three + sections, for MIPS, non-ECOFF_DEBUGGING, and ELF. + (mips_pop_insert): New function. + (mips_flush_pending_output): New function. + (mips_enable_auto_align): New function. + * config/tc-mips.h (mips_pop_insert): Declare. + (md_pop_insert): New macro. + (mips_flush_pending_output): Declare. + (md_flush_pending_output): New macro. + (mips_enable_auto_align): Declare. + (md_elf_section_change_hook): New macro, calls + mips_enable_auto_align. + +Tue May 9 17:07:41 1995 Michael Meissner + + * configure.in: Add little endian PowerPC support. + * configure: Rebuild with autoconf. + * config/ppc-big.mt: New file for big endian PowerPC systems. + * config/ppc-lit.mt: New file for little endian PowerPC systems. + + * config/tc-ppc.h (target_big_endian): Declare. + (TARGET_FORMAT): Deal with little and big endian ELF variants. + (TARGET_BYTES_BIG_ENDIAN): Define as 1, not empty. + + * config/tc-ppc.c (ppc_big_endian): Delete variable, use + target_big_endian instead. + (md_parse_option): Parse -mlittle and -mlittle-endian to use + little endian support. Parse -mbig and -mbig-endian to use big + endian support. + (md_show_usage): Update to reflect current switches. + (ppc_set_cpu): Recognize powerpcle as little endian PowerPC. Use + as_fatal, not abort if unknown machine. + +Tue May 9 10:58:41 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_apply_fix): Cast *valp to an integer when + comparing against signed values. + (hppa_force_relocation): Make "distance" an integer. + +Tue May 9 00:47:03 1995 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * obj.h (struct format_ops) [BFD_ASSEMBLER]: New type. + (this_format) [BFD_ASSEMBLER]: Declare new variable, if not + already defined as a macro. + +Mon May 8 21:44:13 1995 Ken Raeburn + + * subsegs.h (seg_info): Provide dummy version for + non-BFD_ASSEMBLER, non-MANY_SEGMENTS configuration. It should + never get invoked, but this is easier than conditionalizing some + of the uses. + (struct seg_info_trash): Dummy type used by above to make code + compile. + +Fri May 5 14:47:13 1995 Ken Raeburn + + * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define to 1, not + empty. + * config/obj-elf.h (SEPARATE_STAB_SECTIONS): Ditto. + * config/obj-som.h (SEPARATE_STAB_SECTIONS): Ditto. + +Thu May 4 19:26:55 1995 Ken Raeburn + + * stabs.c (get_stab_string_offset): Always define. If + SEPARATE_STAB_SECTIONS isn't set, abort. + (SEPARATE_STAB_SECTIONS): Default to zero. + (aout_process_stab): New function, split out from s_stab_generic. + (OBJ_PROCESS_STAB) [AOUT_STABS]: Define to call aout_process_stab, + if not already defined. + (s_stab_generic): Test SEPARATE_STAB_SECTIONS at run time. If + it's not set, and OBJ_PROCESS_STAB isn't defined, abort. Always + pass six arguments to OBJ_PROCESS_STAB. + * read.h (get_stab_string_offset): Declare unconditionally. + * config/obj-aout.h (AOUT_STABS): Define. + * config/obj-bout.h (AOUT_STABS): Define. + * config/obj-ecoff.h (OBJ_PROCESS_STAB): Add new first argument, + ignored. + * config/obj-elf.h (OBJ_PROCESS_STAB) [ECOFF_DEBUGGING]: Ditto. + + * config/obj-ecoff.h (ECOFF_DEBUGGING): Define to 1, not empty. + * config/obj-elf.h (ECOFF_DEBUGGING): Ditto. Test value, not + whether it's defined. + +Wed May 3 21:38:20 1995 Ken Raeburn + + * as.h (LOCAL_LABELS_DOLLAR, LOCAL_LABELS_FB): If not already + defined, define them to zero. + * config/tc-*.h, config/te-*.h: If defining them, define them to + be 1 instead of empty. + * expr.c (integer_constant, operand): Test them at run time + instead of compile time. + * read.c (read_a_source_file): Ditto. + * symbols.c (colon): Ditto. + (dollar_*, define_dollar_label, fb_*): Define unconditionally. + * symbols.h (dollar_*, define_dollar_label, fb_*): Declare + unconditionally. + +Wed May 3 13:08:53 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_apply_fix): Do nothing for an out of range + PC relative call since those only occur in cases where the linker + can fix them up. + (hppa_force_relocation): Force relocations for out of range PC + relative calls. + +Tue May 2 16:34:47 1995 Jeff Law (law@snake.cs.utah.edu) + + * configure (hppa*-*-lites*): Handle just like hppa*-*-*elf*. + * configure.in: Likewise. + +Tue May 2 11:22:00 1995 Ken Raeburn + + * read.c (pop_insert): New function. + (pop_override_ok, pop_table_name): New variables. + (md_pop_insert, obj_pop_insert): New macros. + (pobegin): Use them. + + * config/tc-mips.c: Use USE_STDARG and USE_VARARGS instead of + NO_STDARG &c. + + * read.c (target_big_endian): If TARGET_BYTES_BIG_ENDIAN is + defined, initialize to 1. + * config/tc-mips.c (mips_target_format): Changed to a function, + checking flavor and byte order at run time. + (md_parse_option, cases OPTION_EB and OPTION_EL): Set + target_big_endian here. + (md_begin): Not here. + * config/tc-mips.h (mips_target_format): Adjust declaration. + (TARGET_FORMAT): Call mips_target_format. + + * config/tc-mips.h (USE_GLOBAL_POINTER_OPT): Define in terms of + OUTPUT_FLAVOR. + * config/tc-mips.c (g_switch_value, g_switch_seen): Define + unconditionally. + (md_begin, mips_ip, md_parse_option, s_change_sec, s_option, + s_abicalls, nopic_need_relax): Check USE_GLOBAL_POINTER_OPT at run + time, instead of compiling conditionally on GPOPT. + (GPOPT): Don't define. + (md_shortopts): Always include -G. + (RDATA_SECTION_NAME): Select at run time. + (md_begin): Test for ELF format at run time instead of compile time. + (mips_ip, s_change_sec): Ditto. + (md_parse_option, cases OPTION_CALL_SHARED and OPTION_NON_SHARED): + Ditto. + (OPTION_CALL_SHARED, OPTION_NON_SHARED, mips_regmask_frag): Define + unconditionally. + +Tue May 2 00:17:04 1995 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * Makefile.in (TARG_CPU_DEP_*): New variables. + (targ-cpu.o): Depend on one, selected by autoconf substitution, + instead of TARG_CPU_DEPENDENTS. + * configure.in: Substitute $cpu_type, $obj_format, $atof, and + $emulation into Makefile.in. + * config/h8300.mt: Deleted. + * config/h8500.mt: Deleted. + * config/i386coff.mt (TARG_CPU_DEPENDENTS): Deleted. + * config/m68k.mt: Deleted. + * config/m68kcoff.mt (TARG_CPU_DEPENDENTS): Deleted. + * config/m88kcoff.mt (TARG_CPU_DEPENDENTS): Deleted. + * config/mips-big.mt (TARG_CPU_DEPENDENTS): Deleted. + * config/mips-lit.mt (TARG_CPU_DEPENDENTS): Deleted. + * config/sh.mt: Deleted. + * config/w65.mt: Deleted. + * config/z8k.mt: Deleted. + + * config/te-dpx2.h (dpx2): Deleted unused macro. + * config/te-generic.h (TE_GENERIC): Ditto. + * config/te-go32.h (TE_GO32): Ditto. + * config/te-hp300.h (TE_HP300): Ditto. + * config/te-hppa.h (PA, _TE_PA_H): Ditto. + * config/te-ic960.h (TE_IC960): Ditto. + * config/te-nbsd532.h (TE_NETBSD532): Ditto. + * config/te-pc532mach.h (TE_PC532MACH): Ditto. + * config/te-ppcnw.h (TE_PPCNW): Ditto. + * config/te-sco386.h (scounix): Ditto. + +Mon May 1 15:59:56 1995 Ken Raeburn + + * read.c (s_app_file): If obj_app_file is defined, call it with + string as argument. Don't call c_dot_file_symbol or + elf_file_symbol. + * config/obj-coff.h (obj_app_file): Define as c_dot_file_symbol. + * config/obj-elf.h (obj_app_file): Define as elf_file_symbol. + + * as.h (OUTPUT_FLAVOR): Don't define here. + * config/obj-aout.h (OUTPUT_FLAVOR) [BFD_ASSEMBLER]: Define. + * config/obj-bout.h (OUTPUT_FLAVOR): Define. + * config/obj-coff.h (OUTPUT_FLAVOR) [BFD_ASSEMBLER]: Define. + * config/obj-ecoff.h (OUTPUT_FLAVOR): Define. + * config/obj-elf.h (OUTPUT_FLAVOR): Define. + + +Thu Apr 27 20:07:33 1995 Doug Evans + + * Makefile.in (RUNTEST): Use one in srcdir if present. + (RUNTESTFLAGS): Define. + +Wed Apr 26 15:54:10 1995 Ken Raeburn + + Support for more portable alignment handling in assembly code, + based on patches from Bryan Ford : + * read.c (potable): Added balign and p2align, for aligning by + bytes or powers of two independent of what ".align" does for a + given target. + * doc/as.texinfo: Document them. + +Tue Apr 25 11:12:04 1995 Rob Savoye + + * configure, configure.in: Look for m68k-*-vxworks* rather than + just m68k-wrs-vxworks so gas can be configured for + m68k-vxworks5.1. + +Fri Apr 21 15:19:06 1995 Ken Raeburn + + * config/tc-sh.c (md_apply_fix): If fx_r_type is zero, handle + fx_size of 1, and abort on unrecognized sizes. + + * config/tc-m68k.c (m68k_ip): Fix bug in last change regarding + non-isvar case. + +Sun Apr 16 01:52:52 1995 Ken Raeburn + + * config/tc-m68k.h (md_relax_table, TC_GENERIC_RELAX_TABLE): + Missed this one in 11 Apr changes. + + * config/tc-i386.h (TC_GENERIC_RELAX_TABLE): Fix typo. + +Thu Apr 13 18:18:08 1995 Ken Raeburn + + * config/tc-sh.c (md_convert_frag): Instead of aborting on large + displacements, print an error message. Don't invoke the code that + followed the abort call until it's been verified. + + * config/tc-m68k.c (md_show_usage): Add 68060 to list. Split cpu + list into three lines. + +Thu Apr 13 14:34:36 1995 Torbjorn Granlund + + * tc-m68k.c (m68k_init_after_args): Test for m68360. + (md_parse_option): Likewise. + (md_show_usage): Mention m68360. + * tc-m68k.h (TARGET_WORD_SIZE): Define. + (TARGET_ARCH): Define. + + * expr.c (integer_constant): If TARGET_WORD_SIZE is defined, + sign-extend appropriately. + +Thu Apr 13 11:20:17 1995 Michael Meissner + + * config/tc-ppc.c (ppc_elf_validate_fix): Properly use PARAMS to + hide prototype from non-ANSI compilers, and don't use ANSI syntax + for arguments. + +Wed Apr 12 12:20:19 1995 Stan Shebs + + * mpw-config.in (TDEFINES): Put empty definition into + makefile fragment. + * mpw-make.in (xmalloc.c.o): Remove. + (as.new): Depend on Version.r. + (Version.r): Generate from version info. + + * mpw-make.in: Delete references to hex-value.c. + + * mpw-config.in: Add mapping from configs to object file formats, + get VERSION from Makefile.in and add to mk.tmp. + (mips-idt-ecoff) [TDEFINES]: Add TARGET_BYTES_BIG_ENDIAN. + * mpw-make.in (VERSION, gC): Don't define. + (ALL_CFLAGS): Remove -d flags. + (config.h): Remove definition of MPW, add HAVE_STDARG_H, + BFD_ASSEMBLER. + + * mpw-make.in (ALL_CFLAGS): Add definition of HAVE_STDARG_H, + include of ::libiberty:. + (config.h): Ifdef contents on GAS_VERSION. + + * mpw-make.in (as.c): Compile with C not gC. + (config-stamp): Touch correctly. + (install-only): New target. + (install): Depend on all and install-only. + + * mpw-config.in: Parse target and use to generate forward includes + to tc-, obj-, and atof- files, use te-generic.h for emulation. + * mpw-make.in (VERSION): Define. + (as.c): Compile with GCC. + (TARG_OBJECTS, CLIBS): Define. + (as.new): Use LDFLAGS, TARG_OBJECTS, CLIBS and EXTRALIBS in link + command. + (config.h, config-stamp): Build. + + * mpw-make.in (C, CFLAGS): Removed definitions. + (ALL_CFLAGS): Define. + Set default rule to use {CC} instead of {C}. + + * mpw-make.in (install): Moved here from mpw-build.in. + * mpw-build.in: Removed, functionality in mpw-make.in + + * mpw-make.in (CFLAGS): Add more include paths. + + * mpw-config.in (varargs.h, sys/*.h): Don't create when + configuring. + * mpw-make.in (CFLAGS): Add -w flag. + + * mpw-make.in: Replace 8-bit chars with their names. + + * mpw-config.in: New file, MPW version of configure.in. + * mpw-make.in: New file, MPW version of Makefile.in. + + +Tue Apr 11 01:42:36 1995 Ken Raeburn + + * configure.in: Require at least autoconf 2.3, because earlier + versions lose on some AIX versions. + * configure: Regenerated. + + * configure.in: Add m68k-*-elf. + * config/tc-m68k.c (comment_chars) [OBJ_ELF]: Include '#'. + (md_pseudo_table) [OBJ_ELF]: Ignore "swbeg". + (md_begin): Set alt_notend_table['&'], so svr4-style immediate + operands are accepted. + (md_apply_fix): Argument VALP should point to valueT. + (md_convert_frag): Argument SEC should be type segT. + (md_shortopts) [OBJ_ELF]: Accept 'Q' with an argument. + (md_parse_option): Ignore it. + (md_convert_frag_1): Add in frag address for the symbol in the + displacement calculation. + * config/tc-m68k.h (TARGET_FORMAT) [OBJ_ELF]: Use "elf32-m68k". + (TARGET_ARCH): Define. + (REGISTER_PREFIX_OPTIONAL) [OBJ_ELF]: Default to 0. + (LOCAL_LABEL, FAKE_LABEL_NAME, REGISTER_PREFIX_OPTIONAL): Handle + these the same way for OBJ_ELF as for M68KCOFF. + + * gdbinit.in: Add breakpoint in as_abort. + + * write.c (cvt_frag_to_fill): If offset is less than zero, + complain about it specifically, instead of reporting an assertion + failure. + (relax_segment): Complain about .org backwards, then ignore it. + Do generic rs_machine_dependent relaxation only if + TC_GENERIC_RELAX_TABLE is defined, and use its value for the base + of the table. + * tc.h (md_relax_table): Delete declaration. + * as.h (struct relax_type): Add forward declaration for type. + * config/tc-a29k.c: Deleted md_relax_table. + * config/tc-{alpha,arm,h8300,hppa,i860,m88k,mips,ppc,sparc,z8k}.c: + Ditto. + * config/tc-{h8500,i386,i960,ns32k,sh,tahoe,vax,w65}.h: Declare + md_relax_table here, and define TC_GENERIC_RELAX_TABLE to expand + to md_relax_table. + * config/tc-h8500.c (md_relax_table): No longer const. + * config/tc-w65.c (md_relax_table): Ditto. + * config/tc-sparc.c (md_short_jump_size, md_long_jump_size): + Deleted. + * doc/internals.texi: Describe TC_GENERIC_RELAX_TABLE and + WORKING_DOT_WORD. Mention md_*_jump_size (but description needs + to be fleshed out later). Note m68k PCINDEX mode has been checked + in. + +Mon Apr 10 15:57:42 1995 Ken Raeburn + + * config/tc-mips.c (nopic_need_relax): New static function, split + out from md_estimate_size_before_relax. + (md_estimate_size_before_relax): Call it. + (load_address, macro): In NO_PIC branches, if nopic_need_relax + returns nonzero, don't attempt GP optimization. + + * config/tc-m68k.c (PCINDEX): New macro. + (md_relax_table): No longer const. Add PCINDEX entries. + (m68k_ip): For AINDX with simple symbol operand, generate a + PCINDEX frag if PC is used, or do normal non-AINDX processing for + address register. + (m68k_init_after_args): If cpu is 68000 or 68010, fix + md_relax_table to prevent relaxation of PCINDEX/BYTE mode to + SHORT, since they don't support that mode. + (md_convert_frag_1, case PCLEA/LONG): Add 4 to offset, not 2. Add + support for new PCINDEX modes. + (md_estimate_size_before_relax): Process PCINDEX/SZ_UNDEF mode. + + * config/tc-m68k.c (md_convert_frag_1, case PCLEA/SHORT): Add 2 to + offset. + (m68k_ip, case most punctuation/AOFF): If using PC, call add_frag + using PCLEA. + + * config/tc-m68k.c: Don't explicitly include config.h. Deleted a + bunch of "#if 0" code and useless comments. + (struct m68k_cpu): New type. + (archs, n_archs): New variables, with single list of name/enum + mapping and aliases. + (m68k_ip): Delete the table here. + (m68k_init_after_args): Use the new table here instead of + open-coding it. + (md_parse_option, case 'm'): Ditto. + + * doc/Makefile.in (Makefile): Fix rule for running config.status. + (internals.dvi, internals.ps, internals.ps4): New targets, not + built by default. + + * doc/internals.texi: Add loud disclaimer. Refill to 79 columns, + specify fill-column in local-variables section. Change + subheadings to subsections so they can be cross-referenced. + Describe broken words, frags, frag chains, generic relaxation, + relax table, m68k relaxation, m68k addressing modes, test suite + code. Add a few words about various file formats. + + * doc/as.texinfo (m68k): Recommend using `%' with registers as the + normal case, instead of the exceptional case. + + +Thu Mar 30 14:38:47 1995 H.J. Lu (hjl@nynexst.com) + + * configure.in: Change linux to default to elf. Using + i[345]86-*-linuxaout will defaults to a.out. + * configure: Rebuild. + +Wed Mar 29 17:16:30 1995 Torbjorn Granlund + + * config/tc-m68k.c (md_apply_fix_2): Cast negative offsets to offsetT + (for hosting on 64 bit machines). + +Tue Mar 21 16:53:27 1995 Ian Lance Taylor + + * config/tc-mips.c (md_show_usage): Mention -mips4 and -m4650. + +Fri Mar 17 16:47:13 1995 Stan Shebs + + * write.c (write_object_file): Add PROGRESS macros. + +Fri Mar 17 12:40:34 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_comm): Make sure to always reset the frag + and section for common symbols. + +Thu Mar 16 17:26:18 1995 Michael Meissner + + * config/tc-ppc.c (ppc_elf_validate_fix): Allow non PC relative + pointers in the .ctors and .dtors section also when using the + -mrelocatable option. + (md_parse_option): Support -m403 as a PowerPC computer. + (md_show_usage): Ditto. + +Wed Mar 15 14:45:42 1995 Ian Lance Taylor + + * ecoff.c (ecoff_build_debug): The cur_scope field of a fil_ptr + may be NULL when given strange input. Don't core dump. + +Tue Mar 14 21:36:34 1995 Ian Lance Taylor + + * config/tc-mips.c (load_register): Don't use addiu for dli of an + unsigned seemingly negative number. Don't bother shifting a zero + value. + (mips_ip): For case 'j', if there are more alternatives, and the + ISA level is at least 3, don't accept an unsigned seemingly + negative number. + +Tue Mar 14 19:16:43 1995 Ken Raeburn + + * read.c (s_app_line): Fix last patch to deal with a line number + of 1. + +Tue Mar 14 17:00:57 1995 Michael Meissner + + * config/tc-ppc.c (ppc_elf_validate_fix): Use as_warn_where, not + as_bad_where to give a warning instead of an error. + +Mon Mar 13 17:03:46 1995 Pat Rankin (rankin@eql.caltech.edu) + + * config/tc-vax.c (md_assemble): issue a warning if a constant + is used as an operand where an immediate value is not allowed. + +Fri Mar 10 19:21:19 1995 Ken Raeburn + + * config/obj-coff.c: Redo my 10 Jan change, but get it right this + time. :-) + (fixup_segment): If linkrelax is set, just return. + (write_object_file): Don't treat h8300 and z8k specially with + regard to fixups. + * config/tc-h8300.c (md_begin): Set linkrelax. + * config/tc-z8k.c (md_begin): Ditto. + +Thu Mar 9 18:01:37 1995 Ian Lance Taylor + + * config/obj-coff.c (coff_header_append): Check return value of + bfd_coff_swap_scnhdr_out. + +Thu Mar 9 13:51:30 1995 Doug Evans + + Delete this patch, it breaks the h8300 assembler. + Tue Jan 10 13:34:14 1995 Ken Raeburn + * config/obj-coff.c (write_object_file): Don't treat h8300 and z8k + specially with regard to fixups. + +Thu Mar 9 12:28:18 1995 Michael Meissner + + * config/tc-ppc.c (mrelocatable): Change type to boolean. + (md_begin): Set the EF_PPC_RELOCATABLE if -mrelocatable. + +Wed Mar 8 15:39:39 1995 Ian Lance Taylor + + * config/tc-mips.c (md_begin): Check for a cpu string of r8000 or + r10000. If mips_isa is 4, set the machine number to 8000. + (append_insn): If mips_isa is at least 4, don't generate nops for + coprocessor delays. Check INSN_READ_FPR_R when setting + mips_cprmask[1]. + (mips_emit_delays): If mips_isa is at least 4, don't generate nops + for coprocessor delays. + (mips_ip): Check for INSN_ISA4 instructions. Handle new argument + types 'h', 'R', 'N', and 'M'. + (md_longopts): Accept "mips4". + (md_parse_option): Handle -mips4, and -mcpu=10000 and -mcpu=8000. + (s_mipsset): Permit .set mips4. + +Wed Mar 8 09:36:05 1995 Michael Meissner + + * config/tc-ppc.c (ppc_elf_validate_fix): Allow .stab sections to + have non PC relative relocations with -mrelocatable. + +Wed Mar 8 02:57:53 1995 Ken Raeburn + + * config/tc-m68k.c (opcode_ptr): Return pointer to const. + (md_begin): Make hash table errors fatal. Process opcode aliases + after main opcode table. + (md_apply_fix_2, case 4): Recode setting of lower_limit to avoid + gcc warning. + + +Tue Mar 7 16:07:10 1995 Ian Lance Taylor + + * doc/as.texinfo: Add documentation for SPARC V9, from Doug Evans + . + +Mon Mar 6 09:58:34 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c: Change all occurences of pa-89 with pa-11 to + be consistent with current naming conventions. + (md_begin): Set a default architecture and machine type. + (pa_ip): If the current instruction specifies a newer machine type + than the current machine type, then update the current machine + type. + (need_pa11_opcode): Likewise. + +Sun Mar 5 19:38:09 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_ip, case 'z'): Don't lose argument + relocation bits for absolute calls. + +Fri Mar 3 17:41:50 1995 Ken Raeburn + + * config/tc-h8300.* (md_operand): Change empty function to empty + macro. + + * config/tc-h8300.c (build_bytes): Make H8/300-H warning message + clearer. + + * write.c (write_contents): If bfd_set_section_contents fails, + print a message and exit, instead of aborting. + +Fri Mar 3 16:26:19 1995 Michael Meissner + + * tc.h (md_apply_fix3): If MD_APPLY_FIX3 is defined, declare + md_apply_fix3. + + * write.c (fixup_segment): If MD_APPLY_FIX3 is defined, call + md_apply_fix3 with the normal 2 arguments and the current segment + pointer instead of md_apply_fix. + + * config/tc-ppc.h (MD_APPLY_FIX3): Define. + + * config/tc-ppc.c (ppc_elf_validate_fix): Warn if -mrelocatable + and a non PC relative relocation that isn't in the .got2 segment + was performed. + (md_apply_fix3): Rename from md_apply_fix and take segment pointer + as third argument. If ELF object format, call ppc_elf_validate_fix + for normal relocations. + (md_parse_option): If ELF object format, recognize the + -mrelocatable switch. + +Thu Mar 2 16:34:44 1995 Ian Lance Taylor + + * config/tc-i386.h (AOUT_MACHTYPE): Define as 100, not 0. + +Tue Feb 28 18:29:27 1995 Ken Raeburn + + * config/tc-arm.c, config/tc-arm.h (md_operand): Replaced empty + function in .c file with empty macro in .h file. + * config/tc-h8500.*, config/tc-hppa.*, config/tc-i386.*, + config/tc-i860.*, config/tc-i960.*, config/tc-ns32k.*, + config/tc-ppc.*, config/tc-sh.*, config/tc-sparc.*, + config/tc-tahoe.*, config/tc-vax.*, config/tc-w65.*, + config/tc-z8k.*: Ditto. + * config/tc-m68k.*: Ditto. + + * config/tc-m68k.c (mote_pseudo_table): Removed dots from opcode + names. + + * read.c (s_app_line): Ignore non-positive line numbers. + +Tue Feb 28 15:34:14 1995 Ian Lance Taylor + + * config/tc-i386.c (tc_i386_fix_adjustable): Don't adjust PLT or + GOT relocs either. + +Mon Feb 27 13:03:41 1995 Kung Hsu + + * configure.in: add a29k-*-vxworks configuration. + +Fri Feb 24 14:41:15 1995 Ian Lance Taylor + + * config/tc-mips.c (load_register): Take dbl argument to determine + handling of signed 32 bit values in 64 bit modes. Change all + callers. + (macro): Handle M_DLI and M_DLA_AB. + +Wed Feb 22 23:10:56 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_apply_fix): Don't subtract the value of the + add symbol if it's a common symbol (the value of a common symbol + is its size, not a value in the traditional sense). + +Wed Feb 22 21:12:28 1995 Ian Lance Taylor + + * config/tc-mips.c (append_insn): If listing_prev_line is called, + call frag_grow to make sure there is still room for a variant. + +Fri Feb 17 14:50:08 1995 Ian Lance Taylor + + * config/tc-mips.c (md_pseudo_table): Add 2byte, 4byte and 8byte + if OBJ_ELF. From gary@Intrepid.COM (Gary Funck). + + * config/obj-elf.c (elf_frob_symbol): Warn if a symbol is both + weak and common. + * config/obj-aout.c (obj_aout_frob_symbol): Likewise. + +Fri Feb 17 12:43:47 1995 Michael Meissner + + * config/tc-ppc.c (md_pseudo_table): Don't redefine byte under + ELF. + (ppc_elf_cons): Don't support @pcrel any more, since DIFF_EXPR_OK + allows the normal expressions to generate it. + (md_apply_fix): Convert BFD_RELOC_32 with pcrel bit set into + BFD_RELOC_32_PCREL. Abort if either BFD_RELOC_16 or BFD_RELOC_8 + need PC relative relocations. + + * config/tc-ppc.h (DIFF_EXPR_OK): Define to allow PC relative + expressions to be handled. + +Thu Feb 16 14:30:13 1995 Doug Evans + + * expr.c (operand): Move md_operand handling to default case + (so it works). + +Wed Feb 15 16:08:47 1995 Jason Molenda + + * config/tc-h8500.c (tc_coff_symbol_emit_hook): Add ignored + parameter, to match prototype. + +Wed Feb 15 15:07:00 1995 Michael Meissner + + * config/tc-ppc.c (md_pseudo_table): If ELF, go to ppc_elf_cons + instead of cons. + (md_show_usage): Show all of the PowerPc options. + (ppc_elf_suffix): New function to recognize ELF suffixes that + specify a relocation, such as @GOT. + (ppc_elf_cons): Replacement for the standard cons function that + knows about the ELF suffixes. + (ppc_fixup): Add reloc field to hold non-standard relocation. + (md_assemble): Handle ELF suffixes like @GOT. + (md_create_short_jump): Dummy in case WORKING_DOT_WORD is not + defined. + (md_create_long_jump): Ditto. + (md_short_jump_size): Ditto. + (md_long_jump_size): Ditto. + (md_apply_fix): Handle BFD_RELOC_32_PCREL, BFD_RELOC_LO16, + BFD_RELOC_HI16, BFD_RELOC_HI16_S, BFD_RELOC_PPC_TOC16, and + BFD_RELOC_16 relocations. If relocation can not be found, print + the decimal value of the relocation. + +Wed Feb 15 11:46:02 1995 Ian Lance Taylor + + * config/tc-mips.c (md_apply_fix): Accept BFD_RELOC_16, for + DWARF. From gary@Intrepid.COM (Gary Funck). + + * config/tc-mips.c (macro): Handle M_U{L,S}D[_A] (unaligned double + loads and stores). + + * config/tc-i386.c (tc_i386_fix_adjustable): Do adjust global + symbols if OBJ_AOUT. + + * config/tc-mips.c (macro): Don't use the target register as a + base register when building the address for M_L{W,D}{L,R}_AB. + +Mon Feb 13 14:44:32 1995 Ian Lance Taylor + + * config/tc-mips.c (KT0, KT1): Define. + (mips_ip): Recognize $kt0 and $kt1 as register names. + + * config/tc-sparc.h (tc_fix_adjustable): Define if OBJ_ELF. + * config/tc-sparc.c (md_apply_fix): If OBJ_ELF, subtract out the + value of a defined symbol; the value was added in by + fixup_segment. This was previously corrected, if the reloc was + changed to be against a section symbol, in tc_gen_reloc. + + +Fri Feb 10 14:04:04 1995 Ian Lance Taylor + + * config/tc-i386.c (tc_i386_fix_adjustable): Use S_IS_EXTERN + rather than !S_IS_LOCAL. + + +Thu Feb 9 18:16:34 1995 Ian Lance Taylor + + * config/tc-i386.c (md_assemble): Adjust conditions for changing + BFD_RELOC_32 to BFD_RELOC_386_GOTPC to handle a switch in frags. + Patch originally from Rob Ryan . + + * config/tc-i386.c: Include subsegs.h. + (tc_i386_fix_adjustable): Declare return value. + (i386_operand): Don't use an assignment directly as a condition. + +Thu Feb 9 10:37:13 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_apply_fix): In some cases subtract the + value of the add symbol from valp. Offsets braindamage in the + "machine independent" fixup_segment. + +Wed Feb 8 18:51:23 1995 Ken Raeburn + + * messages.c (as_abort): New function. + * as.h (as_abort): Declare it. + (abort): New macro. + + Thu Jan 19 18:10:05 1995 Pat Rankin (rankin@eql.caltech.edu) + + * config/vms-conf.h (HAVE_UNISTD_H): define it unconditionally. + * config-gas.com: test for availability of ; create a + rudimentary one if necessary. + +Tue Feb 7 13:34:46 1995 Michael Meissner + + * configure.in: Add powerpc-*-eabi support, which is the same as + powerpc-*-elf. + (configure): Rebuild with autoconf. + +Mon Feb 6 03:37:00 1995 Ken Raeburn + + Changes from Bryan Ford for i386 + 16-bit and msdos support: + * config/tc-i386.c (flag_16bit_code): New variable. + (set_16bit_code_flag): New function. + (md_pseudo_table): Added entries "code16" and "code32". + (md_assemble): Ensure that correct data-size prefixes get emitted, + based on the current mode. Ensure that 32-bit addressing will + always be done. Move segment-prefix handling code. (Why?) Use + 16-bit jumps for 16-bit code, 32-bit jumps for 32-bit code. + * config/tc-i386.h (MAX_PREFIXES): Bump to 5. + (Data16, Data32): Define. + * doc/as.texinfo (i386-16bit): New node. + * configure.in (i386-*-msdos*): New target, using a.out format. + * configure: Regenerated. + +Thu Feb 2 15:21:24 1995 Ken Raeburn + + * config/tc-m68k.c (cpu32_control_regs): New macro. + (m68k_init_after_args): Use it, for cpu32 processors. + + Tue Jan 31 17:20:45 1995 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.c (vms_tir_stack_psect): new routine; + (VMS_Set_Data, VMS_Set_Psect, VMS_Store_PIC_Symbol_Reference, + VMS_TBT_Routine_Begin, VMS_TBT_Line_PC_Correlation): use it; + (VMS_Global_Symbol_Spec, VMS_Procedure_Entry_Pt): treat + Psect_Number as `unsigned'. + + Thu Jan 26 17:06:28 1995 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.c: performance tuning. + (VMS_Symbol_type_list): convert from single list head to small + array of list heads; + (SYMTYP_HASH): new macro for accessing VMS_Symbol_type_list[]; + (find_symbol, setup_basic_type, VMS_typedef_parse): use it; + (VMS_RSYM_Parse): move S_GET_VALUE() inside switch to avoid + calling it for uninteresting cases. + +Wed Feb 1 23:52:45 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_apply_fix): Go ahead and call + hppa_field_adjust to get a new value for R_DATA_ONE_SYMBOL + relocations in SOM. + (hppa_fix_adjustable): Refine somewhat. + +Fri Jan 27 21:29:53 1995 Michael Meissner + + * config/tc-ppc.h (NO_STRING_ESCAPES): Don't define if we are + using ELF. + +Thu Jan 26 19:03:42 1995 Ken Raeburn + + * config/tc-h8300.c (get_specific): Add parens around | inside &. + (skip_colonthing): Set L_8 if ":8" is specified. + +Thu Jan 26 18:38:01 1995 Ian Lance Taylor + + * config/tc-ppc.c (md_begin): Permit mfdec to be duplicated on the + 601. Check that the error return from hash_insert is "exists". + +Thu Jan 26 11:35:33 1995 Michael Meissner + + * configure: Add support for configuring powerpc-*-eabi. + + * config/tc-ppc.c (GOT_symbol): Define if object format is ELF. + + * config/tc-ppc.h (GLOBAL_OFFSET_TABLE_NAME): Define if object + format is ELF and not defined to be "_GLOBAL_OFFSET_TABLE_". + +Wed Jan 25 16:23:13 1995 Jim Wilson + + * tc-sh.c (little): Add argument IGNORE to avoid compiler warnings. + (md_pseudo_table): Add space for consistent formatting. + (COND8_RANGE, COND12_RANGE): Delete unused macros. + (COND8_F, COND8_M, COND12_F, COND12_M, UNCOND12_F, UNCOND12_M): + Correct minimum and maximum branch offsets. Add comments explaining + why these numbers are correct. + +Wed Jan 25 15:32:09 1995 David Edelsohn + + * config/tc-ppc.c (md_parse_option): Accept mpwr2 as a synonym for + mpwrx; mppc32, m603, and m604 as synonyms for mppc; and mppc64 and + m620 for PowerPC64 mode. + (ppc_symbol_new_hook): Add T0 as synonym for TC0 suffix. + +Tue Jan 24 16:44:23 1995 Ken Raeburn + + * config/tc-vax.c (vip): Introduce new ptr-to-const local variable + for scanning operand string. + + Sat Jan 21 17:50:38 1995 Pat Rankin (rankin@eql.caltech.edu) + + * config/vax-inst.h (struct vop, fields `vop_warn', `vop_error'): + make them pointers to const char; + (struct vit, field `vit_error'): ditto. + * config/atof-vax.c (md_atof): rename local `littlenum_pointer' + to `littlenumP' to avoid shadowing file scope variable. + * config/tc-vax.c (vip_begin, vip_op_defaults, vip_op_1): make + string arguments be pointers to const char; + (vip): make `alloperr' const char *; + (vip_op): make `err' and `wrn' const char *; rename `access' to + `access_mode' to avoid shadowing library function. + * config/obj-vms.c (`symbol_name'): make it const char *; + (get_struct_name): cast one use of `symbol_name' to char * + [caller guarantees that it won't modify the pointer's target]; + (PUT_COUNTED_STRING): use pointer to const char; + (VMS_typedef_parse): make `pnt2' const char *; + (Write_VMS_MHD_Records): make `cp' const char *; + (VMS_Modify_Psect_Attributes, array `Attributes'): make const, + and make field `Name' pointer to const char; + + * as.h (`seg_name[]' declaration): pointers to const char; + (struct _pseudo_type, field `poc_name'): pointer to const char. + * subsegs.c (`seg_name[]' definition): ditto; + * hash.c (hash_ask): rename argument `access' to `access_type' + to avoid shadowing library function. + * write.c (variable `the_object_file'): move from file scope + to block scope within write_object_file(); free it after use; + (fixup_segment): conditionally exclude it for OBJ_VMS. + (cvt_frag_to_fill): rename argument `headers' to `headersP' + to avoid shadowing file scope variable. + +Mon Jan 23 21:42:39 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_ip, case 'D'): Fix typo which caused + miscompilation of "diag" instructions. + +Mon Jan 23 15:51:41 1995 Ken Raeburn + + * configure: Regenerated. + + * config/tc-mips.c: Include libiberty.h. + +Mon Jan 23 14:07:58 1995 Ian Lance Taylor + + * config/tc-sh.h (tc_init_after_args): Don't define. + * config/tc-sh.c (md_begin): Remove unused variable table. + (md_assemble): Remove unused variable p. + (md_convert_frag): Cast fr_address to unsigned long for printf. + (md_apply_fix): Use as_warn_where rather than as_warn. + (sh_init_after_args): Remove empty function. + + * configure.in (i386-*-gnu*elf*): New target. + +Sat Jan 21 19:02:23 1995 Ian Lance Taylor + + * hash.c (hash_ask): If we find the slot after wrapping around, + break out of the loop. Fixes bug in Jan 18 change. + +Fri Jan 20 17:07:31 1995 Ken Raeburn + + * hash.c (hash_code): Undo last change. + +Thu Jan 19 14:49:47 1995 Ken Raeburn + + * config/tc-alpha.c (alpha_ip): Initialize local variables to keep + gcc quiet. + (gpdisp_hi16_howto): Don't use "const" with reloc_howto_type. + (in_range_signed): Add parens around subtraction inside shift. + * gasp.c (do_data): Initialize local variable "opname". + (istrue): Provide a default case to set "res" and keep "gcc -Wall" + quiet. + * write.c (write_contents): Deleted unused variable. + (print_symbol_value_1): Declare. + * hash.c (hash_ask): Delete disabled non-strcmp version of the + code, and automatic variables used only in those sections. + * write.c (chain_frchains_together_1): Only define local variable + "prev_fix" if BFD_ASSEMBLER. + * flonum-konst.c (dummy1): Return void. + * config/tc-vax.c (md_assemble): Remove two comparisons of + unsigned numbers versus zero. + * as.h (bcopy): If neither memcpy nor bcopy is defined as a macro, + define to use memcpy. + + * config/tc-alpha.c, config/alpha-opcode.h: Revert 2 June changes. + Turns out we never got the assignment done after all. + + Cleanup of VAX and VMS code, from Pat Rankin: + * config/obj-vms.c: Changed exported function names to lower case. + (Changed call sites in write.c.) Declare VMS system function + names used, conditional on actually being on VMS. Changed many + functions that returned no useful value to now be declared to + return void. Removed many unused variables. Supply missing + return statements or values. Supply `default' case in switch + statements. Ensure local variables get initialized. + * config/tc-vax.c: Minor changes to silence "gcc -Wall". + * config/obj-vms.h, config/tc-vax.h: Added some missing + declarations. + +Wed Jan 18 13:49:26 1995 Ken Raeburn + + * atof-generic.c (flonum_print) [TRACE]: New function. + (atof_generic) [TRACE]: Print multiplier before multiplication, + and print multiplication result before and after copy. + + * flonum-mult.c (flonum_multip): Avoid sign extension problems + around multiplication operation. + + * atof-generic.c (ASSUME_DECIMAL_MARK_IS_DOT): Define. + (atof_generic) [ASSUME_DECIMAL_MARK_IS_DOT]: Check for '.' + explicitly instead of calling strchr. + + * config/tc-sparc.c (sparc_ip): When scanning successive opcode + table entries, check names for pointer equality before doing + string comparisons. + + * hash.c (hash_ask): Call strcmp instead of expanding it inline. + (hash_code): Replaced with a version from bfd. + + * config/obj-coff.c (write_object_file): If COFF_FLAGS isn't + defined, default it to zero. + +Wed Jan 18 12:16:07 1995 Ian Lance Taylor + + * write.c (fix_new_internal): Clear fx_bsr on those targets which + use it. + + * expr.c (operand): Parenthesize && within ||. + * listing.c (listing_newline): Likewise. + (list_symbol_table): Use %lu to print sizeof. + * symbols.c: Comment out unused function indent. + (print_symbol_value_1): Cast pointer to unsigned long for printf. + * config/obj-coff.c (do_relocs_for): Only declare symbol_ptr if it + will be used. + * config/tc-h8300.c (md_begin): Remove unused variable reg. + (get_operand): Declare type of parameter direction. Remove unused + variable size. + (get_specific): Fix comment to avoid nested comments. + (check_operand): Cast X_add_number to unsigned long for printf. + (build_bytes): Remove unused local variables output_ptr, part, and + high. + (build_bytes): Cast X_add_number to unsigned long for printf. + (clever_message): Remove unused variable scan. + (md_assemble): Remove unused variable i. + (tc_coff_sizemachdep): Remove unused function. + * tc-h8300.h (tc_reloc_mangle): Declare. + +Tue Jan 17 10:58:06 1995 Ian Lance Taylor + + * config/tc-mips.c (mips_4650): New static variable. + (md_begin): Handle a cpu string of "4650". If mips_4650 was not + initialized, set it to 0. + (append_insn): Don't insert nops around HI and LO on a 4650. + (mips_emit_delays): Likewise. + (mips_ip): Use INSN_ISA mask to check ISA of instruction. Check + for INSN_4650. + (md_longopts): Add m4650 and no-m4650. + (md_parse_option): Handle mips-cpu=4650. Handle -m4650 and + -no-m4650. + * doc/as.texinfo: Document new MIPS options. + +Sat Jan 14 23:48:13 1995 Steve Chamberlain + + * config/tc-w65.c, config/tc-w65.h, config/w65.mt: Newfiles. + * config/obj-coff.h: Cope with w65. + * configure, configure.in: Recognize w65. + +Thu Jan 12 17:56:24 1995 Ken Raeburn + + * app.c (do_scrub_next_char) [__GNUC__ && __OPTIMIZE__]: If `get' + function is scrub_from_file, call scrub_from_file directly, and + get gcc's inlining capability into the act. + + * Makefile.in (VMS_OTHER_OBJS): Add ../libiberty/hex.o. + (OBJS): Delete hex-value.o. + (REAL_SOURCES): Delete hex-value.c. + (hex-value.o): Delete dependencies. + * hex-value.c: Deleted. + * as.c (main): Call hex_init. + * expr.c, config/tc-mips.c: Include libiberty.h. Replace + hex_value array references with hex_* macros. + +Wed Jan 11 17:51:38 1995 Ken Raeburn + + * config/tc-h8300.h (COFF_FLAGS): Don't define. + * config/tc-h8500.h (COFF_FLAGS), config/tc-sh.h (COFF_FLAGS), + config/tc-z8k.h (COFF_FLAGS): Ditto. + + * config/obj-coff.c (KEEP_RELOC_INFO): Make sure it's always + defined. + + * config/tc-m68k.c (m68k_ip, cases AOFF and AINDEX): Don't + generate 68020 addressing modes for a 68000 processor. + (md_estimate_size_before_relax, cases PCREL and PCLEA): Ditto. + +Tue Jan 10 13:34:14 1995 Ken Raeburn + + * config/obj-coff.c (write_object_file): Don't treat h8300 and z8k + specially with regard to fixups. + +Mon Jan 9 16:22:28 1995 Ken Raeburn + + * config/tc-mips.c (RELAX_RELOC1, RELAX_RELOC2): Cast values to + bfd_vma before subtracting. + + * config/obj-coff.c (size_section): Handle rs_space like rs_fill, + but make sure fr_symbol is null. + (fill_section): Ditto. + +Sun Jan 8 16:14:19 1995 Ian Lance Taylor + + * config/tc-mips.c (mips_ip): Fix handling of floating point + values when GPOPT is not defined. + +Fri Jan 6 16:59:41 1995 Ken Raeburn + + * gasp.c: Include string.h. Put config.h before other includes. + + * config/tc-alpha.c (alpha_ip): Delay calls to emit_add64 until + after any remaining operands are also known to match. + +Fri Dec 30 18:21:41 1994 Ken Raeburn + + * listing.c (list_symbol_table): Build a format string based on + the size of the value to be printed, as long as "unsigned long" is + at least as wide, after handling the special case of 4-byte + values. + + * Makefile.in (dependencies): Make $(OBJS) depend on as.h and + everything it includes. Delete those files from per-file + dependencies. + + * as.h (relax_substateT): Now defined to be unsigned int. + (relax_stateT): Separate typedef from enum definition. + (enum _relax_state): Reordered for better punctuation. Added new + values rs_align_code and rs_space. + (lineno, struct lineno_struct): Unused, deleted. + + * as.h: No longer include assert.h. + (as_assert): Declare. + (assert): New definition, calls as_assert longer needed. + (__PRETTY_FUNCTION__): Provide default for older versions of gcc. + * messages.c (as_assert): New function. + * gdbinit.in: Put a breakpoint there. + + * read.c (s_space): Rewrite to handle general expressions. + Generate rs_space frags for non-constant values. + * write.c (cvt_frag_to_fill): Treat rs_align_code and rs_space + like rs_align and rs_org. Verify that fr_offset is non-negative, + and force frag type to rs_fill only after assertion checks. + (relax_segment): Treat rs_align_code like rs_align. Treat + rs_space like rs_org in the first switch; in the second, force the + operand to a constant, and use it for the growth size. + +Wed Dec 28 20:57:37 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_subspace): For sections with the ZERO + attribute, set the "bss" field in the appropriate seginfo structure. + +Wed Dec 28 15:01:01 1994 Ken Raeburn + + * subsegs.h: Include obstack.h. + +Tue Dec 27 18:16:04 1994 Ken Raeburn + + * as.h (struct frag): Enable align* components now. + +Tue Dec 20 14:56:31 1994 Ken Raeburn + + * frags.c (frag_init): Call obstack_begin on `frags'. + * subsegs.c (subsegs_begin): Don't do it here. + * as.c (main): Call frag_init before subsegs_begin. + + * frags.c (frag_append_1_char): New function. + * frags.h (frag_append_1_char): Declare it. + (FRAG_APPEND_1_CHAR): Call it. Old definition is commented out + for now. + + * as.h (struct frag): Added (but commented out) new fields for + tracking current alignment. + (frag_now_fix): Changed macro to function declaration. + * frags.c (frag_now_fix): Define function here. + (frag_new): Use it instead of accessing `frags' directly. + * frags.h (frags): Change comment to indicate it shouldn't be + accessed directly. + * subsegs.h (struct frchain): New field frch_obstack, intended to + eventually replace global `frags' obstack. + * subsegs.c (subseg_set_rest): Use frag_now_fix instead of + accessing `frags' directly. Initialize fields of new frchainS + explicitly instead of with memset. + * config/obj-coff.c (obj_coff_ln) [!BFD_ASSEMBLER]: Use + frag_now_fix. + * config/tc-mips.c (s_loc), config/obj-vms.c + (vms_resolve_symbol_redef), symbols.c (colon): Likewise. + + * config/tc-m68k.c (md_apply_fix_2): Use offsetT and addressT + instead of long and unsigned long. + (md_apply_fix): Cast value before passing it. + + * config/obj-aout.h, config/obj-coff.c, config/obj-elf.h, + config/obj-som.h, config/tc-h8500.c, config/tc-hppa.c, + config/tc-hppa.h, config/tc-sh.c, config/tc-z8k.c: Don't rely on + use of ".." when including header files. + + * config/obj-coff.c (fixup_segment): Reformat condition in an `if' + statement. + + * Makefile.in (SUBDIR_INCLUDES): Deleted. + +Tue Dec 20 13:40:36 1994 Ian Lance Taylor + + * config/obj-coff.h: Include bfd/libcoff.h, not libcoff.h. + + +Mon Dec 19 16:53:36 1994 Ian Lance Taylor + + * config/tc-mips.c (load_register): Rewrite to handle O_big 64 bit + constants. + (mips_ip): Accept O_big constants in case 'I'. Change case + 'i'/'j' to treat an O_big constant as an out of range value. + +Mon Dec 19 14:15:07 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_subspace): Make sure SEC_HAS_CONTENTS is + clear for a section with the "ZERO" attribute. + + * Reduce useless symbols for ELF in an attempt to make smaller + objects and speed up the linker. + * config/tc-hppa.c (struct call_info): Replace end_symbol field + with a size field. + (hppa_elf_mark_end_function): Delete unneeded function. + (pa_build_unwind_subspace): For the 2nd unwind relocation, use + the function symbol + function size instead of a special symbol + for the end of the function. + (process_exit): Compute the function size here. Don't call + hppa_elf_mark_end_of_function anymore. + (pa_procend): Likewise. + (hppa_fix_adjustable): Only reject 32bit relocations for SOM. + (elf_hppa_final_processing): Simplify. + + +Mon Dec 19 13:49:07 1994 Ken Raeburn + + * configure.in: Recognize mips-sony-bsd and mips-dec-bsd, but + reject other vendors until we can be sure we're consistent with + bfd. + + * config/obj-vms.c (Create_VMS_Object_File): Instead of formatting + a buffer to pass to `error', just call `as_fatal' directly. + (VMS_Psect_Spec): Ditto. + (VMS_TBT_Module_Begin, VMS_TBT_Source_File, gen1, + VMS_typedef_parse, VMS_LSYM_Parse, VMS_Emit_Globalvalues): Call + as_tsktsk instead of printf. + (VMS_TBT_Module_Begin, VMS_TBT_Line_PC_Correlation, + VMS_TBT_Source_File, VMS_TBT_Source_Lines, + VMS_Store_Repeated_Data, VMS_Check_For_Main): Use explicit + integers rather than sizeof expressions using basic integer types, + in case host and target aren't the same. Use memcpy or COPY_* + macros instead of possibly unaligned word or longword assignment. + + * config/obj-vms.h (OBJ_SYMFIELD_TYPE): New macro. + * config/obj-vms.c (VMS_Store_PIC_Symbol_Reference, + VMS_Check_For_Main, VMS_write_object_file): Use sy_obj instead of + forcing sy_number to hold a pointer. + +Fri Dec 16 14:40:16 1994 Ken Raeburn + + * config/tc-sh.c (md_begin): Don't fill in md_relax_table here. + (md_relax_table): Use static initialization. + + * config/tc-h8300.c (parse_exp, get_operands, clever_message, + md_assemble, tc_crawl_symbol_chain, md_undefined_symbol, + tc_headers_hook, md_operand, md_number_to_chars): Don't use DEFUN. + + * Makefile.in (CHECKFLAGS): Don't pass AS_FOR_TARGET, + CC_FOR_TARGET, OBJDUMP_FOR_TARGET, NM_FOR_TARGET; they're not + used. + (AS_FOR_TARGET, CC_FOR_TARGET, OBJDUMP, OBJDUMP_FOR_TARGET, NM, + NM_FOR_TARGET): Don't define. + (VMS_OTHER_OBJS): Add xmalloc.o and xexit.o from libiberty. + (tooldir): Use exec_prefix, not libdir. + +Fri Dec 16 11:07:10 1994 Stan Shebs + + * config/obj-coff.h: Include libcoff.h, not ../bfd/libcoff.h. + + * as.h: Include progress.h. + * as.c (main): Call START_PROGRESS and END_PROGRESS. + (main, perform_an_assembly_pass): Call PROGRESS. + +Fri Dec 16 00:46:08 1994 Ian Lance Taylor + + * write.c (adjust_reloc_syms): Use bfd_is_und_section and + bfd_is_abs_section rather than comparing against &bfd_und_section + and &bfd_abs_section. + +Thu Dec 15 15:27:14 1994 Jim Wilson + + * config/tc-sh.c (md_begin): Use a local variable when + initializing md_relax_table to avoid errors about modifying a + const data structure. + +Tue Dec 13 15:42:27 1994 Ian Lance Taylor + + * config/tc-ppc.c (tc_gen_reloc): Remove OBJ_ELF hack which + appears to no longer be needed. + +Tue Dec 13 08:04:15 1994 Ian Lance Taylor + + * config/tc-mips.c (macro_build): Accept BFD_RELOC_PCREL* without + requiring that the X_op_symbol be in the text_section. + (macro): Change the test for a legel expression difference to + correspond to changes in pseudo_set in read.c. + +Fri Dec 9 21:04:17 1994 Ken Raeburn + + * write.c (write_relocs) [RELOC_EXPANSION_POSSIBLE]: Use + bfd_install_relocation. + + * ecoff.c (ecoff_set_gp_prolog_size): If there is no current + routine, just return. + + * config/tc-alpha.c (alpha_ip, case 'B', subcase 'c'): Use opcode + value from pattern instead of assuming jsr. + * config/alpha-opcode.h (jmp): Add a "1,Bc" form. + +Thu Dec 8 17:48:25 1994 Ken Raeburn + + * Makefile.in (NM_FOR_TARGET): Use ../binutils/nm.new, not just + plain nm. + + * configure.in (ns32k-pc532-mach*): Select correct emulation. + (mips-sony-bsd*): Use ecoff. + (mips-*-gnu*): New target, using aout format, from Roland McGrath. + * configure: Regenerated. + + +Tue Nov 29 13:58:10 1994 Ken Raeburn + + Use libiberty version of xmalloc: + * Makefile.in (REAL_SOURCES): Delete xmalloc.c. + (OBJS): Delete xmalloc.o. + (xmalloc.o): Delete dependencies. + * as.c (main): Call xmalloc_set_program_name once program name is + known. + + * config/tc-alpha.c (in_range_signed, in_range_unsigned): New + routines, split from in_range. + (in_range): Deleted. All calls changed to in_range_*signed. + (create_lita_section): Macro deleted. Single use expanded in + place. + (alpha_ip): Handle `t' and `8' operand types. + (md_apply_fix): Handle BFD_RELOC_12_PCREL. Print name of + unhandled relocation types. + * config/alpha-opcode.h: Added HALT and DRAINA. Disabled MOVI, + since it doesn't work, and isn't supported by the native + assembler. + + * input-scrub.c: Change wording of a comment to avoid interference + with Cygnus source-control tools. + + * as.h (errno) [NEED_DECLARATION_ERRNO]: Declare. + + * config/tc-m68k.c (init_table): List buscr and pcr control + registers. + (m68k_ip, case 'J'): Handle them. + + Delete signal handler code. It's been disabled since March 1993 + without complaints. + * as.c: Don't include signal.h. + (got_sig): Unused function deleted, declaration deleted. + (SIGTY): Macro deleted. + (main): Deleted disabled code for establishing signal handler. + + +Mon Nov 28 11:37:35 1994 Doug Evans + + * app.c (do_scrub_next_char): Insert missing newline at end of file + like warning says we do. + +Mon Nov 28 00:11:15 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.h (pa_check_eof): Declare new extern function. + (tc_frob_file): Define to call pa_check_eof. + + * config/tc-hppa.c (pa_check_current_space_and_subspace): New + function to verify the current space and subspace are reasonable. + Call for the appropriate pseudo-ops and before instruction parsing. + (pa_check_eof): New function to verify enter/exit and proc/procend + pairs match at EOF. + (pa_code): Simplify. + + * config/obj-som.c: Delete #if 0 code. + +Wed Nov 23 19:36:09 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * config/obj-coff.h (TARGET_FORMAT): Select between coff-shl and + coff-sh. + * config/sh.mh (TARG_CPU_DEPENDENTS): Get it right. + * config/tc-sh.c (little): New function. + (md_parse_option): Notice new option. + (build_relax, build_Mytes, md_atof, md_convert_frag, md_apply_fix): + Cope with little endian data. + * config/tc-sh.h (COFF_MAGIC, LISTING_HEADER): Endian dependent. + +Wed Nov 23 10:54:38 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (tc_gen_reloc, ELF variant): Revert last + change. The real bug was in bfd/elfcode.h and has been fixed. + +Tue Nov 22 23:31:20 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (tc_gen_reloc, ELF variant): Add section->vma + to the relocation's offset. + +Tue Nov 22 14:37:58 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * Makefile.in (INSTALL_XFORM): Fix typo. + +Tue Nov 22 10:23:25 1994 J.T. Conklin + + * config/tc-alpha.c (s_alpha_set): Ignore the .set (no)move and + .set (no)volatile directives. + +Tue Nov 15 21:44:13 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_subspace): Make sure to always reset + current_subspace. + (pa_text, pa_data): Likewise. + + * config/tc-hppa.c (pa_align): New function. Aligns the current + offset within the current subspace along with updating the + alignment of the subspace itself. + (pa_subspace): Default alignment to one byte rathern than zero + bytes to avoid setting alignment to log2(0). + (md_pseudo_table): Use pa_alignment for .align. + +Tue Nov 15 15:24:45 1994 Ken Raeburn + + * messages.c (as_fatal): Always put a space after "fatal error:" + when printing message. + +Tue Nov 15 11:10:43 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.h (obj_frob_symbol): Delete. + (tc_frob_symbol): Make definition conditional on OBJ_SOM or + OBJ_ELF. For ELF subtract out symbol->section->vma for non common + symbols. + +Wed Nov 9 14:53:03 1994 Ken Raeburn + + * config/te-delta.h: New file, derived from te-sysv32.h. + +Wed Nov 9 11:52:44 1994 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-ppc.c (ppc_bf): Always set coff_line_base. + +Mon Nov 7 01:58:49 1994 Ken Raeburn + + * Makefile.in (VERSION): Bump to 2.5.3. + + * configure.in: Compare generic cpu name against "sparc", not + "sparc*", since sparc variants should be changed to "sparc". + * configure: Regenerated with autoconf 2.1. + + * config/tc-a29k.c (octal, toHex): Variables deleted. + (isoctal): Macro deleted. + (md_begin): Don't initialize them. + (machine_ip, case 'P'/'A'): For absolute operand, generate an + error message if it's out of range. + (md_apply_fix, case RELOC_JUMPTARG): Check range for PC-relative + jumps. + (md_apply_fix): Delete code inside "#if 0". + +Thu Nov 3 20:20:40 1994 Ken Raeburn + + * config/go32.mh: Unused file deleted. + + * read.c (get_absolute_expression): Indicate that the error may + merely be that the expression can't currently be reduced. + +Thu Nov 3 16:09:59 1994 J.T. Conklin (jtc@rtl.cygnus.com) + + * config/tc-m68k.h (TARGET_FORMAT): If TE_NetBSD define as + "a.out-m68k-netbsd". + * config/tc-sparc.h (TARGET_FORMAT): If TE_NetBSD define as + "a.out-sparc-netbsd". + + * config/te-nbsd.h: New file, NetBSD target emulation + * config/te-netbsd.h: Removed. + * configure.in (i[345]86-*-netbsd*,m68*-*-netbsd*,sparc*-*-netbsd*): + Set bfd_gas. Use nbsd emulation. + +Thu Nov 3 17:44:47 1994 Ken Raeburn + + Changes from net 2.5.2 release branch: + + * configure.in: Put AC_DEFINE(sparcv9) on its own line, so that + the shell variable settings associated with it are permanent. For + CPUs requiring bfd_gas=yes, select it based on CPU only, not + individual target names. Handle m68k-hp-hpux*, not just -hpux. + + * config/tc-z8k.c (tc_coff_symbol_emit_hook): Add dummy argument + to match prototype in obj-coff.h. + + * configure.in: Skip tests for defining WANT_FOPEN_BIN and + IBM_COMPILER_SUX. + * acconfig.h: Deleted them. + * configure, conf.in: Rebuild with autoconf 2.0. + * config/go32.cfg, config/vms-conf.h: Updated. + + * config/tc-m68k.c (md_apply_fix_2, md_convert_frag_1): Always use + IBM_COMPILER_SUX version of code, with comments indicating why. + + * listing.c (file_info): Use text mode when opening file for read. + Use "r" directly, no macro. + * input-file.c (input_file_open): Don't use FOPEN_RT, just use + "r". + * read.c (s_include): Ditto. + * output-file.c (output_file_create): Try both "wb" and "w", don't + bother with FOPEN_* macros. + * as.h: Don't include fopen-*.h. + + * config/alpha-opcode.h: Make "ret" with no operands equivalent to + "ret zero,(ra)", to match OSF1 and to be consistent with both + one-operand forms. + + Patches from DJ Delorie: + * as.h (alloca): undef alloca before defining it just in case + * config/go32.cfg: new file for autoconf values + * config/te-go32.h: new file + * configure.bat: new for autoconf + + * config/tc-i386.c (md_assemble): Fix typo in GOTPC check; had = + for ==. + + * configure.in: If target_frag doesn't exist, use /dev/null. + + * as.c (parse_args): For non-VMS systems, re-add `v' to + std_shortopts. Add "verbose" to list of long options. + + * write.c (adjust_reloc_syms): When generating an absolute section + symbol as a placeholder, don't mark it as used in a relocation + entry, here. + + * Makefile.in (comparison): Compare using makefile code from gcc, + stripped down to discard subdir stuff and adapted to give a + non-zero exit status if either file differs. + +Thu Nov 3 15:43:02 1994 Ian Lance Taylor + + * config/tc-mips.c (load_address): Fix RELAX_ENCODE arguments for + NO_PIC case. + +Tue Nov 1 16:10:59 1994 Ian Lance Taylor + + * config/tc-mips.c (s_change_sec): If not GPOPT, don't permit + switching to the readonly data section. + + * ecoff.c (ecoff_directive_type): Fix warning message. + +Sun Oct 30 00:57:35 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_proc): Delete disabled code to put each + proc in its own subspace, we're not going to use it. + +Tue Oct 25 14:44:33 1994 Ian Lance Taylor + + * config/tc-mips.c (macro): Ensure that mips2 case of M_LI_DD in + .rdata does not become a variant frag. + + * config/tc-mips.c (mips_cpu): Initialize to -1. + (md_begin): Don't mips_cpu if it was already set. + (md_parse_option): For -mipsN, don't set mips_cpu if it was + already set. For -mcpu=, just set mips_cpu, not mips_isa. + +Fri Oct 21 20:42:29 1994 Ian Lance Taylor + + * config/tc-mips.c (md_pseudo_table): If OBJ_ELF, handle .section. + (s_elf_section): New static function. + * ecoff.c (ecoff_build_symbols): Don't abort if we don't recognize + the section when setting the storage class; default to sc_Data. + +Thu Oct 20 00:43:38 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_apply_fix): Set new_val to 8 for all + fixups to branch instructions (not just pc-relative ones) which + will generate SOM relocations. + +Wed Oct 19 13:41:56 1994 Ian Lance Taylor + + * config/tc-a29k.c: Include ctype.h with angle brackets. + (define_some_regs): Add new special register names defined on the + 29040. + (parse_operand): Add argument opt. If non-zero, don't warn about + a missing operand. + (machine_ip): If handling argument type 'I', pass opt as non-zero + to parse_operand. Handle new optional operand type 'I'. + (md_undefined_symbol): Handle special register names (srNN). + +Tue Oct 18 00:45:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * write.c (renumber_sections): New static BFD_ASSEMBLER function. + (write_object_file): Call it after removing gas created sections. + +Mon Oct 17 18:06:05 1994 Ian Lance Taylor + + * symbols.c (symbol_create): Use udata.p, not just udata. + * config/obj-elf.c (obj_ecoff_set_ext): Likewise. + (elf_get_extr): Likewise. + + * read.c (read_a_source_file): The second argument to as_where is + unsigned int *, not int *. + +Mon Oct 17 02:26:32 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c: Eliminate all uses of fx_addnumber. + (tc_gen_reloc): Simplify. It's no longer necessary to set a + reloc's addend field to zero for function symbols. + (md_apply_fix): Simplify. For fixups which will require a SOM + reloc, just clear out the necessary bits in the output file. + +Fri Oct 14 19:06:46 1994 Ken Raeburn + + * Makefile.in (BISON): Use bison -y, not bison. + +Thu Oct 13 19:22:54 1994 Ken Raeburn + + * Makefile.in (VERSION): Updated to 2.5. + (clean-here): Delete stamp-mk.com. + (distclean): Delete .gdbinit. + * Version 2.5 released. + +Wed Oct 12 20:30:51 1994 Ken Raeburn + + * config/te-nbsd532.h: Renamed from te-netbsd532.h. + * configure.in, configure: Adjusted. + +Wed Oct 12 16:33:38 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * config/cplus-dem.c: Removed. It isn't used. Even if it was, + it's better to use the one in libiberty. + +Wed Oct 12 18:48:39 1994 Ken Raeburn + + * symbols.c (resolve_symbol_value, case O_symbol): Undo last + change; it breaks the rs6000 support, and doesn't seem to be + needed. + +Wed Oct 12 11:56:50 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * config/tc-i386.h,te-netbsd532.h (TARGET_FORMAT): Changed to + a.out--netbsd to match corresponding changes in BFD. + +Wed Oct 12 11:06:11 1994 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-ppc.c (ppc_fix_adjustable): Resolve symbol values + rather than explicitly adding the frag address. + * config/obj-coff.c (coff_frob_symbol): Add a zero entry to mark + the end of the line numbers; this replaces the zero entry which + used to be added by coff_add_linesym, removed Oct 7. + (coff_adjust_section_syms): Ignore sections with no seginfo. + +Wed Oct 12 01:41:37 1994 Ken Raeburn + + * Makefile.in (bootstrap, bootstrap2, bootstrap3): Create a + "stage" symlink to the appropriate stage* directory, and use it + instead in the -B options. + (comparison): Revert yesterday's change. + +Tue Oct 11 16:48:11 1994 Ken Raeburn + + * config/tc-sparc.c (tc_gen_reloc): For non-a.out relocations, if + pc-relative, use fx_offset only, ignore address of relocation. + +Tue Oct 11 15:24:00 1994 Ian Lance Taylor + + * config/tc-mips.c (mips_ip): Don't use S_IS_LOCAL when checking + for an embedded PIC switch expression, since the definition of + S_IS_LOCAL was changed. + +Tue Oct 11 15:05:11 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * Makefile.in (comparison): When comparing as.new or gasp.new, try + running the binary through sed to avoid differences due to + "stage1" or "stage2" having been written into the binary. + +Sat Oct 8 01:48:04 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + ELF symbol size handling, based on code from Eric Youngdale: + * config/obj-elf.h (OBJ_SYMFIELD_TYPE): New macro. Adds an + expression pointer to the symbol structure, used for `size' + expressions that couldn't be reduced to constants when initially + processed. + (elf_frob_symbol): Declare. + (obj_frob_symbol): Call elf_frob_symbol always, rather than + ecoff_frob_symbol only if ECOFF_DEBUGGING defined. + * config/obj-elf.c (obj_symbol_new_hook): Deleted unused code. + Clear sy_obj field. + (obj_elf_size): Deleted unused code. If size is non-reducible + expression, allocate some storage for the sy_obj field and copy + the expression. + (elf_frob_symbol): New function. Computes sizes, calls + ecoff_frob_symbol if appropriate. + + * write.c (fixup_segment): For i386 elf and coff (for now), don't + add in value of symbol from another defined section of the file. + +Fri Oct 7 17:54:02 1994 Ken Raeburn + + * config/tc-m88k.h (TC_KEEP_FX_OFFSET): Define. + * config/obj-coff.c (do_relocs_for): Test only TC_KEEP_FX_OFFSET, + rather than both it and TC_M88K. + (coff_adjust_section_syms): New function. + (coff_frob_section): For non-empty sections, create aux entry for + the section symbol, indicating the size. + (n_line_nos): New variable. + (add_lineno): Increment it. + (coff_add_linesym): Increment n_line_nos, don't call add_lineno. + (coff_frob_file): New function; map coff_adjust_section_syms over + sections. + (obj_coff_line): Only reset line_base for .bf symbols. + * config/obj-coff.h (coff_adjust_section_syms, coff_frob_file): + Declare. + (obj_frob_file): New macro. + + * config/obj-coff.h (OBJ_COPY_SYMBOL_ATTRIBUTES): Renamed from + obj_frob_forward_symbol, and rewritten for new parameter list. + + Mon Oct 3 21:02:38 1994 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.h (S_IS_LOCAL): fix obsolete flagseen[] reference. + +Wed Oct 5 11:49:26 1994 Ian Lance Taylor + + * config/obj-ecoff.c (obj_pseudo_table): Accept .esize and .etype + as synonyms for .size and .type. + +Wed Oct 5 00:08:10 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-coff.c (coff_frob_section): Remove assert about + section alignment. + * config/tc-sparc.c (md_section_align): Use section alignment, not + xvec align_power_min field. + +Fri Sep 30 19:05:20 1994 Pat Rankin (rankin@eql.caltech.edu) + + * vmsconf.sh (make-gas.com): handle DCL verification to enable + sensible feedback to the user while gas is being built. + +Fri Sep 30 16:23:31 1994 Ken Raeburn + + * Makefile.in (DISTSTUFF): New variable, listing only make-gas.com + for now. + (diststuff): New target; builds DISTSTUFF. + (realclean): Separate target, depend on clean and distclean, then + delete DISTSTUFF. + * make-gas.com: Deleted. + + * config/tc-i386.c (i386_validate_fix) [BFD_ASSEMBLER]: New + function. Converts reloc for "foo-GOT" to BFD_RELOC_386_GOTOFF + reloc for "foo". + (i386_operand): Don't look up section symbol for + undefined_section. + (reloc): Always permit return of 8- and 16-bit relocation types. + Add a space after "pc-relative" in the error message. + (tc_i386_fix_adjustable) [BFD_ASSEMBLER]: Reject + BFD_RELOC_386_GOTOFF relocs. + (i386_operand): For any GOTOFF reloc, convert it to a BFD_RELOC_32 + with a "foo-GOT" value. + * config/tc-i386.h (i386_validate_fix): Declare it. + (TC_VALIDATE_FIX): New macro -- call it. + (NOP_OPCODE): Cast to `char' to avoid compiler warnings. + + * as.h: If __STDC__ is not defined and varargs.h is available, use + it rather than stdarg.h. + + * write.h (struct fix): Added new bitfield fx_plt, for fixups + referring to PLT entries. + * write.c (fix_new_internal): Initialize fx_plt to zero. + (adjust_reloc_syms): Re-fetch `sym' after top of reduction loop. + Don't adjust fx_offset by frag address, since S_GET_VALUE now + includes the frag address. + (fixup_segment): Changed local var PCREL to type int, added PLT. + If PC-relative fixup refers to a PLT entry for a symbol in the + current section, don't reduce it. + + * write.c (adjust_reloc_syms): Exit loop through a label. If + DEBUG5 is defined, print out each fixup before and after + processing. + (fixup_segment): If DEBUG5 is defined, print out each fixup before + and after processing. + (print_fixup): Added prototype. Show address on first line. Show + fx_offset and fx_subsy. [!BFD_ASSEMBLER]: Only show fx_r_type if + NEED_FX_R_TYPE is defined. + + * symbols.c (print_symbol_value_1): Check S_IS_LOCAL, S_IS_EXTERN, + S_IS_DEBUG, S_IS_DEFINED also. + +Thu Sep 29 18:57:06 1994 Ken Raeburn + + * Makefile.in (all): Depend on .gdbinit. + (.gdbinit): Rebuild from gdbinit.in by running config.status. + + * gdbinit.in: Define new function "pf". Fix doc on "pe" and "ps". + + * write.c (print_fixup): Print source location on first line. + Show fx_r_type and fx_addsy fields. + +Wed Sep 28 14:56:39 1994 Ken Raeburn + + * configure.in: Set bfd_gas for all sparc targets in one place, + instead of separately for each. Correctly handle user-supplied + "--enable-bfd-gas" option. + + * gdbinit.in: Move "break abort" to end, in case gdb complains. + + * as.h (PRINTF_WHERE_LIKE, PRINT_LIKE) [USE_STDARG, !__GNUC__]: + Use PARAMS macro. + + * symbols.c (resolve_symbol_value, case O_symbol): Don't do any + processing if add_symbol is undefined or in expr_section. + (resolve_symbol_value, case O_add): For symbol plus + constant-valued symbol, convert to O_symbol and re-reduce. + (S_GET_VALUE): If symbol needs resolving, resolve it. + (indent_level): No longer static. + (print_symbol_value_1): Don't print frag address if it matches + zero_address_frag. Don't print "resolving" if already resolved. + Print segment name. Don't call print_expr_1 on an undefined + symbol. + (print_expr_1): Fix whitespace before printing X_add_number. + + * expr.c (make_expr_symbol): No longer static. Use symbol_create, + not symbol_new, for symbols holding expression values. + * expr.h (make_expr_symbol): Move declaration here. + * write.c (fix_new_exp): Handle O_add by creating an + expression-valued symbol, and calling fix_new_exp recursively. + (adjust_reloc_syms): If a fixup's symbol value is a sum of an + undefined symbol and a constant, fold the constant into the fixup, + and refer to the undefined symbol directly. Then process the + fixup again from scratch. + (write_object_file): Before calling adjust_reloc_syms, make a pass + through the symbol list trying to resolve values. + + * write.c (print_fixup): New routine, for debugging. + (write_relocs): Call bfd_install_relocation. Deleted various + hacks for working around problems with bfd_perform_relocation. + + * Makefile.in (VERSION): Update to 2.4.90. + +Wed Sep 28 11:50:40 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * Makefile.in (gasp.o): Depends upon config.h. + + * config/tc-mips.c: Include subsegs.h. + (md_apply_fix): If an unconditional b or bal overflows, and we are + not assembling PIC code, replace it with a j or jal. + + * config/tc-mips.c (md_apply_fix): Correct branch overflow test. + Use as_bad_where and as_warn_where rather than as_bad and as_warn. + +Mon Sep 26 17:15:59 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * write.c (write_relocs): Add file name and line number to + as_fatal calls. Handle bfd_reloc_overflow case specifically when + RELOC_EXPANSION_POSSIBLE. + +Fri Sep 23 16:11:28 1994 Ken Raeburn + + * as.h (USE_STDARG, USE_VARARGS): Define one or neither of these + here. Use them for deciding which PRINTF*LIKE macro definitions + to use. + * messages.c: Use them, instead of NO_STDARG, NO_VARARGS. + [!USE_STDARG && !USE_VARARGS] (va_alist, va_dcl, ...): Provide + default definitions matching what we were doing before. + (as_tsktsk): Remove the non-stdarg, non-varargs version, and + always use the varargs form if not using stdarg. It's safe to + always use vfprintf, because libiberty will provide it if the + native system doesn't. Also, always make format be const. + (as_warn, as_warn_where, as_bad, as_bad_where, as_fatal): Ditto. + +Fri Sep 23 14:42:34 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-mips.c (load_register): Always use addiu when adding a + constant to $zero--no need to use daddiu. + (macro): Hack the -mips3 overflow tests to not fail when offsetT + is only 32 bits. + + * symbols.h (copy_symbol_attributes): Declare. + +Thu Sep 22 21:58:24 1994 Ken Raeburn + + * listing.c: Bugfixes based in part on patches from Paul + Kranenburg. + (listing_newline): Check filename as well as line number when + deciding whether to record it. + (list_symbol_table) [S_IS_REGISTER]: Check that S_IS_REGISTER is + false (if defined) as well as checking for reg_section. + (listing_listing): Iterate fetching lines while line number is too + low, and we haven't run off the end of the input file. + + * config/vms-conf.h: Changed HAVE_DELETE to HAVE_REMOVE. + +Thu Sep 22 13:39:10 1994 Kung Hsu (kung@x1.cygnus.com) + + * ecoff.c (ecoff_generate_asm_lineno): check if + current_stabs_filename is NULL before strcmp. + * read.c (read_a_source_file): fix a bug in generate_asm_lineno + checking. + +Wed Sep 21 18:17:35 1994 Ken Raeburn + + * config/ho-*.h: Now-unused files deleted. + + * symbols.c (copy_symbol_attributes): New function. Copies BFD + symbol flags and calls OBJ_COPY_SYMBOL_ATTRIBUTES. + (resolve_symbol_value, case O_symbol): Call it, if X_add_number is + zero. Don't call obj_frob_forward_symbol. + * read.c (pseudo_set): Call copy_symbol_attributes, but only if + X_add_number is zero. + * config/obj-elf.h (obj_frob_forward_symbol): Deleted. + + * config/tc-i960.c: Lots of whitespace, comment reformatting, + using GNU indent. + (strchr): Don't declare. + [BFD_ASSEMBLER]: Don't compile md_convert_frag, + md_estimate_size_before_relax, md_ri_to_chars, + md_create_short_jump, md_create_long_jump. + (brtab_emit): Use data_section, not SEG_DATA. + + Mon Sep 19 17:14:44 1994 Pat Rankin (rankin@eql.caltech.edu) + + * config/vms-conf.h: new file, manually derived from conf.in. + * config-gas.com: use it, and eliminate obsolete "host.h". + +Wed Sep 21 11:11:30 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-ppc.c (ppc_current_block): New static variable. + (ppc_stabx): Set sy_tc.within of a C_STSYM symbol to + ppc_current_block. Don't move around any stab symbol, just those + for common symbols. + (ppc_bs): Set ppc_current_block. + (ppc_es): Clear ppc_current_block. + (ppc_frob_symbol): Set the value of a C_STSYM symbol to the offset + from the csect of the enclosing block. + + * config/tc-mips.c (insns_since_cache_access): Remove. + (append_insn): Remove setting of insns_since_cache_access, and + special 4600 handling; it turns out not to be required. + +Tue Sep 20 16:13:18 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-mips.c (md_shortopts): Remove E. + (md_longopts): Add EB and EL. + (md_parse_option): Handle -EB and -EL as separate options, rather + than as a single -E option with an argument. + +Mon Sep 19 12:42:05 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (hppa_fix_adjustable): Reject reductions + involving global symbols too. + +Mon Sep 19 12:12:46 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * as.h: Test NEED_DECLARATION_*, not NEED_*_DECLARATION. + + * configure.in: Test for remove, not delete. Fix cross-assembler + test. + * as.h: Test HAVE_REMOVE, not HAVE_DELETE; define unlink to + remove, not delete. + + * read.c (pseudo_set, case O_symbol): If + OBJ_COPY_SYMBOL_ATTRIBUTES is defined, invoke it. + [BFD_ASSEMBLER]: Copy BSF_FUNCTION setting too. + * config/obj-elf.h (OBJ_COPY_SYMBOL_ATTRIBUTES): Define. + + Wed Aug 10 19:15:30 1994 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.h (DSG_S_C_UBITU, DST_K_VFLAGS_DSC, DST_K_TS_ATOM, + many others): new macros; values obtained from "DSTRECRDS.SDL". + * config/obj-vms.h (various): use them. + (USE_BITSTRING_DESCRIPTOR): new macro, for selecting bitfield + representation (only enum bitfields can avoid being bitstrings). + (bitfield_suffix, setup_basic_type): new routines. + (VMS_typedef_parse): use them. Now recognize bitfields of all + integral types, not just type `int'. Caveat: the representation + used for bitfields still does not work for objects placed in + registers, and gcc's optimizer sometimes puts small structs there. + + Tue Jun 14 17:31:44 1994 Pat Rankin (rankin@eql.caltech.edu) + + * read.c (s_text) [#if OBJ_VMS]: clear the IN_DEFAULT_SECTION + bit from const_flag. + * config/obj-vms.h (IN_DEFAULT_SECTION): define this macro. + (tc_frob_label): define this to call vms_check_for_special_label, + and declare the latter. + * config/obj-vms.c (vax_g_doubles): declare this file-scope + variable. + (const_flag): initialize to IN_DEFAULT_SECTION instead of 0. + (vms_check_for_special_label): new routine (tc_frob_label). + (VMS_TBT_Routine_End): don't bother checking for `gcc_compiled.' + and `gcc2_compiled.' labels; they won't reach here any more. + (VMS_typedef_parse) [case 'r']: for types `double' and `complex + double', use `vax_g_doubles' flag to select type of double. + (VMS_write_object_file) [traceback setup]: don't pass symbols + with the IN_DEFAULT_SECTION attribute to the TBT_Routine_Begin + and TBT_Routine_End functions. + + Mon Jun 6 20:52:20 1994 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.c (VMS_TBT_Routine_End): cache the result of + S_GET_VALUE() to avoid many repeated function calls. + (VMS_Check_For_Main) [#if HACK_DEC_C_STARTUP]: capitalize + _C$MAIN_ARGS in advance, in case -h3 (leave symbol name as-is) + gets requested. [All the HACK_DEC_C_STARTUP code appears to + be obsolete; gcc does it automatically for vms target. It's + also misnamed, because it is for the "VAX C" run-time library, + not the newer "DEC C" one which has much different startup code.] + {various}: use `S_SET_xxx(symbol,new_value)' rather than + `S_GET_xxx(symbol) = new_value'. + +Mon Sep 19 12:05:03 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/obj-coff.c (c_dot_file_symbol): Use bfd_abs_section_ptr, + not &bfd_abs_section. + +Thu Sep 15 18:36:34 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * expr.c (clean_up_expression): Use addressT, not bfd_vma. + +Tue Sep 13 20:05:47 1994 Jeff Law (law@snake.cs.utah.edu) + + * expr.c (expr): Don't reduce the difference of two symbols in the + same frag if the symbols are not in normal sections. + + * config/obj-som.h (S_SET_OTHER, S_SET_TYPE): Delete a.out crud. + (S_SET_DESC, S_GET_OTHER, S_GET_TYPE, S_GET_DESC): Likewise. + (obj_attach_unwind_info): Do not define. Not needed anymore. + * config/tc-hppa.c: Delete whitespace at EOL. + (struct hppa_fix_struct): Delete fx_unwind field and all references. + (fix_new_hppa): Last arg is now a pointer to an int. Do not + call obj_attach_unwind_info anymore. For SOM R_ENTRY and R_EXIT + fixups, store 32bits of unwind information in the fx_addnumber + field of the fixup. + (md_assemble, pa_entry, process_exit, pa_procend): For SOM R_ENTRY + and R_EXIT fixups, pass a NULL pointer to fix_new_hppa, and a + pointer to 32 bits of unwind info. + (tc_gen_reloc): For SOM R_ENTRY and R_EXIT fixups, set the symbol + pointer to the dummy symbol; set the addend field to fx_addnumber. + (pa_comm, pa_equ, pa_type_args, pa_import): Use bfd_XXX_section_ptr + rather than &bfd_XXX_section. + +Tue Sep 13 21:15:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/tc-i386.c (md_apply_fix_1): For GOTPC relocs, decrement + value by one; discard adjustments previously being made. From + Eric Youngdale. + + VMS- and Vax-related changes from Pat Rankin: + * Makefile.in (VMS_OTHER_OBJS): add concat, getopt, and getopt1. + * vmsconf.sh: no longer have make-gas.com echo text about needing + to modify the gcc-vms driver when intending to use with gcc 1.x. + * as.c (parse_options): suppress 'v' from std_short_options and + eliminate VMS-specific conditional initialization; + [default case]: check for '-v' if md_parse_options doesn't recognize + an option; + [default case, #if VMS]: check for filename argument when '-v' seen; + [case 'v']: delete. + * config/tc-vax.c (md_assemble): don't rely on `this_add_number' + for O_big literal operands (double floats and long long ints); + [VMS, md_shortopts]: add second colon after 'v'; + (md_parse_options) [VMS, case 'v']: check for argument, so + caller can handle `-v' w/o arg. + +Tue Sep 13 16:45:08 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * config/obj-coff.c (do_relocs_for): If TC_KEEP_FX_OFFSET + is defined, put the tx_offset into the r_offset. + * config/tc-sh.c (line_comment_chars): Add # + (tc_reloc_mangle): Deleted. + * config/tc-sh.h (TC_KEEP_FX_OFFSET): Define. + (TC_RELOC_MANGLE): Delete. + +Tue Sep 13 16:20:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * flonum-konst.c: Change preprocessor tests of HO_VMS to just VMS. + * hex-value.c: Ditto. + * config/obj-vms.c: Ditto. + + * config/tc-sparc.c (sparc_ip): Replace as_bad/exit sequence with + a call to as_fatal. + * config/tc-i860.c (i860_ip): Ditto. + * config/tc-hppa.c (pa_ip): Ditto. + * config/tc-alpha.c (alpha_ip): Ditto. + * as.c (parse_args): Ditto. + + * config/tc-mips.c (mips_ip): Replace as_warn/exit sequence with a + call to as_fatal. + + * write.c (write_contents): Use EXIT_FAILURE. + * output-file.c (output_file_create, output_file_close, + output_file_create, output_file_close): Ditto. + * messages.c (as_fatal): Ditto. + * config/obj-som.c (obj_som_version, obj_som_copyright): Ditto. + * config/obj-ieee.c (write_object_file): Ditto. + * config/obj-coff.c (write_object_file): Ditto. + * config/tc-vax.c (main): Use EXIT_SUCCESS. + * config/tc-m68k.c (main): Ditto. + + * hash.c (main): Pass a value to exit(). + + * as.h (EXIT_SUCCESS, EXIT_FAILURE): Moved here. + * as.c: ...from here. + (parse_args): Use them always. + (main): Use exit rather than return. + + * Makefile.in (*_FOR_TARGET, INSTALL_XFORM, install, uninstall): + Rewrite handling of program_transform_name. + + * configure.in: Test for functions unlink and delete. + * as.h: If unlink isn't available but delete is, define unlink to + be delete. + + Update for autoconf 1.118: + * gdbinit.in: New file, created from old .gdbinit. + * .gdbinit: Deleted. + * aclocal.m4 (GAS_GDBINIT): Deleted. + * configure.in: Don't use it. Instead, generate .gdbinit from + gdbinit.in. Don't substitute cpu_type, obj_format, emulation, + atof. Switched order of AC_LINK_FILES arguments. Use AC_PREREQ + to ensure that older versions of autoconf aren't used. + * Makefile.in: Added @configure_input@ line. + (configure): Deleted rule. + +Tue Sep 13 12:08:20 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/obj-coff.c (fixup_segment): After handling the difference + of two symbols from the same segment, set fx_subsy to NULL, to + satisfy existing TC_COUNT_RELOC macros. + +Tue Sep 13 01:47:08 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * aclocal.m4 (GAS_GDBINIT): New macro. + * configure.in: Use it. + * configure: Regenerated. + +Mon Sep 12 20:56:38 1994 Ken Raeburn (raeburn@kr-laptop.cygnus.com) + + * .gdbinit (pe, ps): Define new commands. + * symbols.c (indent_level): New static variable. + (indent, print_expr_1, print_symbol_value_1, print_symbol_value, + print_expr): New functions. + + * Makefile.in (config-stamp): Add a "this file generated by make" + message to config.h. + + PIC implementation for i386-linux, based on code from Eric + Youngdale and Paul Kranenburg, with some work of my own: + + * write.c (fixup_segment): Test TC_RELOC_RTSYM_LOC_FIXUP on fixup + before processing same-section pcrel relocations. + (TC_RELOC_RTSYM_LOC_FIXUP): Default to 1. + + * expr.c (make_expr_symbol): If operator is O_symbol and + X_add_number is zero, just return the symbol. If operator is + O_constant, resolve the symbol's value before returning. + (operand): Permit use of "[]" for grouping. + (clean_up_expression): For difference of two symbols in the same + frag, add the difference of their offsets into X_add_number. + (expr): Reduce difference of two symbols in same frag to their + difference. + + * config/tc-i386.c (TC_RELOC): New macro. + (struct _i386_insn): New field disp_reloc. + (GOT_symbol): New variable. + (operand_special_chars): Added square-brackets and at-sign. + (reloc) [BFD_ASSEMBLER]: Added new argument OTHER; if it is not + NO_RELOC, just return it. + (reloc) [! BFD_ASSEMBLER]: Add third argument to dummy macro. + (BFD_RELOC_386_PLT32, _GOT32, _GOTOFF) [! BFD_ASSEMBLER]: More + dummy macros. + (tc_i386_fix_adjustable): New function. Returns zero if symbol in + fixup is not local, to prevent relocations against externals from + being dropped. + (md_assemble): Initialize disp_reloc field to NO_RELOC. Pass + disp_reloc field to reloc() function, and use TC_RELOC to generate + value to pass to fix_new_exp. + (md_assemble): Change 32-bit reloc against GOT_symbol into a GOTPC + reloc. + (i386_operand): Initialize disp_reloc field to NO_RELOC. Handle + @GOTOFF, @PLT, @GOT operands. For GOTOFF relocations with local + symbols, force generation of the section symbol. + (md_estimate_size_before_relax): If GOT_symbol exists, decide + we're generating PIC code, and convert relocations against + undefined symbols from PCREL to PLT32. + (md_apply_fix_1) [OBJ_ELF]: Fix up values for dynamic-linking + relocs. + (md_undefined_symbol): Notice GLOBAL_OFFSET_TABLE_NAME and set + and return GOT_symbol if it matches. + (F, MAP): Move macro definitions outside function. + (tc_gen_reloc): Only switch on size and pcrel if code wasn't + already supplied as PLT32. GOT32, GOTOFF, or GOTPC. Convert + BFD_RELOC_32 using GOT_symbol into GOTPC. + * config/tc-i386.h (TC_RELOC, tc_fix_adjustable, + TC_RELOC_GLOBAL_OFFSET_TABLE, TC_RELOC_RTSYM_LOC_FIXUP): New + macros. + (NEED_FX_R_TYPE): Define. + (LOCAL_LABEL): Accept ".X" prefix too. + (GLOBAL_OFFSET_TABLE_NAME): Default to "_GLOBAL_OFFSET_TABLE_". + +Mon Sep 12 17:51:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/obj-elf.c (obj_elf_type): Rewrite to accept syntax + reportedly to be used on Irix 6. + + * config/tc-mips.c (md_pseudo_table): Handle .globl and .global. + (s_mips_globl): New static function; needed for Irix 5 support. + * ecoff.c (ecoff_build_symbols): If BSF_FUNCTION is set for an + external symbol with no type, set the type to st_Proc rather than + st_Global. Don't set the index of an external st_Proc or + st_StaticProc symbol unless it is also a local symbol. + + * read.c (read_a_source_file): The second argument to as_where is + unsigned int *, not int *. + +Thu Sep 8 17:18:24 1994 Kung Hsu (kung@mexican.cygnus.com) + + * config/obj-ecoff.h : Change names to OBJ_GENERATE_ASM_LINENO, + and generate_asm_lineno. + * config/obj-elf.h : ditto. + * read.h : ditto. + * read.c (read_a_source_file): if no file when inst is read, set + generate_asm_lineno to true. + * ecoff.h : change name to generate_asm_lineno and add function + ecoff_no_current_file. + * ecoff.c : change name to generate_asm_lineno. + * ecoff.c (ecoff_generate_asm_lineno) : new function, to generate + ecoff style line for asm file. + +Thu Sep 8 19:43:49 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/obj-coff.c (size_section): Do an fprintf to stderr rather + than a printf. + (fixup_segment): Use as_bad_where rather than as_bad. + +Wed Sep 7 17:21:12 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * config/tc-{h8300,sh}.[ch] (tc_coff_symbol_emit): Function doing + nothing becomes macro doing nothing. + +Wed Sep 7 19:10:09 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (Makefile): Depend on config.status. + (config.status): Run config.status from . instead of srcdir. + + * config/tc-i386.c (tc_gen_reloc): Use bfd_get_reloc_code_name to + display the name of the relocation type that couldn't be handled. + * config/tc-sparc.c (tc_gen_reloc): Likewise. + * config/tc-alpha.c (tc_gen_reloc): Likewise. Deleted abort call + after call to as_fatal. + + * configure.in (i386-*-linux*): Don't set bfd_gas. + + * Makefile.in (CC_FOR_TARGET, NM_FOR_TARGET, OBJDUMP_FOR_TARGET, + install, uninstall): Don't use "brokensed" hack any more, the new + autoconf code should never let program_transform_name be empty. + + Update for autoconf beta 1.112: + * aclocal.m4 (GAS_CHECK_DECL_NEEDED, GAS_WORKING_ASSERT): New + macros. + * configure.in: Use them. Use AC_ARG_PROGRAM (now provided by + autoconf) instead of my hacked-up AC_PROGRAM_TRANSFORM_NAME. Move + test for CROSS_COMPILE just before AC_FUNC_ALLOCA, and emit a + message to try to ease confusion about autoconf's + "cross-compiling" message. + * acconfig.h (NEED_DECLARATION_MALLOC, NEED_DECLARATION_FREE, + NEED_DECLARATION_ERRNO): Renamed from NEED_*_DECLARATION. + * configure, conf.in: Regenerated. + +Wed Sep 7 12:49:55 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * configure.in: Check ${host} and ${target} rather than + ${host_canon} and ${target_canon}. + * configure: Likewise. + +Tue Sep 6 11:42:38 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-mips.c (mips_cpu): New static variable. + (insns_since_cache_access): New static variable. + (md_begin): Set mips_cpu as well as mips_isa. + (append_insn): If mips_cpu is 4600, require four nop instructions + between an instruction which accesses the cache and certain CACHE + instructions. Keep track of the number of instructions seen since + an instruction which accesses the cache. + (md_parse_option): Set mips_cpu as well as mips_isa. + +Mon Sep 5 07:09:00 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * doc/Makefile.in (VPATH): Define using @srcdir@. + (prefix, program_transform_name, exec_prefix): Use autoconf style + @-substitutions. + +Sun Sep 04 17:58:10 1994 Richard Earnshaw (rwe@pegasus.esprit.ec.org) + + * config/ho-riscix.h, config/tc-arm.c, config/tc-arm.h: New files + * configure.in: Recognize the arm. + +Fri Sep 2 16:05:50 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * ecoff.c (add_file): Don't try to generate line numbers if the + symbol table has been frozen. + +Thu Sep 1 19:48:01 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * aclocal.m4 (AC_PROG_CC): Use AC_DEFUN, and omit AC_PROVIDE. + + * configure.in: Handle user-specified bfd-assembler option with + separate variable from preferred configuration, until the two are + resolved. Indicate bfd_gas=preferred for linux a.out. Use + AC_PROGRAM_TRANSFORM_NAME, for which a patch has been sent to djm. + * Makefile.in (target_alias, program_transform_name): Define, + using autoconf @-substitutions. + +Wed Aug 31 17:43:06 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * atof-generic.c: Deleted alloca handling here. + + * Makefile.in (prefix, exec_prefix): Use @-subtitutions. + + * aclocal.m4 (AC_OUTPUT_LINKS): Deleted redefinition, since + autoconf 1.109 has this fixed. + * configure.in: Don't change quote characters around AC_MSG_ERROR + invocation. Don't use AC_HEADER_STDC, since it requires running a + program. Cache NEED_*_DECLARATION values. + * configure, conf.in: Regenerated with a modified autoconf 1.109. + + * as.h (volatile): Don't test or define here; not needed. + (alloca): Replace alloca-conf.h inclusion with code recommended in + autoconf documentation. Include config.h first. + +Wed Aug 31 11:20:48 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/obj-coff.h (S_IS_DEFINED): Absolute symbols are defined + also. + + * configure.in, configure: Initialize bfd_gas to no. + +Tue Aug 30 19:31:14 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * as.h: Include alloca-conf.h from "libiberty", not + "../libiberty". + +Mon Aug 29 16:11:30 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-ppc.c (md_apply_fix): Don't generate a reloc when a + symbol is used as an offset into a CSECT that is not a TOC. These + types of loads are generated by gcc -mminimal-toc. + +Sun Aug 28 13:22:52 1994 Ken Raeburn (raeburn@rtl.cygnus.com) + + * as.h (flag_*): Added comments describing meanings of some of + these variables. + (struct frag): Add some comments about the ns32k-specific fields + and why they're here. + (SIZEOF_STRUCT_FRAG): Cast addresses to char*, not int. + (flag_print_statistics): Declare. + + * as.c (parse_args): Set flag_print_statistics instead of + statistics_flag. Options array is now const. Added new option + "dump-config"; if specified, print TARGET_ALIAS, TARGET_CANONICAL, + TARGET_CPU, TARGET_OBJ_FORMAT, and TARGET_FORMAT, if defined. + (main): Change test to check flag_print_statistics. + (statistics_flag): Deleted. + + * frags.c (frag_variant): Removed PCREL_ADJUST and BSR arguments. + Always initialize them to zero. + * frags.h (frag_variant): Fixed prototype. + * config/tc-i960.c (get_cdisp): Don't pass the extra zero args. + * config/tc-ns32k.c (convert_iif): Don't pass the arguments; cache + the value of frag_now and fill in the fields later. + + * Makefile.in (distclean, realclean): Remove new + configure-generated files. + +Sat Aug 27 20:26:12 1994 Ken Raeburn (raeburn@kr-laptop.cygnus.com) + + Conversion to autoconf: + * acconfig.h, aclocal.m4: New files. + * configure.in: Rewritten (except for some target-specific code) + for autoconf. + * conf.in, configure: New files, generated from the above. + * Makefile.in: Changed magic sequence indicating insertion of + makefile fragments. + (VPATH, srcdir, CC, LIBS, OBJS dependencies): Use @-substitutions + from configure. + (LINKED_HEADERS): Deleted a.out.gnu.h, a.out.h, and host.h. + (config.status, configure): Rewrite rules. + (config-stamp): Depend on conf. Skip variables that configure is + now substituting itself. + (*.o dependencies): Deleted host.h. + (distclean, realclean): Don't delete host.h. + * as.c: Don't include stdio.h, string.h, sys/types.h. Include + signal.h after as.h. + * as.h: Include alloca-conf.h first. Include ctype.h, string.h, + strings.h, stdlib.h, unistd.h, sys/types.h, fopen-bin.h, + fopen-same.h, as suggested by autoconf test results. + [BROKEN_ASSERT]: Don't include assert.h. + (strdup): Declare. + (volatile, const): Define if not __STDC__ and not already defined. + (malloc, realloc) [NEED_MALLOC_DECLARATION]: Declare. + (free) [NEED_FREE_DECLARATION]: Declare. + * gasp.c: Include config.h, stdlib.h (if HAVE_STDLIB_H). Don't + include host.h. + (malloc) [NEED_MALLOC_DECLARATION]: Declare. + * messages.c: Include as.h first. Include errno.h only if + HAVE_ERRNO_H. If HAVE_VARARGS_H and not __STDC__, undefine + HAVE_STDARG_H. Set NO_STDARG and NO_VARARGS as appropriate. + * doc/Makefile.in (srcdir, INSTALL, INSTALL_PROGRAM, + INSTALL_DATA): Use autoconf @-substitutions. + + * input-file.c: Don't include assert.h here, 'cause as.h already + includes it. + + * config/tc-alpha.c: Added various prototypes for static + functions. + (in_range): New function, tests whether a value can fit in an + N-bit field. + (build_mem, build_operate_n): New functions for constructing + opcode values. + (emit_sll_n, emit_ldah_num, emit_addq_r, emit_lda_n): New + functions for emitting single instructions, no longer requiring a + recursive call to md_assemble. + (emit_add64): New function for expanding a REG:=REG+CONST + operation into one or more instructions, to handle wide constants. + (clear_insn): New variable. + (md_begin): Fill it in with zeros and BFD_RELOC_NONE values. + (alpha_ip): Use it to initialize local variable insns. + (alpha_ip, label "immediate" and cases 'P', 'G'): Use emit_add64 + for calculations. + +Fri Aug 26 14:46:15 1994 Ken Raeburn (raeburn@kr-laptop.cygnus.com) + + * subsegs.c (section_symbol): Reverse still-wrong test of + EMIT_SECTION_SYMBOLS. + + * write.c (BFD_FAST_SECTION_FILL): Always define. + (write_contents): If fill_size is 1, use memset instead of looping + calling memcpy. + +Wed Aug 24 12:46:08 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-mips.h (LOCAL_LABEL): Define as 0, for compatibility + with native MIPS assembler. + * configure.in (mips-*-irix*): Don't set emulation. + * config/te-irix.h: Remove. + + * ecoff.c (ecoff_symbol_new_hook): Don't add a new file if we + haven't seen any input files yet. + * config/tc-alpha.c (md_begin): Just call symbol_create, rather + than calling symbol_new and then removing the symbol from the + list. + + * as.c (main): Move a inside the #if 0 block which uses it. + * ecoff.c (current_stabs_filename): Make const. + * frags.h (frag_align_pattern): Declare. + * gasp.c (new_file): Cast isp to long, and use %ld to print it. + * config/tc-alpha.h (md_operand): Add cast to void. + (alpha_do_align): Declare argument types. + (tc_get_register): Declare. + (alpha_frob_ecoff_data): Declare. + * config/tc-alpha.c: Include . + (s_mask): Don't declare; does not exist. + (line_comment_chars): Remove /* from descriptive comment. + (tc_get_register): Remove unused local reg. + (tc_gen_reloc): Don't bother to compare unsigned to zero. + (s_base): Correct warning to actually print register number. + (md_begin): Remove unused locals retval, lose, and i. + (alpha_fix_adjustable): Move default case inside switch to avoid + warning. + (load_symbol_address): Remove unused locals reloc_addr, p, sym, + and addend. + (emit_byte_manip_r): Declare types for all arguments. + (emit_extract_r, emit_insert_r, emit_mask_r): Likewise. + (emit_sign_extend, emit_bis_r, s_proc): Likewise. + (alpha_ip): Use sprint_value to print offsetT value. Remove + unused local size. Remove unused label get_macro. + (alpha_do_align): Make fill const. + (md_apply_fix): Remove unused label check_zov. + + * configure.in: Recognize i586 as a synonym for i[34]86. + +Tue Aug 23 12:32:14 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/obj-coff.c (c_line_new): Change line_number argument from + unsigned short to int so that the type in the prototype matches + the promoted type in the definition. + (stack_delete): Comment out; not used. + * config/obj-coff.h (tc_coff_symbol_emit_hook): Declare if not + BFD_ASSEMBLER, not if BFD_ASSEMBLER. Declare argument type. + * config/tc-m68k.h (tc_coff_sizemachdep): Declare. + * config/tc-m68k.c (tc_coff_symbol_emit_hook): Add ignored + argument. + +Tue Aug 16 01:48:20 1994 Jeff Law (law@snake.cs.utah.edu) + + * gas/config/tc-hppa.c (pa_comm): Undo last change. Set sy_frag for + the common symbol to the zero address frag (the correct fix). + +Tue Aug 16 01:48:20 1994 Jeff Law (law@snake.cs.utah.edu) + + * gas/config/tc-hppa.c (pa_comm): Undo last change. Set sy_frag for + the common symbol to the zero address frag (the correct fix). + + * config/tc-hppa.c (pa_comm): Set sy_resolved for the common + symbol. + +Fri Aug 12 17:51:48 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-mips.c (md_begin): Drop "el" from the end of + TARGET_CPU. Check for mips64orion. + +Tue Aug 9 19:43:45 1994 Stu Grossman (grossman@cygnus.com) + + * configure.in: Recognize ppc-*-netware. + * config/te-ppcnw.h: New file to support Power-PC/Netware + configurations. Currently, it just enables the use of backslash + escapes in string directives. + +Tue Aug 9 11:12:13 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-ppc.c (ppc_stabx): Call expression directly, rather + than via pseudo_set. If expression is a symbol, move stab symbol + to just after symbol from expression. + + * ecoff.c (ecoff_build_procs): Don't force adr of first fdr to be + zero. Undoes change of June 4, 1993. + + * config/tc-mips.c (md_parse_option): Accept -mcpu=4400, 4600, and + orion. + +Mon Aug 8 16:28:08 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * as.h: Remove FOPEN_WB patch of Aug 6. + * configure.in: Configure for ho-go32 correctly. + * config/ho-go32.h: Fix copyright. + +Mon Aug 8 11:59:51 1994 Jeff Law (law@snake.cs.utah.edu) + + * gas/config/tc-hppa.c (md_pseudo_table): Delete redundant + upper-case versions of the pseudo-ops. + +Mon Aug 8 13:42:16 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-sparc.c (md_apply_fix): If we are going to generate a + non PC relative reloc, don't put the addend in the object file. + +Sat Aug 6 01:15:02 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * as.h: If FOPEN_WB is not defined, do the right thing in a go32 + environment. + +Mon Jul 11 11:34:52 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * config/tc-h8300.c (pint): New function for handling varying + size of int pseudo op. + * doc/as.texinfo: Fix typo describing .h8300h pseduop. + +Mon Aug 1 02:40:43 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (create_new_space): Initialize sd_subspaces + field in the space chain. + + * config/tc-hppa.c (tc_gen_reloc): Cast return value from + hppa_gen_reloc_type. + +Thu Jul 28 15:45:37 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Check more carefully for + conflicting architectures. + (md_parse_option) [NO_V9]: Complain if v9 was selected. + (md_show_usage): Derive architecture list in usage message from + architecture_pname array. + (cypress): Macro deleted. + (op_hash): Don't initialize. + (s_common): Use bfd_und_section_ptr instead of bfd_und_section. + + * config/tc-sparc.c (BSR): New function. + (sparc_ip): Use it for right-shift operations of 32 bits or more. + + * config/tc-sparc.c (sparc_ip): Implement new operand type 'x'. + +Tue Jul 26 18:21:24 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/obj-coff.h: Moved common includes and TARGET_FORMAT + definitions together. + (WORKING_DOT_WORD, WARN_SIGNED_OVERFLOW_WORD, + OBJ_COFF_OMIT_OPTIONAL_HEADER, BFD_HEADERS, BFD) [!BFD_ASSEMBLER]: + Moved these definitions to the start of the file, before the + includes. + (SYMBOLS_NEED_BACKPOINTERS, OBJ_COFF_MAX_AUXENTRIES): Always + define these. + (S_GET_ZEROES): Deleted. + (S_SET_ZEROES): Moved to obj-coff.c. + + * config/obj-coff.c (obj_coff_* psuedo-op fns): Deleted + forward declarations. + (obj_pseudo_table): Moved to one version end of file, + conditionalized internally. + (stack typedef, stack_init, stack_delete, stack_push, stack_pop, + tag_hash, tag_init, tag_insert, tag_find, tag_find_or_make): Moved + to one combined version at top of file, unconditional. Deleted + forward declarations. + (s_get_name): Moved one copy of declarations to start of file. + (def_symbol_in_progress): Ditto. Don't initialize. + (S_SET_ZEROES): Moved here from obj-coff.h. + (write_object_file): If TC_COFF_SET_MACHINE is defined, call it on + the file headers. + + * config/obj-coff.c (seg_info_off_by_4): Now const and static. + (SEG_INFO_FROM_SEG_NUMBER): Unused macro deleted. + (previous_file_symbol, def_symbol_in_progress, symbol_externP, + symbol_extern_lastP, last_functionP) [!BFD_ASSEMBLER]: Don't + bother explicitly initializing to zero value. + + * config/obj-coff.c (fixup_segment) [TC_I960]: Use SF_GET_BALNAME + and SF_GET_CALLNAME instead of the TC_S_IS_ versions. + + * config/tc-i960.h (TC_COFF_SET_MACHINE): New macro. Calls + tc_headers_hook. + + * config/tc-i960.c (targ_has_iclass): Use I_CX | I_CX2 where I_CX + was used previously. + (tc_headers_hook): If I_CX2 is found, set flags to F_I960CA. + + * config/tc-i960.c (po_hash): Declaration deleted. + (next_object_file_charP): Ditto. + (regnames, aregs, coj): Now const. + (parse_memop): Static array def_scale now const. + (md_begin): Cast away const when passing hash routines addresses + of values in regnames or aregs. + (md_longopts): Added "link-relax" and "no-relax" hyphenated forms. + Continue to accept one-word forms. + (struct tabentry, arch_tab): Moved to top level from inside + md_parse_option. Now const. + (md_show_usage): Use arch_tab to generate usage message. Print + hyphenated forms of relax options. + + * config/tc-i960.h (DEFINE_I960_AOUT, TC_S_IS_*, TC_S_*_SYSPROC, + TC_S_FORCE_TO_*): Moved from here... + * config/tc-i960.c: ... to here. Changed DEFINE_I960_AOUT stuff + to test OBJ_AOUT and OBJ_BOUT directly. + + * config/tc-i960.h (CTRL, COBR, COJ, REG, MEM*, FBRA, CALLJ, + M1-M3, REG_OPC, R_*, SFR, LIT, FP, OP, R, RS, RL, RSL, F, + {R,F}{,L}{2,4}, M, SFR_OK, LIT_OK, FP_OK, REG_ALIGN, MEMOP, I_*): + Macros deleted. + + +Fri Jul 15 15:36:51 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * subsegs.c (section_symbol): Had last change backwards. + +Thu Jul 14 13:21:06 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/atof-ns32k.c: Deleted. + + * config/obj-aout.c (obj_aout_frob_symbol): Use + bfd_ind_section_ptr and bfd_und_section_ptr. + + * subsegs.c (subseg_set_rest): Compare segT values directly, + without casting to int first. + + * config/tc-ns32k.c (md_begin): Return value from hash_insert + should be pointer to const. Don't call exit explicitly after + calling as_fatal; it won't return. + (convert_iif): Make local variable j be pointer to bit_fixS, since + that's how it's used. + (encode_operand, case 'b'): Ignore sprintf return value. Don't try + converting freeptr to int and back. + + Merged in NS32K support update from Ian Dall (dall@hfrd.dsto.gov.au): + + * config/te-pc532mach.h: New file. pc532-mach target emulation. + + * config/te-netbsd532.h: New file. Netbsd532 target emulation. + + * config/tc-ns32k.h: Add definition of NOP_OPCODE. + + * config/tc-ns32k.h: Add prototype for fix_new_ns32k_exp. + + * config/tc-ns32k.h: Add BFD_ASSEMBLER support. + + * config/tc-ns32k.c (tc_gen_reloc): New function for BFD_ASSEMBLER. + + * config/tc-ns32k.c (fix_new_ns32k_exp): Get reloc type + differently for BFD_ASSEMBLER. + + * config/tc-ns32k.c (md_estimate_size_before_relax): Get reloc + type differently for BFD_ASSEMBLER. + + * config/tc-ns32k.c (md_create_long_jump): Size of opcode is one + not 2. + + * config/tc-ns32k.c (md_convert_frag): Code for the BFD_ASSEMBLER + case. Also use smart md_pcrel_adjust function. + + * config/tc-ns32k.c (md_apply_fix): Code for the BFD_ASSEMBLER + case. Also use smart md_fix_pcrel_adjust function. + + * config/tc-ns32k.c (md_fix_pcrel_adjust): New function which can + find offset from opcode to operand even if in another frag + and in the presence of relaxing. + + * config/tc-ns32k.c (md_pcrel_adjust): New function which can + find offset from opcode to operand even if in another frag + and in the presence of relaxing. + + * config/tc-ns32k.c (md_number_to_disp): Check ranges properly. + + * config/tc-ns32k.c (md_atof): use atof_ieee instead of special + atof_ns32k. + + * config/tc-ns32k.c (reloc): New (static) function for + BFD_ASSEMBLER. + + * config/tc-ns32k.c (convert_iif): More correct pc relative code. + md_relax must be able to find opcode address even if in another frag. + + * config/tc-ns32k.c: More extensive comments. + + * config/tc-ns32k.c (encode_operand): Support new operand classes I + and Z. Drop Q. + + * config/tc-ns32k.c (fix_new_ns32k_exp): new function and + corresponding prototype. + + * config/tc-ns32k.c: make 32532 default machine instead of 32032. + + * config/tc-ns32k.c: include opcode/ns32k.h after as.h + + * aout_gnu.h: r_disp needs to be 2 bits for TC_NS32K + + * write.h: fx_im_disp needs to be 2 bits big for TC_NS32K + + * write.c (relax_segment): Use TC_PCREL_ADJUST macro (if defined) + instead of adding pcrel_adjust. + + * write.c (write_object_file): Adjust to_addr for the + BROKEN_DOT_WORD feature for the BFD_ASSEMBLER case. + + * write.c (write_object_file): Use TC_CONS_FIX_NEW if it is defined. + + * write.c (write_contents): Add code (currently if + BFD_FAST_SECTION_FILL is defined) to make large fills a lot faster. + + * configure.in: Remove ns32k from special FP list. All the ns32k + series use ieee float. + + * configure.in: Add ns32k-pc532-mach and ns32k-pc532-netbsd targets + + * as.h: include expr.h before targ-env.h. Some target dependent file + want to use expr structures. + +Wed Jul 13 14:49:05 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-m68k.c (m68k_ip): Change rp to be a const pointer. + (md_parse_option): Clear cpu field of current_architecture before + setting a new cpu type. Clear no_68881 for m68881 or m68882. + Clear no_68851 for m68851. + +Tue Jul 12 21:27:05 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/ho-sysv.h (realloc): Declare. + + * symbols.c (symbol_create): New function, most of the guts of the + old symbol_new function. + (symbol_new): Now just checks symbol_table_frozen, calls + symbol_create, and enters the symbol into the symbol table. + * subsegs.c (section_symbol): If EMIT_SECTION_SYMBOLS is not true, + and the symbol table is frozen, call symbol_create instead of + symbol_new. + * symbols.h (symbol_create, symbol_table_frozen): Declare. + + * symbols.c (symbol_clear_list_pointers): Always a function now. + * struc-symbol.h (symbol_clear_list_pointers): Deleted macro + version. + + * symbols.c (debug_verify_symchain): New macro, defined to be + verify_symbol_chain or a cast to void, depending on DEBUG_SYMS. + (many functions): Invoke debug_verify_symchain unconditionally. + +Tue Jul 12 12:06:42 1994 Kung Hsu (kung@x1.cygnus.com) + + * config/obj-ecoff.h: change calling interface of + OBJ_GENERATE_ASM_LINE_STAB. + * config/obj-elf.h: ditto. + * read.c (read_a_source_file): ditto. + * ecoff.h: change calling interface of + ecoff_generate_asm_line_stab. + * ecoff.c (add_file): record of filename to handle case of include + files, also change default built-in type from int to void for + asm file. + * ecoff.c (ecoff_generate_asm_line_stab): handle case of include + files. + +Mon Jul 11 17:20:23 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-mips.c (macro): In case M_LA_AB, SVR4_PIC, large + constant, and case ldd_std, set mips_optimize to 2 temporarily to + avoid inserting an unexpected nop instruction. + +Sat Jul 9 00:05:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_build_lineno): Handle count correctly for last + line number. + +Fri Jul 8 15:22:07 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * gasp.c (process_pseudo_op): Pass right args to do do_aif. + (get_any_string): New arg 'pretend_quote'. + (get_and_process, do_formals, macro_expand, do_sdata, + process_pseudo_op): Use new arg. + +Fri Jul 8 12:23:44 1994 Kung Hsu (kung@mexican.cygnus.com) + + * config/obj-ecoff.h: define macro OBJ_GENERATE_ASM_LINE_STAB. + * config/obj-elf.h: ditto. + * read.c (read_a_source_file): generate line stabs for asm file. + * read.h: add extern generate_asm_line_stab. + * ecoff.h : add prototype for ecoff_generate_asm_line_stab(). + * ecoff.c (add_file): if there's no filename provided, set switch + to generate line stabs for .s file. + * ecoff.c (add_procedure): add stabs symbol for .ent directive. + * ecoff.c (generate_ecoff_stab): creates an artificial stabs. + * ecoff.c (generate_asm_line_stab): generate a artifitial label + for each line and generate a stabn for the line. + +Thu Jul 7 17:04:03 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * gasp.c (get_any_string): Cope with getting a string with an + alternate base specifier. + (do_aif, do_aelse): Only enable output if expression is true and previous + level was on. + (chartype_init): Add BASEBIT chartype. + (process_pseudo_op): Notice nesteed AIFs. + +Thu Jul 7 12:30:22 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * h8300.c (do_a_fix_imm): Code for 2 bit reloc type using in trapa + insn. (fix pr 5165, 5174) + +Thu Jul 7 11:31:32 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (R_DLT_REL): If it isn't defined, then define + to an appropriate value to avoid losing on old hpux systems. + + * config/tc-hppa.c (hppa_fix_adjustable): Reject reductions for + symbols in DLT relative relocs. + (tc_gen_reloc): Zero out the addend field for DLT relative relocs. + +Wed Jul 6 01:07:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-ppc.c (ppc_tc): If not OBJ_COFF, force TOC entry to + align to a four byte boundary. + +Tue Jul 5 15:42:09 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/tc-alpha.c (load_expression): Handle 32-bit addends. + (gpdisp_hi16_howto): Now points to const. + (load_insn_table, alpha_ip): Fix uses of const. + + * doc/internals.texi: Updates to COFF description. Added "@end + defmac" as needed, and some extra heading and "@bye" so it'll + format as a separate document. + +Tue Jul 5 13:54:00 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/obj-elf.h (S_GET_ALIGN, S_SET_ALIGN): Define. + * config/obj-elf.c (obj_elf_common): Set alignment of common + symbol. + * config/tc-sparc.c (s_common): If OBJ_ELF, set alignment of + common symbol. + +Mon Jul 4 18:29:43 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (is_complex): New macro. + (cons_fix_new_hppa): "Handle" complex expressions. + +Fri Jul 1 00:48:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-coff.c (write_object_file): Set s_align field from + section_alignment array. + +Thu Jun 30 15:05:28 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * write.c (write_object_file): Use bfd_com_section_ptr. + * as.h (absolute_section, undefined_section): Use new BFD macros + bfd_abs_section_ptr and bfd_und_section_ptr. + +Thu Jun 30 14:36:37 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/tc-mips.c (macro): For M_LI_SS, decide how to handle it + based on contents of imm_expr and offset_expr, rather than + mips_pic. For M_LI_DD, decide how to handle it based on segment + name of offset_expr, rather than mips_pic. + (mips_ip): If g_switch_value < 4, use immediate values for 'l'. + If g_switch_value < 8, use .rdata rather than .lit for 'L'. + +Wed Jun 29 17:30:46 1994 Stan Shebs (shebs@andros.cygnus.com) + + * as.c (show_usage): Break long string into shorter ones. + (parse_args): Add -v, prints version id and continues. + * config/tc-mips.c (md_show_usage): Break long string. + +Mon Jun 27 09:47:16 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * config/tc-i386.c (md_parse_option): Handle "-V" and "-Q" if + OBJ_ELF is defined. + +Sun Jun 26 16:30:48 1994 Stan Shebs (shebs@andros.cygnus.com) + + * as.c (main) [HOST_SPECIAL_INIT]: New hook, for host-specific + initialization. + +Wed Jun 22 00:24:55 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.h (obj_frob_symbol): Define for OBJ_ELF. + More gas/bfd lossage exposed by the new linker code. + +Tue Jun 21 11:32:18 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * subsegs.c (subseg_change): Clear seginfo after allocating it. + (subseg_get): Pass actual size of seginfo to memset. + + * subsegs.c (abs_seg_info, und_seg_info): Define if BFD_ASSEMBLER. + (subseg_change): Store seg_info for bfd_abs_section_ptr in + abs_seg_info, and store seg_info for bfd_und_section_ptr in + und_seg_info. + (subseg_get): Likewise. Also, don't set output_section if it is + already set. + (seg_info): Define as function. + * subsegs.h (seg_info): Declare as function rather than defining + as macro. + * write.c (relax_and_size_seg): Call seg_info rather than + bfd_get_section_userdata. + +Mon Jun 20 16:30:54 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * configure.in (ppc-*-elf*): New target, like -sysv4*. + + * expr.c (operand): If "0f" is followed by '\0', don't do eol + checks. + +Mon Jun 20 15:17:43 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * ecoff.c (ecoff_build_aux): Call swap_tir_out and swap_rndx_out + via backend pointer, not directly. + +Fri Jun 17 18:05:06 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (config-stamp): Make sure there is at least one + element in the for loop. + +Fri Jun 17 11:01:04 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c: Misc trivial changes to make gcc -Wall happy. + + * config/tc-hppa.h (elf_hppa_final_processing): Declare. + +Wed Jun 15 20:44:46 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * as.c (parse_args): Cast xmalloc return value. + + * Makefile.in (config-stamp): If $(defs) contains multiple words, + emit a #define line for each. + * configure.in: For sparc64 target, use sparc cpu files and add + sparcv9 to extra_defs. No longer treat sparc64-*-aout* specially. + + * config/tc-sparc.c (membar_masks): Now static and const. + (md_show_usage) [!NO_V9]: Add -Av9 to usage message. + (current_architecture) [sparcv9]: Initialize to v9. + (md_begin) [sparcv9]: Don't bother changing it unconditionally + here. + (s_reserve): Don't pass unexpected argument to as_bad with + bad-segment message. + + * as.h (bfd_alloc_by_size_t) [BFD_ASSEMBLER]: Declare. + + * config/atof-ieee.c (int_to_gen): Commented out unused routine. + + * config/tc-vax.c (md_assemble): Removed check of operand section. + + Fri Jun 3 17:25:08 1994 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.h (DBG_S_C_COMPLX4, DBG_S_C_COMPLX8): define + these new VMS symbol-type macros for `complex float' and + `complex double' support. Their values come from the existing + DSC$K_DTYPE_FC and DSC$K_DTYPE_DC macros in . + (DBG_S_C_REAL8_G, DBG_S_C_COMPLX8_G): G_float versions of + REAL8 and COMPLX8; not used yet, because gcc outputs the same + .stabs for `double' regardless of whether `-mg' is used. + * config/obj-vms.c (VMS_typedef_parse) [case 'r']: add entries + for gcc2's predefined types "complex float", "complex double", + and "complex long double" (identical to complex double). + +Wed Jun 15 12:32:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-coff.c (coff_frob_symbol): Use C_STAT for the .text + section symbol, not C_LABEL. + + * config/tc-mips.c (mips_ip): Permit a modifier in 'o' case, and + permit non constant expressions in 'u' case. Lets ``lui + $8,%hi(foo); lw $8,%lo(foo)($8)'' work correctly. + +Mon Jun 13 12:08:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-aout.c (obj_aout_frob_symbol): Warn about an attempt + to put a common symbol in a set. + +Sat Jun 11 16:41:21 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Add weak symbols as an extension to a.out. + * read.c (pseudo_set): Only preserve external bit for OBJ_AOUT and + OBJ_BOUT if not BFD_ASSEMBLER. + * config/aout_gnu.h (N_WEAKU, N_WEAKA, N_WEAKT, N_WEAKD, N_WEAKB): + Define as in ../include/aout/aout64.h. + * config/obj-aout.h (OBJ_SYMFIELD_TYPE): If not BFD_ASSEMBLER, + define as char. + (S_GET_WEAK, S_SET_WEAK): Define if not BFD_ASSEMBLER. + * config/obj-aout.c (obj_pseudo_table): Add "weak". + (obj_emit_symbols): Adjust type of weak symbols. + (obj_aout_weak): New static function. + +Fri Jun 10 13:48:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-elf.c (obj_elf_section): Don't set any flags based on + the type of a special section. + + * config/ho-sunos.h: Include . Don't declare malloc, + realloc, free, or atol. + +Wed Jun 8 06:28:37 1994 Bill Cox (bill@cygnus.com) + + * Makefile.in (check): Delete as.new dependency, so that + regression test doesn't trigger an assembler build. + +Tue Jun 7 13:33:18 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (mostlyclean, realclean): New targets. + * doc/Makefile.in, testsuite/Makefile.in: Likewise. + +Mon Jun 6 13:10:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (RDATA_SECTION_NAME): Define. + (macro): Correct M_LI_SS SVR4_PIC/EMBEDDED_PIC case. After M_LI_D + or M_L_DOB or label dob, force a new frag to avoid getting + confused in tc_gen_reloc. + (mips_ip): Use RDATA_SECTION_NAME, not .rdata. + (s_change_sec): Likewise. + +Fri Jun 3 23:35:36 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * read.c (emit_expr): Use memset to zero out memory, rather than + going through md_number_to_chars. This permits handling symbolic + arguments when the size is larger than sizeof (valueT), if + TC_CONS_FIX_NEW is prepared to handle the case (as it is on MIPS). + +Fri Jun 3 12:50:13 1994 David J. MacKenzie (djm@rtl.cygnus.com) + + * as.c (show_usage), config/tc-alpha.c (md_show_usage), + config/tc-mips.c (md_show_usage): Fix up messages. + + * as.h: Replace flagseen with separate variables. + * as.c (parse_args): Set them. Don't accept -1 option, or -v + explicitly (it's a synonym for --version). + * as.c, input-scrub.c, messages.c, read.c, symbols.c, write.c, + config/obj-aout.c, config/obj-aout.h, config/obj-bout.c, + config/obj-bout.h, config/obj-coff.c, config/obj-coff.h, + config/obj-vms.c, config/tc-hppa.c, config/tc-i386.c, + config/tc-i960.c, config/tc-m68k.c, config/tc-mips.c, + config/tc-vax.c: Use the new flag variables instead of flagseen. + * config/tc-vax.c [OBJ_VMS]: Recognize -+, -1, -v, and document in + usage. + + * as.c (show_usage): Remove target specific messages; + instead, call md_show_usage. + (parse_args): Use getopt_long_only. Take pointers to argc and + argv. + (main): Pass parse_args pointers. + * as.h: Remove 3 variables that are redundant with flagseen. + * as.c, messages.c: Change their users to use flagseen. + Define getopt stuff. + * tc.h: Update md_parse_option decl. Add md_show_usage decl. + * config/tc-*.c: Add md_shortopts, md_longopts, + md_longopts_size, md_show_usage. Change calling convention for + md_parse_option. Remove md_parse_long_option. + * config/tc-ns32k.c: Rename `struct option' to `struct ns32k_option'. + * config/tc-i386.h: Don't define md_parse_option. + +Thu Jun 2 13:54:46 1994 David J. Mackenzie (djm@rtl.cygnus.com) + + * as.c (show_usage): New function. + (parse_args): Code moved from main. + Recognize --help and --version. + * config/tc-ns32k.h: Define TC_NS32K. + * doc/as.texinfo: Document all of the target-independent command + line options. + +Thu Jun 2 12:07:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * gasp.c (hash_new_table): Clear newly allocated table. + + * config/tc-m68k.c (enum _register): Add 68060 control registers + BUSCR and PCR. + (last_movec_reg): New macro. + (m68000_control_regs, m68010_control_regs, m68020_control_regs, + m68040_control_regs, m68060_control_regs): New arrays. + (control_regs): New pointer. + (m68k_ip): Use control_regs instead of testing CPU every time. + Use last_movec_reg too. In error messages, handle 68060, and + print 68060 for mfloat, too. + (m68k_init_after_args): Handle "68060". Use m68040up for making + m68851 choice. Set control_regs. + (md_parse_option): Handle "68060". + * configure.in: Setting cpu_type, recognize m68060 too. + + * config/obj-coff.c (fixup_segment) [!BFD_ASSEMBLER] + [DIFF_EXPR_OK]: Do conversion to pc-relative for difference, even + if pcrel is already set. + + * read.c (potable): Add this_gcc_requires_the_gnu_assembler in all + lower-case, in case we're ignoring case of opcodes in the input + file. + + * doc/as.texinfo (.section): Document as unavailable for a.out + type formats. + + * config/tc-alpha.c (machine): New variable. + (load_insn): New macro. + (load_insn_table): New function. + (md_begin): Call load_insn_table, once for basic instructions and + once for appropriate PAL instruction table. + (md_parse_option): Set `machine' based on -m##### arguments. + * config/alpha-opcode.h (alpha_pal21064_opcodes): Split out from + alpha_opcodes. + (alpha_pal21164_opcodes): New table. + (NUM21064OPCODES, NUM21164OPCODES): New macros. + + * configure.in (target i386-*-netbsd0.8): Use 386bsd emulation. + + * doc/Makefile.in (install-info-gasp): Use $$dir when installing + file. + +Wed Jun 1 10:48:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_ip): Force floating point values to be + aligned correctly. + +Fri May 27 10:05:53 1994 Ken Raeburn (raeburn@cygnus.com) + + Merged in changes from gas-2.3 net release: + + * Makefile.in (VERSION): Updated to cygnus-2.3.1. + + * config/obj-vms.c: Replaced unchecked uses of malloc with + xmalloc. + + * listing.c (list_symbol_table): Only test BFD64, not + BFD_ASSEMBLER too. + + * config/obj-coff.c (fixup_segment) [BFD_ASSEMBLER] + [DIFF_EXPR_OK]: Don't check pcrel, just convert it. + + * config/obj-vms.c: Removed lots of extra semicolons after + compound statements. + (strchr): Don't declare here. + + * config/ho-vax.h (realloc): Declare. + + * config/ho-vms.h (strchr, strdup): Declare. + + * config/tc-sparc.c (md_parse_option) [OBJ_ELF]: Accept and ignore + option `-q'. + + Wed May 18 20:50:35 1994 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.h (DBG_S_C_SQUAD, DBG_S_C_UQUAD): define these + new VMS symbol-type macros; signed and unsigned quadword integers, + for `long long' support. Their values come from the existing + DSC$K_DTYPE_QU and DSC$K_DTYPE_Q macros in . The + VMS debugger now recognizes `long long' variables correctly. + * config/obj-vms.c (VMS_typedef_parse) [case 'r']: add entries + for gcc2's predefined types "long double" (same as double, as + per gcc's current state), "long long int", "long long unsigned + int", and final `otherwise' case (to avoid uninitialized type + and size fields). [caveat: predefined types "complex int", + "complex float", "complex double", and "complex long double" are + still missing.] + + * config/ho-vms.h (EXIT_FAILURE): define as 0x10000002 instead + of 0, because the latter indicates success rather than failure + when passed to `exit' or return from `main' compiled by gcc2. + + * config/obj-vms.c (array_suffix, generate_suffix): replace two + hardcoded `0xa3's with macro DBG_S_C_ADVANCED_TYPE from obj-vms.h. + (VMS_typedef_parse): eliminate redundant if-then-else when + allocating new symbol entry and linking it to VMS_Symbol_type_list. + + Tue May 17 20:47:31 1994 Pat Rankin (rankin@eql.caltech.edu) + + * config/obj-vms.c (Write_VMS_MHD_Records): don't try to interpret + the contents of the GAS_VERSION string when falling back to it for + language processor identification. + + * make-gas.com, vmsconf.sh (ENVIRON): fix misspelling of + `psect_attr' in linker options. + + Wed May 11 22:32:00 1994 DJ Delorie (dj@ctron.com) + + * configure.bat: update to latest makefile.in + * config/te-go32.h: [new] go32's environment + +Fri May 20 17:59:34 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * as.h: Don't declare parameters for strstr. + +Thu May 19 15:40:13 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-sparc.c (md_section_align): Don't change the size if + OBJ_ELF. + +Wed May 18 13:08:07 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (install): Redirect ln output to /dev/null. If ln + fails on gasp, install gasp.new, not gasp. + +Wed May 18 09:16:36 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_ip): Use R_HPPA_ABS_CALL, not R_HPPA for + absolute calls. + +Tue May 17 12:50:46 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_parse_fp_cmp_cond): Report an error + on a partial completer match. + +Mon May 16 12:03:49 1994 Jeff Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c: Change .hppa_unwind to .PARISC.unwind + throughout code. + (is_complex): Delete definition and support for complex relocation + types. + (tc_gen_reloc): Delete special unwind crud for ELF. Simplify and + rewrite ELF code based on 94-02-02 PA ELF draft spec. + (pa_build_unwind_subspace): Use standard PARISC_DIR32 relocs for + the unwind descriptors. + +Fri May 6 14:13:15 1994 Steve Chamberlain (sac@cygnus.com) + + * config/go32.mh: New makefile fragment for go32 crossing. + * configure.in (host==go32): Use new fragment. + +Fri May 6 14:35:58 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * gasp.c: Include libiberty.h. + (main): Remove unused variable i. + + * config/tc-ppc.c (md_begin): When using -many, permit comparison + instructions to appear multiple times in the opcode table. + +Thu May 5 19:14:43 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (VERSION): Update to 2.2.90. + + * symbols.c (symbol_new) [BFD_ASSEMBLER]: Don't permit additions + to the symbol table if it's already been set in the output bfd. + (symbol_begin) [! EMIT_SECTION_SYMBOLS] [RELOC_REQUIRES_SYMBOL]: + Don't use bfd_abs_section.symbol for gas absolute symbol. + + * doc/Makefile.in (distclean, clean-dvi, clean-info): Delete gasp + files too. + +Thu May 5 18:12:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_emit_delays): Make call to + mips_no_prev_insn unconditional. + +Thu May 5 17:25:38 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/obj-coff*.*: Merged coffbfd versions into coff versions, + with a single "#ifdef BFD_ASSEMBLER" controlling most of it for + now. Deleted obj-coffbfd.* files. + * configure.in: Always use obj-coff.* for COFF targets. + +Wed May 4 13:34:11 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/te-dpx2.h (TARGET_FORMAT, REGISTER_PREFIX_OPTIONAL): + Define. + * configure.in (m68k-bull-sysv3*): Enable. + + * config/coff_gnu.h: Deleted. + +Wed May 4 11:29:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-m68k.h (TARGET_FORMAT): If not TE_SUN3, define as + "a.out-zero.big". + + * config/obj-coffbfd.c (fixup_segment): Make common symbol and PC + relative adjustments when TE_LYNX is defined as well as when + TC_I386 is defined. + +Wed May 4 02:29:21 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * as.h (strstr): Restore declaration. + (subseg_get) [BFD_ASSEMBLER]: Declare. + + * write.c (write_object_file): If obj_adjust_symtab is defined, + invoke it. Then call set_symtab, and finally invoke *_frob_file + hooks. + * config/obj-coff.c (coff_adjust_symtab): Renamed from + coff_frob_file. + * config/obj-coff.h (coff_adjust_symtab): Changed declaration + accordingly. + (obj_adjust_symtab): Macro also changed. + + * configure.in (i386-*-gnu*): New target, handled like i386-mach. + +Tue May 3 21:04:16 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/obj-coff.h (TARGET_FORMAT) [TC_I960]: Select little + endian version. + + * config/obj-coffbfd.h (TARGET_FORMAT) [TC_I960]: Ditto. + + * config/obj-coff.c (coff_frob_section): Round up the size of + every section to a multiple of the alignment, so that BFD doesn't + surprise us. + + Eliminate many simple differences between the two COFF back ends: + + * config/obj-coffbfd.c: Removed all uses of DEFUN and DEFUN_VOID. + Made minor stylistic changes, deleted some register declarations. + (stack_top): Deleted. + (symbol_to_chars): Use absolute_section and reg_section instead of + the corresponding SEG_* symbols. + (obj_coff_endef, tag_find_or_make, fixup_segment): Likewise. + (stack typedef, stack_init, stack_delete, stack_push, stack_pop): + Moved to just after pseudo-op table. All functions now static. + (stack_delete): Removed declaration. + (tag_init, tag_insert, tag_find_or_make, tag_find): Moved to just + after stack functions. + * config/obj-coffbfd.h: Reordered some declarations and macros. + (stack_init, stack_delete, stack_push, stack_pop): Don't declare. + (stack typedef): Deleted. + (SYMBOLS_NEED_BACKPOINTERS): Always undef then define; don't test. + (SYM_AUXENT): New macro. + (SA_GET_*, SA_SET_*): Define in terms of SYM_AUXENT when feasible. + (SF_GET_*, SF_SET_*): Define in terms of SF_GET when feasible. + (SA_GET_SYM_TAGNDX, SA_GET_SYM_ENDNDX, SA_SET_SYM_TAGNDX, + SA_SET_SYM_ENDNDX, object_headers typedef, data_section_header, + text_section_header): Delete non-BFD_HEADERS versions, since we + always define that symbol now. + + * config/obj-coff.c (stack_top): Deleted. + (obj_coff_endef, obj_coff_dim, obj_coff_line, obj_coff_size, + obj_coff_scl, obj_coff_tag, obj_coff_type, obj_coff_val): Change + argument name from "ignored" to "ignore". + (obj_coff_val): Use frag_now_fix. + (obj_pseudo_table): Removed IGNORE_DEBUG version, since it doesn't + get used. + (stack typedef, stack_init, stack_delete, stack_push, stack_pop): + Moved to just after pseudo-op table. All functions now static. + (tag_init, tag_insert, tag_find_or_make, tag_find): Moved to just + after stack functions. + * config/obj-coff.h: Reordered some declarations and macros. + Protected against multiple inclusions. + (stack_init, stack_delete, stack_push, stack_pop): Don't declare. + (stack typedef): Deleted. + (SYMBOLS_NEED_BACKPOINTERS): Always undef then define; don't test. + (stdoutput): Deleted declaration. + (TARGET_FORMAT) [TC_I386]: Don't define if already defined. + +Mon May 2 17:09:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * subsegs.h (segment_info_type): Use fix_tail field even if + BFD_ASSEMBLER. + * subsegs.c (subseg_change): Initialize fix_tail field. + (subseg_get): Likewise. + * write.c (frags_chained): New static variable. + (fix_new_internal): If frags_chained is set, use fix_root and + fix_tail from seg_info (now_seg), rather than frchain_now. + (chain_frchains_together_1): Set fix_tail field. + (chain_frchains_together): Set frags_chained. + +Thu Apr 28 01:39:15 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * config/tc-mips.c (s_option): Only refer to g_switch_* variables + if GPOPT is defined. + (s_abicalls): Ditto. + (md_apply_fix): Cast char* to unsigned char* to avoid pointer + mismatch. + +Wed Apr 27 11:06:32 1994 Steve Chamberlain (sac@cygnus.com) + + * configure.in (i386-*-go32): Uses coff now. + * gasp.c (main): Now takes -D on command line. + (show_usage): Describe new options. + +Tue Apr 26 17:10:30 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * listing.c (list_symbol_table): Print "NO DEFINED SYMBOLS" and + "NO UNDEFINED SYMBOLS" if there aren't any, instead of displaying + the header with an empty list. + + * config/obj-coffbfd.c (fill_section): Check COFF_NOLOAD_PROBLEM + also before setting STYP_NOLOAD for .bss section. + + * config/tc-m68k.c (flag_reg_prefix_optional): New variable. + Initialized to value of REGISTER_PREFIX_OPTIONAL, if defined, or + zero. + (m68k_reg_parse): If flag_reg_prefix_optional is set, permit + register prefix to be absent. + (m68k_ip_op): Accept `&' also for immediate constants. + (insert_reg): Don't bother with (two!?) sanity checks of the + symbol table when inserting each register. + (m68k_parse_long_option): New function. Set + flag_reg_prefix_optional if "register-prefix-optional" is passed. + * config/tc-m68k.h (REGISTER_PREFIX): Always define if not already + defined. + (OPTIONAL_REGISTER_PREFIX): Don't define. + (REGISTER_PREFIX_OPTIONAL): If not already defined, define as zero + or one depending on M68KCOFF. + + Some changes to help Apollo support, from troy@cbme.unsw.edu.au: + * config/tc-m68k.c (DATA, ADDR, SP, FPREG, COPNUM, BAD, BAC): + Define as macros instead of enumerators, since the Apollo compiler + can't handle "enumVal1, enumVal2 = enumVal1" when defining an enum + type. + (make_pcrel_absolute) [NO_PCREL_RELOCS]: New function. + (tc_coff_fix2rtype) [NO_PCREL_RELOCS]: Generate only R_RELBYTE, + R_DIR16, and R_DIR32 relocs. + * config/tc-m68k.h [TE_APOLLO] (COFF_MAGIC, COFF_AOUTHDR_MAGIC): + Use Apollo versions. + [TE_APOLLO] (OBJ_COFF_OMIT_OPTIONAL_HEADER): Undefine. That is, + do include the optional header for Apollo target. + (COFF_MAGIC): Don't define as MC68MAGIC if it's already defined. + + * config/tc-m68k.h [TE_DELTA] (LEX_PCT): Define as 1, so that `%' + can be used within a label name. + + * config/tc-m68k.h (m68k_init_after_args): Declare. + (tc_init_after_args): Define as m68k_init_after_args. + * config/tc-m68k.c (m68k_init_after_args): New function, + containing one-shot code from md_assemble. Added warning for + combination of 68040 and 68851. + (md_assemble): Startup-time code deleted. + +Mon Apr 25 16:19:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * doc/Makefile.in (clean, distclean): Remove asconfig.texi. + +Sun Apr 24 00:13:08 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_ip): 13 bit immediate constant (for break + instruction) is unsigned. + +Fri Apr 22 17:58:22 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-ecoff.c (ecoff_frob_file): Use bfd_ecoff_set_gp_value + and bfd_ecoff_set_regmasks to set the GP value and the register + masks, rather than using the now obsolete fake .reginfo section. + +Fri Apr 22 15:17:06 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * listing.c (list_symbol_table): Don't print register symbols as + undefined. + + * config/obj-coff.c (obj_symbol_new_hook): Don't need to strip + underscores, since symbol_new will already have done it. + * config/obj-coffbfd.c (obj_symbol_new_hook): Ditto. + + * as.c (main): If tc_init_after_args is defined, invoke it after + all arguments have been processed. + + Some changes to help Apollo support, from troy@cbme.unsw.edu.au: + * as.c (perform_an_assembly_pass) [TE_APOLLO]: Create .wtext + section instead of .text. Call create_target_segments. + * read.c (demand_copy_string): No longer static. + +Thu Apr 21 15:50:04 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (append_insn): Permit branches to be switched + with the preceding instruction even if .set nobopt has been seen. + .set nobopt actually controls whether to bring up an instruction + from the branch target, which gas does not currently support. + +Wed Apr 20 18:46:14 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/obj-coff.h, config/obj-coff.c: Deleted all code used only + when BFD_ASSEMBLER is not defined, and all conditionals relating + to such code. No such targets remain. + + Fixes for stabs-in-coff: + * config/obj-coff.c: Include subsegs.h. + (coff_frob_section): New function. + (obj_coff_init_stab_section): New function. + * config/obj-coff.h (obj_coff_init_stab_section, + coff_frob_section): Declare. + (obj_frob_section): New macro; uses coff_frob_section. + (INIT_STAB_SECTION): New macro; uses obj_coff_init_stab_section. + + * config/tc-sparc.c (md_section_align): Always round up to + multiple of alignment power specified in bfd target vector. + + * gasp.c: Include ctype.h. + +Mon Apr 18 21:08:01 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * doc/Makefile.in, doc/as.texinfo: Renamed asdoc-config.texi to + asconfig.texi. + + * doc/Makefile.in (install-info-as, install-info-gasp): Get file + names from source directory without pathname. + + * config/obj-vms.c (VMS_write_object_file): While looking for + register mask, skip empty fill frags caused by enabling listing + output. + + * config/ho-sysv.h: Include string.h. + + * doc/internals.texi: New (well, recently added) file. Just added + info on as_warn and friends. + +Mon Apr 18 14:28:22 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_parse_space_stmt): Use the built-in + defaults for defined, private, and spnum fields for the + $TEXT$ and $PRIVATE$ spaces. Do not clobber spnum. Do + not reset the segment if just updating a space. + (pa_spaces_begin): Set BFD section flags for all built-in + subspaces. + +Fri Apr 15 10:51:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (first_proc_ptr): New static variable. + (add_procedure): Set first_proc_ptr if it hasn't been set. + (ecoff_build_lineno): If the first procedure does not start at + address zero, insert a dummy line to compensate. + + * Makefile.in (bootstrap, bootstrap2, bootstrap3): Make gasp.new + as well as as.new. + +Thu Apr 14 15:12:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * expr.c (operand): Try to parse "0f" and "0b" sequences as + floating point and binary numbers respectively; if it doesn't + work, treat them as local labels. + + * Makefile.in: Make $(OBJS) depend on $(ALL_OBJ_DEPS). + * configure.in: Set ALL_OBJ_DEPS in output Makefile. + + Based on suggestions from + (Charles Bailey): + * vmsconf.sh: In generated file, get ".obj" suffix right, build + source files from other directories into objects in the current + directory, and specify PSECT attributes explicitly to linker. + Also added missing label. + * Makefile.in (stamp-mk.com): Reference new variable + VMS_OTHER_OBJS for list of non-local object files, instead of + listing them here. + (VMS_OTHER_OBJS): New variable, added more libiberty files. + * make-gas.com: Regenerated. + + * config/ho-vms.h (unlink): Define as delete. + + * config-gas.com: Fix quoting on TARGET_CANONICAL definition. + Delete files before creating them. + +Thu Apr 14 13:34:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (de-stage1, de-stage2, de-stage3): Use rm -f. + + * config/tc-mips.h (DIFF_EXPR_OK): Define. + * config/tc-mips.c (macro_build): Permit BFD_RELOC_PCREL_LO16 for + certain cases of 'i', 'j' and 'o'. Change 'u' to take an + argument, the reloc type. + (load_register): Pass reloc type to macro_build for 'u'. + (macro): Likewise. For M_LA_AB permit a difference expression + when generating embedded PIC code between an arbitrary symbol and + a symbol in the .text section. + (mips_force_relocation): Force BFD_RELOC_PCREL_HI16_S and + BFD_RELOC_PCREL_LO16 to be emitted. + (md_apply_fix): Check that most relocs are not PC relative. + Handle BFD_RELOC_PCREL_HI16_S and BFD_RELOC_PCREL_LO16. + (tc_gen_reloc): Change #error to as_fatal. Handle + BFD_RELOC_PCREL_LO16 and BFD_RELOC_PCREL_HI16_S. + +Tue Apr 12 18:25:13 1994 Stan Shebs (shebs@andros.cygnus.com) + + * subsegs.c (subsegs_begin): Call memset with args in the correct + order. + (subseg_get): Clear newly allocated seginfo, set its pointer slots + to NULL instead of 0. + +Mon Apr 11 09:00:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_procend): Handle case where label was + defined after the .proc directive. + + * config/tc-hppa.c (pa_procend): Give an error if we encounter a + procend for a procedure without a name. + +Thu Apr 7 14:28:30 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (macro): Pass NULL for expression argument to + macro_build for nori case. + (SWITCH_TABLE): Define. + (mips_force_relocation): Force a relocation for a switch table + entry. + (md_apply_fix): Write switch table entry value into file. + (tc_gen_reloc): Use BFD_RELOC_GPREL32 for a switch table entry, + and set the addend to the difference between the reloc address and + the subtrahend. + +Thu Apr 7 10:38:18 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.h (elf_tc_symbol): Delete. No longer used. + (elf_tc_make_sections): Likewise. + (hppa_tc_make_sections, hppa_tc_symbol): Delete extern decls. + + * config/tc-hppa.c (hppa_tc_make_sections): Delete function. + (hppa_tc_symbol): Likewise. + + * config/obj-elf.c (elf_frob_file): Delete elf_tc_symbol and + elf_tc_make_sections stuff. It was there to support PA braindamage + which has been fixed, and in the case of elf_tc_make_sections is + redundant with elf_tc_final_processing. + +Wed Apr 6 20:48:30 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * configure.in (hppa*-*-*elf*): Don't require "-hp-" for the + manufacturer. + +Tue Apr 5 15:48:03 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_ip): For case 'o', when generating + embedded PIC code, accept the difference between two local symbols + as being constant. + (mips_force_relocation): Only force a reloc to be generated for a + PC relative fixup. + (md_apply_fix): For BFD_RELOC_32 and BFD_RELOC_LO16, put the fixup + value into the file if the fixup will not generate a reloc. + +Tue Apr 5 11:14:14 1994 Ken Raeburn (raeburn@rtl.cygnus.com) + + * config/tc-sparc.c (s_reserve): If section passed isn't bss, + don't spew remainder of input file in error message. + (tc_gen_reloc): If bfd_reloc_type_lookup returns null, print error + message with reloc type and try to process remainder of file. + + * doc/Makefile.in (install-info-as, install-info-gasp): New + targets, now explicitly checking $(srcdir) for info files. + (install-info): Depend on both of them; do nothing more. + +Mon Apr 4 17:06:04 1994 Jeffrey A. Law (law@cygnus.com) + + * config/tc-hppa.c (tc_gen_reloc): Fix thinko in ELF version. + +Mon Apr 4 12:39:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-ppc.c (ppc_insert_operand): Check PPC_OPERAND_SIGNED + flag rather than signedp field. Only permit extended range if + PPC_OPERAND_SIGNOPT flag is set and assembling in 32 bit mode. + Based on patch from David Edelsohn (edelsohn@npac.syr.edu). + + * config/tc-ppc.c (ppc_size): New static variable. + (ppc_arch): Check for PPC_OPCODE_PPC before PPC_OPCODE_POWER. + (md_begin): If an instruction has a size specific flag set, only + add it if we are assembling that size. + +Thu Mar 31 16:51:16 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-sparc.c (tc_gen_reloc): Add a gruesome hack to get + cross section PC relative relocs right for COFF and ELF. + +Mon Mar 28 14:38:23 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Always define. + (OBJ_PROCESS_STAB): Don't define. + +Mon Mar 28 12:40:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-aout.c (obj_aout_frob_symbols): Don't let BFD clobber + the type of symbol set symbols which happen to be in the absolute + or undefined section. + +Mon Mar 28 12:35:00 1994 David Edelsohn (edelsohn@npac.syr.edu) + + * config/tc-ppc.c (md_parse_option): Add -mpwrx (POWER/2 aka + RIOS2), -mpwr (POWER aka RIOS1), -mppc (PowerPC aka MPC603/604), + and -many (all architectures). + +Sun Mar 27 14:04:19 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (tc_gen_reloc): Set addend for relocation + involving a function symbol which is not a plabel to zero. + (md_apply_fix): Never pass a function symbol to field_adjust. + +Fri Mar 25 17:35:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-aout.c (obj_aout_frob_symbol): If N_EXT is set for an + N_INDR symbol, set BSF_EXPORT and clear BSF_LOCAL. + + * config/tc-mips.c (append_insn): If EMBEDDED_PIC, don't swap a + branch with an instruction that uses $at, in case the branch is + later expanded. + (macro): If EMBEDDED_PIC, case M_JAL_A may use $at. + (md_pcrel_from): If not OBJ_AOUT, return 4 for an undefined symbol + to make it pcrel_offset. + (tc_gen_reloc): If not OBJ_AOUT, set the reloc addend to + reloc->address; another gruesome hack to get gas reloc handling to + do the right thing. + +Thu Mar 24 21:29:29 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/tc-alpha.c (alpha_ip): Only set GP prolog size if using + PV register. + (T12): New macro. + (emit_insn): New function. + (md_assemble): Call it. + (alpha_force_relocation): Handle BFD_RELOC_26, for call_pal + instructions. + (lituse_pending): New variable. Set by anything that generates a + LITERAL reloc, cleared by anything that generates a LITUSE reloc, + tested by code that might want to emit a LITUSE reloc. + (emit_unaligned_io): New function. Currently calls md_assemble, + but it should eventually be converted to generate the insn itself + and call emit_insn directly. + (emit_load_unal, emit_store_unal, emit_byte_manip_r, + emit_extract_r, emit_insert_r, emit_mask_r, emit_sign_extend, + emit_bis_r): Likewise. + (alpha_ip, case 'I'): Handle with BFD_RELOC_23. + (alpha_ip, label get_macro): Don't emit the final instruction if + the opcode is zero. + (alpha_ip, case 'B', subcase 'd'): New case, for subword and + unaligned memory access macros. + (md_apply_fix): Handle BFD_RELOC_26. Generate an error message if + the value can't be resolved. + +Wed Mar 23 16:06:08 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (md_parse_option): For -membedded-pic, force + the -G value to 0x7fffffff. For SVR4 PIC options, don't call + bfd_set_gp_size here, it's done in md_begin. Don't permit -G with + -membedded-pic. + (mips_force_relocation): New function. + (md_apply_fix): Set fixP->fx_done appropriately. + (s_change_sec): For EMBEDDED_PIC, change .data and .rdata to + .sdata. + * config/tc-mips.h (TC_FORCE_RELOCATION): Define. + (mips_force_relocation): Declare. + (TC_HANDLE_FX_DONE): Define. + +Tue Mar 22 13:58:37 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (enum mips_pic_level): New enum. + (mips_pic): Change from int to enum mips_pic_level. Change all + uses (0 becomes NO_PIC, 2 becomes SVR4_PIC). + (load_address): Handle EMBEDDED_PIC. + (macro): Handle EMBEDDED_PIC in all PIC cases. + (md_parse_option): Accept -membedded-pic to use EMBEDDED_PIC. If + OBJ_ELF, accept -KPIC and -call_shared to use SVR4_PIC and accept + -non_shared to use NO_PIC (this is how the Irix 5 assembler + works). Do not permit -G with SVR4_PIC. + (s_abicalls): Warn if -G was used, and force -G 0. + (tc_gen_reloc): Set reloc->addend to 0 for a PC relative reloc for + anything but a.out, not just for ELF. For ECOFF, don't generate a + BFD_RELOC_16_PCREL_S2 reloc unless using EMBEDDED_PIC. + + * config/obj-ecoff.h (obj_sec_sym_ok_for_reloc): Define to be 1. + +Sun Mar 20 16:31:55 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (create_new_space): Use ints, not chars as + parameters to avoid losing when compiling with HP CC. + (create_new_subspace, update_subspace, fix_new_hppa): Likewise. + +Sun Mar 20 14:43:14 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (config-stamp): If `defs' is defined, emit a + preprocessor directive to create a macro named by this value into + config.new; don't explicitly go for BFD_ASSEMBLER. + * configure.in: Define `defs', not `BFDDEF'. Set it to + MANY_SEGMENTS for any obj-coffbfd target. + * config/obj-coffbfd.h (BFD_HEADERS, BFD): Define. + * config/i386coff.mt (TDEFINES): Don't define BFD, MANY_SEGMENTS, + or BFD_HEADERS. + (LOCAL_LOADLIBES): Deleted. + * config/m68kcoff.mt (TDEFINES): Don't define those macros. + * config/m88kcoff.mt (TDEFINES): Ditto. + * config/ebmon29k.mt: Deleted. + * config/h8300hds.mt: Deleted. + * config/ic960coff.mt: Deleted. + * config/sparc.mt: Deleted. + * config/h8300.mt (LOCAL_LOADLIBES, TDEFINES): Deleted. + * config/h8500.mt (LOCAL_LOADLIBES, TDEFINES): Deleted. + * config/sh.mt (LOCAL_LOADLIBES, TDEFINES): Deleted. + * config/z8k.mt (LOCAL_LOADLIBES): Deleted. + (TDEFINES): Don't define the coffbfd macros. + + * Makefile.in: Insert makefile fragments before OBJS definition. + (OBJS): Add $(TE_OBJS). + + * config/obj-coff.c (obj_pseudo_table): Supply "section" + unconditionally. + + * write.c (set_symtab): Define only if BFD_ASSEMBLER. + +Sun Mar 20 12:06:05 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Makefile.in (STAGESTUFF): Add gasp.new. + +Fri Mar 18 20:09:16 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * write.c (symbol_table_frozen): New variable, to be set after + bfd_set_symtab is called. + (dump_section_relocs): Note whether a symbol is a section symbol + or not. + (adjust_reloc_syms): For now, always supply an absolute symbol for + fixups without symbols but not yet `done'. Use section_symbol to + get the symbol, instead of going directly for abs_symbol. + (write_relocs) [DEBUG4]: Abort if any symbol referred to by a + reloc is not a section symbol and is not in the symbol table. + (set_symtab): New function, broken out from write_object_file. + Counts symbol table instead of relying on an earlier count. + (write_object_file): Call set_symtab, but do it after potentially + invoking the *_frob_file macros. Don't bother counting symbols. + Call symbol_remove, instead of expanding it in place. Moved the + conditionalized `object_file_size' declaration down to + conditionalized block where it's used. When using the absolute + symbol for a fixup without a symbol, set sy_used_in_reloc. + (write_object_file) [BFD_ASSEMBLER]: Call section_symbol to get + the correct symbol for the absolute section. + + * subsegs.c (section_symbol): Use symbol_new instead of + symbol_make, since we may want it to go into the symbol table. + Make the new symbol have internal linkage. If + obj_sec_sym_ok_for_reloc says it's okay, use the BFD section + symbol with the newly created GAS symbol. + (obj_sec_sym_ok_for_reloc): Default to always returning 0. + * config/obj-aout.h (obj_sec_sym_ok_for_reloc) [BFD_ASSEMBLER]: + New macro. + * config/obj-elf.h (obj_sec_sym_ok_for_reloc): New macro. + + * config/tc-sparc.c: Include subsegs.h. + (in_signed_range): New function. + (sparc_ip): Use it. + (sparc_ip, case 'i'): Use BFD_RELOC_SPARC13, not _BASE13. + (sparc_ip, label "immediate"): Reject constants for pcrel + instructions only if the relocation type indicates a "call" + instruction and the offset is within range of a "jmpl %g0". If + it's not in range, use the absolute section symbol plus an offset. + (md_apply_fix): Use in_signed_range. Combined _SPARC13 and + _BASE13 cases. + (tc_gen_reloc): Permit BFD_RELOC_SPARC13. + + * config/ic960coff.mt (TDEFINES): Fixed typo (MANY_SECTIONS, not + MANY_SEGMENTS). + + * configure.in: Eliminated all targets using obj-coff but not + defining BFD_ASSEMBLER; I think all such targets that are + supported will be matched by real CPU-OS combinations earlier in + the case statement. + (targets *-*-coff*, *-sysv*, *-*-sco*, *-*-sysv32): Deleted. Made + some comments about the dpx2 configuration, but left it disabled, + since it couldn't be reached before. + (target a29k-amd-ebmonold): Deleted. + +Thu Mar 17 13:36:09 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_import): Correctly handle importing of an + already defined symbol. + +Wed Mar 16 17:11:37 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_ip): Only accept overly large values for + the 'j' operand if there are no further alternatives for this + instruction. + + * config/obj-coffbfd.c (adjust_stab_section): Initialize + stabstrseg to SEG_UNKNOWN, not -1. After loop, check whether it + is not SEG_UNKNOWN rather than checking whether it is >= 0. + + * config/tc-mips.c (mips_align): Take new argument, label, and use + it instead of global insn_label. + (s_align, s_cons, s_float_cons, s_gpword): Save insn_label before + call to mips_emit_delay and pass it to mips_align. + +Wed Mar 16 11:54:12 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_equ): Handle both .reg and .equ correctly. + + * config/tc-hppa.c (pa_callinfo): Accept "millicode" as an + argument to a .callinfo directive. Don't loop forever on errors. + + * config/tc-hppa.c (pa_equ): Use pa_parse_number so that we can + use pre-defined registers as arguments. + +Mon Mar 14 14:29:45 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * write.c (write_object_file): Check both S_IS_LOCAL and + S_IS_EXTERNAL when deciding whether to discard a symbol. + + * config-gas.com: Scan Makefile.in, not version.c, for current + version number. Delete all versions of temp files when finished + with them. Create config.h. + + * config/obj-vms.c (VMS_Initialized_Data_Size): Cache symbol + values to reduce number of lookups with S_GET_VALUE. Skip debug + symbols to avoid "a really nasty bug". (From Holger Teutsch, + holger@botbso.rhein-main.de.) + (VMS_write_object_file): For "__vt.*" symbols, set S_GET_OTHER + field. (Also from Holger Teutsch.) Watch for a would-be register + mask that spans frags. + + * config/obj-coffbfd.c (obj_coff_line): Set symbol lnno field with + this_base, not line_base. (Patch from Andreas Arens, + ari@obelix.av.rwth-aachen.de.) + + * config/obj-aout.c (obj_crawl_symbol_chain): Retain symbols that + look local if they're exported or undefined. Used to be done for + i960 only. + + * read.c (s_lcomm, s_comm): Print symbol name being redefined. + Get it from the looked-up symbol, instead of using the string from + the input stream, which is no longer null-terminated. + (LEX_PCT): New macro, defaults to 0. + (lex_type): Use it for `%'. + + * config/tc-vax.c (md_parse_option): Handle `-h#' option for VMS. + (vip_op): Now static, and returns void. Callers changed. Added + forward decl. + (vip): Ditto. Call as_fatal directly if a program bug is + detected. + (op_hash): Let default initialization suffice. + + * Makefile.in (literal.o): Provide dependencies. + + * configure.in: Set new makefile variable OPCODES_LIB. + * Makefile.in (LIBS): Use it. + + * Makefile.in (make-gas.com, stamp-mk.com): New targets. + * vmsconf.sh: New file. + * make-gas.com: Regenerated from new script. + + * configure.in (sparc*-*-lynxos*): Handle any version number + suffix after "lynxos". Set emulation to lynx. + +Mon Mar 14 11:30:49 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * config/obj-coff.c (obj_coff_section): Delete declaration. + +Fri Mar 11 22:25:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-ppc.c (md_pcrel_from): Return 0 for undefined ELF + symbols. + (ppc_is_toc_sym): Change .toc to .got. + (md_apply_fix): Change handling of ELF relocs. + (tc_gen_reloc): Likewise. + +Fri Mar 11 17:42:20 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/obj-vms.c (Close_VMS_Object_File): Add comment pointing + out some code that doesn't belong in this file. + + * config/obj-vms.h: Include aout/stab_gnu.h. + (N_GSYM, ..., N_LENG): Deleted. + (NO_RELOC): Undefine before defining as part of enum reloc_type. + + * config/tc-alpha.c: Add comment questioning need for all the + characters in FLT_CHARS. + + * as.c (main) [OBJ_VMS]: Don't call output_file_close. + + * config/obj-ecoff.c (ecoff_frob_file): Set strict order for + sections with recognized names, before computing VMA values. + +Fri Mar 11 17:56:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_ip): Accept numbers between 0x8000 and + 0xffff for 'j' to be compatible with MIPS assembler. These + numbers are actually treated as negative. + +Thu Mar 10 13:36:29 1994 Doug Evans (dje@canuck.cygnus.com) + + * config/tc-sparc.h (LOCAL_LABEL): Local labels are .Lfoo. + +Tue Mar 8 21:17:12 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/obj-coff.c: Minor formatting/stylistic changes, plus: + (obj_coff_section): Declare. + (obj_pseudo_table): Make it available only if MANY_SECTIONS. + (obj_symbol_to_chars) [CROSS_COMPILE]: Some attemps to make this + work. It still doesn't. It now fails to compile, instead of + silently compiling to do nothing. + * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define only if + MANY_SECTIONS. + (OBJ_PROCESS_STAB) [! MANY_SECTIONS]: New macro, just emits + warning. + + Handle Alpha load-immediate-FP pseudo-instructions: + * config/alpha-opcode.h (ldif, ldig, ldis, ldit): New patterns. + * config/tc-alpha.c (lit8_sec, lit4_sec, lit8_sym, lit4_sym): New + variables. + (create_literal_section): New function. + (create_lita_section): Now a macro. + (get_lit8_offset, get_lit4_offset): New functions. + (maybe_set_gp): New function. + (select_gp_value): Call it. + (load_expression): Preserve addend if symbol is a section symbol. + (alpha_ip): Handle new operand type `F' for floating-point + constants; store them in .lit{4,8} sections. + (alpha_ip, case 'G'): Emit LITUSE relocations for symbol exprs. + + * config/tc-i386.c (smallest_imm_type): Never return Imm1. + +Tue Mar 8 14:18:15 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * config/obj-coffbfd.c (w_strings): Only copy strings out if + their symbols are going to be written. + +Tue Mar 8 11:49:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * messages.c (as_perror): Declare arguments const. + * as.h (as_perror): Change declaration. + +Mon Mar 7 16:08:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (load_address): When calling frag_grow, allow + for the (up to) two nops which may be inserted by append_insn if + mips_optimize is 0. + (macro): Likewise. + +Thu Mar 3 11:37:55 1994 Doug Evans (dje@canuck.cygnus.com) + + * config/atof-ieee.c (make_invalid_floating_point_number): + Add cast to avoid warning from gcc. + +Wed Mar 2 10:31:01 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c: Add a few casts to make HP C compiler happy. + + * config/obj-som.c (obj_som_version, obj_som_copyright): Be + prepared + to handle an error from bfd_som_attach_aux_hdr. + + * config/tc-hppa.h: Wrap ELF specific decls inside an ifdef. + +Mon Feb 28 15:03:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/tc-alpha.c (md_atof): Omit warning about FP values. + (line_comment_chars): Add ! to list. + (md_apply_fix): Do process 32- and 64-bit relocations. + + * config/obj-coffbfd.c (obj_coff_lcomm): Put "#if 0" around the + unused parts (most of the function). + (obj_coff_init_stab_section): Cast alloca result. + + * configure.in (i960-*-coff, i960-*-vxworks5.*): Use coffbfd, and + gas_target ic960coff. + * config/ic960coff.mt: New file. + * config/obj-coffbfd.h [TC_I960]: Include coff/i960.h. + (TARGET_FORMAT) [TC_I960]: Use coff-Intel-little. + * config/te-ic960.h (CROSS_COMPILE): Don't undef this. We'll + always build little-endian object files. + * config/tc-i960.c (md_reloc_size): Don't define at all if BFD or + BFD_ASSEMBLER is defined. + (mem_fmt): Since COFF doesn't handle callx relocations yet, treat + them like normal 32-bit relocations. + (md_apply_fix): For callx relocations, store zero. + (tc_bout_fix_to_chars): Store symbol index for all callx + relocations, regardless of link-relax setting. + (tc_coff_fix2rtype, tc_coff_sizemachdep): New functions. + (i960_handle_align) [! OBJ_BOUT]: If link-relax option is + selected, print an error message and clear it. + * config/tc-i960.h (BFD_ARCH, COFF_FLAGS, COFF_MAGIC, + TC_COUNT_RELOC, TC_COFF_FIX2RTYPE, TC_COFF_SIZEMACHDEP, + tc_fix_adjustable): New macros. + (tc_coff_fix2rtype, tc_coff_sizemachdep): Declare. + +Fri Feb 25 20:56:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (hppa_tc_symbol): Call PA ELF BFD version. + (hppa_tc_make_sections): Likewise. + (pa_build_symextn_section): Delete unused function. + (hppa_tc_make_symextn_section): Likewise. + (pa_export): Delete call to pa_build_symextn_section. + + * config/tc-hppa.h (hppa_tc_symbol): Add extern decl. + (elf_hppa_final_processing): Delete extern decl. + (hppa_tc_symbol): Delete extern decl. + +Fri Feb 25 13:15:31 1994 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-coffbfd.c (fill_section): Correct test for whether to + fill a section (from Minh Tran-Le ). + +Thu Feb 24 11:30:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * configure.in: Don't require version number for i386-*-mach. + + * read.c (potable): Added ".this_GCC_requires_the_GNU_assembler", + which is ignored by gas, but will cause other assemblers to choke. + Intended for use by gcc ports that require gas instead of native + assemblers. + +Thu Feb 24 07:10:31 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/ho-hppaosf.h: Fix braino in test for ANSI-C. + +Wed Feb 23 16:51:43 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * write.c (write_contents): Give the user a reasonable error + message rather than "assertion failed" if bfd_set_section_contents + fails. + +Tue Feb 22 10:07:32 1994 Ken Raeburn (raeburn@rtl.cygnus.com) + + * config/ho-mach3.h: New file. + +Mon Feb 21 11:41:18 1994 Ian Lance Taylor (ian@cygnus.com) + + * ecoff.c (ecoff_build_debug): Don't set hdr->magic here. It is + now set in bfd/ecofflink.c:ecoff_write_symhdr. + + * config/obj-coffbfd.c (write_object_file): use bfd_get_error (), + not bfd_error. + * config/obj-elf.c (elf_frob_file): Likewise. + + * read.c (s_lcomm): Use an alignment power of 3 for 8 byte .lcomm + variables. + + * config/ho-hpux.h (BROKEN_ASSERT): Define if not __GNUC__. + + * read.c (read_a_source_file): Use correct arguments to memcpy + (broken 19 Jul 1993). From kjd@pescadero.stanford.edu (Kenneth + Duda). + +Sun Feb 20 18:01:54 1994 Ian Lance Taylor (ian@lisa.cygnus.com) + + * config/obj-coff.h (obj_coff_section): Declare. + * config/obj-coff.c (obj_pseudo_table): For "section", use + obj_coff_section. + (obj_coff_section): Rewrite. + +Fri Feb 18 14:16:32 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * configure.in (i386-*-mach3*): New target; uses BFD. + * config/te-mach.h: New file. + * config/obj-aout.c (obj_aout_frob_file): New function. + * config/obj-aout.h (obj_aout_frob_file): Declare it. + (frob_file): New macro. + * config/tc-i386.c (md_apply_fix_1) [TE_Mach]: Don't adjust + pcrel32 relocations. + * config/tc-i386.h (TARGET_FORMAT) [TE_Mach]: Use a.out-mach3. + + * write.c (write_object_file): Removed register declarations. + +Thu Feb 17 16:25:18 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Some support for PowerPC ELF. + * configure.in: If cpu is powerpc*, use ppc. + (ppc-*-sysv4*): Use object format elf. + * config/tc-ppc.h: Only declare a number of things if OBJ_COFF is + defined. + (TARGET_ARCH): Make it call ppc_arch. + (ppc_arch): Declare. + (TARGET_FORMAT): Set based on OBJ_COFF or OBJ_ELF. + (NO_STRING_ESCAPES): Define. + (LOCAL_LABEL, FAKE_LABEL_NAME): Define for OBJ_ELF. + * config/tc-ppc.c: Only define a number of functions of OBJ_COFF + is defined. + (md_pseudo_table): Most pseudo-ops are OBJ_COFF specific. Added + OBJ_COFF specific "bi" and "ei". + (md_parse_option): Fix handling of -u. Make -m601 set + PPC_OPCODE_601. If OBJ_ELF, accept -V and -Q. + (ppc_set_cpu): New function. + (ppc_arch): New function. + (md_begin): Call ppc_set_cpu. + (ppc_insert_operand): For a signed operand accept an unsigned + value, for IBM compatibility. + (ppc_byte): Don't call stringer for strings; instead, treat two + double quotes as a single double quote. + (ppc_comm): Set sy_tc.output for a .lcomm symbol. + (ppc_biei): New function. + (ppc_tc): If not OBJ_COFF, ignore first argument. + (ppc_fix_adjustable): Call as_bad_where, not as_bad. + (ppc_is_toc_sym): New function. + (md_apply_fix): Use ppc_is_toc_sym. Handle BFD_RELOC_16 and + BFD_RELOC_8. + +Thu Feb 17 09:29:37 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * messages.c (as_perror) [BFD_ASSEMBLER]: Use bfd_get_error and + bfd_set_error and new error names. + +Tue Feb 15 20:23:20 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * configure.in: Support i960-vxworks versions > 5.0 as coff. + Default is still bout if no version is specified. + + * atof-generic.c (atof_generic): Use switch and strcasecmp instead + of large number of compares when looking for inf/nan values. + +Fri Feb 11 13:13:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (macro): Do unaligned loads and stores + correctly when big endian, and give errors on overflow rather than + generating incorrect code. + +Thu Feb 10 11:24:20 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * as.c: Include libiberty.h. + + * read.c (do_align): Don't define label just_record_alignment + unless it might be used. + + * as.c (main): If md_parse_long_option is defined, call it with a + long option. + * config/tc-mips.h (md_parse_long_option): Define. + * config/tc-mips.c (mips_trap): New static variable. + (md_begin): Report an error if mips_trap is set at ISA level 1. + (macro): If mips_trap, use trap instructions instead of break + instructions for overflow and divide by zero detection. + (mips_parse_long_option): New function. Support --trap, + --no-break, --break and --no-trap. + * doc/as.texinfo: Document new options. + + * read.c (potable): Add "zero". + * config/tc-i386.c (md_pseudo_table): Remove "zero". + * config/tc-m88k.c (md_pseudo_table): Likewise. + +Thu Feb 10 01:24:27 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Reject integer values for + pc-relative operand fields. This forces "call 0" to become "jmpl + %g0,%o7" with no relocations needed. + +Wed Feb 9 13:08:32 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * as.h (xmalloc, xrealloc): Declare using PTR rather than char *. + * xmalloc.c (xmalloc, xrealloc): Use PTR rather than char *. + + * app.c (do_scrub_next_char): If NO_STRING_ESCAPES is defined, + don't treat backslash specially inside strings. + * read.c (next_char_of_string): Likewise. + +Wed Feb 9 09:42:45 1994 Stan Shebs (shebs@andros.cygnus.com) + + * config/obj-coffbfd.c (obj_coff_init_stab_section): Use memset + instead of memcpy to zero the initial stab symbol, duh. + * config/obj-elf.c (obj_elf_init_stab_section): Ditto. + * config/obj-som.c (obj_som_init_stab_section): Ditto. + +Tue Feb 8 17:25:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * write.c (fixup_segment): Use as_bad_where, not as_bad. + + * subsegs.c (subseg_set_rest): Call memset with the arguments in + the right order. Explicitly clear fix_root and fix_tail fields. + +Tue Feb 8 16:00:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/obj-coff.c (coff_frob_symbol): For abs_symbol, set *punt + and do nothing else. + + * symbols.c (symbol_begin): Initialize value of abs_symbol + properly. + + * write.c (adjust_reloc_syms): Use abs_symbol instead of calling + section_symbol. + + * ecoff.c (ecoff_build_debug): Fix "/*" in comment to silence + complaint from "gcc -Wall". + + * configure.in (alpha-*-netware*): New target, like alpha-*-osf*. + + * config/tc-alpha.c (GP_ADJUSTMENT): Move definition to start of + file. + (tc_gen_reloc): Remove uninitialized variable `code', and code + that tried to use it (incorrectly). For LITERAL reloc, set addend + to negative of GP value. + (load_symbol_address): Don't adjust return value by GP_ADJUSTMENT. + + * write.c (write_relocs): Print some sensible error message if + bfd_perform_relocation returns bfd_reloc_overflow. + +Mon Feb 7 15:49:24 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * configure.in (hppa*-*elf*): New configuration for PA ELF. + (hppa*-*-osf*): Default object format is SOM. + +Mon Feb 7 16:07:35 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/tc-alpha.c (md_atof): Warn that floating-point values + might not assemble properly. + + * configure.in (target alpha-*-osf*): Don't set "dev=yes" any + more. + + * config/tc-alpha.c (load_expression): Parenthesize operations in + range checking, to avoid precedence questions. + + * config/tc-alpha.c (addr32): New static variable. + (md_parse_option): Set it for "-32addr". + (load_symbol_address): If addr32 is set, use ldl instead of ldq. + + * atof-generic.c (atof_generic): Calculate maximum_useful_digits + and more_than_enough_bits_for_digits in integer arithmetic, to + eliminate the only sources of dependence on floating point + support, which doesn't work yet on the Alpha. + +Mon Feb 7 03:56:05 1994 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * ecoff.c (ecoff_build_debug) [TC_ALPHA]: Specify version stamp as + 0x30b for Alpha for now, until ".verstamp" is handled. + + * literal.c (add_to_literal_pool): Use seginfo->frchainP, which + actually refers to the literal pool section, rather than + frchain_now, which refers to whatever section the assembler was + in. + + * write.c (fixup_segment): Only do range checking if size of fixup + is smaller than word size. Otherwise, we always wind up with + zeros. + + * config/tc-alpha.c (md_section_align): Change second argument and + return type to valueT, to agree with tc.h. + (alpha_do_align): Local static array nop_pattern is now unsigned + char, to avoid overflow warnings. + * config/tc-alpha.h (md_section_align): Delete declaration. + + * config/obj-ecoff.c (ecoff_frob_file): Ensure that ecoff_data for + output bfd is non-null before indirecting through it. + + * config/tc-alpha.c (alpha_frob_ecoff_data): Renamed from + alpha_frob_file. + * config/tc-alpha.h (tc_frob_file): Macro deleted. + * config/obj-ecoff.c (ecoff_frob_file) [TC_ALPHA]: Call + alpha_frob_ecoff_data, then fill in optional-header info with gp + value and register masks. + +Sun Feb 6 16:13:47 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * configure.in (hiux): Fixes from m-kasahr@sramhc.sra.co.JP. + + * config/obj-som.c (obj_som_init_stab_section): Same change + as coffbfd and elf below. Zero the initial stab symbol after + allocating it. + +Sat Feb 5 12:30:32 1994 Stan Shebs (shebs@andros.cygnus.com) + + * config/obj-coffbfd.c (obj_coff_init_stab_section): Zero the + initial stab symbol after allocating it. + * config/obj-elf.c (obj_elf_init_stab_section): Ditto. + +Sat Feb 5 11:53:31 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_ip): addb[tf] should only accept + non-negated condition completers. Add support for addb pseudo-op + which accepts both negated and non-negated completers. + +Sat Feb 5 00:15:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * configure.in (rs6000*): Use cpu_type ppc. + (ppc-*-aix*): New target; use coff and force bfd_gas. + * config/tc-ppc.h, config/tc-ppc.c: New files for PowerPC/POWER + (RS/6000) support. At the moment, only XCOFF is supported. + + * config/obj-coff.c (SA_SET_SYM_ENDNDX): Made non-static. + (S_SET_DATA_TYPE): Likewise. + (coff_last_function): Renamed from local static last_functionP in + coff_frob_symbol and made externally visible. + (coff_frob_symbol): New local static set_end; use it to try to + avoid calling SA_SET_SYM_ENDNDX on a symbol that will be punted. + * config/obj-coff.h (S_SET_DATA_TYPE): Declare. + (SA_SET_SYM_ENDNDX): Declare. + (coff_last_function): Declare. + + * expr.c (operand): If DOLLAR_DOT is defined, accept `$' as + equivalent to `.' to mean the current location. + + * read.c (LEX_BR): If not defined, define as 0. + (lex_type): Use LEX_BR as the type of `{',`}',`[',`]'. + + * symbols.c (symbol_new): If tc_canonicalize_symbol_name is + defined, call it with preserved_copy_of_name. If + tc_symbol_new_hook is defined, call it on the new symbol. + (symbol_find_base): If tc_canonicalize_symbol_name is defined, + call it on a copy of the name argument. + + * write.c (write_object_file): Simplified usage of obj_frob_symbol + and tc_frob_symbol. Always call both if the symbol is going to be + output. + + * write.c (relax_segment): Use %ld rather than %d when printing + fragP->fr_var, and cast it to long. + + Changed relocs to be based on subsegments (when BFD_ASSEMBLER). + * subsegs.h (struct frchain): If BFD_ASSEMBLER, added new fields + fix_root and fix_tail. + (segment_info_type): If BFD_ASSEMBLER, don't define fix_tail + field. + * write.c (fix_new_internal): If BFD_ASSEMBLER, set fix_rootP and + fix_tailP based on frchain_now, not seg_info (now_seg). + (chain_frchains_together_1): Chain the subsegment relocs together. + * subsegs.c (subseg_change): Don't clear fix_tail field. + (subseg_get): Likewise. + * literal.c (add_to_literal_pool): Look through the relocs via + frchain_now, not seginfo. + +Thu Feb 3 23:07:30 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-ecoff.h (TARGET_SYMBOL_FIELDS): Changed + ecoff_undefined to ecoff_extern_size. + * config/obj-elf.h (ELF_TARGET_SYMBOL_FIELDS): Likewise. + * config/tc-mips.c (s_extern): Set ecoff_extern_size to the + external symbol size, rathern than setting the symbol value. + (md_estimate_size_before_relax): Check both ecoff_extern_size and + symbol value to see if GP referencing can be used. + * ecoff.c (ecoff_symbol_new_hook): Clear ecoff_extern_size, not + ecoff_undefined. + (ecoff_frob_symbol): Don't check ecoff_undefined. + (ecoff_build_symbols): Get size of an undefined symbol from + sym->ecoff_extern_size, not S_GET_VALUE (sym). + +Wed Feb 2 13:55:08 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Makefile.in: Avoid bug in losing hpux sed. + +Wed Feb 2 11:40:11 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (file_mips_isa): New static variable. + (md_begin): Set it. + (s_mipsset): Add support for .set mipN to set the ISA level. + + * gasp.c (kinfo): Fully bracket initializer. + +Tue Feb 1 19:28:12 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * gasp.c (malloc): Don't declare, since host.h or system header + files may declare it differently. + + * config/atof-ieee.c (int_to_gen): Now static. + + * config/ho-i386aix.h: Include sys/types.h and stdlib.h, not + ho-sysv.h. Based loosely on a patch from Minh Tran-Le. + +Tue Feb 1 10:50:17 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * gasp.c: Include host.h. + +Tue Feb 1 12:13:01 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_ip): Make an unsupported instruction a + warning, not an error. + + * config/obj-coff.c (dot_text_symbol, dot_data_symbol, + dot_bss_symbol): Don't define if BFD_ASSEMBLER. + (obj_symbol_to_chars): bfd_coff_swap_aux_out now takes more + arguments. + (coff_line_base): Renamed from line_base. Changed all uses. + (coff_add_linesym): Renamed from add_line_sym. Made non-static. + Changed all uses. + * config/obj-coff.h: If TC_PPC, include coff/rs6000.h. + (S_SET_STORAGE_CLASS, S_GET_STORAGE_CLASS): Declare if + BFD_ASSEMBLER. + (coff_line_base): Declare. + (coff_add_linesym): Declare if BFD_ASSEMBLER. + * config/obj-coffbfd.c (symbol_to_chars): bfd_coff_swap_aux_out + now takes more arguments. + +Mon Jan 31 17:55:14 1994 Stan Shebs (shebs@andros.cygnus.com) + + * as.c (statistics_flag): Renamed from quiet_flag. + (main): Get statistics with --statistics instead of -noquiet. + +Mon Jan 31 07:19:30 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * Makefile.in: Support for Gnu ASsembler Preprocessor. + * gasp.c: New file. + * read.c (s_lcomm): Align lcomm data. + * config/tc-z8k.c (tc_reloc_mangle): Don't allow subtraction + from different sections. + +Sun Jan 30 14:58:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * write.c (write_object_file): If tc_frob_file is defined, call it + just before calling obj_frob_file. + * config/tc-alpha.c (alpha_gp_value): Renamed from gp_value + (references changed), and made non-static. + (getExpression): Return void. + (select_gp_value): Abort if gp_value is non-zero. Delete call to + non-existent bfd_set_gp_value. + (alpha_validate_fix): Function deleted. + (alpha_frob_symbol): Function deleted. + (alpha_local_label): Function deleted. + (alpha_frob_file): Renamed from alpha_end. + * config/tc-alpha.h (alpha_frob_symbol, alpha_validate_fix, + alpha_local_label, alpha_end): Declarations deleted. + (alpha_gp_value, alpha_frob_file): Declare. + (tc_frob_symbol, TC_VALIDATE_FIX, md_end): Macros deleted. + (LOCAL_LABEL): Move code here from tc-alpha.c:alpha_local_label. + (md_convert_frag): Simplified slightly. + (tc_frob_file): New macro. + + * read.c (do_align): New function, most of guts of s_align_* + functions. Look for md_do_align macro, give it a chance to bypass + all but recording of section alignment. + (s_align_bytes, s_align_ptwo): Call do_align. + (s_lcomm) [TC_ALPHA]: Align object to largest power of two that + divides object size. + + * frags.c (frag_align_pattern): New function. + (frag_align): Rewrite for clarity. + + * config/tc-vax.c (md_assemble): Handle O_constant expression. + (vip_begin): Returns pointer to const char. Cast hash_insert arg + to PTR to avoid compiler complaints about const. + (md_begin): Local variable errtxt must point to const. + + * configure.in: Handle host vax-*-ultrix* like vax-*-bsd*. Don't + bother with *-*-ultrix or *-*-sysv*, except *-*-sysv, since only + the last has an existing host support file. Do handle vax-bsd and + vax-ultrix targets. + +Fri Jan 28 11:26:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-coff.c (obj_coff_section_header_append): Do not + declare if BFD_ASSEMBLER. + (stack_pop): Correct test for stack underflow. + (obj_coff_endef, obj_coff_dim, obj_coff_line, obj_coff_size, + obj_coff_scl, obj_coff_tag, obj_coff_type, obj_coff_val): Declare + type of ignored argument to avoid gcc warning. + (align): Removed unused function. + +Thu Jan 27 18:14:19 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/tc-alpha.c, config/tc-alpha.h, config/alpha-opcode.h: New + files, based on port of gas-1.38 contributed by CMU, using a.out + variant. Updated for gas-2.x and ECOFF. Floating-point constants + are still broken, bootstrap testing incomplete. + + * literal.c: Comment changes. + + * listing.c (listing_source_file): Check for null listing_tail + before indirecting through it. + + * expr.h (struct expressionS): Added struct tag. + + * as.h: If __GNUC__ and inline are both undefined, define inline + away. + + * write.c (cvt_frag_to_fill): Don't assume that fr_var for + rs_align or rs_org frags will be 1. + (relax_segment): For rs_align, if fr_var is not 1, complain if + required padding is not a multiple of the size of the pad pattern. + (fixup_segment): Leave gp-relative relocations alone. For pcrel + relocations referring to the same segment, clear fx_pcrel when + clearing fx_addsy. + * as.h: Adjust comments on rs_align. + + * atof-generic.c: Some reformatting. + (atof_generic): Be careful when mixing signed/unsigned values of + different sizes. + + * write.c, config/obj-{aout,bout,coff*}.c, config/tc-sparc.c: + Query the fx_done field instead of fx_addsy to see if the fixup + still needs to be applied. Set fx_done and clear fx_addsy both, + for now. If TC_HANDLES_FX_DONE isn't defined, assume md_apply_fix + will only clear fx_addsy, and set fx_done accordingly after + returning. + * config/tc-sparc.h (TC_HANDLES_FX_DONE): Define. + * config/tc-sparc.c (md_apply_fix): Set fx_done for non-pcrel fix + with no fx_addsy. + + * symbols.c (dot_text_symbol, dot_data_symbol, dot_bss_symbol): + Deleted. + (symbol_begin): Moved to end of file, so function inlining can + work better. + (fb_label_count, fb_label_max): Default C static initializers are + sufficient. + * symbols.h (dot_text_symbol, dot_data_symbol, dot_bss_symbol): + Declarations deleted. + * config/obj-coff.c (dot_text_symbol, dot_data_symbol, + dot_bss_symbol): Defined here, static. + + * config/obj-aout.c [BFD_ASSEMBLER]: Undef NO_RELOC before + including aout/aout64.h. + + * write.c (write_object_file): If EMIT_SECTION_SYMBOLS is false, + don't write out a section symbol even if it's used in a + relocation; assume relocations will handle section numbers + somehow. Rename "punt_it" label to "punt_it_if_unused" to reflect + it's true use. + (EMIT_SECTION_SYMBOLS): Default to 1. + (adjust_reloc_syms): Don't create a new symbol for an absolute + reference; just use the absolute section symbol. + (write_relocs): Make printout of reloc values dependent on flag + DEBUG3, not DEBUG2. + * config/obj-aout.h (EMIT_SECTION_SYMBOLS): Define as 0. + * config/obj-ecoff.h (EMIT_SECTION_SYMBOLS): Ditto. + +Thu Jan 27 16:43:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * read.c (lex_type): No longer make '{' a valid character for + symbol names. + + * as.c (main): Print long values using %ld. + + * messages.c (as_warn_internal): New static function. + (as_warn, 3 versions): Use as_warn_internal. + (as_warn_where, 3 versions): New function. + * as.h (as_warn_where): Declare. + +Tue Jan 25 18:30:34 1994 Stan Shebs (shebs@andros.cygnus.com) + + * as.c (quiet_flag): New flag. + (main): If -noquiet given, display execution time and memory used. + +Tue Jan 25 15:53:11 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * doc/{all.texi,as.texinfo}: Add documentation for HPPA port. + +Mon Jan 24 19:18:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_frob_symbol): New function. Put undefined + symbols of known size in the undefined section. Put small common + symbols in a .scommon section. + * ecoff.h (ecoff_frob_symbol): Declare. + * config/obj-ecoff.h (obj_frob_symbol): Define. + * config/obj-elf.c (obj_elf_write_symbol_p, obj_elf_write_symbol, + obj_elf_frob_symbol): Removed unused functions. + * config/obj-elf.h (obj_frob_symbol, obj_write_symbol): Removed + unused macros. + (obj_elf_frob_symbol, obj_elf_write_symbol): Removed declarations + of unused functions. + (obj_frob_symbol): Define if ECOFF_DEBUGGING. + + * tc-mips.c (g_switch_seen): New static variable. + (md_parse_option): Set g_switch_seen for -G option. + (s_option): If creating PIC code, force the GP size to be 0. Warn + if -G switch used with a non-zero value. + + * symbols.c (S_IS_COMMON): Use bfd_is_com_section rather than + comparing against bfd_com_section. + +Mon Jan 24 14:12:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * read.c (s_lcomm): Treat Alpha like MIPS in handling of .sbss + section. + +Thu Jan 20 13:17:58 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * expr.c (operand): For floating point operand with unusual fp + char from FLT_CHARS, preserve the character. Patch from Lisa + Repka. + +Wed Jan 19 23:15:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (md_pseudo_table): Add all data allocation + pseudo-ops: .hword, .int, .long, .octa, .quad, .short, .single. + +Tue Jan 18 15:51:59 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * config/obj-coffbfd.c (obj_coff_endef): For C_EFCN, C_BLOCK and + C_FCN assume .val has been set to . + +Tue Jan 18 16:19:58 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c: Disable multiple $CODE$ subspace code. It + confuses GDB for some unknown reason. + * cofnig/obj-som.c: Likewise. + +Tue Jan 18 19:05:32 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * literal.c (add_to_literal_pool): Handle duplicates of values + already written to literal pool. + +Tue Jan 18 17:23:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-aout.c (obj_aout_frob_symbol): Try to get symbols + with explicitly marked stabs through BFD: if a symbol marked + N_UNDF | N_EXT is in the absolute section, move it to the + undefined section; move a symbol marked N_INDR into + bfd_ind_section and set the BSF_INDIRECT flag; set the + BSF_WARNING flag for a symbol makred N_WARNING. + +Mon Jan 17 15:40:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.h (ecoff_set_gp_prolog_size): Declare. + * ecoff.c (ecoff_set_gp_prolog_size): Return type is void. + +Mon Jan 17 00:18:55 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_ip): Explicitly check for comma before 'u' + and 'f' template operand. + + * config/tc-hppa.c (pa_ip): Handle 'N', 'O', 'o', '0', '1', 'u', + and '2' in copr and sfu instruction templates. + +Sun Jan 16 16:44:23 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * as.h (subseg_force_new): Add prototype. + +Sat Jan 15 09:20:55 1994 Doug Evans (dje@canuck.cygnus.com) + + * app.c (do_scrub_next_char): Allow lines like " foolab :". + + * read.c (emit_expr): Fix computation of mask. + * config/obj-elf.c (obj_elf_section): Fix loop termination test. + +Thu Jan 13 16:15:15 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * ecoff.c (ecoff_set_gp_prolog_size): New function. + (current_file_idx): New static variable. + (add_file): Use and increment current_file_idx instead of indx + parameter. + + * struc-symbol.h (struct symbol): Make all bitfields unsigned. + + * config/tc-i960.c (i960_validate_fix): Added argument + add_symbolPP. Indirect through it to get "add_symbolP". + * config/tc-i960.h (i960_validate_fix): Supply prototype. + (TC_VALIDATE_FIX): Pass address of add_symbolP. + + * configure.in (i386-*-netbsd*): New target, using te-netbsd.h. + (i386-*-netbsd0.8): New target, like 386bsd. + + * configure.in: Set BFDDEF in Makefile to "define" or "undef". + * Makefile.in (config.h): Protect against multiple inclusions. + Define or undef BFD_ASSEMBLER as specified by $(BFDDEF). + (ALL_CFLAGS): Omit $(BFDDEF). + * as.h: Include config.h. + (struct symbol): Added forward declaration. + (add_to_literal_pool): Fix declaration. + * as.c: Don't include config.h. + + * literal.c (add_to_literal_pool): Take symbol and addend as + arguments, instead of expression, for now. Fix calculation of + offset to return. + + * subsegs.h (segment_info_type) [NEED_LITERAL_POOL]: Add field + literal_pool_size. + +Thu Jan 13 12:14:21 1994 Jeffrey A. Law (law@snake.cs.utah.edu + + * subsegs.c (subseg_get): Accept new argument "force_new". If + set then a new segment is always created. All callers changed. + (subseg_force_new): New function. Similar to subseg_new, but + always force a new segment to be created. + + * config/obj-som.c (som_frob_file): Call adjust_code_sections + for each section. + (adjust_code_sections): New function. Adjusts the VMA for all the + $CODE$ subspaces. + + * config/tc-hppa.c (md_assemble): Also handle creating a fixup + for the unwind descriptors if a function's label follows the + .PROC and .ENTRY directives. + (pa_entry): Don't set BSF_FUNCTION for the label symbol here; it + is done elsewhere. Don't create a fixup for the unwind + descriptors if the function's label has not been defined yet. + (pa_proc): For SOM, place each procedure within a new $CODE$ + subspace. Adjust the segment and frag for the associated + function label if it exists. + +Wed Jan 12 22:05:33 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (hppa_fix_struct): Add new "segment" field. + (hppa_fix_new): Initialize segment field. + (md_apply_fix): Do nothing for pc-relative fixup which involves + crossing a segment boundary. + (pa_procend): Undefine the current label after handling .PROC + and .PROCEND directives. + (dummy_symbol): Make type "symbolS *". Change references as + appropriate. + +Wed Jan 12 13:29:31 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * read.c (read_a_source_file): Cast array argument to unsigned + char. + * write.c (adjust_reloc_syms): Remove unused variable symseginfo. + (write_object_file): Don't define punt_it if it won't be used. + (fixup_segment): Don't define skip if it won't be used. + + * config/tc-mips.h (TARGET_FORMAT): Define as mips_target_format. + (mips_target_format): Declare. + * config/tc-mips.c (mips_target_format): Define with appropriate + default definition. + (md_parse_option): If -EL or -EB is used, change byte_order and + mips_target_format as appropriate. + +Tue Jan 11 21:52:36 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * app.c (do_scrub_next_char): Another attempt to fix bugs + dealing with labels without colons (for HPPA and MRI). + +Tue Jan 11 17:01:06 1994 Doug Evans (dje@canuck.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Truncate args to %hi/%lo to 32 bits. + + * expr.c (integer_constant): Fix computation of too_many_digits. + Variable digit_2 renamed to start. Fix check for whether number + will fit in 32 bits. + * read.c (emit_expr): Use valueT instead of long. + +Tue Jan 11 13:01:20 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-elf.c: If TC_MIPS, include elf/mips.h. + (special_sections): Define. + (obj_elf_special_section): Get default types and attributes from + list of special sections. + * config/tc-mips.c (ELF_TC_SPECIAL_SECTIONS): Define. + + * config/obj-ecoff.c (ecoff_frob_file): Force .sdata and .sbss + sections to be close together. + + * config/tc-mips.c (macro): Corrected $at warnings in a couple of + spots. + + * listing.c (listing_prev_line): New function. + * listing.c: Include subsegs.h. + (listing_prev_line): New function. + (calc_hex): Reset byte_in_frag to zero for each new frag. + * config/tc-mips.c (append_insn): Call listing_prev_line after + emitting nop instructions. + * Makefile.in (listing.o): Depends upon subsegs.h. + +Mon Jan 10 09:52:23 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_ip): Put check for missing label on .PROC + here. Handle case where label may be defined after the .PROC. + (pa_proc): It is not an error if the procedure's label isn't + defined before the .PROC directive. + +Sun Jan 9 04:43:30 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * config/te-netbsd.h: New file. + * config/tc-i386.h (TARGET_FORMAT) [TE_NetBSD]: Use bfd target + a.out-netbsd-386 for this configuration. + +Fri Jan 7 17:38:28 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_stab): Don't clobber the ECOFF symbol information + with the associated stabs information. + (ecoff_build_symbols): Never set the type of stabs symbols to + st_Global. Don't update the symbol index or ifd if the gas symbol + is not the same as the ECOFF symbol (which is now the case for + stabs symbols). + +Fri Jan 7 11:14:07 1994 Stan Shebs (shebs@andros.cygnus.com) + + * config/tc-mips.c (macro): Add a LOSING_COMPILER ifdef that + splits the function. + (macro2): New function, if LOSING_COMPILER defined. + +Fri Jan 7 09:38:25 1994 Steve Chamberlain (sac@cygnus.com) + + * config/obj-coffbfd.c (fill_section): Don't ever fill past the + end of a section. (write_object_file): Temporary fix - setup + stdoutput. + +Thu Jan 6 18:05:21 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/tc-sparc.c (tc_gen_reloc): Fix handling of addends in + non-pcrel_offset relocations. + +Thu Jan 6 01:06:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_ip): Warn about using $1 as well as $at + without .set noat. + +Wed Jan 5 14:22:22 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * literal.c: New file. + * Makefile.in (REAL_SOURCES, OBJS): List it. + + * as.h (DEBUG): Don't define. + (struct expressionS, struct fix): Declare in case they're used in + prototypes. + (add_to_literal_pool) [BFD_ASSEMBLER]: Declare. + + * config/tc-mips.h (TARGET_FORMAT) [OBJ_AOUT]: Fix for new names + in bfd. + + * subsegs.c (subseg_get): New function. Creates segment if + needed, returns pointer, but doesn't change current segment. + (subseg_new): Use it. + +Tue Jan 4 15:12:43 1994 Stan Shebs (shebs@andros.cygnus.com) + + * Makefile.in (INCLUDES): Add $(srcdir)/.. to places to search. + * config/obj-ecoff.c: Include files as "bfd/" instead of "../bfd/". + * app.c, flonum.h, hex-value.c (const): Change #if to be more + portable. + +Tue Jan 4 22:11:34 1994 Rob Savoye (rob@darkstar.cygnus.com) + + * config/ho-vsta.h, configure.in, .Sanitize: Add support for VSTa + micro-kernel. + +Thu Dec 30 15:27:16 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * write.c (write_relocs): bfd_perform_relocation now takes an + additional argument, to return an error string (which we ignore). + +Wed Dec 29 14:37:26 1993 Ken Raeburn (raeburn@cujo.cygnus.com) + + * write.h (struct fix): Field tc_fix_data should be type PTR, not + void*, for compatibility with non-ANSI compilers. Added + single-bit field "fx_done". + +Sun Dec 26 14:31:47 1993 Torbjorn Granlund (tege@adder.cygnus.com) + + * tc-hppa.c (pre_defined_registers): Convert to lower case. + Delete spurious register names "%r4L", etc. + (selector_table): Sort and convert to lower case. + (cons_fix_new_hppa): `reloc_type' => `rel_type'. + (pa_ip): Always use strcmp for non-text and strcasecmp for text. + (reg_name_search): Rewrite to call strcasecmp only once per + iteration. + (pa_chk_field_selector): Rewrite to use binary search. + (pa_parse_neg_add_cmpltr): Use strcasecmp for completer comparisons. + (pa_parse_space_stmt): $TEXT$ and $PRIVATE$ are symbols; use case + sensitive comparisons. + (pa_parse_space_stmt): Canonicalize strncasecmp arg to lower case. + (pa_space): "$text$" => "$TEXT$"; "$private$" => "$PRIVATE$". Use + case sensitive comparison for all symbolic names. + (pa_subspace): Canonicalize strncasecmp arg to lower case. + (pa_subspace_start): Use case sensitive comparison for symbolic names. + +Mon Dec 20 10:37:48 1993 Ken Raeburn (raeburn@cujo.cygnus.com) + + * write.c (adjust_reloc_syms) [RELOC_REQUIRES_SYMBOL]: If no + symbol is present (i.e., relocation against absolute), create a + phony local symbol, and use it in the reloc. + (fixup_segment): When adjusting a reloc with an absolute symbol, + have TC_FORCE_RELOCATION control clearing add_symbolP too. + * config/tc-sparc.h (RELOC_REQUIRES_SYMBOL): Define, for OBJ_COFF. + + * symbols.c (S_IS_EXTERNAL, S_IS_LOCAL): Don't use both BSF_EXPORT + and BSF_GLOBAL, since they're the same. + + * as.c (main): Only invoke md_end if it's defined as a macro. + * tc.h (md_end): Don't declare it. + * config/tc-*.[ch] (md_end): Deleted, in cases where it doesn't do + anything. + * config/tc-vax.c (vip_end): Deleted null function. + * config/tc-mips.c (md_mips_end): Renamed from md_end. + * config/tc-mips.h (md_mips_end): Declare. + (md_end): New macro, calls md_mips_end. + + * write.c (write_object_file): Don't close output file. + * as.c (main): Close output file (if needed) after calling + listing_print, which should be after calling write_object_file, + which sets the frag addresses. + + * config/obj-coff.c (obj_coff_dim, obj_coff_endef, obj_coff_line, + obj_coff_scl, obj_coff_size, obj_coff_tag, obj_coff_type, + obj_coff_val): Add unused int argument to satisfy prototypes; goes + with Ian's 10 Sep changes. + (S_GET_DATA_TYPE, S_SET_DATA_TYPE, S_GET_STORAGE_CLASS, + S_SET_STORAGE_CLASS): Now function instead of macros. + (obj_emit_lineno) [BFD_ASSEMBLER]: Deleted. + (tag_insert): Local var ERROR_STRING is const. Use "const" not + "CONST" for argument NAME. Fixed prototype. + (coff_frob_symbol): Removed explicit "#if 1" directive. If + S_IS_EXTERNAL, set storage class to C_EXT. + (s_get_name): Use "const" not "CONST". + * config/obj-coff.h (S_GET_DATA_TYPE, S_SET_DATA_TYPE, + S_GET_STORAGE_CLASS, S_SET_STORAGE_CLASS): Deleted. + (obj_emit_lineno): Declare only for non-BFD_ASSEMBLER. For + BFD_ASSEMBLER, define as macro that aborts. + (obj_extra_stuff, tc_headers_hook): Declare only for + non-BFD_ASSEMBLER. + (coff_frob_symbol): Fix prototype. + +Sun Dec 19 00:37:20 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c (tc_gen_reloc): Test of pcrel_offset had sense + reversed. + +Thu Dec 16 21:13:11 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_begin): Initialize "dummy_label". + (tc_gen_reloc, SOM version): For relocations which have no symbol, + set sym_ptr_ptr to dummy_label. Avoids lossage in generic BFD code. + +Thu Dec 16 16:07:56 1993 Ken Raeburn (raeburn@cujo.cygnus.com) + + * read.c (lex_type): No longer make '[' a valid character for + symbol names. + + * config/tc-vax.c (tc_aout_fix_to_chars): Local variable + NBYTES_R_LENGTH now const. + + * config/obj-*.c, config/tc-*.c: Omit superfluous "return" + statements at ends of functions. Don't check for null return from + hash_new, since it won't return at all if there's no memory + available. Also, check for null return from hash_insert, rather + than zero-length string, as success indicator. + + * subsegs.c (section_symbol): New function. + * subsegs.h (section_symbol): Declare. + * write.c (adjust_reloc_syms): Use it. + +Wed Dec 15 15:39:53 1993 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (RUNTEST): New variable. + (CHECKFLAGS): Pass it down. + + * ecoff.c (ecoff_directive_frame): Permit extra trailing operands; + unused for now, but supplied by Alpha OSF1 compiler. + + * as.h: Protect against multiple inclusions. + (int_to_gen): Don't declare. + + * config/atof-vax.c (atof_vax): NULL is not a valid character + constant. + +Tue Dec 14 21:38:25 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * configure.in (hppa*-*-osf*): Do not consider this a developmental + configuration. + + * config/tc-hppa.c (md_apply_fix): Handle cases where no + relocation will be emitted for 32bit formats. + +Mon Dec 13 23:33:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_apply_fix): Do not call hppa_field_adjust + for any of the 'T' field selectors. + +Sat Dec 11 11:23:12 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * config/tc-h8500.c (build_bytes): Get reloc type right for a + %page operation. (md_assemble): Don't modify input_line_pointer. + (mdcoff_sizemachdep): New function. + * config/tc-h8500.h (TC_COFF_SIZEMACHDEP): New macro. + * config/tc-z8k.c (get_operand): Delete bogus check. + +Wed Dec 8 16:31:51 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * write.c (number_to_chars_*): Delete bogus range check. + + * output-file.c (TARGET_ARCH): No default. + +Tue Dec 7 16:02:53 1993 Steve Chamberlain (sac@jonny.cygnus.com) + + * config/tc-sh.c (md_convert_frag): Truncate disps before calling + md_number_to_chars. (md_assemble): Don't modify + input_line_pointer. + +Mon Dec 6 11:49:03 1993 Doug Evans (dje@canuck.cygnus.com) + + * config/tc-h8300.c (md_assemble): Don't update input_line_pointer. + +Mon Dec 6 11:20:02 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/obj-som.[ch] (obj_read_begin_hook): Remove last change. + Breaks with the HP compilers. + + * config/tc-hppa.c (struct call_info): Remove fields which were + set but never used. Remove all code which sets those fields. + (struct subspace_dictionary_chain): Likewise. + (struct space_dictionary_chain): Likewise. + (pa_desc): Delete useless function. Delete all references. + (hppa_tc_make_sections): No need to count the number of symbols for + the symbol extension section. + +Sun Dec 5 17:05:29 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/obj-som.c (obj_som_version): Pass version string to + SOM BFD backend. + (obj_som_copyright): New function. Much like obj_som_version. + + * config/tc-hppa.c (obj_copyright): Define as appropriate for + SOM and ELF. + (pa_copyright): Just a stub now. + + * config/obj-som.c (obj_read_begin_hook): Delete unused function. + * config/obj-som.h (obj_read_begin_hook): Provide dummy definition. + (TARGET_SYMBOL_FIELDS): Delete. SOM isn't making use of them. + + * config/tc-hppa.c (tc_gen_reloc, SOM version): Handle relocation + expansion due to rounding mode selectors. Handle R_[RDSN]_MODE + relocations for selecting the current rounding mode. + + * config/tc-hppa.c (evaluate_absolute): Support e_rrsel and + e_rlsel field selectors. + +Fri Dec 3 18:33:24 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-elf.h: If ECOFF_DEBUGGING, undef + SEPARATE_STAB_SECTIONS and INIT_STAB_SECTION, and define + OBJ_PROCESS_STAB to call ecoff_stab. + * config/obj-elf.c: Don't compile obj_elf_init_stab_section if + INIT_STAB_SECTION is not defined. + +Fri Dec 3 10:56:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_apply_fix): Delete old wrapper function. + (md_apply_fix_1): Rename to md_apply_fix. Fix argument decls. + Fix comments in various places. Always return a value. + Avoid dereferencing a NULL fx_addsy. + (hppa_force_relocation): Avoid dereferencing a NULL fx_addsy. + + Fri Dec 3 09:47:30 1993 Pete Hoogenboom (hoogen@cs.utah.edu) + + * tc-hppa.c: (tc_gen_reloc): Addend for a plabel relocation should + be either 0 or 2 (no static link or static link required). Always + assume no static link. + +Thu Dec 2 11:52:21 1993 Ken Raeburn (raeburn@cygnus.com) + + * config/tc-sparc.c (tc_gen_reloc): Make adjustment to addend be + dependent on howto fields, not on format flavour. + + * struc-symbol.h (struct symbol): New fields sy_obj and sy_tc, + defined as types OBJ_SYMFIELD_TYPE and TC_SYMFIELD_TYPE, if those + macros are defined. + * config/obj-coff.h (TC_SYMFIELD_TYPE, OBJ_SYMFIELD_TYPE): Define. + (TARGET_SYMBOL_FIELDS, I960_SYM_FIELDS): Don't define. + (sy_tc, sy_obj): Define so that the fields look like they used to, + until all references get changed. + + * write.c (fixup_segment): Lots of variables no longer register. + Reordered some code for easier reading. + * config/obj-coff.c (obj_coff_dim): dim_index no longer register. + Deleted superfluous return statement. + (obj_coff_line, obj_coff_size, obj_coff_scl, obj_coff_type, + obj_coff_val, tag_init, tag_insert): Deleted superfluous return + statement. + (align, obj_coff_section): Deleted debugging printfs. + * config/tc-i386.c (md_assemble): Discard some register decls. + Use assignment rather than memcpy to copy template. + (op_hash, reg_hash, prefix_hash): Default C initialization of + statics is sufficient. + * config/tc-sparc.c (print_insn): Array Reloc is now const, and + points to const. + + * config/obj-coff.h (TARGET_FORMAT): Only use coff-sparc-lynx if + TE_LYNX; use coff-sparc otherwise. + [USE_NATIVE_HEADERS]: Delete this code; it isn't used. + + * write.c (fixup_segment): Call TC_VALIDATE_FIX, if defined, + before processing a fixup. Call TC_ADJUST_RELOC_COUNT just before + returning. Remove some i960-coff-specific code. + (TC_ADJUST_RELOC_COUNT): Default to doing nothing. + * config/tc-i960.h (TC_ADJUST_RELOC_COUNT) [OBJ_COFF]: Define. + (i960_validate_fix): Declare. + (TC_VALIDATE_FIX): Define. + * config/tc-i960.c (i960_validate_fix): New function. + + * write.c (number_to_chars_littleendian): New function. Write out + bytes in little endian order, doing size and range checking. + (number_to_chars_bigendian): New function, similar. + * write.h: Declare them. + * config/tc-*.c (md_number_to_chars): Use them. + * config/tc-vax.c (md_apply_fix): Ditto. + * config/tc-i386.c (md_apply_fix): Ditto. + + * config/obj-coff.c: Rearranged code for handling line number + data. + (line_fsym): Renamed from function_lineoff in BFD_ASSEMBLER case, + since the usage is different from non-BFD_ASSEMBLER case. + (in_function, clear_function, set_function): New macros, to + combine some of the functionality implemented in differnet ways in + BFD_ASSEMBLER and non-... code. Used in other functions that used + to check function_lineoff &c. + (obj_emit_lineno): Split into two copies, one for BFD_ASSEMBLER, + one for not. Non-BFD_ASSEMBLER version now has temporary variable + to contain char* pointer pointed to by char** argument. Always + follow CROSS_COMPILE code; easier to read that way. + (obj_coff_ln): Don't call add_lineno or c_line_new if appline is + set. + (obj_coff_endef) [BFD_ASSEMBLER]: Don't do anything special for + ".bf", it's been done elsewhere. + (coff_frob_symbol): If ilne number data is pending, call + add_linesym to flush it. + (coff_frob_file): Don't do that here. + * config/obj-coff.h (coff_frob_file): Declare. + (obj_frob_file): Define, to call it. + + * config/tc-sparc.h (md_create_short_jump, md_create_long_jump, + md_estimate_size_before_relax: Define them as macros calling + as_fatal. + * config/tc-sparc.c: Don't define them as functions. + + * configure.in: Handle target alpha-*-osf*. (No cpu files yet.) + +Wed Dec 1 23:37:14 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Makefile (clean): Depend on clean-here. + +Wed Dec 1 11:35:21 1993 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/ho-go32.h: Include fopen-bin.h. + * as.h: If FOPEN_WB isn't defined, include fopen-same.h. + * output-file.c (output_file_create): Use FOPEN_WB instead of "w". + * input-file.c (input_file_open): Use FOPEN_RT instead of "r". + * listing.c (file_info): Use FOPEN_RB instead of "rb". + * read.c (s_include): Use FOPEN_RT instead of "r". + + * stabs.c: Include obstack.h. + + * tc.h (md_create_long_jump): Don't declare if it's already + defined as a macro. + (md_create_short_jump, md_estimate_size_before_relax): Ditto. + + * messages.c (as_perror) [BFD_ASSEMBLER]: Use bfd_errmsg instead + of strerror. Clear bfd_error. + + * config/te-lynx.h (LOCAL_LABELS_FB): Define, if not already + defined. + +Wed Dec 1 10:41:56 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (hppa_elf_mark_end_of_function): New function. + (pa_process_exit, pa_procend): Call it for ELF objects. + +Wed Dec 1 12:10:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (macro): Subtract 8 from offset in non PIC l.d + case. See comment. From wilson@cygnus.com: for M_L_DAB, set + coproc before doing goto ld. + +Tue Nov 30 13:40:30 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * write.c (TC_FORCE_RELOCATION): Provide a default definition. + (fixup_segment): Allow the target machine to specify that a + relocation must be generated for a particular fixup. Remove + #ifndef TC_HPPA hack. + + * config/tc-hppa.h (TC_FORCE_RELOCATION): Define. + + * config/tc-hppa.c (md_apply_fix_1): Never change fx_addsy to + be NULL. Only fixup_segment is supposed to do that. + (hppa_force_relocation): New function. + +Tue Nov 30 11:21:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (stabs.o): Added dependencies. + + * config/obj-ecoff.c (ecoff_frob_file): Don't call bfd_set_symtab. + +Sun Nov 28 12:11:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * app.c (do_scrub_next_char): Output a TAB before any + .app* directive. + + * config/tc-hppa.c (fix_new_hppa): Make sure a sub_symbol + exists before trying to peek at its name. + (pa_space): Do not call pa_align_subseg. See hppa/unsorted/align3.s + for testcase. + (pa_align_subseg): Delete unused/unwanted function. + +Sat Nov 27 22:49:07 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * read.c (read_a_source_file): Fix test for when to stick a colon + on the end of a label. Make code conditional on either MRI or + LABELS_WITHOUT_COLONS. + + * app.c (do_scrub_next_char): If a line begins with whitespace, leave + the single whitespace character alone. Eat all others. + + * config/tc-hppa.h (LABELS_WITHOUT_COLONS): Define. + +Wed Nov 24 01:22:54 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_procend): Do not call process_exit. + (exit_processing_complete): Delete unwanted variable and all + references. + +Wed Nov 24 02:31:38 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ecoff.c (ecoff_setup_ext): Renamed from ecoff_build_ext. + Changed to not actually build the external symbol information, as + that is now done by the ECOFF back end. + (ecoff_build_debug): Changed accordingly. + * ecoff.h (obj_ecoff_set_ext): Declare. obj-format.c function + called by ecoff_setup_ext. + * config/obj-ecoff.c (ecoff_frob_file): If debug_info count is 0, + set corresponding pointer to NULL. Don't set raw_size and + raw_syments. + (obj_ecoff_set_sym_index): Removed. + (obj_ecoff_set_ext): New function. + * config/obj-ecoff.h (obj_set_sym_index): Don't define. + (obj_ecoff_set_sym_index): Don't declare. + * config/obj-elf.c (obj_ecoff_set_ext, elf_get_extr, + elf_set_index): New functions used for ECOFF_DEBUGGING. + (elf_frob_file): Reworked ECOFF debug generation to use + new functions in bfd/ecofflink.c. + +Sun Nov 21 23:54:52 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_def_subspaces): Only create the unwind + subspace for ELF. In the SOM world, the linker is responsible + for creating the unwind subspaces. + +Fri Nov 19 16:25:09 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-coffbfd.c: Use PARAMS rather than EXFUN. + (yank_symbols): Don't call S_SET_EXTERNAL if the storage class is + already set. Fixes .def var; .val external_var; .scl 3; .endef. + (adjust_stab_section): Make static. Declare return type. Remove + unused variables. + + * config/tc-i386.h: Declare tc_coff_fix2rtype and + tc_coff_sizemachdep. + +Fri Nov 19 04:33:59 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * write.c (write_object_file): Disable obj_check_file_symbols + hook; only back end using it wasn't using it correctly. + (write_object_file): Always call obj_frob_symbol and + tc_frob_symbol; always retain symbol if it's used by a relocation, + regardless of what these routines indicate. + * config/obj-coff.c (coff_frob_symbol): Renamed from + coff_check_file_symbols. + * config/obj-coff.h (obj_check_file_symbols): Deleted. + (coff_frob_symbol): Declare. + (obj_frob_symbol): Call it. + + * config/obj-coff.c (obj_crawl_symbol_chain, obj_emit_strings, + obj_pre_write_hook): Don't define for BFD_ASSEMBLER. + (c_section_header): Ditto. Delete superfluous return at end of + function. + + * config/obj-coff.h [TC_SPARC]: Include coff/sparc.h, and specify + coff-sparc-lynx. + (SA_GET_SYM_TAGNDX): Use BFD_HEADERS version for BFD_ASSEMBLER + too. + (c_section_header): Rewrite prototype so that it contains no + preprocessing directives. Don't declare it at all if + BFD_ASSEMBLER. + + * configure.in (sparc*-*-lynxos): New target, using coff and + BFD_ASSEMBLER. + + * stabs.c: New file. + * Makefile.in (REAL_SOURCES, OBJS): List it. + * read.c (STAB_SECTION_NAME, STAB_STRING_SECTION_NAME, + get_stab_string_offset, s_stab_generic, s_stab, s_xstab, s_desc): + Moved to new file. + + * config/tc-sparc.c (tc_gen_reloc): Handle coff files like elf + files. + +Wed Nov 17 17:23:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * configure.in (mips-*-irix5*): New target. Use elf and mips-big. + * config/obj-elf.c: If ECOFF_DEBUGGING, include ecoff.h. + (obj_pseudo_table): If ECOFF_DEBUGGING, define ECOFF + pseudo-ops. + (obj_read_begin_hook): If ECOFF_DEBUGGING, call + ecoff_read_begin_hook. + (obj_symbol_new_hook): If ECOFF_DEBUGGING, call + ecoff_symbol_new_hook. + (obj_elf_init_stab_section): Cast alloca result. + (elf_frob_file): If ECOFF_DEBUGGING, finish up ECOFF debugging + information and write it out into .mdebug section. + * config/obj-elf.h (ELF_TARGET_SYMBOL_FIELDS): New macro. + (TARGET_SYMBOL_FIELDS): Use ELF_TARGET_SYMBOL_FIELDS. + (ECOFF_DEBUGGING): Define if TC_MIPS. + (TARGET_SYMBOL_FIELDS): If ECOFF_DEBUGGING, override to add + fields required by ECOFF. + * config/tc-mips.c: Check ECOFF_DEBUGGING rather than + OBJ_ECOFF in many cases. + (mips_any_noreorder): New variable. + (mips_cprestore_offset): Initialize to -1. + (mips_frame_reg): New variable. + (RELAX_ENCODE, RELAX_OLD, RELAX_NEW, RELAX_RELOC1, + RELAX_RELOC2, RELAX_RELOC3, RELAX_WARN): New macros. + (md_pseudo_table): Handle "gpword" and "cpadd". + (md_begin): Initialize ok to false. If OBJ_ELF, set alignment + of text, data and bss sections to 4. Set alignment of + .reginfo section to 2. If ECOFF_DEBUGGING, create .mdebug + section. + (ALIGN_ERR, ALIGN_ERR2): Removed unused and useless alignment + check. + (append_insn, macro_build, macro_build_lui): Take place + argument. Changed all callers. + (append_insn): If appending a nop, don't emit one. + (macro_build): Changed assertion for 'i', 'j', 'o' case. + (gp_reference): Removed. + (load_address): New function. + (macro): If mips_noreorder is used, set mips_any_noreorder. + Extensive changes to handle GP and PIC symbols differently. + Build both possible code choices using a variant frag, and + make a final decision at the end of assembly when all + information is known. Added PIC support for all symbol + references. + (mips_ip): Don't permit anything but a number after $ for a + coprocessor register. Don't use .lit4 or .lit8 sections when + generating PIC code. If OBJ_ELF, set alignment of .lit4 or + .lit8 section to 4. + (md_apply_fix): Accept and ignore GOT16 and GPREL32 relocs. + (s_change_sec): Set alignment of ELF .rodata or .sdata section + to 4. + (s_mipsset): If .set noreorder, set mips_any_noreorder. + (s_cpload): Ignore .cpload if not generating PIC code. Warn + if .cpload is not in noreorder section. + (s_cprestore): Ignore .cprestore if not generating PIC code. + (s_gpword, s_cpadd): New functions. + (tc_get_register): Added frame argument; if true, set + mips_frame_reg to return value. Changed all callers. + (md_estimate_size_before_relax): Don't error out, but instead + determine how much a frag should grow. + (tc_gen_reloc): Return multiple relocs if appropriate, as + determined by md_estimate_size_before_relax. + (md_convert_frag): New function. + (mips_elf_final_processing): Set ELF header flags based on + mips_any_noreorder and mips_pic. + * config/tc-mips.h (RELOC_EXPANSION_POSSIBLE): Define. + (MAX_RELOC_EXPANSION): Define to be 3. + (md_relax_frag): Define to be 0. + (md_convert_frag): Don't define. + (tc_get_register): Changed declaration. + + * ecoff.h, ecoff.c: New files pulled out of config/obj-ecoff.c to + support generating ECOFF debugging information for MIPS ELF + targets. Compiled only if ECOFF_DEBUGGING is defined. Changed + handling of external symbols: it now always generates exactly + those external symbols that are defined in the global symbol list. + * Makefile.in (REAL_SOURCES): Added ecoff.c. + (REAL_HEADERS): Added ecoff.h. + (OBJS): Added ecoff.o. + (ecoff.o): New target. + * config/obj-ecoff.c: Almost entirely moved into ecoff.c. + Remaining code mostly just calls ecoff.c code. + * config/obj-ecoff.h: Define ECOFF_DEBUGGING. + (TARGET_SYMBOL_FIELDS): Make ecoff_symbol a pointer to a + struct localsym. + (obj_read_begin_hook, obj_symbol_new_hook): Define to call + functions in ecoff.c. + (ecoff_stab): Don't declare (now declared in ecoff.h). + (obj_set_sym_index): Define. + (obj_ecoff_set_sym_index): Declare. + + * frags.h (frag_grow): Declare. + * frags.c (frag_grow): Made non-static. + + * write.c (is_dnrange): Do not define if md_relax_frag is defined. + (relax_segment): If md_relax_frag is defined, use it to handle a + frag of type rs_machine_dependent rather than looking through + md_relax_table. + + * read.c (read_a_source_file): If we find a bad pseudo-op, + do a continue to go on to the next line rather than a break. + Removed duplicate bad pseudo-op code which was never executed. + + * read.c (s_lcomm): Do not require a comma after the name. + + * subsegs.h (segment_info_type): Changed hadone field to bitfield. + Added bss bitfield. + * as.c (perform_an_assembly_pass): Set bss flag for bss_section. + * read.c (s_lcomm): Set bss flag for .sbss section if used. + * write.c (relax_and_size_seg): Don't set SEC_HAS_CONTENTS for a + bss section. Set SEC_RELOC if there are any relocations, even for + a zero size section. + + * write.c (write_relocs): In RELOC_EXPANSION_POSSIBLE case, base + data offset on reloc[0]->address rather than reloc[j]->address, so + that multiple relocs can affect different memory locations. + + * write.c (chain_frchains_together, relax_and_size_seg, + adjust_reloc_syms, write_relocs): Make third argument PTR, not + char *, to match definition of bfd_map_over_sections. + + * app.c (do_scrub_next_char): Don't interpret a comment character + as starting a CPP line directive unless it is a '#' and is the + very first characters on the line (i.e., do not permit leading + whitespace). + + * messages.c (identify): Make file argument non-const, to match + callers. + +Tue Nov 16 20:38:21 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_ip): Fix thinko in 21bit range check. + +Sat Nov 13 18:22:48 1993 Steve Chamberlain (sac@jonny.cygnus.com) + + * config/tc-sh.c (md_apply_fix): Cope with IMM16 type too. + * config/tc-z8k.c (build_bytes, md_apply_fix): Understand nDISP7 + relocs. + +Fri Nov 12 16:51:47 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.[ch]: Fix assorted trivial indention problems. + * config/obj-som.c (obj_som_version): Add missing ';'. + (som_frob_file): Delete whitespace at EOL. + +Fri Nov 12 15:26:21 1993 Ken Raeburn (raeburn@cygnus.com) + + * Makefile.in (VERSION): Updated following 2.2 release. + +Fri Nov 12 14:52:17 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (hppa_fix_struct): Use a real type for the + field selector, rather than an int. All uses of field selectors + fixed. + (tc_gen_reloc): For SOM PLABELs, always set addend to zero for now. + (md_apply_fix_1): Do not call hppa_field_adjust for any PLABEL + field. + + Thu Nov 11 15:49:08 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (pa_type_args): For .import statements, + silently ignore attempt to change the symbol type for a function + from ST_ENTRY to ST_CODE on .import. + +Wed Nov 10 16:19:13 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * write.h (fixS): Rename fx_callj field to fx_tcbit. + * write.c, config/obj-coff.c, config/obj-coffbfd.c, + config/tc-i960.c: Corresponding changes. + +Tue Nov 9 00:49:01 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Makefile.in (distclean): Delete config-stamp and config.h + + * config/tc-hppa.c (evaluate_absolute): Avoid relying on + ANSI-C features. + + * config/tc-hppa.c (pa_type_args): Renamed from pa_export_args. + Accept new argument "is_export". All callers changed. When + processing a .export directive for a function, do not allow + the user to set the type to "CODE", instead warn and set the + type to "ENTRY". + +Mon Nov 8 12:05:07 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_ip, printInsn): Handle 'k' (from Ted + Lemon ). + (mips_ip): Permit odd numbered floating point registers if -mips3. + (macro): Use BFD_RELOC_MIPS_LITERAL relocation for M_LI_SS. + +Mon Nov 8 07:45:01 1993 Doug Evans (dje@canuck.cygnus.com) + + * configure.in: Remove h8300h, we have multilib now. + +Mon Nov 8 06:09:18 1993 D. V. Henkel-Wallace (gumby@cirdan.cygnus.com) + + * configure.in: Support generic netware as being ELF format. + Recognise unixware if the user supplies it. + +Sun Nov 7 01:02:08 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * First cut at cleaning up PA instruction parsing. + * config/tc-hppa.c (pa_get_absolute_expression): Accept pointer to + insn structure as an argument, and a pointer to a string. All + callers changed. Always read any field selector here. Call + evaluate absolute to get a return value. + (evaluate_absolute): Addept pointer to insn structure as its + argument. All callers changed. + (INSERT_FIELD_AND_CONTINUE): New macro for inserting a bitfield + into an instruction and continuing the main pa_ip loop. + (CHECK_FIELD): New macro for simple range checking of fields. + (pa_ip): Delete unused variables. Use INSERT_FIELD_AND_CONTINUE + and CHECK_FIELD. All immediate fields now pass through + pa_get_absolute_expression which will also handle field selectors. + Delete dead code. Simplify. + (md_apply_fix_1): Use CHECK_FIELD to verify any fixes that are + applied are in range. Use bfd_put_32 rather than inserting each + byte of the fixed instrution into the buffer ourselves. + + * write.c (fixup_segment): Delete {SEG,GLOBAL}_DIFF_ALLOWED code, + it was PA specific and is no longer needed (it's now handled + within the PA backend). + * config/tc-hppa.h (SEG_DIFF_ALLOWED): Delete definition. + * config/tc-hppa.c (fix_new_hppa): If the subtract symbol for + a fixup is $global$ change it to NULL as $global$ is really only + needed long enough to determine the base type of relocation to use. + + * config/tc-hppa.c (create_new_subspace): Initialize subspace_defined. + + * config/tc-hppa.c (pa-ip, case 'z'): Make field selectors work + for 'z' operands (target of ble branch). + +Sat Nov 6 22:41:57 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c: (update_subspace): Fix type and name of last + parameter. All callers fixed. + (md_begin, pa_chk_field_selector, pa_entry): Lint. + + * config/tc-hppa.c (cons_fix_new_hppa): Reset field selector + to default state after it's been used. + +Fri Nov 5 12:08:21 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/obj-som.c (obj_som_init_stab_section): Change + space/subspace sort keys for the stab sections so as to avoid + bugs in the hp linker and pxdb. + +Thu Nov 4 17:00:05 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * write.c (chain_frchains_together): Update pointer to last + frag for a segment in the seginfo structure. + +Thu Nov 04 09:09:35 1993 Jeffrey Wheat (cassidy@cygnus.com) + + * Makefile.in: Changed RUNTESTFLAGS to RUNTEST_FLAGS + +Wed Nov 3 12:16:27 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * write.c (fixup_segment): Handle conversion of subtraction to + pc-relative addressing even if pc-relative flag is already set. + + * config/tc-m68k.c (m68k_ip_op): Use strchr, not index. Don't + declare either. + + * doc/Makefile.in (distclean): Delete intermediate files from dvi + build, but not the dvi or info files. + * Makefile.in (clean-here): New target; cleans up current + directory only. + (distclean): Use it instead of clean. + + * read.c (s_xstab): Don't use alloca. + + * messages.c (identify): New routine; print message identifying + following messages as coming from assembler. + (as_show_where, as_bad_internal, as_bad_where): Call it. + (as_fatal): Don't need to identify program any more. + +Tue Nov 2 18:04:11 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Add default case to reloc switch. + + * read.c (s_lcomm): Put small objects in .sbss for MIPS ELF as + well as MIPS ECOFF. + (get_stab_string_offset): Remove unused variable aligned. + +Tue Nov 2 15:07:07 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * tc-hppa.c: Add %dp and %rp as synonyms for %r27 and %r2 in the + predefined register table. + (pa_parse_number): Handle %rp in common register shortcut code. + Consistently set return value to -1 for an error. Clean up error + messages and only print them when "print_errors" is true. Handle + empty string case like the HP assembler -- assume a value of + zero. + + * config/ho-hpux.h: Do not include ho-sysv.h. Instead include + standard hpux include files to pick up various function decls. + + * config/ho-hppaosf.h: Delete _IO* macros. They are defined in + stdio.h. Delete bogus declaration of free. Get path to + alloca-conf.h right. + +Tue Nov 2 13:57:30 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * expr.c (operand): Fix checks for characters following "0b" or + "0f". + +Mon Nov 1 21:37:04 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/obj-som.h (obj_attach_unwind_info): Define as a hook + so GAS can attach unwind descriptor information to a BFD symbol. + * config/tc-hppa.c (fix_new_hppa): If necessary attach unwind + descriptor information to the BFD symbol. + (md_apply_fix): R_HPPA_ENTRY and R_HPPA_EXIT can never be "applied", + they are simply markers. Make R_HPPA_UNWIND_* handling OBJ_ELF + dependent. + (pa_build_unwind_subspace): Whole function is OBJ_ELF dependent. + (pa_entry): Build a R_HPPA_ENTRY relocation when configured for SOM. + (pa_exit): Likewise, but built a R_HPPA_EXIT relocation. Do not + build "end-of-function" symbols for SOM, they are not needed. + + * config/tc-hppa.c (process_exit): Create temporary symbols with + correct prefixes so they can be eliminated later. + + * config/tc-hppa.c (call_info struct): Delete unused "frame" field. + (pa_callinfo): Insert framesize into the unwind information as + soon as it's available. + (pa_build_unwind_subspace): Do not insert framesize into the unwind + information here. + + * Add support for marker type relocations. These mark areas + of interest to the linker. ENTRY/EXIT relocations for SOM are + an example of marker relocations. + * write.c (write_relocs): Instead of assuming size of a relocation + is 4 bytes, pick up the size from relocation itself. + (fixup_segment): Do not complain that a value is too small for + marker relocations. + + * struc-symbol.h: Add new "sy_used" field to the symbol structure. + * expr.c (operand): Set sy_used for any symbol used as an operand. + (expr): Likewise for any symbol used in an expression. + * config/tc-hppa.h (tc_frob_symbol): Define. Punt imported + symbols which are never used and absolute symbols which local scope. + + * config/obj-som.h (obj_frob_file): Define. + * config/obj-som.c (obj_som_init_stab_section): Set alignment + of stab sections. Make space for the special stab entry. + (adjust_stab_sections): Adjust the special entry in the + stabs section. + (som_frob_file): New function. Simply calls adjust_stab_sections + for each section. + +Mon Nov 1 17:54:29 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (PIC_CALL_REG, SP, FP): Define. + (mips_pic, mips_cprestore_offset): New static variables. + (md_pseudo_table): Handle .abicalls, .cpload, and .cprestore. + Ignore .bgnb and .endb. + (gp_reference): _gp_disp is never addressed off GP. + (macro_build): Ignore macros while searching for insn. For cases + i, j, and o, accept the reloc type as an argument rather than + assuming BFD_RELOC_LO16. Don't try to convert BFD_RELOC_LO16 to + BFD_RELOC_MIPS_GPREL. Added new case a. + (set_at, load_register, macro): Changed calls to macro_build to + pass new argument for i, j and o cases. + (macro): Handle M_JAL_1, M_JAL_2 and M_JAL_A. These require + special handling when generating SVR4 PIC code. + (mips_ip, tc_get_register, s_frame): Use macros FP, SP, GP and AT + rather than hard coded constants. + (md_apply_fix): Handle BFD_RELOC_MIPS_LITERAL and + BFD_RELOC_MIPS_CALL16. + (s_option): Set mips_pic based on .option picN. + (s_abicalls): New function; set mips_pic to 2. + (s_cpload): New function; handle .cpload. + (s_cprestore): New function; handle .cprestore. + + * config/obj-ecoff.c (obj_pseudo_table): Add entries for .bgnb, + .endb and .verstamp, setting them to s_ignore. + +Sun Oct 31 00:36:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (subspace_dictionary_chain): Add new ssd_defined + field. Define SUBSPACE_DEFINED accessor macro. + (pa_subspace): Allow user to override subspace attributes for + built-in subspaces. Set ssd_defined at the end of fcn -- that + way the attributes can only be changed once. Pass newly allocated + name to is_defined_subspace, not a pointer to the input line. + Fix typo in space/subspace rework. + (is_defined_subspace): Delete unused 2nd arg. All callers changed. + + * config/tc-hppa.c (pa_import): If currently in the text segment + and a symbol is imported without type information, set BSF_FUNCTION + for the symbol. + * write.c (relax_and_size_seg): Correct test to determine if + the section's size was rounded up. + + * config/obj-som.h (obj_set_symbol_type): Define a hook so GAS + can properly set all the SOM symbol types. + * config/tc-hppa.c (pa_symbol_type): New enum to represent the + symbol types which can be set from an IMPORT/EXPORT statement. + (pa_export_args): Set the pa_symbol_type type based on arguments. + If defined, call obj_set_symbol_type to pass this information on + to the BFD backend. + + * read.c (get_stab_string_offset): Set SEC_DEBUGGING for any + stab section we make. + (s_stab_generic): Likewise. + +Sat Oct 30 14:26:20 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Allow backends to override the value of the fake label. + * write.h (LOCAL_LABEL): Delete DOT_LABEL_PREFIX code. Instead + assume backends will define LOCAL_LABEL if anything other than + 'L' is used to denote a local label. + (FAKE_LABEL_NAME): New macro. Defines the default name used for + the "fake" label. + * expr.c (make_expr_symbol): Delete DOT_LABEL_PREFIX code + and instead simply use the string defined by FAKE_LABEL_NAME. + (operand): Likewise. + * read.c (s_stab_generic): Likewise. + * config/tc-hppa.h (FAKE_LABEL_NAME): Define as L$0\001 so it's + known to be a local label. + * config/tc-i386.h (DOT_LABEL_PREFIX): Delete. + (LOCAL_LABEL, FAKE_LABEL_NAME): Define. + * config/tc-m68k.h (DOT_LABEL_PREFIX): Delete. + (LOCAL_LABEL, FAKE_LABEL_NAME): Define. + * config/te-sco386.h (DOT_LABEL_PREFIX): Delete. + (LOCAL_LABEL, FAKE_LABEL_NAME): Define. + + Rework space/subspace handling in PA code to fully support + SOM spaces/subspaces. + * config/tc-hppa.c (USE_ALIASES): New object-format dependent define + to control the use of space/subspace name aliases. + (update_subspace): Accept space chain entry for containing space + as a new parameter. All callers changed. + (pa_get_label): Use current_space rather than pa_segment_to_space. + (pa_define_label): Likewise. + (pa_undefine_label): Likewise. + (md_begin): Change into the (possibly modified) text_section. + (pa_parse_space_stmt): Create a new segment/space if create_flag + is true, and the space name is not one of the two predefined spaces. + (pa_subspace): Use current_space rather than a lookup via + pa_segment_to_space. Reset BFD section flags as required by + the .subspace directive. Likewise for the section alignment. + Pass the current space to update_subspace and create_new_subspace. + (pa_spaces_begin): Only use space/subspace aliases if USE_ALIASES + is true. When not using aliases, create a BFD section for each + subspace encountered. When not using aliases replace the default + text, data, and bss segments with new ones. + (create_new_subspace): When not using aliases each subspace has a + section/segment and subsegments are not needed, so set the subsegment + to zero. + + * config/tc-hppa.c (pa_parse_space_stmt): If needed, call + obj_set_section_attributes to pass space attributes to the + BFD backend. + (create_new_space): Likewise. + (create_new_subspace): Likewise for subspace attributes using + obj_set_subsection_attributes. + (update_subspace): Likewise for subspace attributes using + obj_set_subsection_attributes. + + * config/tc-hppa.c (pa_parse_space_stmt): Get segment and sort key + for $TEXT$ and $PRIVATE$ from the default space structure. + + * config/tc-hppa.c (pa_export_args): Always set BSF_FUNCTION + as appropriate for the given type. + + * config/tc-hppa.c (tc_gen_reloc): Preliminary stab at handling + SOM relocations. + + * config/tc-hppa.c (pa_comm): Delete incorrect check for symbol + redefinition. + + * config/obj-som.[ch]: New files for SOM support. Note SOM + support is not yet complete in GAS or BFD. + + * config/ho-hppabsd.h: Delete IO* macros, they are defined in + stdio.h. Delete declaration of free. Include stdlib.h, unistd.h, + and string.h. + +Fri Oct 29 13:26:12 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Allow backends to override the section names used for embedded + stabs support. Needed for SOM. + * read.c (STAB_SECTION_NAME): Default the name of the stab section + to ".stab". + (STAB_STRING_SECTION_NAME): Likewise for the stab strings section. + (get_stab_string_offset): Is now passed the full name for the + stab string section rather than a name prefix. All references + changed. + (s_stab_generic): New argument for the stab string section name. + all references changed. + (s_xstab): Append "str" to the stab section name to get the + stab string section name. + * config/obj-coffbfd.c (obj_coff_init_stab_section): Append "str" + to stab section name to get the stab string section name. Pass + the full name of the stab string section to get_stab_string_offset. + * config/obj-elf.c (obj_elf_init_stab_section): Likewise. + + * config/tc-hppa.c (md_begin): Disable "-R" option to fold + textand data segments. Warn user "-R" is unsupported on the + PA. + +Thu Oct 28 12:36:13 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * config/tc-hppa.c (md_pseudo_table): Default alignment is 8 for + .align and .ALIGN directives. + + * config/tc-hppa.c (pa_space): Do not report an error for a .space + directive which does not define a "well-known" space and does + not include a space number as an argument. + + * config/tc-hppa.c (pa_def_subspaces): Correct initialization of the + "defined", "loadable", "code_only" and "space_index" fields. + (pa_def_spaces): Correct initialization of the "spnum", "defined", + and "private" fields. + + * write.h (struct fix): Add new tc_fix_data field for the various + backends to attach machine dependent fixup information to. + * write.c (fix_new_internal): Initialize new tc_fix_data field. + * config/tc-hppa.c (hppa_fix_struct): Delete unnecessary fix_fixP and + fx_next fields. + (hppa_find_hppa_fix): Delete unnecessary function. Fix all + callers to get HPPA fixup information from the tc_fix_data field + in the GAS fixup. + (hppa_fix_root): Delete unnecessary variable. + (fix_new_hppa): Attach HPPA fixup data to the GAS fixup. + + * config/tc-hppa.c (pa_set_start_symbol); Delete unwanted + function. Fix all callers. + (subspace_dictionary_chain): Delete unused ssd_start_sym field. + + * config/tc-hppa.c (hppa_fix_adjustable): New function to determine + if a particular fixup is adjustable. + * config/tc-hppa.h (tc_fix_adjustable): Call hppa_fix_adjustable to + perform the real work. + + * config/tc-hppa.h (RELOC_EXPANSION_POSSIBLE): Move definition out + of OBJ_XXX conditionals. + (MAX_RELOC_EXPANSION): Likewise. + + * config/tc-hppa.c (log2): Renamed from is_power_of_2. Fix all + callers. Now returns log2 (N) for positive N which are an exact + power of two or -1 for an error. + + * config/tc-hppa.c (pa_callinfo): Range check values provided for + ENTRY_GR, ENTRY_FR and ENTRY_SR. Properly adjust vaues before + inserting them into the unwind table. + + * config/tc-hppa.c (NEEDS_FIXUP): Delete definition and all references. + (hppa_gen_reloc_type): New object format dependent macro. + (pa_ip): Delete tons of code which was either OBJ_SOM or OBJ_ELF + conditional. The code can (and will) be shared between SOM & ELF + formats in the near future. + (cons_fix_new_hppa, md_apply_fix_1): Likewise. + (pa_build_unwind_subspace, process_exit, pa_exit): Likewise. + (tc_gen_reloc): Use hppa_gen_reloc rather than an object format + specific call. + + * config/tc-hppa.c (pa_comm): Set the segment for a common symbol + to bfd_und_section. + + * config/obj-elf.h (obj_elf_version): Add extern prototype. + + * configure.in (hppa-*-bsd*): New configuration. + BFD is always used for GAS generating SOM objects. + + * write.c (adjust_reloc_syms): Set sy_used_in_reloc if an + adjustment is rejected by the target machine. + + * config/tc-hppa.c (pa_big_cons): Delete function and its + declaration. All callers changed to use pa_cons. + + * write.c (fixup_segment): Fix indention and open/close brace + problem. + + From Pete Hoogenboom: + * config/tc-hppa.c (md_atof): Return a NULL on success rather than + an empty string. + + * config/tc-hppa.c (pa_parse_space_stmt): Advance + input_line_poitner when an invalid argument is encountered. + +Thu Oct 28 13:09:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-a29k.c (md_begin): When opcodes are mashed together in + the table, require that the one without bit 0x1000000 set come + first. Require further that it be case 'b' or 'P'. The a29k + opcode table already meets these constraints. + (machine_ip): When handling case 'i' or 'A', make sure that the + appropriate opcode really exists by looking at the next entry in + the opcode table. + +Wed Oct 27 11:48:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-m68k.c (m68k_ip): Adjust offsets for PC relative + fixups. Add 6 for long 7.3 case, 2 for short 7.2 case. + + * config/obj-ecoff.c (obj_ecoff_ent): Ignore an optional number + after a .ent directive. + + * config/tc-mips.c (mips_ip): Handle '>' case (shift amount + between 32 and 63 for double shift instruction). Do & 0x1f rather + than % 32. + (printInsn): Handle '>'. + +Tue Oct 26 16:58:36 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-ns32k.c (tc_aout_fix_to_chars): Output the symbol + number in the right place. Untested. Probably does not work for + cross assembly. From cagney@cs.adelaide.edu.au (Andrew Cagney). + + * config/tc-m68k.c (md_apply_fix_2): Error if a short branch uses + an illegal offset of 0 or -1. + + * config/obj-elf.c (obj_elf_init_stab_section): Align .stab + section to a longword boundary. + +Tue Oct 26 10:24:31 1993 Ken Raeburn (raeburn@cygnus.com) + + * Makefile.in (CHECKFLAGS): Pass down RUNTESTFLAGS. + + From Jeff Law: + * config/tc-hppa.c (tc_gen_reloc): ELF32_HPPA_R_ADDEND -> + HPPA_R_ADDEND. + +Mon Oct 25 14:06:17 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Fix up membar argument handling. + +Mon Oct 25 11:17:58 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * config/tc-sh.c (build_Mbytes): Write the relocs to the correct + address. (md_assemble): Make error handling a bit more graceful. + (md_apply_fix): Don't warn on non aligned displacement. + + * config/tc-z8k.c (get_specific, built_bytes): Understand all the + aspects of lda. + +Mon Oct 25 10:20:31 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * doc/Makefile.in (install-info): Use "$<*" so VPATH will find + as.info* even if they're in $(srcdir) (e.g., for FSF + distributions). + + * write.c (write_relocs): For relocs that are pc_relative and + pcrel_offset and not partial_inplace, adjust reloc->addend to + compensate for a bfd_perform_relocation bug. + + * config/tc-sparc.h: Removed remaining non-BFD_ASSEMBLER code. + * config/tc-sparc.c: Ditto. + (tc_gen_reloc): Include fx_offset for pcrel fixups. + +Sun Oct 24 16:49:00 1993 Jim Wilson (wilson@x1.cygnus.com) + + * tc-mips.c (md_pseudo_table): Add dword pseudo op. + +Fri Oct 22 20:40:56 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * messages.c: replaced all variables called Format with 'format', + for consistency throughout + + * configure.in: handle mips*- instead of mips, mips*el for little + endian configurations + +Fri Oct 22 14:45:49 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * input-scrub.c (physical_input_file, logical_input_file, + physical_input_line, logical_input_line): Made static. + (as_where): Return current file name and line number, don't print + them out. + * messages.c (as_show_where): New static function. Other + functions use it instead of as_where. + (as_bad_internal): New static function. + (as_bad): Use as_bad_internal. + (as_bad_where): New function, like as_bad but taking a file name + and line number. + * as.h (as_bad_where): Declare. + (as_where): Change prototype for new arguments. + * write.h (fixS): Added fields fx_file and fx_line. + * write.c (fix_new_internal): Save file and line number in fix. + (fixup_segment): Use as_bad_where, not as_bad. + * input-file.c (f_in, file_name): Made static. + * cond.c (struct file_line): Just use file and line fields. + (s_else): Use as_where and as_bad_where, not get_file_line and + set_file_line. + (get_file_line, set_file_line): Removed. + * listing.c (listing_newline): Use as_where. + * config/obj-coffbfd.c (obj_coff_init_stab_section): Use as_where. + * config/obj-ecoff.c (add_file): Use as_where. + * config/obj-elf.c (obj_elf_init_stab_section): Use as_where. + * config/tc-m68k.c (md_apply_fix_2): Use as_bad_where. + * config/tc-mips.c (tc_gen_reloc): Use as_bad_where, not assert. + +Thu Oct 21 12:52:01 1993 Ken Raeburn (raeburn@cygnus.com) + + * config/tc-m68k.h: Don't define REGISTER_PREFIX or + OPTIONAL_REGISTER_PREFIX if either is already defined. + + * config/tc-m68k.c (m68k_ip): Delete some code in "#if 0". + + * configure.in: Set bfd_gas for all sparc targets. Added facility + for keeping or rejecting configurations still under development; + default is to assume production environment, and reject configs + still being worked on. Mark Elf configurations (except sparc and + i386) as developmental. Deleted cases matching some generic names + in favor of more specific names. (E.g., when we get Alpha + support, we'll still only support VMS for Vax.) + + * config/tc-sparc.h (md_end): New macro. + * config/tc-sparc.c (md_end): Function deleted. + (BFD_RELOC_*): Delete macros that used to help keep the non-bfd + version compiling. All sparc targets will use bfd now. + * tc.h (md_end): Don't declare if it's defined as a macro. + + Changes from Jeff Law and Peter Hoogenboom: + + * read.c (next_char_of_string): Limit octal character constants to + three digits. + + * config/tc-hppa.h: Major cleanup. Use GNU-style comments. Warn + against placing additional object-file dependent code here. Warn + against contaminating all of GAS with the internals of tc-hppa.c + through inclusion of tc-hppa.h. Delete all forward declarations + for functions only used within tc-hppa.c, likewise for structures, + variables, and #defines. Try to group OBJ_ELF and OBJ_SOM + conditional code in a few small places. + + * config/tc-hppa.c: Major cleanup. Use GNU-style comments. Group + structures, global variables, forward declarations together. + Reduce (or in some cases eliminate) OBJ_ELF and OBJ_SOM + conditional code -- try to group conditional code together + into a few places. Make all functions and variables which + are only used within tc-hppa.c static. PARAMize all functions. + Add comments to functions. Delete unused functions, variables, + #defines, etc. Delete unused members within structures. Delete + ldil;ble hacks -- it is believed they were installed to work + around old gas bugs. Avoid using mixed case for local + functions, variables, and structures. Fix formatting problems + not found by GNU-indent. Add FIXME notices for things which + should be worked on the near future. Delete lots of old + useless (1.36 PA-SOM) code. + + * config/tc-hppa.c: (fix_new_hppa): Initialize the fx_r_type + field of the fixS structure. Needed to build unwind + descriptors correctly. + + * write.c: (fixup_segment): Allow expressions such as + sym1-sym2+const as long as sym2 is $global$. + + * write.c (adjust_reloc_syms): Provide a hook so that a target + cpu configuration can reject certain relocation reductions. + * tc-hppa.h (tc_fix_adjustable): New macro. Only accept relocations + which do not involve function symbols. + + * config/tc-hppa.h: Reindent with GNU-indent. Delete references + to OBJ_OSFROSE. Fix typos (OBJ_SOME -> OBJ_SOM). Delete unused + STAB_FIXUP macro. + * config/tc-hppa.c: Likewise. + + * config/tc-hppa.c (md_apply_fix_1): Use elf_symbol_type, instead + of elf32_symbol_type. + (pa_export_args): Likewise. + (elf_hppa_final_processing): Likewise. + (pa_desc): Do not call obj_elf_desc. (Is pa_desc even needed + anymore?) + (hppa_tc_make_sections): Do not declare elf_get_symtab_map any + ore. + + * config/tc-hppa.c: (md_section_align): Align all sections to + a multiple of the section alignment rather than always a + multiple of 8. + + * config/tc-hppa.c (hppa_tc_symbol): If the argument relocation + bits are zero (eg they specify no relocations), then do not even + bother adding their entries to thesymextn section. + +Thu Oct 21 15:44:55 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-sparc.c (md_parse_option): Accept and ignore -sparc + option, which is used by the SunOS make default .s.o rule. + +Wed Oct 20 12:26:33 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * config/tc-sparc.c (sparc_ip, label "immediate"): Convert relocs + operating on upper 32 bits of immediate constants to lower-half + relocs with adjusted constants. + +Tue Oct 19 18:13:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-m68k.h (AOUT_MACHTYPE): Define to be external variable + m68k_aout_machtype. + * config/tc-m68k.c (omagic): Remove obsolete and unused variable. + (m68k_aout_machtype): New variable, if OBJ_AOUT. + (md_assemble): Initialize m68k_aout_machtype based on + current_architecture, if OBJ_AOUT. + (md_parse_option): Remove obsolete reference to omagic. + +Thu Oct 14 16:51:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (md_pseudo_table): Ignore .livereg pseudo-op. + (s_option): Ignore .option O* and .option pic*. + (s_ent): Skip whitespace between symbol and optional digit. + (my_getSmallExpression): Handle ($xx) correctly: assume 0($xx). + + * app.c (do_scrub_next_char): Always accept 'x' and 'X' as escape + characters in state 6. + * read.c (next_char_of_string): Accept \Xh* and \xh* where h* are + hexidecimal digits. + + * config/tc-i386.c (md_apply_fix_1): Make cross segment calls work + for ELF by hacking around bizarre bfd_perform_relocation behaviour + that I don't dare change. + +Thu Oct 14 11:33:25 1993 Michael Meissner (meissner@osf.org) + + * config/tc-i386.c: (md_begin): Do not zero static arrays. Don't + call strchr for each character to see if it is a special char, + instead add a second loop over special_chars. Set alignment + of text, data and bss sections to 4. + (pi, te, pt, pe, ps): Add declarations so that DEBUG386 can be + used again. + (reloc): Don't return 8 and 16 bit non-PC relative relocations on + ELF, since the ELF object format does not have these type of + relocations. Change the abort into as as_bad and return + BFD_RELOC_NONE to silence compiler warnings. + (md_assemble): Keep track of the instruction size. Allow white + space between the $ and the constant for compatibility with older + gases and other assemblers. + (i386_operand): Skip spaces between $ and expression. + (tc_gen_reloc): Don't allow anything but 32 bit relocations on + ELF. Convert abort into an as_bad and assert into as_fatal. + +Wed Oct 13 16:50:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-coffbfd.c (fixup_segment) [DIFF_EXPR_OK]: If + sub_symbolP is in the current segment, convert to a PC-relative + fixup and discard the symbol. + +Wed Oct 13 14:00:02 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-ecoff.c (ecoff_build_symbols): Handle st_End symbol + for st_StaticProc just like st_Proc. + + * write.c (relax_and_size_all_segments): Moved #endif for OBJ_BOUT + so that OBJ_BOUT doesn't forget to adjust all the fragments in the + .bss section. + +Tue Oct 12 17:26:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c: If OBJ_ELF, include elf/mips.h. + (mips_regmask_frag): New static variable, if OBJ_ELF. + (md_begin): If OBJ_ELF, create .reginfo section and set + mips_regmask_frag to a frag. + (mips_elf_final_processing): New function, if OBJ_ELF. Set + mips_regmask_frag to register mask information. + * config/tc-mips.h (elf_tc_final_processing): New macro, defined + if OBJ_ELF. + +Tue Oct 12 03:33:26 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * messages.c (as_fatal): Use myname when printing messages. + + * config/tc-i960.c (md_begin): Use null pointer, not empty string, + as initial "return" value in case hashing isn't needed. + + * config/tc-a29k.c (md_atof): Return null, not empty string, on + success. + * config/tc-h8300.c (md_atof), config/tc-h8500.c (md_atof), + config/tc-hppa.c (md_atof), config/tc-i860.c (md_atof), + config/tc-i960.c (md_atof), config/tc-m88k.c (md_atof), + config/tc-ns32k.c (md_atof), config/tc-sh.c (md_atof): Ditto. + +Mon Oct 11 16:46:31 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + fix for pr 3571 + * config/tc-h8300.c (get_specific): Special action if 8 bit + address seen. (check_operand): Don't complain if truncating top + bits of an 8 bit address. (build_bytes): Allow an immediate and + an absolute in the same insn. + +Mon Oct 11 17:18:51 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * write.c (write_contents): Don't crash if seginfo is NULL. + + * config/obj-ecoff.c (ecoff_frob_file): Write out register masks + by modifying .reginfo section, not by directly modifying BFD + backend data. + +Mon Oct 11 14:11:32 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * config/ho-sunos.h: remove extern time declaration + +Mon Oct 11 16:14:43 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * messages.c (as_fatal): Do mention that it's the assembler that + got the fatal error. + +Fri Oct 8 14:09:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_gprmask, mips_cprmask): New variables to + hold register masks. + (md_begin): Initialize them to zero. + (append_insn): Update mips_gprmask and mips_cprmask. Also add + register variables pinfo and prev_pinfo. + * config/tc-mips.h (mips_gprmask, mips_cprmask): Declare. + * config/obj-ecoff.c (ecoff_frob_file): If TC_MIPS, set gprmask + and cprmask from mips_gprmask and mips_cprmask. + + * config/tc-mips.h: Define TARGET_FORMAT if OBJ_ELF. + * config/tc-mips.c (GPOPT): Define if OBJ_ECOFF or OBJ_ELF. + (various): Change all references to GP references to apply if + GPOPT, not if OBJ_ECOFF. + (s_change_sec): Rearrange somewhat. If OBJ_ELF, use .rodata + instead of .rdata. If OBJ_ELF, set section flags for .rodata and + .sdata sections. + (s_frame, s_loc, s_mask): Comment out entire functions, rather + than just body. They're not used anyhow. + * configure.in: Set cpu_type to mips for mips*. Accept + mips-*-elfl* and mips-*-elf*. + +Thu Oct 7 18:36:29 1993 Michael Meissner (meissner@osf.org) + + * config/obj-elf.c (obj_elf_common): Allow the alignment field to + not be specified. + +Wed Oct 6 13:01:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (cons_fix_new_mips): New function. Turn + BFD_RELOC_64 into BFD_RELOC_32. + * config/tc-mips.h (TC_CONS_FIX_NEW): Define. + (cons_fix_new_mips): Declare. + + Changes to let cons handle bignums like general expressions. + * expr.h (expressionS): New field X_unsigned. + * expr.c (operand): Initialize X_unsigned to 1. Set it to 0 for + unary minus case. + (expr) Fix typo resultP to right if missing operand. Set + X_unsigned to 1 when building new expression. + * read.c (potable): Make "octa" and "quad" call cons, not + big_cons. + (cons): Handle bignums. If given an O_constant (small integer) to + fill a big space, turn it into a bignum. + (parse_bitfield_cons): Set X_unsigned field. + (bignum_low, bignum_limit, bignum_high, grow_bignum, big_cons): + Removed. + * read.h (big_cons): Remove prototype. + * symbols.c (resolve_symbol_value): Don't give a warning if a + symbol in expr_section can not be resolved. + (S_SET_VALUE): Clear X_unsigned. + * write.c (write_object_file): If resolve_symbol_value failed on a + symbol we are writing out, give a warning. + * config/tc-h8500.c (parse_reglist): Set X_unsigned. + * config/tc-hppa.c (md_pseudo_table): Change "octa" and "quad" to + call pa_cons, not pa_big_cons. + (pa_big_cons): Remove. + * config/tc-hppa.h (pa_big_cons): Remove declaration. + * config/tc-i960.c (md_pseudo_table): Change "quad" to call cons, + not big_cons. + +Tue Oct 5 10:53:36 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * doc/as.texinfo (Copying): new node, to handle the recent changes + in the texinfo/gpl.texinfo file + +Mon Oct 4 17:10:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * read.c (big_cons): Handle "0" correctly. + + * config/tc-mips.c (md_begin): Set target_big_endian correctly. + +Mon Oct 4 15:37:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-m68k.c (m68k_ip): Mode 7.3 operand using PC should + have pc-relative fixup. + (md_parse_option): Move "-k" case down near "-pic" case. + + * configure.in: Alphabetize list of cpu type alternatives. Enable + OS values of "linux*elf*" and "linux*coff*" to select those + formats, with linux emulation. Don't bother checking for upper- + or mixed-case versions of "ose". + +Thu Sep 30 11:05:35 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * config/z8k.c (md_pseudo_table): add "unseg". + +Wed Sep 29 16:15:11 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * config/m88k-opcode.h (m88k_opcodes): correct a few mistakes + found while extending the dissassembler. + +Tue Sep 28 12:02:04 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * configure.in: Split i386 LynxOS out from other coff targets, + add a specific Lynx emulation. + Add m68k LynxOS target. + * config/tc-i386.c: Define specific Lynx target format. + * config/tc-m68k.c: Define specific Lynx target format. + * config/te-lynx.h: New file. + + * config/obj-coffbfd.h: Don't set TARGET_FORMAT to be + "coff-{i386,m68k}" if TARGET_FORMAT already defined. + (INIT_STAB_SECTION): Define. + * config/obj-coffbfd.c: Include . + (write_object_file): Look for .stab sections and call + adjust_stab_section. + (adjust_stab_section): New function, fills in the first symbol + of a stab section with number of symbols and string table size. + (obj_coff_init_stab_section): New function, creates the initial + symbol for a stab section. + +Mon Sep 27 15:21:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/atof-vax.c (md_atof): Return null on success instead of + empty string. + * config/atof-tahoe.c (md_atof): Ditto. + * read.c (float_cons): Expect a null pointer for success, not an + empty string. + + * hash.c (hash_insert, hash_jam, hash_grow): Return null pointer + on success, instead of empty string. All callers changed. + + * config/tc-vax.c: Use PARAMS in declarations. + (vip_op): Use NULL instead of empty string for success in error + and warning fields. + +Sun Sep 26 23:45:29 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * expr.c (expr) [DIFF_EXPR_OK]: Permit subtraction of two symbols + in different defined segments. + + * write.c (relax_segment): Localize "aim" variable. If + DIFF_EXPR_OK, don't impose checks on symbol segment types. + (fixup_segment) [DIFF_EXPR_OK]: If sub_symbolP is in the current + segment, convert to a PC-relative fixup and discard the symbol. + + * config/tc-m68k.c (flag_want_pic): New variable, mostly ignored. + (md_parse_option) [TE_SUN3]: Set it for "-k". + (m68k_ip): Generate proper fixup for mode 7.3. + * config/tc-m68k.h (DIFF_EXPR_OK): Define. + +Sat Sep 25 05:08:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-m68k.c (struct m68k_incant, getone, gettwo): Moved + earlier in the file. + (insop, add_exp): Now defined as functions, for readability. + (insop): Now takes two arguments; callers changed. + +Fri Sep 24 12:37:59 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * config/tc-m88k.c (get_o6): new function. + (get_bf, get_cmp, get_cnd, get_cr, get_fcr, get_imm16, get_reg, + get_vec9, getval, get_pcr, calcop, match_name): make static and + prototype. + (s_file): remove extraneous forward decl. + (md_begin): add const to retval decl. + (calcop): cope with instructions without arguments. Handle 'o' + type argument, the o6 field of the prot insn. + (md_estimate_size_before_relax): return a dummy value. + + * config/m88k-opcode.h (m88k_opcodes): comment change; o6 field is + in bits 10 through 7. flt.[dxs]s requires an r register in the + second argument. New instruction lda.x. New instruction muls + (alias for mul). + +Fri Sep 24 13:43:30 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (distclean): Recurse like clean. + * doc/Makefile.in (distclean): New target. + + * config/tc-mips.c (md_begin): Set BFD architecture and machine + based on MIPS ISA level. + +Thu Sep 23 17:58:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * as.c (main): "exhausted", not "exhuasted". + + * struc-symbol.h (struct symbol): Add sy_used_in_reloc field. + * write.c (adjust_reloc_syms): Set sy_used_in_reloc. + (write_object_file): Never strip symbols with sy_used_in_reloc + set. + + * config/obj-elf.c (obj_elf_section): Rewrote to handle both + Solaris and SVR4 style .section pseudo-ops. + (obj_elf_ident): Set SEC_READONLY for .comment section. + * config/tc-sparc.c (md_apply_fix): If this is ELF, and we're + generating a reloc, don't apply a fix. + +Thu Sep 23 13:16:58 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-coffbfd.c (relax_align): Now static. + +Mon Sep 20 19:23:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * read.c (get_stab_string_offset): Make non-static. Make + arguments const. Don't align strings to 4 byte boundaries. + * read.h: Declare get_stab_string_offset. + * config/obj-elf.c (obj_elf_section): Set SEC_ALLOC as well as + SEC_LOAD for progbits section. + (obj_elf_init_stab_section): New function. + (adjust_stab_sections): Add casts to avoid warnings. + * config/obj-elf.h (INIT_STAB_SECTION): Call + obj_elf_init_stab_section. + (OBJ_PROCESS_STAB): Removed definition. + +Fri Sep 17 18:12:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-elf.h (S_GET_SIZE): Define. + (obj_frob_forward_symbol): Define. + * config/tc-i386.c (line_comment_chars): Initialize in all cases. + +Thu Sep 16 14:23:08 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * tc.h: Declare tc_gen_reloc differently depending upon + RELOC_EXPANSION_POSSIBLE. + * config/obj-elf.c (obj_elf_section): Only set flags when first + creating the section. + +Wed Sep 15 12:15:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (append_insn): Don't swap a trap instruction + with a branch. + +Tue Sep 14 13:31:04 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-elf.c (obj_elf_data, obj_elf_text): New functions; + set previous_section and previous_subsection and then call s_data + and s_text, respectively. + (obj_pseudo_table): Add data and text. + (obj_elf_section): Add SEC_LOAD to default initialization of + flags. Treat .rodata1 like .rodata. Set SEC_LOAD as well as + SEC_ALLOC for "alloc" string. Don't bother trying to find the + section; just use subseg_new. + + * read.c (change_to_section): Removed. This is now done by + subseg_new. + (get_stab_string_offset): Rearranged somewhat. Create the section + using subseg_new. Store the string index in seg_info, rather than + in a static variable. Force the first string to be empty. Use + frag_more rather than FRAG_APPEND_1_CHAR. + (s_stab_generic): Rewrote. + * subsegs.h (segment_info_type): Added stabu union. + * subsegs.c (subseg_new): Initialize stab_string_size to 0. + * config/obj-aout.c: Don't include aout/stab_gnu.h. + (obj_aout_stab, obj_aout_desc): Removed. + (obj_pseudo_table): Removed desc and stabX entries. + * config/obj-bout.c: Same changes as config/obj-aout.c. + * config/obj-bout.h (S_SET_TYPE): Define. + (tc_bout_fix_to_chars): Declare. + * config/obj-coff.c (obj_coff_stab): Removed. + (obj_pseudo_table): Removed desc and stabX entries. + * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define. + * config/obj-coffbfd.c (current_stab_symbol): Removed. + * config/obj-coffbfd.h (obj_symbol_type): Removed n_strx, n_type, + n_other, n_desc and n_value fields. + (S_{S,G}ET_{OFFSET,OTHER,TYPE,DESC}): Removed. + (MAKE_STAB_SYMBOL): Removed. + * config/obj-ecoff.c (obj_ecoff_stab): Renamed to ecoff_stab. + Changed arguments and removed parsing code. + (obj_pseudo_table): Removed stabX entries. + * config/obj-ecoff.h (ecoff_stab): Declare. + (OBJ_PROCESS_STAB): Define. + * config/obj-elf.c: Don't include aout/stab_gnu.h. + (obj_elf_stab, obj_elf_xstab, obj_elf_desc, + elf_stab_symbol_string, elf_stab_symbol, obj_elf_stab_generic): + Removed. + (obj_pseudo_table): Removed desc, stabX and xstabs entries. + (obj_elf_version): Use subseg_new, not bfd_make_section. Don't + set SEC_LOAD for .note section. + (adjust_stab_sections): Get frag pointer from seg_info, rather + than looking through frags. + * config/obj-elf.h (S_{S,G}ET_{OTHER,TYPE,DESC}): Removed. + (SEPARATE_STAB_SECTIONS, INIT_STAB_SECTION, OBJ_PROCESS_STAB): + Define. + * config/obj-vms.c (obj_aout_stab): Removed. + (obj_pseudo_table): Removed stabX entries. + * config/obj-vms.h (S_SET_TYPE): Define. + + * as.h: Declare listing. + * read.c: Don't declare listing. + (emit_expr): Cast fix_new_exp argument. + (parse_bitfield_cons): Correct printf format. + * symbols.c (symbol_new): Add cast to avoid warning. + * write.h: Declare text_last_frag and data_last_frag. + * config/obj-bout.c (obj_bout_line): Added dummy argument. + * config/obj-coffbfd.c: Add some casts to avoid warnings. + * config/tc-a29k.c: Likewise. + * config/tc-i960.c: Likewise. Also fully bracket structure + initializations, fix printf formats, and remove unused variables. + +Mon Sep 13 16:48:38 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * read.c (s_desc): Only compile and use if S_SET_DESC is defined. + * struc-symbol.h: Declare verify_symbol_chain and + verify_symbol_chain_2 even if not SYMBOLS_NEED_BACKPOINTERS. + * symbols.c (verify_symbol_chain): Removed useless expression. + * write.c (headers, the_object_file): Only use if not + BFD_ASSEMBLER and not BFD. + (fixup_segment, cvs_frag_to_fill): Only use if BFD_ASSEMBLER or + not BFD. + (merge_data_into_text): Only use if BFD_ASSEMBLER or (not BFD and + not OBJ_AOUT). + * write.h: Declare relax_segment. + * config/obj-coffbfd.c (stack_pop, stack_push, stack_init): Made + static. + (stack_top): Commented out, since it's not used. + Fixed up pseudo-op functions to take an ignored int argument. + (size_section): Added default BAD_CASE to switch. + Changed bzero calls to memset. + * config/obj-coffbfd.h (S_IS_LOCAL): Call strchr on S_GET_NAME + (s), not on s itself. + * config/tc-a29k.c (s_use): Take ignored int argument. Only + define if OBJ_COFF is not defined. + * config/tc-i386.c: (fits_in_signed_byte, smallest_imm_type): Make + argument signed again. + * config/tc-m68k.c (s_bss, s_even, s_proc): Take ignored int + argument. + (m68k_ip): Fully bracket initialization of archs. + Correct several formats for __LINE__ to be %d rather than %s. + (init_table): Fully bracket initialization. + Cast values larger than 0x7f assigned to fr_opcode to char. + + * subsegs.c: Renamed non-BFD_ASSEMBLER subseg_new to subseg_set. + Wrote non-BFD_ASSEMBLER subseg_new. Now subseg_new always takes a + section name, and subseg_set always takes a segT. Changed all + callers as appropriate. + * config/obj-coffbfd.c (change_to_section): Renamed to + obj_coff_add_segment. Corrected. Made callers use subseg_new. + * config/obj-coffbfd.h (obj_segment_name, obj_add_segment): + Define. + +Mon Sep 13 13:15:03 1993 Doug Evans (dje@canuck.cygnus.com) + + * config/tc-sparc.h (LOCAL_LABEL): Remove test for name[0] == 'L'. + +Fri Sep 10 11:22:08 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-elf.h (S_SET_SIZE): Actually set the size. + + Gcc lint. + * Added a number of casts to function calls. + * app.c (do_scrub_begin), as.c (main), expr.c (integer_constant, + operand, expr), read.c (read_begin, HANDLE_CONDITIONAL_ASSEMBLY, + read_a_source_file, s_align_bytes, demand_empty_rest_of_line, + ignore_rest_of_line, big_cons, is_it_end_of_statement, s_ignore), + read.h (is_name_beginner, is_part_of_name), config/obj-elf.c + (obj_elf_section), config/tc-i386.c (parse_register), + config/tc-sparc.c (isoctal, s_proc): Cast char + array indices to unsigned char. + * app.c (process_escape): Make static. Add prototype. Change + argument from char to int. + * as.c: Include output-file.h for prototypes. Comment out unused + function got_sig. + * Makefile.in (as.o): Depend on output-file.h. + * as.h (BAD_CASE): Cast val argument to long, and use %ld. + (pseudo_typeS): Add prototype to poc_handler field. + (print_version_id): Add prototype. + (xmalloc, xrealloc): Change size arguments to unsigned long. + (do_scrub_next_char): Add prototypes for function arguments. + (had_errors, had_warnings, scrub_from_file): Remove duplicate + declarations. + * atof-generic.c (atof_generic): Make size variables unsigned. + * cond.c (ignore_input): Removed unused local variable ptr. + * expr.c (floating_constant, integer_constant): Make static. Add + prototypes. + * flonum-copy.c (flonum_copy): Make size variables unsigned. + * frags.h: Add prototype for frag_init. + * hash.h, hash.c: Change hash values from char * to PTR, make hash + strings const, make returned error strings const char *. Added + prototypes for functions. + * input-file.h, input-file.c (input_file_buffer_size): Return + unsigned int. + * input-scrub.c (buffer_length): Make unsigned. + (input_scrub_push, input_scrub_pop): Make static. + * listing.c (list_symbol_table): Cast sprintf argument to unsigned + long and use %lx. Print name of segment rather than address of + structure. + (listing_list, listing_title): Change argument to int. + (listing_eject, listing_flags, listing_psize): Add int argument. + * listing.h: Corresponding declaration changes. + * obj.h (obj_emit_symbols): Rename prototype argument to avoid + shadowing. + * read.h: Change get_absolute_expression prototype to return + offsetT. Add prototype for next_char_of_string. Various + prototype changes. + * read.c: Remove prototype for next_char_of_string. + (pobegin): Make errtxt const. Make new_length, tmp_len and num + unsigned. + (s_abort, s_align_ptwo, s_comm, s_data, s_app_line, s_fill, + s_globl, s_lsym, s_org, s_set, s_text, s_desc): Add int argument. + Change all callers. + (s_comm): Change temp from valueT to offsetT. Cast to long when + printing and use %ld (only for error messages anyhow). + (s_long, s_int): Remove unused functions. + (cons): Change argument to int. + (emit_expr): Use %lx when printing longs. + (get_absolute_expression): Return offsetT, not long. + (get_stab_string_offset): Comment out unless + SEPARATE_STAB_SECTIONS. + (s_stab_generic): Remove unused offset. Define seg_is_new only + if SEPARATE_STAB_SECTIONS. Use toP only in local block. + * struc-symbol.h (verify_symbol_chain_2): Add prototype. + * symbols.c: Remove nested comment. + (symbol_new): Rename value to valu. + (colon): Use %ld and cast to long in error message. + * symbols.h: Remove duplicate verify_symbol_chain declaration. + * tc.h: Remove unused md_emit_relocations declaration. + (tc_gen_reloc): Add declaration. + * write.c (cvt_frag_to_fill): Change first argument name depending + on BFD_ASSEMBLER. + (write_relocs): Remove unused offset, frags. Remove tc_gen_reloc + declarations. Make n unsigned. + (write_contents): Remove unused i, n, relocs, fixp. Rename frags + to f to avoid shadowing. + (write_object_file): Define fragP only if not BFD_ASSEMBLER or not + WORKING_DOT_WORD. Remove unused keep. Only declare punt and + punt_it if they will be used. Make i and n unsigned. + (fixup_segment): Cast to long and use %ld in error message. + * xmalloc.c (xmalloc, xrealloc): Make size argument unsigned. + * config/obj-aout.h: Remove nested comment. Add prototype for + obj_aout_frob_symbol. + (obj_aout_line, obj_aout_desc): Add int argument. + * config/obj-ecoff.c: Changed build routines to use an unsigned + offset. + (add_string): Make len unsigned long. + (obj_ecoff_stab): Use %lu in error message. + * config/obj-elf.c (obj_elf_common): Comment out unused label + allocate_bss. + (obj_elf_frob_symbol): Return 0 (currently broken). + (obj_elf_desc, obj_elf_version, obj_elf_size, obj_elf_type, + obj_elf_ident, obj_elf_weak, obj_elf_local, obj_elf_common, + obj_elf_line, obj_elf_previous): Add int argument. + (obj_elf_write_symbol_p): Make static. + * config/obj-elf.h (obj_elf_write_symbol): Add prototype. + * config/tc-hppa.h: Remove declarations of functions declared in + read.h. + * config/tc-i386.c (ENCODE_RELAX_STATE): Cast to relax_substateT. + (s_bss): Add int argument. + (fits_in_signed_byte, smallest_imm_type): Make argument unsigned. + (dummy): Remove unused function. + (md_assemble): Rename local o to op to avoid shadowing. + (tc_gen_reloc): Rename local reloc to rel to avoid shadowing. + * config/tc-m68k.c (s_data1, s_data2): Add int argument. + * config/tc-mips.c (mips_ip, md_apply_fix): Cast to long and use + %ld in error messages. + * config/tc-sparc.c: Remove duplicate declarations. + (getExpression): Rewrite condition to avoid empty conditional + body. + (s_reg, s_proc, s_reserve, s_common, s_seg, s_xword): Add int + argument. + +Thu Sep 9 17:10:00 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + Changes from Jeff Law: + + * config/tc-hppa.c (md_assemble): Fix typo. + (pa_ip): Delete unused variables and labels. Do not check for + unsigned values being < 0, it can't happen. + (is_same_frag): Return a value in recursive call case. + (pa_callinfo): Delete unused variables and labels. + (pa_comm): Likewise. + (pa_copyright): Likewise. + (pa_export): Likewise. + (pa_import): Likewise. + (pa_param): Likewise. + (pa_space): Likewise. + (pa_subspace): Likewise. + +Thu Sep 9 15:05:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * read.c (get_stab_string_offset, s_stab_generic): If + BFD_ASSEMBLER, call subseg_set rather than subseg_new. + +Wed Sep 8 15:09:17 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-elf.c (obj_elf_section): Set SEC_LOAD when using + default flag values. + +Tue Sep 7 10:22:52 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * read.c: (change_to_section): Don't include body if not MANY_SECTIONS. + + * read.c: (s_stab, s_xstab, s_desc): New functions to parse + various stab-related directives. + * read.h: (s_stab, s_xstab, s_desc): New function prototypes. + * write.c: (merge_data_into_text): Fix ifdef tangle. + * config/obj-coffbfd.c (current_stab_symbol): Fake symbol + for stab reader to use. + * config/obj-coffbfdh.h (obj_symbol_type): Added fields for + stab reader, macros to access. + +Fri Sep 3 16:44:03 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-elf.h (elf_symbol): No longer special-cased on + sparcv9, since elf_symbol_type is now independent of size. + + * config/obj-elf.h (elf_symbol): Fixed name of elf_symbol_type. + + * config/tc-hppa.h (struct default_subspace_dict, struct + default_space_dict): Field "sort" is now unsigned char. + + * config/tc-hppa.c (pa_def_subspaces, pa_def_spaces): Align + columns for easier reading. + (bcmp, index): Deleted USG-specific definitions. Should be dealt + with in ho-*.h, or in libiberty. Changed mention of index to + strchr. + (label_symbolP, label_symbol_defined, callinfo_found, + within_entry_exit, exit_processing_complete, within_procedure, + pa_def_subspaces, pa_def_spaces, pa_pseudo_op_moves_pc, + label_symbols_rootP, pa_get_label, pa_label_is_defined, + pa_undefine_label): Now static. + (movers): Now const, in addition to pointing to const data. + * config/tc-hppa.h (label_symbolS_rootP, pa_get_label, + pa_label_is_defined, pa_undefine_label, pa_pseudo_op_moves_pc): + Delete declarations. + + Merged more changes from Jeff Law and Pete Hoogenboom: + + * config/tc-hppa.c (pa_def_subspaces, pa_def_subspaces): Remove + entries for .stab and .stabstr. + + * config/obj-elf.c: (elf_stab_symbol_string): Set the + SEC_LOAD attribute for the .stabstr section. + (obj_elf_stab_generic): Set the SEC_LOAD attribute for the + .stab section. + (obj_elf_stab_generic): Change '#if 1' to '#if 0'. + (obj_elf_stab_generic): Incorrect byte count on call to + md_number_to_chars function. + + * config/tc-hppa.c (hppa_tc_symbol): Static functions need + argument relocation bits too. + + * config/tc-hppa.c (pa_stringer): Correctly handle escaping + characters which should appear unaltered in the output string (for + example an escaped double-quote). + + * config/tc-hppa.c (pa_parse_nonneg_cmpsub_cmpltr): Always + initialize name. + (pa_parse_neg_cmpsub_cmpltr): Likewise. + (pa_parse_nonneg_add_cmpltr): Likewise. + (pa_parse_neg_add_cmpltr): Likewise. + + * config/tc-hppa.h (parse_cons_expression_hppa): Remove prototype + for now. + (cons_fix_new_hppa): Likewise. + * config/tc-hppa.c (md_apply_fix): Fix type of valp to match + prototype. + + * config/tc-hppa.c: Include libhppa.h. + + * config/tc-hppa.h: Delete extern declarations of functions + found in libhppa.h. + + * config/tc-hppa.c (pa_space): Rework to avoid unwanted #ifdef + OBJ_ELF conditionals. + * config/tc-hppa.h (LOCAL_LABEL): Correctly identify local labels + on the PA. + +Thu Sep 2 10:43:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (macro_build): Accept 'z', and ignore it. + (macro): Use "z,s,t" for div instructions to match corresponding + change in opcode table. + (mips_ip): Added 'z'--must be zero register. + +Wed Sep 1 15:56:42 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * write.c (write_relocs) [RELOC_EXPANSION_POSSIBLE]: Declare + tc_gen_reloc correctly. + + * configure.in: Use "case" instead of "if" when possible. Rewrote + Makefile editing to reduce work done. Treat "hppa*" as "hppa". + +Wed Sep 1 12:19:07 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * config/obj-coffbfd.c (obj_coff_section): add 'd' as an alias for + section type of data. 'd' seems to be used for m88k. + +Wed Aug 25 22:33:22 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_align, s_stringer, s_cons, s_float_cons, + s_mips_space): Set insn_label to NULL to avoid changing it at the + next .align statement. + (append_insn): Don't swap jal with instruction that sets the + register that jal sets. + +Wed Aug 25 16:15:57 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * configure.in: recognize m88110. + +Wed Aug 25 13:37:46 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + Merged changes from Pete Hoogenboom and Jeff Law at Utah: + * config/tc-hppa.c (pa_build_unwind_subspace): SEC_ALLOC should + not be on for .hppa_unwind. + (md_pseudo_table): .PARAM and .param are valid pseudo-ops for GAS. + (pa_param): New function to handle .PARAM directives. + (pa_ip): Pass "isbranch" argument down to pa_parse_*_compltr + functions. Handle '|' for movb; allow movb,n. + (pa_parse_nonneg_cmpsub_cmpltr): Delete old useless + version. Handle cases where no completer exists for + comb,n or addb,n. + (pa_parse_neg_cmpsub_cmpltr): Handle cases where no + completer exists for comb,n or addb,n. Make logic + mirror that of pa_parse_nonneg_cmpsub_cmpltr. + (pa_parse_nonneg_add_cmpltr): Likewise. + (pa_parse_neg_add_cmpltr): Likewise. + * tc-hppa.h (pa_param): Declare. + +Tue Aug 24 15:41:35 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-hppa.c (hppa_tc_make_symextn_section): Now static. + Added forward declaration. + + Merged changes from Pete Hoogenboom and Jeff Law at Utah: + + * config/obj-elf.c (elf_frob_file): Arguments were incorrect on + call to elf_tc_make_sections. + (obj_elf_version): A .note section shouldn't have the SEC_ALLOC + attribute. + + * config/tc-hppa.c (hppa_tc_make_sections): Add some processing to + handle symbol extension sections. + + * config/tc-hppa.c (pa_build_symextn_section): New function to + create a symbol extension section. + (pa_export_args): Make call to pa_build_symextn_section. + (hppa_tc_symbol, hppa_tc_make_sections, + hppa_tc_make_symextn_section): New functions. + * config/tc-hppa.h: Update elf_tc_symbol and elf_tc_make_sections + macros. + + * read.c (emit_expr): Place check for TC_CONS_FIX_NEW in the + BFD_ASSEMBLER branch as well. + + * config/tc-hppa.h: If ELF is the target object format, define + some ELF- and hppa-specific types and constants. + + * config/tc-hppa.c (getExpression): Fix a typo. + + * read.c (read_a_source_file): Use TC_EQUAL_IN_INSN to determine + if a `=' is part of an instruction. + (read_a_source_file): Handle case where end-of-line markers are + also used within instructions. + * config/tc-hppa.h (TC_EQUAL_IN_INSN, TC_EOL_IN_INSN): Define. + + * config/tc-hppa.c (md_apply_fix_1): Keep relocations for + out-of-range branches/'calls using "bl" or calls which may need + argument relocation stubs. Do not need/keep relocations for + conditional branches. + (elf_hppa_final_processing): Fix calculation of function size. + + * config/obj-elf.c (obj_elf_version): Mark .note section as + READONLY. + + * config/tc-hppa.c (parse_cons_expression_hppa): Pass exp, not the + address of exp, to expression. + (pa_build_unwind_subspace): Turn SEC_HAS_CONTENTS flag on. + (md_apply_fix_1): Delete unwanted comments. + (process_exit): Symbols marking the end of a function are always + BSF_LOCAL. + + * config/tc-hppa.c: Include elf32-hppa.h from BFD tree. + (pa_space): Declare and initialize gdb_section. + + * config/obj-elf.c (elf_frob_file): Change + elf_tc_final_processing_hook to elf_tc_final_processing. + + * config/tc-hppa.c (fix_new_hppa): Fix argument list to match + argument type declarations. + (getExpression): Fix typo. + (pa_export_args): Change elf_symbol_type to elf32_symbol_type. + (elf_hppa_final_processing): Likewise. Name changed from + elf_hppa_final_processing_hook. + (start_symbol_root, start_symbol_last): Deleted. + + * config/tc-hppa.h (TC_PARSE_CONS_EXPRESSION): Fix typo. + + * config/tc-hppa.h: Replace "symbolS" with "struct symbol" to + avoid changing include ordering. + + * config/tc-hppa.c (pa_ip, case 'y'): Handle just like 't'. + +Mon Aug 23 12:47:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (set_at): Added unsignedp argument. Use + load_register. + (set_at_unsigned): Removed; changed callers to use set_at. + (load_register): Removed unused ip argument. Changed callers. + (append_insn): Don't swap branch and branch likely. + (macro_build): Handle 'u'. + (load_register): Handle 64 bit constants. + (macro): Added M_DABS, removed M_ABSU. Numerous changes to + support 64 bit constants. + (mips_ip): Use hex constants in range checks for clarity. + (md_number_to_chars): Support 8 byte values. + +Fri Aug 20 16:50:59 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * config/tc-m88k.h: updated copyrights. + (TC_CONS_RELOC): declare to be RELOC_32. + +Fri Aug 20 11:16:44 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_isa): New static variable. + (md_begin): Initialize mips_isa based on TARGET_CPU. Don't sanity + check macros. Set text alignment and GP size here. + (md_assemble): Don't set text alignment and GP size here. + (append_insn): Don't insert NOPs for load delays if mips_isa >= 2. + Use the right mask and shift for WRITE_FPR_T and WRITE_FPR_S. Add + a NOP after a branch likely. + (mips_emit_delays): Don't insert NOPS for load delays if mips_isa + >= 2. + (macro): Support r6000 and r4000 macros. + (mips_ip): Check insn ISA level against mips_isa before using it. + Added 'x' case for ignored register. + (md_parse_option): Handle -mipsN and -mcpu=XX. + +Fri Aug 20 01:26:52 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-i386.c (md_pseudo_table) [OBJ_ELF]: Handle ".zero". + +Thu Aug 19 12:15:18 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c (s_local): Function moved and renamed... + * config/obj-elf.c (obj_elf_local): ...to here. + * config/tc-sparc.c (md_pseudo_table), config/obj-elf.c + (obj_pseudo_table): Move handling of ".local". + + * tc.h (md_parse_option): Don't declare if defined as a macro. + + * config/tc-i386.h (NO_RELOC) [BFD_ASSEMBLER]: Define as + BFD_RELOC_NONE. + (md_parse_option): New macro, converted from function. + * config/tc-i386.c (md_parse_option): Function deleted. + (comment_chars) [OBJ_ELF]: Include "/". + (line_comment_chars) [OBJ_ELF || TE_I386AIX]: Don't include "/". + (md_assemble): Cast 0xe9 to char explicitly, to avoid compiler + warning. + (md_assemble, md_estimate_size_before_relax, md_create_long_jump): + Call reloc for fix_new type, or use correct enumerator, instead of + always using NO_RELOC. + (i386_operand): Change "ifndef I386COFF" to "ifdef OBJ_AOUT" for + tests for valid section. + (md_convert_frag) [BFD_ASSEMBLER]: Compensate for frag start + address. + (md_apply_fix_1) [BFD_ASSEMBLER]: For pc-relative reloc with + symbol, compensate for location of reloc. + (reloc, BFD_RELOC_32, BFD_RELOC_32_PCREL) [!BFD_ASSEMBLER]: Define + to return zero. + +Wed Aug 18 16:51:29 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-elf.c: Undef NO_RELOC before including aout/aout64.h. + (obj_elf_weak): New function. + (obj_pseudo_table): Handle ".weak". + (obj_elf_section): If section directive includes a string, ignore + it for now. Accept "progbits" flag. + (obj_elf_type): Accept `@' before flag name. + + * write.c (relax_and_size_seg) [BFD_ASSEMBLER]: Get rid of `if(1)' + condition. + (fixup_segment) [BFD_ASSEMBLER]: Use bfd_is_com_section, rather + than checking for bfd_com_section directly. + (fixup_segment): Simplify range check. + (fixup_segment) [OBJ_COFF && TC_I960]: Simplify cpp condition + test. + + * symbols.h (S_SET_WEAK): Declare. + * symbols.c (S_SET_WEAK): New function. + (S_SET_EXTERNAL, S_CLEAR_EXTERNAL): Don't bother with BSF_EXPORT, + it's not a separate flag any more. Clear BSF_WEAK. + + * read.c (potable): Treat "string" like "asciz". + +Wed Aug 18 15:30:29 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (append_insn): Don't swap branch instructions + if .set nobopt or .set volatile. + (gp_reference): .lit8 and .lit4 are accessed via the GP register. + (macro): Added cases M_LI_S, M_LI_SS. Fixed M_LI_D and M_LI_DD. + (mips_ip): Added cases 'F', 'L', 'f', 'l' for floating point. + * config/obj-ecoff.c: Renamed some variables to avoid shadow + warnings. + +Mon Aug 16 14:16:02 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * config/obj-coff.h (S_IS_COMMON): add missing backslash + + * configure.in (z8k-*-{coff,sim}): use coffbfd for this target + +Thu Aug 12 11:47:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (mips_ip): Suggested by + davidj@ICSI.Berkeley.EDU (David Johnson): Don't accept symbolic + names for 'E' and 'G' argument types (coprocessor registers) and + don't warn if $1 is used on the coprocessor. + (macro): Handle M_{L,S}WC{0,2,3}_AB correctly. + +Mon Aug 9 12:09:14 1993 Doug Evans (dje@canuck.cygnus.com) + + * read.c (emit_expr): Use BFD_RELOC_16 for 2-byte values. + * config/tc-sparc.c (md_apply_fix, tc_gen_reloc): Handle + BFD_RELOC_16. + * config/tc-sparc.h (WORKING_DOT_WORD): Define. + +Mon Aug 9 13:36:22 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * write.c (merge_data_into_text): Define only if BFD_ASSEMBLER is + defined or BFD is not. + (relax_and_size_all_segments): Declare local variable fragP. + +Fri Aug 6 15:22:53 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c (md_apply_fix, case BFD_RELOC_32): Fill in + bytes with real values, not zeros. + +Fri Aug 6 10:57:59 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * configure.in (mips-*-riscos*, mips-*-sysv*): New (untested) + targets, using ecoff and mips-big. + + * config/tc-mips.c (mips_ip): From davidj@ICSI.Berkeley.EDU (David + Johnson): Added case for 'C' for coprocessor instruction codes. + +Thu Aug 5 13:08:56 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c (md_apply_fix, case BFD_RELOC_64): Fill in + bytes with real values, not zeros. + (md_pseudo_table): Call cons for .uaxword. + + * config/obj-elf.c (obj_pseudo_table): Handle ".8byte". + + * read.c (emit_expr): Use BFD_RELOC_64 for 8-byte expressions. + + * write.c (write_object_file): Test DEBUG_SYMS instead of DEBUG + for verifying symbol chain. + (merge_data_into_text, relax_and_size_all_segments): New + functions, split out from write_object_file. + +Tue Aug 3 15:43:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-elf.c (obj_elf_stab_generic, in disabled code): If + debug section is new, allocate an extra 12 bytes at its start. If + ".stabs" type is N_SO, fill in filename symbol field of that first + entry. Return early if "goof", to simplify later code slightly. + (adjust_stab_sections): New function. + (elf_frob_file): Apply adjust_stab_sections to each section. + + * config/obj-elf.c (obj_elf_section, obj_elf_previous): No longer + static. + * config/obj-elf.h (obj_elf_section, obj_elf_previous): Declare. + * config/tc-sparc.c (md_pseudo_table): Call them for "pushsection" + and "popsection", and call cons for "uaword" and "uahalf". + + * config/obj-elf.c (obj_elf_version): Use English in error + messages. + +Tue Aug 3 11:29:06 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-ecoff.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. + +Mon Aug 2 17:35:48 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-ecoff.c (get_tag): Save tag name in permanent memory + and in hash_ptr->string. + + * app.c (do_scrub_next_char): Reset state to 0 after .appline if + file name is not seen. + +Mon Aug 2 11:51:41 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c (md_apply_fix, case BFD_RELOC_64): New case, + parallel to BFD_RELOC_32. + (tc_gen_reloc): Accept BFD_RELOC_64. + +Thu Jul 29 22:21:28 1993 Ian Lance Taylor (ian@cygnus.com) + + * write.c: Don't use short int in a prototype. + + * expr.c (operand): Make return value simply depend on contents of + returned expression. + +Thu Jul 29 18:38:37 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * configure.in: sparc*-aout and sparc*-vxworks are BFD assemblers + +Thu Jul 29 18:38:37 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * config/ho-sunos.h: remove some old function decls that conflict + w/ ANSI, and which weren't needed anyway + +Wed Jul 28 16:34:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-elf.h (obj_frob_symbol): Renamed from tc_frob_symbol, + and disabled since it breaks Ian's new symbol-value code. + + * expr.c (integer_constant): Accept more digits if BFD64. + +Wed Jul 28 11:30:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-m68k.c (m68k_ip): If we have a normal constant when we + expect a bignum, turn it into a bignum. Output extra zeroes + before a short bignum, rather than after. + +Tue Jul 27 15:54:27 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * symbols.c (symbol_new): Conditionalize verify_symbol_chain call + on DEBUG_SYMS, not DEBUG. + (symbol_remove): Likewise. + (symbol_insert): Likewise. + +Tue Jul 27 08:45:05 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-mips.c (mips_optimize): New static variable. + (append_insn): If mips_optimize == 0, always insert NOP + instructions. If mips_optimize < 2, don't swap branches. + (md_parse_option): If -Ox or -gx, set mips_optimize accordingly. + +Mon Jul 26 18:02:43 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * Makefile.in (clean): if testsuite does not exist, then skip it. + +Fri Jul 23 14:13:25 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (prev_insn_unreordered, + prev_prev_insn_unreordered): New static variables. + (append_insn): Don't swap branch instruction if + prev_prev_insn_unreordered (see comment). + (mips_no_prev_insn): Clear the unreordered variables. + (s_mipsset): When turning on reordering, set the unreordered + variables. + +Fri Jul 23 13:09:44 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-elf.c (obj_elf_section): Sections ".init" and ".fini" + are also magic, and have special default flag settings. + (obj_elf_frob_symbol): Since the return value from this function + isn't used, don't bother calling obj_elf_write_symbol_p, since it + doesn't accomplish anything else. + + * config/tc-sparc.c (md_section_align): Round up section size only + for a.out format. + + * symbols.c: Don't define DEBUG by default. + +Thu Jul 22 12:09:41 1993 Ian Lance Taylor (ian@cygnus.com) + + * write.c (fix_new_exp): Handle a O_uminus expression. + + * expr.c (expr): Don't let absolute_section override + undefined_section for the return value. + + * read.c (read_a_source_file): In NO_PSEUDO_DOT case, if we find a + pseudo-op with a poc_handler field of NULL, ignore it and treat it + as an instruction instead. + * config/tc-m88k.c (md_pseudo_table): Add "set" with a NULL + poc_handler field. + + * config/tc-h8500.c (md_begin): Use a local variable when + initializing md_relax_table to avoid warnings about modifying a + supposedly const data structure. + +Thu Jul 22 10:58:51 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + + * config/obj-aout.c: Only include aout/aout64.h if BFD_ASSEMBLER + is defined. + +Wed Jul 21 17:32:02 1993 Fred Fish (fnf@deneb.cygnus.com) + + * configure.in (case ${host}): Map *-*-sysv4* to gas_host=sysv. + * configure.in (case ${generic_target}): Add i[34]86-*-sysv4* + case to set obj_format=elf. Must go before i386-*-sysv* case that + sets obj_format=coffbsd. Add *-*-sysv4* to *-*-elf and + *-*-solaris case, and move to before *-sysv* case that wants to + set obj_format to coff. + * config/tc-i386.c (i386_operand): Change all 'exp.X_op' to + 'exp->X_op'. + * config/tc-i386.c (md_apply_fix): Fix valp to be 'valueT *' for + BFD_ASSEMBLER case. + +Wed Jul 21 12:47:51 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-aout.c: Include aout/aout64.h. + (obj_aout_frob_symbol): Set BSF_DEBUGGING for a constructor + symbol, so that BFD doesn't tamper with the type. + + * read.c (read_a_source_file): If NO_PSEUDO_DOT is defined, look + up opcodes as pseudo-ops even if they don't start with '.'. + * config/tc-m88k.h (NO_PSEUDO_DOT): Define. + * config/tc-m88k.c (md_assemble): Removed special pseudo-op + handling. + (md_apply_fix): Set fx_offset to the upper 16 bits of the reloc. + Output the low 16 bits for RELOC_HI16, not the high 16 bits. + * config/obj-coffbfd.c (do_relocs_for): If TC_M88K, set the + r_offset field of the reloc to the fixup offset. + (fixup_segments): If TC_M88K, don't warn about fixup overflows. + * doc/as.texinfo: Minor updates. + +Tue Jul 20 19:28:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Extensive changes to permit symbols to contain any expression + type and to delay the computation of the expression until the + value is actually needed. This permits setting symbols to values + calculated based on object code size. Expressions were changed to + no longer be in a section, to stop the overloading of segment and + expression type that previously occurred. + + * as.c (big_section, pass1_section, diff_section, absent_section): + Removed. + (expr_section): Added (used for dummy symbols which hold + intermediate expression values). + (perform_an_assembly_pass): Create expr_section, do not create the + sections now removed. + * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and + SEG_DIFFERENCE. Added SEG_EXPR. + (SEG_NORMAL): Corresponding changes. + * subsegs.c (seg_name, subsegs_begin): Changed accordingly. + * write.c (write_object_file): Ditto. + * config/obj-aout.c (seg_N_TYPE): Ditto. + * config/obj-bout.c (seg_N_TYPE): Ditto. + * config/obj-coff.c (seg_N_TYPE): Ditto. + * config/obj-coffbfd.c (seg_N_TYPE): Ditto. + * config/obj-vms.c (seg_N_TYPE): Ditto. + + * expr.h (operatorT): Moved in from expr.c, added some values. + (expressionS): Added X_op field, removed X_seg field; renamed + X_subtract_symbol to X_op_symbol. + * expr.c: Extensive changes to assign expression types rather than + sections and to simplify the parsing. + * write.c (fix_new_internal): New static function. + (fix_new): Removed sub_symbol argument. + (fix_new_exp): New function, takes expression argument. + * write.h: Prototype changes for fix_new and fix_new_exp. + * cond.c (s_if): Changed accordingly. + * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, + parse_repeat_cons, get_segmented_expression, + get_known_segmented_expression, get_absolute_expression): Ditto. + * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): + Ditto. + * write.c (write_object_file): Ditto. + * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. + * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, + obj_coff_endef, yank_symbols): Ditto. + * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. + * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, + print_insn, md_operand): Ditto. + * config/tc-h8300.c (parse_exp, colonmod24, check_operand, + do_a_fix_imm, build_bytes): Ditto. + * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, + get_specific, check, insert, md_convert_frag): Ditto. + * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, + md_assemble, pa_ip, getExpression, getAbsoluteExpression, + evaluateAbsolute, pa_build_unwind_subspace, pa_entry, + process_exit): Ditto. + * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, + is_complex): Ditto. + * config/tc-i386.c (pe, md_assemble, i386_operand, + md_estimate_size_before_relax, md_create_long_jump): Ditto. + * config/tc-i860.c (md_assemble, getExpression, print_insn): + Ditto. + * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, + get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, + i960_handle_align): Ditto. + * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, + subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, + md_estimate_size_before_relax, md_create_long_jump, get_num): + Ditto. + * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, + md_create_short_jump, md_create_long_jump): Ditto. + * config/tc-mips.c (md_assemble, append_insn, gp_reference, + macro_build, macro, my_getExpression): Ditto. Also removed + get_optional_absolute_expression; just use get_absolute_expression + instead. + * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, + fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. + * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. + * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): + Ditto. + * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, + print_insn): Ditto. + * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, + tip_op, md_assemble): Ditto. + * config/tc-vax.c (seg_of_operand, md_assemble, + md_estimate_size_before_relax, md_create_long_jump): Ditto. + * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto. + +Tue Jul 20 12:17:16 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * configure.in: i386-lynx is the same as i386-coff + +Mon Jul 19 15:21:20 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * config/obj-elf.c (obj_elf_previous): New function. + (previous_section, previous_subsection): New vars. + (obj_elf_section): Save current place in case DWARF code wants us + to pop back to it. Handle unquoted section name as well as quoted + section name. Don't crash on invalid strings. + (obj_pseudo_table): Handle new pseudos "previous", "2byte", and + "4byte". + + * config/obj-elf.h: Don't include struc-symbol.h. + (obj_elf_frob_symbol): Declare arg as struct symbol *. + + * tc-sparc.h (LOCAL_LABEL) [OBJ_ELF]: Local labels can start with + "L" or "_.L_". + + * write.c (write_relocs): New function, split off from + write_contents. Use memset instead of bzero. + (write_object_file): Apply write_relocs to each section before + applying write_contents. + + * read.c (read_begin): Call obstack_begin with values closer to 1K + multiples. + (read_a_source_file, big_cons, float_cons): Use memcpy instead of + bcopy. + +Mon Jul 19 14:30:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-m68k.c (m68k_ip_op): Don't decrement strend when + calculating opP->isiz; this permits the expression size to be + determined as well, later on. + + * expr.c (clean_up_expression): Don't cancel the subtraction of + undefined symbols. + + * read.c (s_data), config/obj-coffbfd.c (obj_coff_data): If -R, + switch to text section rather than data section. + +Mon Jul 19 12:35:39 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-m68k.c (m68k_ip, case AINDX): Add 6 to operand + expression (to take the pc-rel instruction itself into account) + before using the expression, instead of after. + +Fri Jul 16 08:56:04 1993 Ian Lance Taylor (ian@cygnus.com) + + * read.c (float_cons): Simplified parsing logic. If + REPEAT_CONS_EXPRESSIONS is defined, accept a repeat count. + + * symbols.c (colon): Rather than a special case for TC_HPPA, + use new macro tc_frob_label. + * config/tc-hppa.h (tc_frob_label): Define. + + * config/tc-mips.c: Many changes to support simple assembler + optimization. + (insn_label, prev_insn, prev_prev_insn, dummy_opcode, + prev_insn_valid, prev_insn_frag, prev_insn_where, + prev_insn_fixp, prev_insn_is_delay_slot): New static + variables. + (insn_uses_reg, mips_no_prev_insn, mips_emit_delays, + mips_align, s_stringer, s_mips_space): New static functions. + (mips_define_label): New global function. + (md_pseudo_table): For "ascii", "asciz", "asciiz", call + s_stringer. Changed argument to float_cons from 0 or 1 to 'f' + or 'd'. For "space" call s_mips_space. + (md_begin): Call mips_no_prev_insn. + (append_insn): Only insert necessary NOP instructions. + (macro): Call mips_emit_delays before setting mips_noreorder. + Increment and decrement mips_noreorder rather than using + save_reorder_condition. Don't bother to use noreorder in + M_L_DOB and M_L_DAB, since append_insn will not insert a NOP. + (md_atof): Handle floating point numbers correctly for both + big and little endian targets. + (s_align, s_cons): Call mips_align rather than frag_align. + (s_change_seg, s_cons): Call mips_emit_delays. + (s_float_cons): Let float_cons do the work. + (s_mipsset): Call mips_emit_delays when setting noreorder. + * config/tc-mips.h (tc_frob_label): Define to be + mips_define_label. + + * config/obj-ecoff.c (ecoff_build_symbols, ecoff_build_procs, + ecoff_frob_files): Consistently use S_GET_VALUE rather than + bfd_asymbol_value. Warn if taking difference of symbols in + different segments. + +Thu Jul 15 11:51:03 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/obj-ecoff.c (ecoff_frob_file): Discard all open scopes, + with a warning. + + * config/obj-coffbfd.c (fixup_segment): If TC_M88K, don't adjust + by md_pcrel_from if we are relocating against a symbol (we still + need md_pcrel_from for a PC relative relocation within the same + file). + * config/tc-m88k.c (md_pcrel_from): Corrected return value. + (omagic): Removed unused variable. + + * Preliminary support for m88k-coff. + * configure.in (m88k-*-coff*): New target. Use coffbfd and + m88kcoff. + * config/m88kcoff.mt: New file. + * read.c (lex_type): New macro LEX_AT to set lex type of '@'. + (pseudo_set): Handle difference of symbols in different fragments + by saving the entire expression as the value of the symbol. + * symbols.c (resolve_symbol_value): Resolve difference + expressions. + * config/obj-coffbfd.c (obj_pseudo_table): If TC_M88K, accept + "sdef" as a synonym for "def". + * config/obj-coffbfd.h: If TC_M88K, include coff/m88k.h and set + TARGET_FORMAT. + (S_IS_LOCAL): Any symbol which includes \001 in the name is local. + * config/tc-m88k.c, config/tc-m88k.h: Numerous changes to bring + m88k port up to date, and to add COFF support. + +Wed Jul 14 15:09:32 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Removed sy_forward and replaced it with an undefined expression + as the value of a symbol. + * struc-symbol.h (struct symbol): Removed sy_forward field. Added + sy_resolved and sy_resolving single bit fields. + * symbols.c (symbol_new): Don't initialize sy_forward field. + (resolve_symbol_value): New function to adjust symbol value by + fragment address, using recursion to resolve forward symbols. + * symbols.h: Added prototype for new function. + * read.c (pseudo_set): Set symbolP->sy_value to an undefined + expression rather than setting symbolP->sy_forward. + * write.c (write_object_file): Use resolve_symbol_value on + symbols, keeping the common case (the old behaviour) inline. + * config/obj-aout.c (obj_aout_frob_symbol): Removed sy_forward + handling (subsumed by write.c change). + * config/obj-coff.c, config/obj-coffbfd.c (obj_coff_val): Set + sy_value rather than sy_forward. + * config/obj-coffbfd.c (obj_coff_endef, yank_symbols): Check + expression segment rather than sy_forward. + (yank_symbols): Use resolve_symbol_value. + (crawl_symbols): Removed extra pass over symbols. + * config/obj-aout.c, config/obj-bout.c, config/obj-coff.c, + config/obj-vms.c (obj_crawl_symbol_chain): Removed extra pass over + symbols which handled sy_forward; use resolve_symbol_value + instead. + * config/obj-coff.h, config/obj-coffbfd.h (obj_frob_forward_symbol): + Define. + * config/obj-elf.c (obj_elf_stab_generic): Check expression + segment rather than sy_forward. + * config/obj-vms.c (VMS_Check_For_Main): Don't initialize + sy_forward; do initialize sy_resolved and sy_resolving. + * config/tc-hppa.h (STAB_FIXUP): Use sy_value, not sy_forward. + + * Changes to keep a full expression as the value of a symbol, not + just a longword: + * struc-symbol.h: New field sy_value. + * as.h: Include expr.h before struc-symbol.h. + * expr.h: Use struct symbol rather than symbolS. + * symbols.c (S_GET_VALUE, S_SET_VALUE): Rewrote to retrieve value + of sy_value field; compile unconditionally, not just if + BFD_ASSEMBLER. + * symbols.h: Compile S_{SG}ET_VALUE prototypes unconditionally. + * write.c (write_object_file): Set BFD symbol value to gas symbol + value. + * config/obj-aout.h, config/obj-bout.h, config/obj-coff.h, + config/obj-coffbfd.h, config/obj-generic.h, config/obj-vms.h + (S_GET_VALUE, S_SET_VALUE): Removed macro definitions. + * config/obj-ieee.c (S_GET_VALUE, S_SET_VALUE): Removed. + * config/obj-coff.h, obj-coffbfd.h: Rewrote several macros to use + S_GET_VALUE rather than ost_entry.n_value. + * config/obj-aout.c (obj_symbol_to_chars), config/obj-bout.c + (obj_symbol_to_chars), config/obj-coff.c (obj_symbol_to_chars), + config/obj-coffbfd.c (symbol_to_chars): Get value to write out + using S_GET_VALUE--don't assume it is already set. + * config/obj-ieee.c (do_symbols): Set BFD symbol value to gas + symbol value. + * config/obj-vms.c (various): Don't assign directly to + S_GET_VALUE; use S_SET_VALUE instead. + +Wed Jul 14 09:35:23 1993 Doug Evans (dje@canuck.cygnus.com) + + * configure.in: Make sparc64-*-aout* use bfd gas. + + * configure.in: Recognize h8300h. + +Tue Jul 13 12:09:44 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * config/tc-h8500.c (line_comment_chars): Add hash. + (parse_exp, skip_colonthing, build_bytes): Add support for + R_H8500_HIGH16 relocation type. + +Mon Jul 12 11:15:34 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * config/obj-elf.c (obj_elf_section): Allow `@' to introduce an + attribute name. Handle `execinstr' attribute. + +Mon Jul 12 07:22:28 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-mips.c (mips_ip): Don't warn on 'i' or 'j' mismatch if + there is another alternative for the instruction. + +Fri Jul 9 17:31:34 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) + + * doc/as.texinfo: updates for H8/300H + +Thu Jul 8 14:41:43 1993 Mark Eichin (eichin@cygnus.com) + + * config/tc-i960.c (md_create_short_jump, md_create_long_jump, + md_number_to_chars, md_section_align): Adjusted to use valueT, + addressT, to match tc.h. + +Thu Jul 8 14:15:05 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c (s_common): Revamp to handle both syntaxes, + independent of format. + +Thu Jul 8 07:25:25 1993 Doug Evans (dje@canuck.cygnus.com) + + * config/tc-h8300.h (TC_CONS_RELOC): Use R_RELLONG if h8/300h. + +Wed Jul 7 18:11:07 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com) + + * configure.in: define CROSS=-DCROSS_COMPILE if it is a cross + build; also recognize h8300-*-coff + +Wed Jul 7 10:21:24 1993 Ian Lance Taylor (ian@cygnus.com) + + * symbols.c (fb_label_instance, fb_label_instance_inc): Don't dump + core just because somebody uses a label before it is defined. + + * config/mips-opcode.h: Moved to opcode/mips.h. + * config/tc-mips.c: Include opcode/mips.h rather than + mips-opcode.h. + (append_insn): An extra NOP is only needed after instructions + which set HI or LO, not after instructions which read it. + (macro_build, mips_ip): Support new 'E', 'G' and 'B' arguments. + (macro): cfc1 and ctc1 now take "t,G" rather than "t,d". + * config/tc-mips.h (struct mips_opcode): Don't define. + * config/mips-big.mt, config/mips-lit.mt (TARG_CPU_DEPENDENTS): + Set to $(srcdir)/../include/opcode/mips.h. + + Get the MIPS assembler up to speed with other gas changes: + + * config/obj-ecoff.c (ecoff_set_vma, ecoff_frob_symbol): + Removed; don't change the symbol value. + (ecoff_build_symbols, ecoff_build_procs, ecoff_frob_file): Use + bfd_asymbol_value rather than S_GET_VALUE to include section + vma in symbol value. + (ecoff_frob_file): Ignore BSF_SECTION_SYM symbols, since ECOFF + doesn't output them. Set the vma of sections. + * config/obj-ecoff.h: Don't define obj_frob_symbol. + * config/tc-mips.c (tc_gen_reloc): Adjustment by section vma is no + longer necessary. + (various): use valueT rather than long. + +Wed Jul 7 08:33:30 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.h (ENV64): Define for v9. + + * config/tc-sparc.c (s_xword): For numbers, call big_cons. + (sparc_ip, md_apply_fix, tc_gen_reloc): Handle some sparc64 + relocation types. + (md_number_to_chars): Handle 8-byte value. + + * config/obj-elf.h (elf_symbol): For v9, use 64-bit symbol type. + + * as.h (valueT): Typedef moved here. + * struc-symbol.h (valueT): ...from here. + * write.c (write_object_file): Locals from_addr, to_addr, + table_addr are now addressT. Supply prototype for bfd_alloc for + now. + (fixup_segment): Local add_number is now valueT. Correct some + range-checking bugs. + (relax_align): Type `int' should be sufficient for the exponent. + (fix_new): Argument offset is type offsetT. Locals size and + newsize are type valueT. + * write.h (struct fix): Fields fx_offset and fx_addnumber are now + type valueT. + (fix_new): Fix prototype. + * symbols.c (symbol_new): Symbol value is type valueT. + (S_SET_VALUE, S_GET_VALUE): Likewise. + (S_IS_*): Specify int return type explicitly. + * symbols.h (symbol_new, S_GET_VALUE, S_SET_VALUE): Fixed + prototypes. + * read.c (s_comm): Values read are type valueT. + * expr.h (expressionS): Field X_add_number is an offsetT. + * tc.h (md_create_long_jump, md_create_short_jump, + md_section_align): Addresses are now type addressT. + (md_number_to_chars, md_apply_fix): Pass value as valueT. + * config/tc-i386.c (md_create_short_jump, md_create_long_jump, + md_number_to_chars, md_section_align): Adjusted. + * config/tc-sparc.c (sparc_ip): Initialize `len' variable to make + gcc shut up. + (md_create_short_jump, md_create_long_jump, md_number_to_chars, + md_section_align): Adjusted. + + * config/tc-sparc.c (s_reserve): Permit use for other than a.out + format. + (s_common): Handle Solaris-2 version. + + * config/ho-generic.h (free): Returns void if __STDC__. + + * config/obj-elf.h (obj_elf_frob_symbol, elf_frob_file, + elf_file_symbol): Declare. + + * expr.c (floating_constant, integer_constant): Now return void. + +Thu Jul 1 12:13:43 1993 Ian Lance Taylor (ian@cygnus.com) + + * configure.in: Match on sparc*-fujitsu-none rather than + sparclite*-fujitsu-none. + +Wed Jun 30 11:12:02 1993 Ian Lance Taylor (ian@cygnus.com) + + * read.c (cons): Conditionalize parsing of expression. Move + putting value into object file into separate function. Separate + out MRI and WANT_BITFIELDS cases into separate functions. + (emit_expr): New function to write data into object file. + Conditionalize on TC_CONS_FIX_NEW and TC_CONS_RELOC rather than on + processor types. + (parse_bitfield_cons): New function to parse bitfield expressions + as used by i960 assemblers. Only compiled if + BITFIELD_CONS_EXPRESSIONS is defined. + (parse_mri_cons): New function to parse MRI style strings. Only + compiled if MRI is defined. + (parse_repeat_cons): New function to parse repeat counts. Only + compiled if REPEAT_CONS_EXPRESSIONS is defined. + * read.h (emit_expr): Added declaration of new function. + * config/tc-a29k.h (TC_CONS_RELOC): Define to be RELOC_32. + * config/tc-h8300.h (TC_CONS_RELOC): Define to be R_RELWORD. + * config/tc-hppa.c (parse_cons_expression_hppa): New function to + parse a HPPA expression, rather than special case in cons + function. + (cons_fix_new_hppa): New function to emit an HPPA fixup, rather + than special case in emit_expr function. + * config/tc-hppa.h (TC_PARSE_CONS_EXPRESSION, TC_CONS_FIX_NEW): + Define to use new functions from tc-hppa.c. + * config/tc-i960.h (BITFIELD_CONS_EXPRESSIONS): Define. + (WANT_BITFIELDS): Removed; now obsolete. + * config/tc-mips.h (REPEAT_CONS_EXPRESSIONS): Define. + * config/tc-ns32k.c (cons_fix_new_ns32k): New function to emit an + NS32K fixup, rather than special case in emit_expr function. + * config/tc-ns32k.h (TC_CONS_FIX_NEW): Define to be + cons_fix_new_ns32k. Also use PARAMS rather than checking + __STDC__. + * config/tc-sparc.h (TC_CONS_RELOC): Define to RELOC_32. + + * write.c (relax_and_size_seg, adjust_reloc_syms, write_contents): + Don't core dump if gas has no information about a section. + +Wed Jun 30 06:21:27 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c (md_begin): If sparcv9 is defined, reset + current_architecture to v9 automatically. + + * config/tc-sparc.h (TARGET_FORMAT): Use elf64-sparc for v9. + + * config/tc-sparc64.h, config/tc-sparc64.c: New files. + * configure.in: Use sparc64 cpu files for v9, and default to elf + format. + + * write.c (relax_and_size_seg): Always fully process a section. + Section size is last frag's (vm)address plus its size. If no + relocations are present, force SEC_RELOC flag clear. + (dump_section_relocs): New debugging routine. + (adjust_reloc_syms): New routine, broken out from write_contents. + Don't adjust relocs that are already relative to section symbol. + Look for obj_fix_adjustable macro to know what else to skip, + instead of obj_write_symbol. Look for section symbol stored in + section information. + (write_object_file): Map adjust_reloc_syms over all sections. + (write_contents): Clear SEC_RELOC flag if no relocations are + found. + + * as.h (__PTR_TO_INT, __INT_TO_PTR): New versions for Saber, to + keep it quiet. + + * write.c (remove_subsegs): Don't define for BFD_ASSEMBLER. + +Fri Jun 25 14:42:53 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * Makefile.in (all, dvi, info, install-info, clean-info): do not + echo recursion lines. + (install-info, clean-info): collapse into the dvi and info rule. + +Fri Jun 25 10:47:24 1993 Doug Evans (dje@canuck.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Remove support for %d/%q fp regs. + All fp regs are now specified as %f. + (priv_reg_table): fpq -> fq. + +Fri Jun 25 03:43:06 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * as.h (strstr): Disable declaration for now. + (fprint_value, sprint_value): Declare. + + * subsegs.c (subseg_new_rest): Use memset to clear new frag. + (subseg_new) [BFD_ASSEMBLER]: Initialize all seginfo fields. + + * expr.c (expr_part): Made sanity checks a.out-specific. + (expr): Disabled sanity checks. + + * subsegs.h (segment_info_type) [BFD_ASSEMBLER]: Add field for + section symbol. + * subsegs.c (subseg_change): Initialize section symbol pointer + when setting up a new section. + + * symbols.c (symbol_new) [BFD_ASSEMBLER]: Point BFD symbol's udata + field back at gas symbol structure. + + * symbols.c (colon): Cast obstack_next_free value to char* before + doing arithmetic on it. + * subsegs.c (subseg_new_rest): Likewise. + * as.h (frag_now_fix): Likewise. + + * config/obj-elf.c (elf_file_symbol): Use subseg_new instead of + calling bfd_make_section_old_way directly, and call subseg_set + instead of subseg_change. Now returns void. + (obj_elf_write_symbol): Only check local symbols for now. + (elf_stab_symbol): Now static and void, and disabled until it + works completely. + (obj_elf_size): For expression values, fail silently for now. + (obj_symbol_new_hook): Do nothing. + + * config/tc-sparc.c (tc_gen_reloc): Handle BFD_RELOC_SPARC_WDISP22 + relocation. + (s_local) [OBJ_ELF]: New function. + (md_pseudo_table) [OBJ_ELF]: Call it for "local". + (s_common): Rearrange to handle Solaris .common pseudo, which may + sometimes use bss space instead of common. + * config/obj-elf.h (TARGET_SYMBOL_FIELDS): Add new `local' field. + +Thu Jun 24 16:33:53 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: set host config to hpux for hppa*-hp-hpux + +Thu Jun 24 13:35:06 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * app.c (app_pop, app_push): Fix bug reported by Chris Arthur. + +Tue Jun 22 01:04:23 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * subsegs.c (subseg_new): Don't special-case a.out -R flag here. + * config/obj-aout.c (s_sect): Do it here. + + * as.h (BAD_CASE): Don't make some lame compilers think we want + substitution inside strings. + + * as.c (print_version_id): New function, split off from main. + (main): Call it. + * config/tc-sparc.c (md_parse_option) [OBJ_ELF]: Print version id + for -V. Ignore -Q and -s options for now. + +Mon Jun 21 17:37:59 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: make installation & builds work again for crosses + +Sun Jun 20 18:18:26 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * listing.c (list_symbol_table): Rewrite to print wide (>32 bits) + symbol values correctly. + + * write.c (write_object_file): Deleted unused variables. + (fixup_segment): Use sprint_value. + + * messages.c (sprint_value, fprint_value): New routines. + + * config/obj-elf.c (elf_stab_symbol): Now returns void. + (obj_elf_stab_generic): Fix typo in logic. + + * Makefile.in (INCLUDES): Look in ../bfd for bfd.h. + + * as.h (addressT, offsetT): New types, using BFD types if + available. + (relax_addressT, struct frag): Use them. + * struc-symbol.h (valueT, struct broken_word): Likewise. + + * as.h (subseg_new) [BFD_ASSEMBLER]: Name argument is const. + * subsegs.c (subseg_new) [BFD_ASSEMBLER]: Name argument is const. + +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) + +Sun Jun 20 02:34:04 1993 Ashley Saulsbury (ans@sics.se) + + * m88k-opcode.h : fixed tiny tiny mistake - xcr was incorrectly + specified, should have both S1 and S2 fields identical + If only finding the problem was as fast as fixing the bug !!!! + +Tue Jun 15 16:01:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * write.c (write_contents): Do write out non-loadable sections. + Debug sections can fall in this category. + + * read.c (s_app_file): Call elf_file_symbol for ELF files. + * config/obj-elf.c (elf_file_symbol): New function. + + * config/obj-elf.c (elf_stab_symbol_string): Renamed from pa_..., + added argument to specify section base name. + (obj_elf_stab_generic): Renamed from ..._stab. New argument + specifies section base name. + (obj_elf_stab): New function, calls obj_elf_stab_generic with + ".stab" as section base name. + (obj_elf_xstab): New function, calls obj_elf_stab_generic. + (obj_elf_type): Handle "object". Use bitwise-or to merge in + symbol flags rather than simply replacing, so global/local flags + are preserved. + (obj_elf_ident): Rewrite. + +Tue Jun 15 17:03:25 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: remove parentdir support; use INSTALL_XFORM + +Wed Jun 9 11:26:07 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-i386.c (md_pseudo_table): .align uses a power of two + for any a.out target, not just Linux and 386BSD. + * config/tc-i386.h (DOT_LABEL_PREFIX): Do not define for any a.out + target. + +Mon Jun 7 13:33:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-m88k.c: Don't include flonum.h, md.h, m88k.h. They + don't exist or duplicate other inclusions. + + * config/tc-vax.h (NO_RELOC): Define. + +Mon Jun 7 09:55:03 1993 Doug Evans (dje@canuck.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Fix parsing of asi number. + Fix error message. + +Sat Jun 5 19:32:52 1993 Torbjorn Granlund (tege@nada.kth.se) + + * gas/config/m88k-opcode.h (m88k_opcodes): Add 88110 instructions. + * gas/config/tc-m88k.c (get_reg): New arg reg_prefix. Compare first + char to reg_prefix instead of to 'r'. + (calcop): Change calls to get_reg. + (calcop): Handle new case 'x' to set reg_prefix. + (calcop): Set reg_prefix to 'r' after each call to get_reg. + (cmpslot): Add 88110 conditions. + + * gas/config/m88k-opcode.h: Swap cases for "rot" for consistency. + + * gas/config/tc-m88k.c (get_bf): Always restore input_line_pointer + before returning. + + * gas/config/m88k-opcode.h (m88k_opcodes): Make equal mnemonics + adjacent; mov.s and mov.d swapped. + (m88k_opcodes): Fix typo `r2' -> `2'. + +Fri Jun 4 15:59:31 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * config/h8300.c: Support for H8/300-H opcodes. + + * config/obj-coffbfd.c (w_strings): String table length is 4 + bytes, no matter what the host int size is. + + * configure.in (alpha-*-osf*): New. + +Fri Jun 4 07:51:18 1993 Ian Lance Taylor (ian@cygnus.com) + + * configure.in (mips-*-ecoffl*): New target; use ecoff and + mips-lit. + (mips-*-ecoff*): Added trailing '*'. + + * config/obj-ecoff.c (ecoff_build_procs): Force the adr of the + first FDR in a file to be zero. + +Thu Jun 3 14:09:59 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * Makefile.in (VERSION): Jump to 2.1.4. + + * config/ho-hppabsd.h: New file, from Peter Hoogenboom. + + * config/tc-mips.c (md_assemble): Call bfd_set_gp_size only for + ECOFF format. + +Tue Jun 1 15:21:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-m68k.c (md_assemble): The 68040 cpu doesn't want a + separate '851 mmu. + + * config/obj-elf.c, config/obj-elf.h: Update for new type, macro, + and routine names. Assuming 32 bits for now. + + * config/obj-elf.c (elf_frob_file): Look for macro + elf_tc_final_processing_hook, instead of assuming a function + always exists. + * config/tc-hppa.c (elf_hppa_final_processing_hook): Renamed from + tc_final_processing_hook. + * config/tc-hppa.h (elf_tc_final_processing_hook): Use it. + + * config/tc-hppa.h (elf_tc_symbol, elf_tc_make_sections): Macros + moved here from obj-elf.h. + * config/obj-elf.h: Don't include CPU-specific header files. + +Sun May 30 16:49:37 1993 Peter Hoogenboom (hoogen@fast.cs.utah.edu) + + * configure.in: configurations should match on 'hppa*' not 'hppa'. + + * read.c: Add support for HPPA assembly language syntax (denoted + with '#ifdef TC_HPPA'). + + * symbols.c: Add support for HPPA assembly language syntax (denoted + with '#ifdef TC_HPPA'). + + * write.c (write_contents): Add support for HPPA-style + relocations. + + * config/obj-elf.c: Stab symbols weren't written properly. + (obj_elf_version): + (obj_elf_desc): + (obj_elf_write_symbol): + (obj_elf_write_symbol_p): + (obj_elf_frob_symbol): + (elf_stab_symbol): + (elf_frob_file): + + * config/tc-hppa.c: Support for HPPA symbol extension sections. + Remove some unused code. Support for HPPA assembly language + syntax. + + * app.c: + + * symbols.c: + + * config/obj-elf.h: + (obj_write_symbol): + (obj_frob_file): + (elf_tc_symbol): + (elf_tc_make_sections): + + * config/tc-hppa.h: + +Sun May 30 21:44:45 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * config/obj-ecoff.c (obj_read_begin_hook, add_file): Assume + hash_new will have succeeded if it returns. + * config/tc-a29k.c (md_begin): Likewise. + + * config/tc-i386.c (tc_aout_fix_to_chars): Now nbytes_r_length is + const. + (mode_from_disp_size, opcode_suffic_to_type): Now inline under + gcc. + (fits_in_{signed,unsigned}_{byte,word}): Likewise. + + * expr.c: Delete register declarations; gcc ignores them anyways. + +Fri May 28 19:03:32 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * hash.c (hash_new): Use xmalloc, since many callers don't check + for failure. + +Thu May 27 13:02:15 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * frags.c (zero_address_frag, bss_address_frag): These are + external. + + * tc.h (md_reloc_size): This is const. + * config/tc-{a29k,h8300,h8500,i386,i860,i960,m68k,ns32k,z8k}.c + (md_reloc_size): Now const. + + * config/aout_gnu.h (enum machine_type, enum reloc_type): Delete + trailing commas. + * as.h (enum _segT): Ditto. + + * struc-symbol.h (N_TYPE_seg): This should be const. + +Thu May 27 11:43:59 1993 Michael Meissner (meissner@osf.org) + + * config/obj-ecoff.c (add_file): Cast file_name to char * in + listing_source_file call. + + * config/obj-elf.c (elf_stab_symbol_string): Cast first argument + of subseg_new call to eliminate const attribute. + (obj_elf_stab): Ditto. + (obj_symbol_new_hook): Cast first argument of bzero call to char *. + + * read.c (s_align_bytes): Properly record alignment. + + * expr.c (__): Undefine __ macro before use, since OSF/1 uses it + for the prototype/no prototype macro. + + * as.c (got_sig): Don't do return ((SIGTY) 0), SIGTY might well be + void. + + * as.h (relax_stateT enum): Delete trailing comma. + +Thu May 27 11:07:50 1993 Ian Lance Taylor (ian@cygnus.com) + + * app.c (do_scrub_begin): Let line_comment_chars override + comment_chars. + (do_scrub_next_char): If a line comment character is not at the + start of a line, treat it as a comment character if it is one. + For a CPP line comment use pseudo-op .appline rather than .line. + * input-scrub.c (logical_input_line): Make int rather than + unsigned. + (input_scrub_push, input_scrub_begin): Initialize + logical_input_line to -1 rather than 0. + (bump_line_counters): Increment logical_input_line. + (new_logical_line): If line_number is -2, decrement + logical_input_line. + (as_where): Use logical_input_line even if it is 0. + * read.h (s_app_file prototype): Now takes an int argument. + * read.c (potable): Make .appfile call s_app_file with 1. New + .appline pseudo-op calls s_app_line. + (s_app_file): If .appfile, call new_logical_line with -2 to + account for newline inserted by do_scrub_next_char. If listing, + call listing_source_file. + (s_app_line): New function to handle fake pseudo-op .appline. + * config/obj-coff.c (obj_pseudo_table): Make .appline call + obj_coff_ln. + (obj_coff_ln): Added argument to indicate whether .appline. + * config/obj-coffbfd.c (obj_pseudo_table): Make .appline call + obj_coff_ln. + (obj_coff_ln): Added argument to indicate whether .appline. + * config/tc-mips.c (s_file): Pass argument to s_app_file. + +Tue May 25 11:59:07 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-bout.h (S_GET_VALUE): Removed unnecessary cast. + +Thu May 20 19:14:24 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-m68k.c (md_apply_fix_2): Straighten out check for + invalid values. + +Wed May 19 07:33:17 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) + + * config/tc-h5000.c (build_bytes): Understand @rd mode and build + relocations correctly. + +Mon May 17 15:06:26 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * Makefile.in (FLAGS_TO_PASS): Leave out TEXI2DVI for now, because + it's wrong. + + * config/tc-m68k.c (md_apply_fix_2): Apply range checks and warn + if value is out of range. + + Patch from Minh Tran-Le: + * config/tc-i386.c (i386_operand): For in/out port register used + as base reg, include InOutPortReg in operand type. + (MATCH): Accept overlap value of InOutPortReg. + +Mon May 17 09:29:34 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-ecoff.c (add_file, obj_ecoff_loc, obj_ecoff_stab): + Add calls to listing routines to produce combined source/assembler + listings. + (obj_ecoff_stab): Create a file pointer if none used yet. + (ecoff_frob_file): Set symcount to correct value. + +Fri May 14 06:53:33 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * Makefile.in (VERSION): Bump to version 2.1, in preparation for + release. + + * config/obj-aout.h (H_GET_HEADER_SIZE, H_SET_SYMBOL_TABLE_SIZE): + Define in terms of constants, not C structure sizes. + + * config/tc-rs6000.c, config/tc-rs6000.h: Delete empty files. + +Thu May 13 17:01:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-aout.c (obj_header_append): Don't define if it's + defined as a macro. + * config/obj-hp300.h (obj_header_append): Define it as a macro. + * config/obj-hp300.c (hp300_header_append): New function. + + * Makefile.in (distclean): Don't bother cleaning up doc files; + they aren't going to be in this directory. + +Thu May 13 07:51:35 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-ecoff.c (ecoff_build_symbols): Handle absolute + symbols. + + * tc.h (TC_COFF_SIZEMACHDEP): Don't define here. + * config/tc-sh.h (TC_COFF_SIZEMACHDEP): Define here instead. + +Mon May 10 06:01:12 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * config/obj-vms.c (VMS_Symbol_type_list): Don't bother with + initialization. + + * configure.in (targets): Treat m68*-*-sysv* like m68k-*-coff. + +Wed May 5 14:00:49 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-mips.c (macro): Correct floating point double word + loads and stores for big endian target. + +Wed May 5 08:39:21 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * config/tc-i386.c: Replace SEG_* with *_section, fix up subseg_* + calls. Deleted some unused code. + * config/obj-coff.c: Likewise. + + ELF support, mostly contributed by Utah: + * config/obj-elf.c (obj_elf_section, obj_elf_stab, obj_elf_line, + obj_elf_type): Rewrite. + (obj_elf_frob_symbol, elf_stab_symbol_string, elf_stab_symbol, + obj_elf_desc, obj_elf_version, obj_symbol_new_hook, obj_elf_size): + New functions. + (obj_elf_ident): Dummy. + * config/obj-elf.h (FALSE, TRUE, S_*, tc_frob_symbol, + TARGET_SYMBOL_FIELDS): New macros. + (gdb_section): New variable decl. + + * config/tc-i386.c (md_atof): Return zero, not empty string, on + success. + + BFD_ASSEMBLER conditional changes: + * config/obj-coff.c (lineno_rootP, seg_N_TYPE, *_section_header): + Don't define these. + (SA_SET_SYM_ENDNDX, SA_SET_SYM_TAGNDX): New functions. + (fetch_coff_debug_section): Ditto. + (obj_coff_endef): Call fetch_coff_debug_section. + (struct line_no): New type. + (c_symbol_merge): New way for copying aux fields. + (c_dot_file_symbol): Put symbol in absolute section, and set flag + BSF_DEBUGGING. + (function_lineoff): New symbol. + (function_lineoff, text_lineno_number, our_lineno_number, + lineno_lastP): Don't define. + (c_line_new): Don't define. + (obj_emit_lineno, obj_coff_endef): Use abort calls as, uh, + placeholders, until + line-number recording gets implemented. + (obj_new_symbol_hook): New code for handling aux fields. + (add_lineno, add_linesym): New functions. + (obj_coff_ln): Call add_lineno, not c_line_new. + (obj_coff_endef): New code for handling symbol names. New lineno + code. Look for section name "*DEBUG*" for debugging section. + (align, coff_check_file_symbols, obj_coff_section, + coff_frob_file): New functions. + * config/obj-coff.h: Reordered some includes. + (BYTE_ORDERING, FILE_HEADER_MAGIC, seg_N_TYPE, N_TYPE_seg, + DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE, AOUTHDR, AOUTHDRSIZE): Don't + define these. + (TARGET_SYMBOL_FIELDS, I960_SYM_FIELDS): New macros. + (SYM_AUXENT): New macro (for non-BFD_ASSEMBLER too) for accessing + aux entries. Most SA_* macros now use it unconditionally. + (S_*): Use `bsym' field, and access BFD private data. + (SF_*): Use `sy_flags' symbol field for most of these. + (H_*, object_headers, lineno, lineno_*P, OBJ_EMIT_LINENO): Don't + define. + (*_section_header): Don't define. + * config/tc-i386.c (md_convert_frag, md_apply_fix): Changed + interface. + (tc_gen_reloc) [I386COFF]: New function. + (tc_aout_fix_to_chars, tc_coff_fix2rtype): Don't define. + * config/tc-i386.h (TARGET_ARCH, TARGET_BYTES_BIG_ENDIAN): New + macros. + + * config/obj-coff.c (stack_init): Don't do assignments inside + conditions. + (obj_coff_def): Simplified handling of symbol name a bit. + (tag_insert): Name argument is now pointer to CONST. + (obj_crawl_symbol_chain): Commented out. + + * config/obj-coff.h: Use PARAMS macro in prototypes. + + * write.c (relax_and_size_seg) [BFD_ASSEMBLER]: Don't indirect + through frchainP pointer if it is null. + + * configure.in: Warn if BFD mode is explicitly turned off but is + required by specified target. + (mips ecoff targets): Don't need to set bfd_gas here; it gets + taken care of later. + + * config/obj-coffbfd.c (crawl_symbols): Don't clear sy_forward + field. + (yank_symbols): Merge symbols only if sy_forward is null. + + * config/tc-m68k.h (AOUT_MACHTYPE): Don't define if already + defined. + + * tc.h (md_convert_frag) [BFD_ASSEMBLER]: Section arg is not + pointer. + * config/tc-m68k.c (md_convert_frag) [BFD_ASSEMBLER]: Ditto. + + * config/tc-sparc.h (LOCAL_LABEL) [OBJ_ELF]: Anything starting + with "." is a local label. + + * config/te-hppa.h, config/tc-hppa.h, config/tc-hppa.c: New config + files. + + * config/te-linux.h, config/te-386bsd.h: New config files. + * configure.in (i386-*-linux, i386-*-bsd): Use them. + * config/tc-i386.h (TARGET_FORMAT): Select format based on target + environment. + (DOT_LABEL_PREFIX): Don't define for 386bsd or Linux. + +Wed May 5 13:14:01 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-ecoff.c (init_file): Set fMerge to 0 since dbx seems + to want it that way. + (ecoff_build_symbols): Turn local st_Proc symbols into + st_StaticProc symbols. Set index field of external st_Proc and + st_staticProc symbols correctly. + * config/tc-mips.h (NO_LISTING): Don't define. People might want + listings. + +Tue May 4 21:22:54 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-hp300.h, config/obj-hp300.c, config/te-hp300.h: New + files. + * configure.in (m68k-*-hpux): Use them. + + * config/obj-aout.c (obj_pre_write_hook): Use AOUT_VERSION if + defined, otherwise zero. + + * config/aout_gnu.h (OMAGIC): Don't define if already defined. + +Mon May 3 15:59:32 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Allow any abs expression as an + address space number. + +Wed Apr 28 19:11:22 1993 Ken Raeburn (raeburn@deneb.cygnus.com) + + * config/obj-aout.h (TARGET_DEFAULT): Don't default this at all. + + * config/tc-a29k.c: Include ctype.h. + (define_some_regs): Added special-purpose registers for 29050. + + * config/tc-i386.c (comment_chars) [TE_I386AIX]: Include "/". + + * config/obj-coffbfd.c (fill_section): Don't set STYP_REG here. + (change_to_section): Set it here instead. + +Wed Apr 28 13:40:29 1993 Ian Lance Taylor (ian@rtl.cygnus.com) + + * config/obj-ecoff.c (obj_symbol_new_hook): Make up a .file if one + hasn't been seen yet. + (add_ecoff_symbol): Don't refer to cur_file_ptr if it is NULL. + +Mon Apr 26 18:29:05 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * config/tc-sh.ch, config/tc-sh.h: New files supporting Hitachi + SH. + +Mon Apr 26 12:28:27 1993 Ian Lance Taylor (ian@cygnus.com) + + * expr.c (operand): Fix unary plus operator (previously was the + same as '~' operator!). + +Wed Apr 21 00:20:11 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * write.c (cvt_frag_to_fill): Define even if BFD is defined. + (write_object_file): Do define if BFD_ASSEMBLER. Invoke + obj_check_file_symbols if defined. Call verify_symbol_chain_2 + instead of open-coding it. Fix some bugs in patching up symbol + chain. + (relax_segment): Make some code we "ought to be able to" use for + all targets no longer conditionalized on ns32k target; instead, do + it always, and if the appropriate conditions fail, abort. + + * symbols.c (DEBUG): Enabled. + (symbol_new): Make sure bfd_make_empty_symbol works. + (verify_symbol_chain_2): New function; takes one symbol as + argument, anywhere in the chain. + (dollar_label*): Use default initializers. + + * as.c (perform_an_assembly_pass): Call md_begin here... + (main): ...and not here. + + * config/tc-m68k.h (TARGET_FORMAT): Use a.out-sunos-big for a.out. + (tc_frob_symbol): New macro: Get rid of symbols in reg_section. + + * config/tc-m68k.c (omagic): Don't define for BFD_ASSEMBLER. + (add_fix, add_frag): Now functions instead of macros. + (m68k_reg_parse, m68k_ip, md_estimate_size_before_relax, get_num, + s_data1, s_data2, s_bss): Use new *_section names, for + compatibility with BFD_ASSEMBLER mode; rewrite switch statements + to handle non-integral segT. + (tc_coff_fix2rtype, tc_aout_fix_to_chars, + tc_coff_symbol_emit_hook): Don't define for BFD_ASSEMBLER. + (tc_gen_reloc): New routine for BFD_ASSEMBLER. + (md_apply_fix, md_apply_fix_2): Renamed old md_apply_fix to + md_apply_fix_2; new md_apply_fix definition varies interface + depending on BFD_ASSEMBLER. + (md_convert_frag, md_convert_frag_1): Likewise. Use new *_section + names. + + * config/obj-vms.c: Include config.h. + (version_string): Delete declaration. + (Write_VMS_MHD_Records): Use GAS_VERSION instead. + (vms_resolve_symbol_redef): New function, taken from VMS code in + symbols.c. + (_doprnt): Deleted. + (VMS_Store_Struct, VMS_Def_Struct, VMS_Set_Struct, + VMS_TBT_Block_End, get_VMS_time_on_unix, generate_suffix, + VMS_Psect_Spec): Fixed to compile under traditional C. + * config/obj-vms.h: Use PARAMS macro. + (vms_resolve_symbol_redef): Declare. + (RESOLVE_SYMBOL_REDEFINITION): New macro. + * symbols.c (colon): Remove some VMS-specific code, look for + RESOLVE_SYMBOL_REDEFINITION macro instead. + + * config/tc-m68k.c (m68k_ip): Don't try expanding DBcc + instructions. + + * config/tc-i386.c: Reordered some functions so inlining might + work. Use PARAMS in function declarations. + (reloc): New routine. + (md_assemble): Rearrange switch statements to work with + non-integral segT. + + * struc-symbol.h [BFD_ASSEMBLER]: Undefine + SYMBOLS_NEED_BACKPOINTERS before defining it. + + * subsegs.c (subseg_new_rest): Now static. + + * read.c (pseudo_set): Better error message for difference of + symbols in different frags. + + * Makefile.in (check): Pass down some new variables, indicating + pathname or program name for cc, nm, objdump. + + * as.h (OUTPUT_FLAVOR): New macro. + * config/tc-sparc.c (tc_gen_reloc): Use OUTPUT_FLAVOR. + + * configure.in: Initialize bfd_gas properly. Warn that ELF + support is incomplete. + +Thu Apr 15 22:39:05 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * read.c (float_cons): Accept null pointer return from md_atof. + * config/tc-m68k.c (md_atof): Return null for success. + * config/tc-sparc.c (md_atof): Ditto. + +Thu Apr 15 16:04:39 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) + + * doc/as.texinfo: formatting and comment cleanups; show SPARC + alternative options in same style as other machines; simplify some + conditional use; include GPL as separate file (from texinfo dir) + + * doc/Makefile.in: (as.info) include directory containing GPL in + makeinfo search path + + * doc/h8.texi: new file; conditional settings for GAS manual + on Hitachi chips + +Tue Apr 13 15:31:40 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) + + * doc/as.texinfo: mention SPARC architecture options. + +Fri Apr 9 17:43:11 1993 Ken Raeburn (raeburn@cygnus.com) + + * configure.in: Rearranged whitespace in per-host/per-target + sections. Added hooks for dropping in HPPA support (not included + yet). Separate out overrides of variables based on target format + and bfd-gas selection from actual target-specific commands. Add + error message for recognized but unsupported format name. + +Fri Apr 9 09:05:47 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-ecoff.h (ecoff_build_lineno): Make ilineMax in + symbolic header match cline in FDR; the native linker seems to + want that. + +Thu Apr 8 15:51:28 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * doc/Makefile.in: as.texinfo is in $(srcdir). Use + $(srcdir)/as.texinfo explicitly in several places + +Thu Apr 8 15:15:02 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) + + * doc/Makefile.in: update dvi, clean targets for new source + file structure + +Thu Apr 8 12:52:46 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/ho-decstatn.h: Define BROKEN_ASSERT if not __GNUC__, + rather than undefining know. + * configure.in: Match ultrix*, not just ultrix. + +Wed Apr 7 20:18:10 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) + + * doc/as.texinfo: converted conditional markup to use new + Texinfo facilities, avoiding m4. + + * doc/as-all.texinfo, all.m4, pretex.m4: deleted. + + * doc/Makefile.in: recast doc configuration to use a link to an + included texinfo file. + + * doc/all.texi: settings for generic form of documentation. + +Tue Apr 6 11:56:21 1993 Ian Lance Taylor (ian@cygnus.com) + + * read.c (cons): Zero out frag when creating reloc. + +Mon Apr 5 09:41:58 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-mips.c (gp_reference): Certain magic symbols can never + be referenced off the GP register. + + * app.c (do_scrub_next_char): Handle states 9 and 10 correctly + when dealing with characters of type LEX_IS_TWOCHAR_COMMENT_1ST, + LEX_IS_STRINGQUOTE, and LEX_IS_ONECHAR_QUOTE. + + * config/te-irix.h: New file; irix needs a different LOCAL_LABEL + definition from other MIPS targets. + * configure.in (mips-*-irix): Use emulation irix. + +Sun Apr 4 15:21:09 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * config/tc-h8500.c: Get relax size of branch instructions right, + (get_operand): Parse @sp+ correctly. + +Fri Apr 2 15:59:49 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * subsegs.h (segment_info_type) [BFD_ASSEMBLER]: Don't include + COFF section header field. + + * configure.in: Print error message if host or target is not + supported. + + * configure.in: If with-bfd-assembler, use obj-coff instead of + obj-coffbfd. + + * config/ho-generic.h: Include string.h. + +Fri Apr 2 08:54:57 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-mips.h (LOCAL_LABEL): Treat any label starting with + '$' as local, for any object file format. + + * config/tc-mips.c (macro): Optimizations to branching code and a + couple of bug fixes from ralphc@pyrps5.eng.pyramid.com (Ralph + Campbell). + + * config/ho-irix.h: New file; if not gcc, define BROKEN_ASSERT. + * configure.in (mips-sgi-irix*): Set gas_host to irix. + +Wed Mar 31 17:53:54 1993 Ian Lance Taylor (ian@cygnus.com) + + * subsegs.c (subseg_new): Set output_section of new section. + * as.c (perform_an_assemly_pass): Don't set output_section here. + * expr.c (expr_part, expr): Turn off section assertions for ECOFF, + since it has additional sections. + * read.c (s_lcomm): For MIPS ECOFF, put small objects in .sbss, + not bss_section. + * config/obj-ecoff.h (TARGET_SYMBOL_FIELDS): Added + ecoff_undefined field. + * config/obj-ecoff.c (obj_symbol_new_hook): Initialize + ecoff_undefined field. + (add_file): If using stabs, just output a stabs symbol rather than + creating a new fdr. + (obj_ecoff_begin, obj_ecoff_bend): Ignore line number by reading + it with get_absolute_expression, rather than skipping it by hand. + (obj_ecoff_loc): If using stabs, just output a stabs symbol rather + than ECOFF line number information. + (obj_ecoff_stab): Accept non-zero values for stabs line number. + (ecoff_build_symbols): Set ifilesym correctly. Set storage class + to small, undefined and/or readonly sections if appropriate. + Don't output symbol names containing \001 characters. + (ecoff_frob_file): Make sure at least one fdr is output. + * config/tc-mips.h: Define TC_MIPS. + * config/tc-mips.c (g_switch_value): New static variable. + (md_assemble): Set gp size of output BFD. + (gp_reference): New function; returns 1 if expression can be + accesssed via gp. Always returns 0 if not using ECOFF. + (macro_build): Convert BFD_RELOC_LO16 to BFD_RELOC_MIPS_GPREL if + possible. + (macro): Generate sequences using gp if possible. + (md_parse_option): Ignore -EL and -EB. Parse -G. + (md_apply_fix): Added BFD_RELOC_MIPS_GPREL to ignored case. + (s_change_sec): Handle .rdata and .sdata for ECOFF. + (s_extern): Mark symbol as external. Set ecoff_undefined field. + +Tue Mar 30 10:11:41 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * output-file.c (output_file_create): Don't call as_perror for + filename rejected by application. + + * as.c (main) [BFD_ASSEMBLER]: If errors occur, close and unlink + the output file. + + * doc/as.texinfo: Don't use @value in node names for the moment; + references don't appear to work right. + + * as.h (const, volatile): Put these definitions back, and use + them. + + * doc/as.texinfo: First pass at using new texinfo features -- + variables, conditional tests. Far from complete. + +Mon Mar 29 16:05:40 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * read.c: Temporary hack to handle some 64-bit constants. This + should be redone later. + (target_big_endian): Declare. + (big_cons): If it's set, reverse order of bytes being copied. + * config/tc-sparc.c (md_begin): Set target_big_endian. + + * read.c (s_ignore): Delete declaration of is_end_of_line. + + * config/obj-coffbfd.c (yank_symbols): Build list of file symbol + forward pointers properly. + +Mon Mar 29 13:47:33 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * config/obj-coffbfd.c (do_relocs_for): Fix bug where nrelocs + wasn't being stored into scnhdr. + * config/obj-coffbfd.h: Add prototype of s_get_segment. + * read.c (TC_START_LABEL): Default definition. + (read_a_source_file): Use TC_START_LABEL macro to work out + if a label has been seen. + +Mon Mar 29 12:56:56 1993 Ian Lance Taylor (ian@cygnus.com) + + * configure.in: Set BFDDEF and BFDLIB at the top of Makefile, not + the bottom (make expands variables in dependencies when the + dependencies are read, not when they are used). + + * config/obj-coffbfd.c (fill_section): Don't set NOLOAD bit for + a29k .bss section; the mondfe program doesn't like it. + +Sun Mar 28 08:12:53 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * config/tc-m68k.c: Use PARAMS macro, and use CONST instead of + const. + (current_architecture): Don't need initializer. + +Fri Mar 26 08:12:48 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * doc/none.m4: Define Z8000. + * doc/Makefile.in (as-*.texinfo): Refer to $(srcdir). Remove the + texinfo file before recreating it. + (TEXI2DVI): Need to set TEXINPUTS if "make as.dvi" is to work in + this directory. + (srcdir): Delete second, bogus definition. + (as.info): Look for as-*.texinfo in current directory rather than + in $(srcdir). + (as.dvi): Ditto. + (dvi): New rule. + * doc/configure.in: Create links to all as-*.texinfo files in the + source directory, if that's not the current directory. + + * configure.in (per-host): Accept MIPS host with BSD version + number. + (per-target): Classify i486 as i386. Use generic cpu_type instead + of target_cpu in selecting format etc. + + * app.c (do_scrub_next_char): Use .appfile, not .app-file. + * read.c (potable): Change .app-file to .appfile. + + * config/ho-decstatn.h: Renamed from ho-decstation.h. + * configure.in: Adjusted. + + * config/obj-bfd-sunos.*: Unused; deleted. + + * Makefile.in (version.c, vers-stamp): Deleted. + (config.h): Define GAS_VERSION. + * as.c (version_string): Deleted declaration. + (main): Look for GAS_VERSION instead. + + * doc/as.texinfo: Updated description of -a* (listing) options, + and describe how to pass them through from gcc. + + * config/obj-coffbfd.c (do_relocs_for): Don't allocate storage or + process relocs if there aren't any relocs to process. Avoids + malloc/free bug on SCO too. + + * as.h: Move local include files below system include files, to + avoid some redefinition complaints on some systems. + (const, volatile): Don't need these conditionally defined if we + use CONST and VOLATILE from ansidecl.h. + (seg_name): Use CONST, not const. + +Fri Mar 26 10:22:04 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-mips.c: Reindented to GNU standards. + +Thu Mar 25 08:59:14 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-coffbfd.c (do_relocs_for): Remove a29k special case. + (fixup_segment): Add a29k special case; the linker is not prepared + to see a segment offset here. + + * app.c (do_scrub_next_char): Added new state, 10, modifying state + 9 to only keep a space in between identifier characters. + +Wed Mar 24 02:16:22 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com) + + * Makefile.in: add dvi target; as-$(config).texinfo might live in + srcdir, might be in objdir. + + * doc/Makefile.in: dvi depends on as.dvi + +Mon Mar 22 23:59:13 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: add installcheck target + +Mon Mar 22 16:25:57 1993 Jim Wilson (wilson@sphagnum.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Add support for membar mask names. + Add missing colons in prefetch error messages. Add support for + ASI names. + +Mon Mar 22 10:19:00 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/tc-mips.c (macro): Use $AT for any floating point load. + +Sat Mar 20 12:50:51 1993 Ken Raeburn (raeburn@urth.cygnus.com) + + * config/tc-m68k.c (m68k_ip): For operand type 'M', reject + bignums, but don't emit error message. + +Fri Mar 19 21:02:19 1993 Jim Wilson (wilson@sphagnum.cygnus.com) + + * Makefile.in (targ-cpu.o): Depend on config.h. + +Wed Mar 17 16:44:06 1993 Ian Lance Taylor (ian@cygnus.com) + + * app.c (do_scrub_next_char): Added new state, 9, to avoid + dropping a space immediately following an identifier. + * expr.c, write.c: Rewrote assert expressions to not use multiple + lines; I don't think that can be done portably. + * config/tc-mips.c (macro): Use $AT if target register is zero in + load instruction, which it can be for a floating point load. + +Mon Mar 15 12:17:28 1993 Ian Lance Taylor (ian@cygnus.com) + + * write.c (write_contents): Compute the relocs before writing out + the section contents. + * config/obj-ecoff.h, config/obj-ecoff.c: Numerous changes to get + symbol table and values right. + * config/tc-mips.h (LOCAL_LABEL): If OBJ_ECOFF, any label starting + with $L is local. + * config/tc-mips.c (tc_gen_reloc): If OBJ_ECOFF, adjust the addend + by the section vma. + + * config/z8k.mt (TARG_CPU_DEPENDENTS): The relevant file is + z8k-opc.h, not z8k.h. + + * config/obj-coffbfd.c (obj_coff_endef): Correct test for .bf + symbol. + +Fri Mar 12 18:33:36 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: recognize sparc-sun-solaris2* instead of -solaris2 + +Fri Mar 12 12:00:07 1993 Ian Lance Taylor (ian@cygnus.com) + + * expr.c, write.c: Ultrix native 4.2 cc requires assert condition + to be on a single line. + +Thu Mar 11 17:56:22 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * Makefile.in (config.h): Create file, writing out definitions of + target cpu, alias, and canonical name. + (ALL_CFLAGS): No longer define TARGET_CPU. + + * Makefile.in (check): Print a message, instead of quitting + silently. + + * as.c (main): Don't catch any signals, for now. + + * version.c: Deleted. + * Makefile.in: Generate it, putting in only the version number + itself. + (VERSION): New variable. + * as.c: Include config.h. + (main): Reformatted version string. Include target alias. Don't + print if not requested (i.e., unknown -v argument). + + * as.c (stralloc): Deleted. + (main): Call strdup instead. + + * configure.in: Handle all 68300 series chips. + * config/tc-m68k.c: Include config.h. + (md_assemble): Assume TARGET_CPU is defined. Accept some 68300 + series cpus as defaults. + (md_parse_option): Accept some m68300 series CPUs as defaults. + +Wed Mar 10 17:41:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * as.c (EXIT_SUCCESS, EXIT_FAILURE): Define to normal values if + not already defined. + (main, got_sig): Use them. + * config/ho-vms.h (EXIT_SUCCESS, EXIT_FAILURE): Reverse default + values. + +Tue Mar 9 07:40:06 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-ecoff.c, config/obj-ecoff.h: Preliminary ECOFF + support. + + * config/tc-mips.h (TARGET_FORMAT): Define based on OBJ_AOUT vs. + OBJ_ECOFF as well as TARGET_BYTES_*_ENDIAN. + (struct loc, struct proc, struct file): Moved to tc-mips.c within + #ifndef OBJ_ECOFF block, since ECOFF uses different versions. + * config/tc-mips.c: Rearranged for ECOFF support. Added + prototypes for all static functions. Moved existing minimal + debugging format support info #ifndef OBJ_ECOFF blocks. + (macro_build_lui): Eliminated sign_extend argument, because ECOFF + does not support a non sign extended high 16 bits reloc. Adjusted + all callers accordingly. + (tc_get_register): Renamed from get_register, and made non-static. + + * config/mips-big.mt, config/mips-lit.mt: New files. Define + TARGET_BYTES_BIG_ENDIAN and TARGET_BYTES_LITTLE_ENDIAN, + respectively. + * configure.in (mips-*-bsd*): Use gas_target mips-lit. + (mips-*-ultrix*, mips-*-irix*, mips-*-ecoff): New targets, using + obj_format ecoff and gas_target mips-lit or mips-big. + +Tue Mar 9 07:43:01 1993 Ken Raeburn (raeburn@cygnus.com) + + * version.c: Bump to version 2.0.1. + +Tue Mar 9 07:40:06 1993 Ian Lance Taylor (ian@cygnus.com) + + * write.c (chain_frchains_together): Check that seg_info (section) + is not NULL. + (write_object_file): Call obj_frob_file after setting the symbols, + not before. + +Tue Mar 9 00:00:00 1993 Ken Raeburn (raeburn@cygnus.com) + + * Version 2.0 released. + +Mon Mar 8 14:57:10 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-i386.h (TC_COUNT_RELOC): Look for fx_addsy only. + +Fri Mar 5 09:05:55 1993 Ian Lance Taylor (ian@cygnus.com) + + * read.h: Define stringer here. + read.c, config/obj-ieee.c, config/obj-tcm88k.c: Not any of these + places. + +Thu Mar 4 11:52:23 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * read.c (s_space): Multiply repeat count by mult, not fill. + +Thu Mar 4 05:20:42 1993 Ken Raeburn (raeburn@cygnus.com) + + * read.c: Include ctype.h. + +Wed Mar 3 10:41:46 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + Patches from Eric Youngdale: + * make-gas.com: Find obstack.obj if it's not in the current + directory. + * read.c (s_ignore): Don't declare is_end_of_line. It's + redundant, and triggers a VMS gcc compiler bug. + + * write.c (write_object_file): Macro SUB_SEGMENT_ALIGN now takes + current segment as an argument. (Ignored in all cases but VMS.) + All callers and definitions changed. + +Tue Mar 2 11:56:19 1993 Ian Lance Taylor (ian@cygnus.com) + + * listing.c: Cleaned up a bit, added prototypes, made NO_LISTING + case compile again. + +Tue Mar 2 08:53:34 1993 Ken Raeburn (raeburn@cygnus.com) + + * config/tc-m68k.c (isbyte): Accept all values from -255 to +255, + so "~0x80" won't be rejected. + + * config/obj-elf.c: No longer include elf/reloc.h. + (obj_elf_section): Set SEC_READONLY and SEC_CODE for text section. + (obj_elf_stab, obj_elf_desc): Deleted do-nothing and commented-out + routines. + (obj_elf_xstab): New routine. + (obj_elf_set_size): Call as_warn, not fprintf. Pass desired + argument to s_ignore. Put "#if 0" around unused code. + (obj_pseudo_table): Use s_ignore instead of do-nothing routines. + Call elf_xstabs for .stabs and .xstabs operators. + + * config/tc-sparc.h (TARGET_FORMAT) [OBJ_ELF]: Now "elf32-sparc". + + * write.c (relax_and_size_seg): Set SEC_RELOC only if fixups are + present. + + * configure.in: mips-bsd configuration was missing format spec. + Should use aout. + + * Makefile.in (Makefile): Depends on configure.in. + + * config/tc-mips.c (append_insn): Don't check for alignment of + frag in memory; alignment of instructions in section is a separate + matter. + + * config/tc-mips.c (macro_build_lui): Fix some assumptions of ANSI + C availability. + + * listing.h: Always provide function declarations, not macros, so + pcc won't lose. + +Tue Mar 2 00:50:43 1993 John Gilmore (gnu@cygnus.com) + + * CONTRIBUTORS: Update Gilmore entry. + +Mon Mar 1 12:03:16 1993 Jim Wilson (wilson@sphagnum.cygnus.com) + + * config/tc-sparc.c (sparc_ip): Correctly assemble prefetch + instructions. Accept integer prefetch function numbers. + +Wed Feb 24 14:58:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c (s_xword): Now call big_cons, so large + constants are accepted, but symbolic values are not. GCC will not + generate the latter currently. + + * frags.c (frag_init): New function. + (zero_address_frag, bss_address_frag): Now initialized at run + time. + * as.c (main): Call frag_init. + +Wed Feb 24 10:32:42 1993 Ian Lance Taylor (ian@cygnus.com) + + * app.c (do_scrub_next_char): In LEX_IS_LINE_COMMENT_START case: + Don't unget ch2 if we didn't get it. + +Wed Feb 24 04:14:07 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * doc/Makefile.in (TEXIDIR): Updated for new layout. + + * config/tc-sparc.c (s_common): Add support for ELF version. + (tc_gen_reloc) [BFD_ASSEMBLER]: New function. + * config/tc-sparc.h (TARGET_ARCH, TARGET_FORMAT) [BFD_ASSEMBLER]: + New macros. + (md_convert_frag): New macro. + + * config/tc-m68k.c (m68k_ip): For PC-relative addressing of a + symbol, fix the offset so "+2" isn't required. + + * config/tc-i960.c (line_comment_chars, line_separator_chars): + Define as common/bss. + (op_hash, reg_hash, areg_hash, iclasses_seen, br_cnt): Default C + initializers are sufficient. + + * config/obj-aout.h [BFD_ASSEMBLER]: Include libaout.h from bfd. + (TARGET_FORMAT) [BFD_ASSEMBLER]: Default to "a.out". + (S_SET_*, S_GET_*, obj_frob_symbol) [BFD_ASSEMBLER]: New macros. + (S_SET_TYPE) [!BFD_ASSEMBLER]: New macro. + * config/obj-aout.c: Use PARAMS macro for declarations. Remove + "IGNORE_DEBUG" conditional, since both branches are identical. + Use S_SET_TYPE, S_GET_TYPE, and S_GET_DESC instead of directly + referencing symbol structure members. + (obj_aout_frob_symbol) [BFD_ASSEMBLER]: New function. + + * as.h (struct frag): Reordered a couple of fields for better + packing. + + * write.c (record_alignment) [BFD_ASSEMBLER]: Record it in the + section info. + (write_contents) [BFD_ASSEMBLER]: New function. + (write_object_file) [BFD_ASSEMBLER]: Always handle -R here. Call + fix_new with BFD_RELOC_NONE instead of 0 or NO_RELOC. Call + obj_frob_file, obj_frob_symbol, tc_frob_symbol if defined. + (fixup_segment): Make sure common-section symbols get treated the + same as undefined symbols. + (fix_new) [BFD_ASSEMBLER]: Argument r_type is of type + bfd_reloc_code_real_type. Use seg_fix_{root,tail}P derived from + section info. + * write.h (fix_new): Update prototype. + + * tc.h (md_operand, md_convert_frag, tc_headers_hook, + md_section_align, md_undefined_symbol): Don't provide prototypes + if these are defined as macros. + (md_convert_frag) [BFD_ASSEMBLER]: BFD version needs bfd and + section passed. + + * symbols.c (symbol_new): Argument NAME is now pointer to const. + Simplified STRIP_UNDERSCORE code. Remove assumptions about null + pointers in freshly allocated storage. [BFD_ASSEMBLER]: Get new + BFD symbol. + (colon): Display other/desc fields of redefined symbol only if + S_GET_OTHER and S_GET_DESC are defined. + (symbol_make): Argument NAME is now pointer to const. + (symbol_find, symbol_find_base): Likewise. + (S_IS_*, S_GET_*, S_SET_*) [BFD_ASSEMBLER]: New functions. + * symbols.h: Fix prototypes for new const arguments. Add + prototypes for BFD_ASSEMBLER S_* functions. + + * subsegs.c (subseg_change) [BFD_ASSEMBLER]: BFD version of code + for changing to an existing section. + (subseg_new_rest) [BFD_ASSEMBLER]: Split off from subseg_new, + called by subseg_new and subseg_set. + (subseg_new) [BFD_ASSEMBLER]: Rewritten to change to new section, + given section name and subseg number. + (subseg_set) [BFD_ASSEMBLER]: New function; change to a possibly + new section/subsection. + + * read.c: Don't include ctype.h. + (cons) [BFD_ASSEMBLER]: For undefined symbols, use BFD_RELOC_32 + for now; should be machine-dependent. + + * configure.in: Accept *-*-elf and *-*-solaris* as ELF format + targets, forcing BFD use. + +Wed Feb 17 18:59:03 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c: Use PARAMS macro for static function + declarations. Use BFD_RELOC_ macros everywhere, with + compatibility macros declared for non-BFD mode. + (struct sparc_it) [BFD_ASSEMBLER]: Use bfd_reloc_code_real_type + instead of enum reloc_type. + (emit_sparc_reloc): Commented-out function deleted. + (md_convert_frag): Deleted. + (tc_aout_pre_write_hook): Don't define for BFD_ASSEMBLER. + (md_apply_fix): Changed calling sequence (conditionally) for BFD + version. + * config/tc-sparc.h (md_convert_frag): New macro. + + * config/obj-aout.c (obj_aout_stab): Refer to undefined_section, + not SEG_UNKNOWN. Use S_SET_TYPE, S_GET_TYPE, S_GET_DESC instead + of referencing fields directly. + + * write.c (cvt_frag_to_fill): New function; extracted from + write_object_file. + (write_object_file) [! BFD_ASSEMBLER]: Call it. + (relax_and_size_seg) [BFD_ASSEMBLER]: New function; relax section + and set its size and flags. + + * struc-symbol.h (struct symbol) [BFD_ASSEMBLER]: Replace some + fields with BFD equivalents. Turn on back-pointers, and add + target-specific fields at end. + +Thu Feb 11 09:20:37 1993 Ian Lance Taylor (ian@cygnus.com) + + * config/obj-coffbfd.c (fill_section): Don't set vaddr here. + (write_object_file): Set it here instead, so that fixup_segment + can see the correct value. + +Mon Feb 8 13:56:17 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * write.c (write_object_file): Check for errors and warnings and + bail out before processing contents. + (chain_frchains_together_1): New function, does most of the work + of remove_subsegs. + (chain_frchains_together) [BFD_ASSEMBLER]: New function. + (remove_subsegs) [! BFD]: Call it. + (write_object_file) [BFD_ASSEMBLER]: Converted to use BFD + structures and routines. + + * config/obj-elf.*: New files. + + * config/mips.mt, config/rs6000.mt: Deleted. + + * config/h8300.mt: Don't specify compiler here. + + * config/z8k.mt: The z8k code depends on the z8k opcode table, + not the h8300 one. + * config/tc-z8k.h: Comment fix. + + * write.c: Reordered some functions for better inlining. + (fixup_segment): Linkrelax code is no longer conditional on + TC_I960. + +Thu Feb 4 12:45:16 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * config/{h8500.mt, tc-h8500.c, tc-h8500.h, obj-coffbfd.c, + obj-coffbfd.h}: support for the H8/500 + +Wed Feb 3 19:28:18 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-vms.h (SUB_SEGMENT_ALIGN): Define VMS version here. + * write.c (write_object_file): Not here. + (fix_new): Initialize fx_addnumber. + + * listing.c: Don't include target-cpu.h explicitly, since as.h + includes it. + +Thu Jan 28 00:35:40 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * write.h [BFD_ASSEMBLER]: Don't declare next_object_file_charP, + *_fix_root, *_fix_tail, seg_fix_rootP, seg_fix_tailP. + (struct fix): Reordered fields for compactness and efficiency. + Converted some logical fields to 1-bit fields. + + * config/obj-aout.h: Use PARAMS. + [BFD_ASSEMBLER]: Don't define/declare AOUT_MACHTYPE, seg_N_TYPE, + N_TYPE_seg, DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE. + + * read.c: Don't include listing.h; as.h includes it. Removed + DONTDEF code. + [BFD_ASSEMBLER]: Include subsegs.h. + (old_buffer, new_broken_words): Default initialization is + sufficient. + + * output-file.c [BFD_ASSEMBLER]: Include bfd.h, default TARGET_MACH + to 0, define stdoutput. + (output_file_create) [BFD_ASSEMBLER]: Call bfd_perror on failure. + Call bfd_set_arch_mach. + (output_file_close) [BFD_ASSEMBLER]: Call bfd_close, not + bfd_close_all_done. Call bfd_perror on failure. + (output_file_append) [BFD_ASSEMBLER]: Don't define. + + * config/m68kcoff.mt (LOCAL_LOADLIBES): Delete definition. + + * subsegs.h (segment_info_type): Always define. Omit field scnhdr + if not MANY_SEGMENTS. Define new field bfd_section if + BFD_ASSEMBLER. + (seg_info): New macro. + + * expr.c, input-scrub.c: Use PARAMS macro. Deleted unused + variables, and some irrelevant comments. + + * Makefile.in (ALL_CFLAGS): Include $(BFDDEF). + (LIBS): Include $(BFDLIB). Don't bother with $(CLIB). + * configure.in: Permit --with-bfd-assembler now, with a warning. + Variable need_bfd is now a boolean, as is new variable bfd_gas. + Set BFDDEF and BFDLIB in Makefile when appropriate. + + * as.c: Removed "#ifdef DONTDEF" and "#ifdef comment" code. + (main): Refer to flag_always_generate_output instead of + flagseen['Z']. + + * as.c (main) [BFD_ASSEMBLER]: Open output bfd. + (*_section) [BFD_ASSEMBLER]: Define them. + (perform_an_assembly_pass) [BFD_ASSEMBLER]: Initialize them, and + set section flags when appropriate. + * as.h (SEG_NORMAL) [BFD_ASSEMBLER]: Require that the specified + section is not absolute, undefined, or an assembler internal one. + (absolute_section, undefined_section): Always define. + * expr.c, read.c, symbols.c: Refer to *_section, not SEG_*; break + switch statements into if-else trees. + * symbols.c [MANY_SEGMENTS]: Deleted redundant definitions of + SEG_BSS and SEG_DATA. + + * as.h (frag_now_fix): New macro. + * symbols.c (colon): Use it. + +Wed Jan 27 21:43:53 PST 1993 Ralph Campbell (ralphc@pyramid.com) + + * config/tc-mips.c: Added mips support for mips-dec-bsd. + * config/tc-mips.h: Added mips support for mips-dec-bsd. + * config/ho-mipsbsd.h: Added mips support for mips-dec-bsd. + * config/mips-opcode.h: Added mips support for mips-dec-bsd. + * configure.in: Added mips support for mips-dec-bsd. + * atof-generic.c: Define TRUE and FALSE if not defined. + +Thu Jan 21 12:48:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * version.c: Bumped version number to 1.93.05. + +Wed Jan 20 17:11:53 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/obj-coff.c (obj_emit_relocations): Don't use #elif. + (obj_emit_lineno): Don't need return at end of void function. + (obj_symbol_new_hook): Ditto. + + * config/tc-m68k.c: Removed some unused code. + (tc_aout_fix_to_chars): Array nbytes_r_length is now const. + + * config/tc-m68k.h (TC_COUNT_RELOC): Don't emit reloc if only + offset field is set. + +Fri Jan 8 05:44:49 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-sparc.c (sparc_ip): For %uhi and %ulo, if not + ENV64, emit no reloc. + (md_pseudo_table): For ".xword", call s_xword. + (s_xword): New function. + + * config/tc-sparc.c (architecture_requested, warn_on_bump, + md_relax_table): Use default zero initialization. + (s_reserve): Since SEG_E2 is equivalent to SEG_BSS, just use the + latter, instead of selecting with preprocessor conditionals. + +Thu Jan 7 08:58:21 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: recognise all sparclite variants + +Thu Jan 7 05:25:25 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * read.c (s_data) [!BFD_ASSEMBLER]: Fix typo in 4 Jan change -- + accidentally changed to use subseg_change where it should have + been subseg_new. + +Tue Jan 5 08:42:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * expr.c (operand): If character other than comma or newline is a + logical end-of-line character, use the newline case. + From Eric Youngdale: + (operand): Set X_add_number field for floating-point numbers. + (operand): Treat zero byte as end-of-operand. + + * configure.in (per-target): Look for with_bfd_assembler option. + For now, only accept "no", until the merge is done. + + Merged changes from Eric Youngdale (youngdale@v6550c.nrl.navy.mil): + * as.c, flonum-konst.c, hex-value.c, input-file.c, version.c, + config/obj-aout.h, config/obj-vms.c: VMS -> HO_VMS. + * read.c: Finish conversion to S_* macros in the VMS only + parts of the program. Add "const" modifier to hex_value. + * as.c, read.c, symbols.c, write.c: Change "ifdef VMS" to + "ifdef OBJ_VMS". + * expr.c: Add "const" modifier to hex_value. + * symbols.c: Finish conversion to S_* macros in the VMS only + parts of the program. Add "const" modifier to + md_[long,short]_jump_size. Remove declaration of const_flag + (which will be declared in obj-vms.h). + * write.c: Add "const" modifier to md_[long,short]_jump_size. + Fix arguments to VMS_write_object_file. + * config-gas.com: New file. Script for VMS systems to set up the + configuration to build gas for VMS, and create config.status. + * make-gas.com: Redone to work with new scheme. + * obj-vms.c: Patch to fix bug where we were not correctly parsing the + stabs directives. + * obj-vms.c: Define macros COPY_LONG and COPY_SHORT which + will swap bytes if needed on a big endian system. Use throughout + as needed. + * obj-vms.c (obj_aout_stab): Add code to generate listing file. + * obj-vms.c (VMS_typedef_parse): Add alias to correctly handle certain + types of malformed stabs. Change parsing algorithm so that we are + more certain of having all of the information that we need on hand. + * obj-vms.c (final_forward_reference): New function, used to help + resolve the data types of as many struct elements as possible + when some part of the struct is not fully defined by the compiler. + * obj-vms.c (VMS_LSYM_Parse): Correctly handle case of continuation + stabs directives. + * obj-vms.c (VMS_write_object_file): Define all vtable psects + as symbols as well in the object file. Look for external functions + that start with "__vt.", and turn them into variables, since the + g++ compiler is incapable of doing this. + * tc-vax.c: Add '1' option for backward compatibility with older GCC + versions. + * bignum-copy.c (bignum_copy): Fix bug where we pad with zeroes. + * input-scrub.c (as_where): Fix bug where as would crash if we did not + have the name of the source file yet. + * config/ho-vms.h: define HO_VMS, not HO_VAX. + +Mon Jan 4 05:17:26 1993 Ken Raeburn (raeburn@cygnus.com) + + * read.c (s_data): Always use "data_section", since it'll map to + SEG_DATA or SEG_E1 if needed. + (s_lcomm): Likewise with bss_section. + (s_fill): Use memset, not bzero. + +Thu Dec 31 04:29:27 1992 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * read.c: Deleted some code under "#ifdef DONTDEF" that was for + handling GDB symbol table data. + + * config/obj-aout.h (segment_name): Delete definition. + (seg_name): Delete declaration. + * config/obj-bout.h (segment_name, seg_name): Ditto. + * config/obj-vms.h (segment_name, seg_name): Ditto. + * config/obj-coff.h (segment_name): Ditto. + * config/obj-coffbfd.h (segment_name): Ditto. + + * Changes for BFD_ASSEMBLER: + * obj.h (obj_crawl_symbol_chain): Declare only if not + BFD_ASSEMBLER. + (obj_header_append, obj_pre_write_hook): Ditto. + * as.h (stdoutput): New var, defined only if BFD_ASSEMBLER. + (segT) [BFD_ASSEMBLER]: New typedef for "asection *". + (segment_name) If BFD_ASSEMBLER, look up BFD section name; + otherwise, use seg_name array. + (seg_name): Declare only if not BFD_ASSEMBLER. + (section_alignment): Declare only if not BFD_ASSEMBLER. + (big_section, reg_section, pass1_section, diff_section, + absent_section, text_section, data_section, bss_section): If + BFD_ASSEMBLER, declare as variables; otherwise, declare as macros, + mapping to segT enum values. + (tc_aout_fix_to_chars, next_object_file_charP): Force parse errors + if these are used or defined, if BFD_ASSEMBLER. + (subseg_set, subseg_new) [BFD_ASSEMBLER]: Functionality of old + subseg_new split into two functions. + (SEG_NORMAL): For BFD_ASSEMBLER, always return true, for now. + + * as.h (volatile): Don't define if already defined. + (had_errors, had_warnings): Provide prototypes for ANSI C even if + NO_STDARG. + (as_bad, as_fatal, as_tsktsk, as_warn): For GNU C version 2, + declare with format attribute for -Wformat checking. + +Wed Dec 30 10:18:57 1992 Ian Lance Taylor (ian@cygnus.com) + + * app.c, config/tc-*.c: Don't include read.h, since it is already + included by as.h. + + * These are based on patches from Minh Tran-le + . + * configure.in (i[34]86-ibm-aix*): Accept i486 for host. Use + obj_format coffbfd and gas_target i386coff for target. + (i[34]86-*-isc*): New host (uses sysv). + * config/i386aix.mt: Removed (no longer used). + * config/mh-i386aix (RANLIB): Use true rather than /bin/true. + (MINUS_G): Removed. + (LDFLAGS): Added, defined as -shlib. + * config/te-i386aix.h (REVERSE_SORT_RELOCS): Undefine. + * config/te-sco386.h (LOCAL_LABEL): Don't define. + (DOT_LABEL_PREFIX): Define. + * expr.c (operand): If DOT_LABEL_PREFIX, use .L0\001 as a label + name rather than L0\001. + * read.c (s_lcomm): Make a frag in SEG_BSS rather than using + local_bss_counter. + * symbols.c, symbols.h (local_bss_counter): Removed. + * write.c (write_object_file): bss no longer uses + local_bss_counter. Pass correct data and bss size to + VMS_write_object_file. + * config/obj-vms.c (VMS_write_object_file): Accept bss size as + argument, rather than using local_bss_counter. + * config/tc-m88k.c (s_bss): Don't use local_bss_counter. + * config/tc-sparc.c (s_reserve): Don't use local_bss_counter. + * config/obj-coffbfd.c (had_lineno, had_reloc): Removed. + (size_section): Restored sanity check. + (do_relocs_for): Base section address on s_paddr rather than + computing it. Adjust a29k R_IHIHALF special case to account for + section paddr (used to require paddr to be zero). If there are no + reclos, set s_relptr to 0. Set relocation size in object_headers. + (fill_section): Always set s_vaddr here, removing + ZERO_BASED_SEGMENTS case. Force s_scnptr for bss to 0. Don't set + NOLOAD for i386 .bss, because it confuses the SVR3 native linker. + Set STYP_INFO for .comment. + (coff_header_append): Use object headers and H_{SET,GET}_* macros. + Make aouthdr writing depend on OBJ_COFF_OMIT_OPTIONAL_HEADER. + (crawl_symbols): Handle 8 character section name correctly. Use + H_{SET,GET}_* macros. + (do_linenos_for): Set lineno size in object_headers. + (write_object_file): Use H_{SET,GET}_* macros. Don't bother to + set s_vaddr here. If string_byte_count remains 4, set it back to + 0, and only write strings out if there are some. Call + fill_section before do_relocs_for and do_linenos_for. + (obj_coff_section): Handle optional quoted second argument giving + section characteristics. + (obj_coff_bss): Added to handle .bss. + (obj_coff_ident): Added to handle .ident (puts string in .comment + section). + (obj_coff_lcomm): Put common symbols in .bss, not .data. + (fixup_mdeps): Change to segment. Call frag_wane after + md_convert_frag. + (fixup_segment): Explicitly check S_IS_COMMON before making 386 + adjustment (already happened only for common symbols, but this is + clearer). + * config/obj-coffbfd.h (OBJ_COFF_OMIT_OPTIONAL_HEADER): Define. + * config/tc-i386.c (s_bss): Don't use if I386COFF. + (md_pseudo_table): Ignore .optim and .noopt. + (tc_coff_sizemachdep): New function. + * config/tc-i386.h (REVERSE_SORT_RELOCS): Undef, for SVR3 + compatibility. + (LOCAL_LABEL): Removed definition. + (DOT_LABEL_PREFIX): Defined. + +Mon Dec 28 10:32:05 1992 Ken Raeburn (raeburn@cygnus.com) + + * app.c (app_push): Use memcpy, not bcopy. + (do_scrub_next_char): For \", return " not '. + (symbol_chars): Now const. + + * expr.c (operand): If not LOCAL_LABELS_FB, don't look for "0f" + and "0b". If LOCAL_LABELS_DOLLAR, check for "0$". + + * config/obj-coff.h: Don't use #elif. + + * config/ho-sunos.h: Don't include sys/stdtypes.h; 4.0.3 doesn't + have it. (Reported by Noah Friedman, friedman@gnu.ai.mit.edu.) + +Wed Dec 16 12:12:33 1992 Ian Lance Taylor (ian@cygnus.com) + + * write.c, obj-ieee.c: don't define SUB_SEGMENT_ALIGN if it is + already defined. + +Tue Dec 15 12:40:11 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * app.c (do_scrub_begin): allow single quote strings if so + configured. + + * config/*z8k*: checkpoint + +Sun Dec 13 00:04:38 1992 Ian Lance Taylor (ian@cygnus.com) + + * read.c (read_a_source_file): avoid calling xmalloc (0). + +Sat Dec 12 15:26:34 1992 Ian Lance Taylor (ian@cygnus.com) + + * listing.c: Call xmalloc, not malloc; don't declare malloc. + + * Changes to support SCO 3.2v4: + * read.c (s_align_bytes, s_align_ptwo): If not SEG_DATA or + SEG_BSS, fill with NOP_OPCODE. + * config/i386coff.mt: Add opcode/i386.h to TARG_CPU_DEPENDENTS. + * config/obj-coffbfd.c (do_relocs_for): Increment addr even if not + using ZERO_BASED_SEGMENTS. + (fill_section): If ZERO_BASED_SEGMENTS, set segment addresses, but + never set segment address for SEG_E2 (.bss) and don't write out + SEG_E2 contents. Set .init and .fini sections to STYP_TEXT. + (obj_coff_endef): Don't merge labels or symbols awaiting forward + definitions, and don't merge tags with non-tags. Check for .bf + rather than just checking whether the second character is b and + the third character is f. + (obj_coff_val): gcc can generate values which we don't handle + correctly; discard information for now, since it only affects the + debugging information. + (tag_find_or_name): Don't insert tags in the symbol table. + (yank_symbols): Don't merge labels. + (write_object_file): Don't define SUB_SEGMENT_ALIGN if it is + already defined. Fill subsegments with NOP_OPCODE, not 0. Don't + set segment address if ZERO_BASED_SEGMENTS. + (obj_coff_section): Accept and ignore a trailing quoted string, as + used in AT&T i386 syntax. + (fixup_segment): Take segment as argument. On the i386, adjust PC + relative addends by the segment vaddr. + * tc-i386.h: Define SUB_SEGMENT_ALIGN. + * tc-a29k.h: Define ZERO_BASED_SEGMENTS. + * tc-i386.c: (i386_operand): If I386COFF, accept any segment type. + +Tue Dec 8 00:06:48 1992 Ken Raeburn (raeburn@rtl.cygnus.com) + + * config/obj-coffbfd.c: Include libcoff.h. + + * version.c: Now version 1.93. + +Mon Dec 7 00:39:09 1992 Ken Raeburn (raeburn@cygnus.com) + + * config/tc-i386.c (md_pseudo_table): For 386bsd and linux, do + power-of-two alignment for .align. + + * as.h: If BROKEN_ASSERT, just redefine `assert' to be trivial, + and leave everything else alone. + +Fri Dec 4 16:58:42 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * Makefile.in (as.new): Don't bother saving as.old. + + * write.c: Conditionalize on OBJ_VMS, not VMS. + (magic_number_for_object_file): Don't define if OBJ_VMS. + + * config/obj-vms.c: Changes for traditional C. + +Thu Dec 3 01:24:07 1992 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * config/ho-generic.h (malloc, realloc): Declare. + + * Lots of comment/whitespace changes. + + * write.h (struct fix): Some fields reordered, narrowed. + + * read.c (MASK_CHAR): Define using C types, not magic number. + + * as.c, input-file.c: Deleted some unused code. + + * app.c, as.h: Doc fix. + + * flonum-konst.c, flonum-mult.c: Include ansidecl.h. + + * as.h (xmalloc): Argument is long. + + * xmalloc.c (error): Remove declaration; as.h takes care of it. + + * doc/as.texinfo: Regrouped documentation of some command-line + options. Updated options documentation for m68k. Some minor + wording/punctuation changes. + +Mon Nov 30 11:42:11 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * configure.in: Accept target OS "vms". + + * symbols.c: Merged ANSI and non-ANSI function decls, using + PARAMS macro. + + * xmalloc.c: Just include as.h, don't bother trying to figure out + other header files. + + * strstr.c, strerror.c: Deleted. + * Makefile.in: Deleted references. + + * config/tc-ns32k.c: Don't include header file for string + declarations; leave that to ho-*.h. + +Fri Nov 27 04:11:36 1992 Ken Raeburn (raeburn at cambridge-laptop.cygnus.com) + + * config/coff_gnu.h [TC_I860]: Guesses for reloc type values, + imported from FSF sources. + + * messages.c (strerror): Declare unconditionally. + + * as.h: Delete alloca and register definitions. + + * config/atof-ieee.c (mask): Now const. + + * obstack.c, obstack.h: Deleted. + + * as.h (flag_readonly_data_in_text): New flag. + * as.c (main): Set it for -R. + + * as.h (flag_suppress_warnings): New flag. + * as.c (main): Set it for -W. + * messages.c (as_warn): Check it instead of flagseen['W']. + + * as.h (flag_always_generate_output): New flag. + * as.c (main): Set it for -Z. + + * config/tc-sparc.h: Define NEED_FX_R_TYPE. + * config/tc-a29k.h: Ditto. + * write.h (struct fix): Don't conditionalize fx_r_type field on TC + macros. + + * as.h: Merged ANSI and non-ANSI function decls, using PARAMS + macro. + * bignum.h, expr.h, flonum.h, frags.h, input-file.h, listing.h, + obj.h, output-file.h, read.h, struc-symbol.h, symbols.h, tc.h, + write.h: Likewise. + * read.c: Likewise. + + * xmalloc.c: Conditionalize on HAVE_MALLOC_H, not USG. Fold in + xrealloc from xrealloc.c. + * xrealloc.c: Deleted. + * Makefile.in (REAL_SOURCES, OBJS): Adjusted. + + * configure.in: For host CPU a29k, rs6000, vax, consider using bsd + or vms ho- files. + + * config/ho-sysv.h (setbuffer, HO_USG): Deleted. + + * config/atof-ieee.c (atof_ieee): Exponent field isn't a pointer; + don't initialize it with NULL. + + * config/ho-vax.h (M_VAX): Deleted; was unused. + + * README-vms, config/ho-vms.h, config/obj-vms.c, config/obj-vms.h: + New files imported from FSF version, contributed by Eric Youngdale. + * README-vms-dbg, config/vms: Deleted. + + * ChangeLog, config/ChangeLog: Merged. + + * config/*tahoe*, configure.in: Tahoe support brought in from FSF + version. + + * input-file.c (input_file_open): Eliminate call to setvbuf. + [USG] (setbuffer): Deleted macro. + +Mon Nov 23 11:00:16 1992 Ken Raeburn (raeburn@cygnus.com) + + * all files: Whitespace changes for GNU indentation style, done by + GNU `indent'. Some cleanup still needed, especially of comments. + + * configure.in: No te-386bsd.h file exists; don't try to use it. + + * obj-coff.c (obj_coff_endef): Use as_warn, not fprintf. + + * tc-m68k.c (md_assemble): Don't complain about 68000 with 68881; + could be doing emulation. + +Thu Nov 19 11:47:19 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + z8000 documentation + * doc/Makefile.in, doc/all.m4, doc/as-all.texinfo, doc/as.texinfo: + all modified. + +Tue Nov 10 09:49:24 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (as.o, obj-format.o): added dependency on subsegs.h. + + * subsegs.h: add extern to segment_info declaration. + + * read.h: added extern declarations for comment_chars, + line_comment_chars, and line_separator_chars. + read.c, app.c: removed definitions of comment_chars, + line_comment_chars, and line_separator_chars. + + * tc-m68k.c (m68k_reg_parse): If REGISTER_PREFIX isn't defined, + still accept (but don't require) OPTIONAL_REGISTER_PREFIX before + the register name. + (insert_reg): put REGISTER_PREFIX before register names before + putting them in the symbol table. + * tc-m68k.h (OPTIONAL_REGISTER_PREFIX): Define to be "%", if not + M68KCOFF. + + * obj-coffbfd.c (fill_section): set STYP_NOLOAD bit for .bss + section. + + * atof-ieee.c, atof-ns32k.c, tc-*.c: made EXP_CHARS, FLT_CHARS, + comment_chars, line_comment_chars and line_seperator_chars + consistently const, and always initialized them. Included read.h. + +Thu Nov 5 17:55:41 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * tc-sparc.c (sparc_ip): Add code to flag error if an absolute + constant will not fit in an immediate field. + (md_apply_fix, RELOC_BASE13 case): Check for relocation overflow. + +Wed Nov 4 07:50:46 1992 Ken Raeburn (raeburn@cygnus.com) + + * obj-coff.c (callj_table): Delete global variable. + (obj_emit_relocations): Define it locally here, and only if + TC_I960 is defined. + + * tc-m68k.c (m68k_reg_parse): Underscore is part of a symbol name. + (m68k_ip): Don't warn about bignum used as float bit-pattern. + + * obj-coff.c: Replaced ANSI and non-ANSI function declarations + with a single set using PARAMS macro. + + * tc-i960.c (tc_bout_fix_to_chars): Bit-field fixups want a length + of 2. + + * tc-i960.c: Missed a couple of 0->NO_RELOC conversions. + + * tc-i960.h (N_BALNAME, N_CALLNAME): Define as char-type values, + so widening works consistently. + +Wed Oct 28 08:52:34 1992 Ken Raeburn (raeburn@cygnus.com) + + * version.c: Put conditional "const" before version_string, not + before dummy function for VMS. Now version 1.91.03. + + * app.c (do_scrub_next_char): Need double-\ before `000' to show + printed rep of null character. + +Fri Oct 23 14:40:38 1992 Ian Lance Taylor (ian@cygnus.com) + + * obj-coffbfd.c (write_object_file): check return value of + bfd_close_all_done. + +Tue Oct 20 12:18:08 1992 Ian Lance Taylor (ian@cygnus.com) + + * Support for i386-sysv. + obj-coffbfd.c (do_relocs_for, write_object_file): set segment + addresses to reasonable sizes. New define ZERO_BASED_SEGMENTS can + be used to set them all to zero as was done before. + (fill_section): segment addresses now set in write_object_file. + (fill_section): Don't set STYP_NOLOAD for .bss section. + (fixup_segment): 386 uses strange common symbol format. + tc-i386.c (tc_coff_fix2rtype): use R_DIR32, not R_RELLONG, for + compatibility with SVR3.2 linker. + * configure.in: i386-sysv and i386-sco use coffbfd. + + * app.c (do_scrub_next_char): discard whitespace after a label. + +Sat Oct 10 12:33:45 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: differentiate between SunOS 4 and Solaris2 for Sun4 + hosts, use the sysv configuration for solaris2 + +Mon Oct 5 09:28:57 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + fix i960+non-bfd coff bit rot. + * obj-coff.c (c_dot_file_symbol, obj_coff_ln, obj_coff_line): + support for C source listings. (obj_coff_endef): look in the right + part of the symbol for the symbol name + + * tc-m68k.c (get_num): make it work for all segments, not just the + first three. + +Mon Oct 5 03:30:36 1992 Mark Eichin (eichin at tweedledumber.cygnus.com) + + * configure.in: recognize i386-*-bsd emulation. + +Thu Oct 1 23:05:12 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: use the cpu-vendor-os triple for host and target + +Tue Sep 29 12:22:52 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * obj-coffbfd.c (write_object_file): don't fixup for the z8k + * tc-z8k.c: lots of bug fixes + +Tue Sep 29 10:51:55 1992 Ian Lance Taylor (ian@cygnus.com) + + * tc-i960.h, tc-i960.c: avoid the ANSI preprocessor addition + #elif, since it is not supported by old compilers. + ho-rs6000.h, tc-m68k.c: the native RS/6000 compiler miscompiles a + couple of expressions in tc-m68k.c. + +Mon Sep 28 21:18:24 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * read.c (cons): If NO_RELOC is defined, use it. + + * tc-i960.c (get_cdisp): Use NO_RELOC, not 0, in call to fix_new. + +Fri Sep 25 18:18:52 1992 Ian Lance Taylor (ian@cygnus.com) + + * tc-m68k.h: if M68KCOFF, define DOT_LABEL_PREFIX (to require + local labels to start with a .) and set REGISTER_PREFIX to %. + tc-m68k.c (m68k_reg_parse): accept REGISTER_PREFIX if defined. + +Fri Sep 25 17:53:43 1992 John Gilmore (gnu@cygnus.com) + + * messages.c: Comment changes. + +Fri Sep 25 14:12:58 1992 Ken Raeburn (raeburn@kyriath.cygnus.com) + + * as.h: Test if __STDC__ is defined only, don't test its value. + * messages.c: If __STDC__ is not defined, define NO_STDARG. + +Thu Sep 24 12:42:32 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * listing.c (debugging_pseudo): Add stabs and stabn as things to + ignore. + +Tue Sep 22 13:02:07 1992 Sean Eric Fagan (sef@cygnus.com) + + * obj-coffbfd.c (do_relocs_for,fill_section): now allocate all + sections starting from zero, rather than making them consecutive. + This makes subsequent reloc calculations easier, esp if the object + format doesn't understand addends. (obj_coff_lcomm): (maybe temporarily) + allocate lcomm in .data rather than in .bss. It seems that some + tools can't cope with a non-zero sized bss before linkage. + +Tue Sep 22 15:10:51 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * tc-m68k.c: Replace "enum m68k_architecture" with "int" + throughout. That enum no longer means what we thought it meant. + + * tc-m68k.c (md_assemble, md_parse_option): Handle new + "-mno-688[58]1" options. + + * tc-m68k.c: Added CPU32 support. + +Fri Sep 18 08:02:18 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * tc-m68k.c (m68k_ip): An(disp) is not pc relative. + +Tue Sep 15 17:25:05 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * Makefile.in (as.new): Remove dependence on LOCAL_LOADLIBES. + Change LIBDEPS dependence to LIBS. + +Tue Sep 15 15:32:02 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (install): if $(tooldir) exists, install as in + $(tooldir)/bin. + +Sun Sep 13 20:30:10 1992 Ian Lance Taylor (ian@cygnus.com) + + * Added WARN_SIGNED_OVERFLOW_WORD define to give an error if any + .word is < -32768 or > 32767. The -J flag causes the error to be + ignored. This is to catch over-sized switches generated by gcc on + systems which don't support the broken .word hack. + as.c (main): permit -J if WARN_SIGNED_OVERFLOW_WORD. + write.c (fixup_segment): check for signed .word overflow if + WARN_SIGNED_OVERFLOW_WORD. + + * write.c (fixup_segment): fixed missing parens in expression + checking for byte or word overflow. + + * obj-coffbfd.h: define WARN_SIGNED_OVERFLOW_WORD. + obj-coffbfd.c (fixup_segment): check for signed .word overflow if + WARN_SIGNED_OVERFLOW_WORD. + + * obj-coffbfd.c (fixup_segment): fixed missing parens in + expression checking for byte or word overflow. + +Fri Sep 11 10:21:04 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + Support for i386 coff + * obj-coffbfd.h : added stuff + * tc-i386.c (tc_coff_fix2rtype): new function + * tc-i386.h : new coff defines + +Thu Sep 10 09:23:15 1992 Ian Lance Taylor (ian@cygnus.com) + + * input-scrub.c (input_scrub_push): call input_file_begin, not + input_scrub_begin. + messages.c (as_perror): print ": " between the passed in error and + the strerror, like perror does. + +Wed Sep 9 11:06:25 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in: use gas_target instead of modifying target_cpu. + From Steve Chamberlain: + Makefile.in: Handle m68*-*-coff*. + read.c, read.h: add mult argument to s_space + + * tc-m68k.c (m68k_ip, m68k_ip_op, get_num, try_moto_index): merge + Motorola and MIT syntax; gas can now assemble either type of + file. + tc-m68kmote.c, tc-m68kmote.h: removed now superfluous files. + From Steve Chamberlain: + m68kcoff.mt: for m68k COFF. + obj-coffbfd.c: (fixup_mdeps) added + (size_section) removed bad sanity check + (fill_section) added rs_machine_dependent case + (write_object_file) call fixup_mdeps + (fixup_segment) set fx_subsy to 0. + obj-coffbfd.h: define WORKING_DOT_WORD (too hard to support) and + handle m68k. + tc-m68k.c, config/tc-m68k.h: added m68k COFF support and Motorala + pseudo ops. + +Tue Sep 8 17:10:58 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * Makefile.in (LIBS): Include opcode library. + +Fri Sep 4 18:20:56 1992 Ken Raeburn (raeburn@cygnus.com) + + * config/tc-m68k.c (get_num, case SEG_BIG): If only small integers + including zero are accepted, pass +0.0. + +Sun Aug 30 21:24:46 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in: map "as" through program_transform_name when + installing. + + * doc/Makefile.in: map "as" through program_transform_name when + installing. + +Sat Aug 29 12:11:12 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * Makefile.in (as.new): Depend on LOCAL_LOADLIBES. + +Fri Aug 28 16:25:22 1992 Ian Lance Taylor (ian@cygnus.com) + + * obj-bout.h, obj-bout.c (obj_header_append, obj_symbol_to_chars), + tc-i960.c (md_ri_to_chars): Always output bout object file in + little endian byte order (used to use endianness of host). + +Tue Aug 25 15:50:48 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * config/tc-m68k.c (init_table): Now const. Always include 68851 + data, so that "bc" is available to 68040 cache instructions. + Added "tt0", "tt1", and 68ec030 variants. + (md_assemble): Complain if 68000 (only) and 68881 are specified. + (enum _register): Added TT0, TT1. + (m68k_ip, cases '3' and 't'): Handle new operand type codes. Pass + line number correctly in "internal error" messages. Don't print + architecture-mismatch message for operand errors. + + From Colin Smith (colin@wrs.com): + * config/tc-m68k.c (m68k_ip, case '_'): Use addword twice rather + than install_operand. + +Tue Aug 25 15:13:48 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * listing.c (buffer_line): rewind to the start of include + files, they might be included twice. + + * z8k.c, z8k.h, z8k.mt: z8000 support stuff + +Mon Aug 24 12:45:43 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in: defined TARGET_CPU for C code so that it can choose + one element of a family. + + * tc-m68k.c: use TARGET_CPU to choose default cpu type. + + * te-generic.h: default to LOCAL_LABELS_DOLLAR and LOCAL_LABELS_FB + so that we can assemble hand-written libgcc code. + +Fri Aug 21 14:38:44 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * messages.c (as_warn): Use fputs, not fprintf, with a buffer that + has already been formatted (but may still contain %-characters). + (as_bad): Likewise. + +Wed Aug 19 11:20:59 1992 Ian Lance Taylor (ian@cygnus.com) + + * tc-m68k.c, tc-m68kmote.c: 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 '(' to notend stuff in + tc-m68kmote.c to accept (a0):(a2) in cas2 instruction. + +Wed Aug 19 09:25:09 1992 Ken Raeburn (raeburn@cygnus.com) + + * as.h (enum _relax_state): Start off at one, not zero, to better + catch uninitialized-variable errors. + (linkrelax): Declare new variable. + + * messages.c (warning_count, error_count): Default initializer is + sufficient. + + * write.c: Merged some declarations, using PARMS macro. + (text_frag_root, data_frag_root, bss_frag_root, text_last_frag, + data_last_frag): No longer static. + (write_object_file, case rs_align or rs_org): If HANDLE_ALIGN is + defined, call it. Change segments before calling fixup_segment. + (relax_align): If linkrelax, provide extra padding. + + * obj-bout.c (obj_emit_relocations): Emit alignment relocs despite + their not having symbols associated. + + * tc-i960.c (norelax, instrument_branches): Default initializer is + sufficient. + (linkrelax): Delete variable definition. + (mem_fmt): Call fix_new with NO_RELOC. + (tc_bout_fix_to_chars): Handle alignment relocs. + (i960_handle_align): New function. + * tc-i960.h (linkrelax): Delete declaration. + (HANDLE_ALIGN): New macro; calls i960_handle_align. + (NEED_FX_R_TYPE, NO_RELOC): New macros. + +Tue Aug 18 14:59:21 1992 Ken Raeburn (raeburn@cygnus.com) + + * config/sparc.mt: New file. Grab sparc opcode table from bfd + library. + +Tue Aug 18 14:16:38 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in: always create installation directories. Removed + MINUS_G, set CFLAGS to default to -g, added FLAGS_TO_PASS, passed + FLAGS_TO_PASS to recursive makes. + + * doc/Makefile.in: always create installation directories. + +Mon Aug 17 15:09:56 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * input-scrub.c (input_scrub_pop, input_scrub_push): memcpy was + being used with args swapped, causing occasional lossage when + refilling buffers after an include file. + +Mon Aug 17 13:18:51 1992 Ken Raeburn (raeburn@cygnus.com) + + * messages.c (as_tsktsk): Use correct ANSI form for stdarg + version. Discard bogus DONTDEF version. + (as_warn, as_bad, as_fatal): Likewise. + +Fri Aug 14 18:31:14 1992 Ken Raeburn (raeburn@cygnus.com) + + * config/tc-m68k.c (m68k_ip): If instruction is invalid for the + selected architecture, print a message saying so and listing what + processors support it, rather than saying "operands mismatch". + +Thu Aug 13 13:53:19 1992 Ken Raeburn (raeburn@cygnus.com) + + * as.h [BROKEN_ASSERT]: If defined, turn off all assertion checks. + + * config/ho-rs6000.h (M_RS6000): Don't define it. + (free): Declare it. + (BROKEN_ASSERT): Define it if not __STDC__. + +Tue Aug 11 12:58:14 1992 Ken Raeburn (raeburn@cygnus.com) + + * sparc.mt: New file. + +Mon Aug 10 14:37:08 1992 Per Bothner (bothner@cygnus.com) + + * tc-m68k.c: ".align N" means align to N-byte boundary *only* + if TN_SUN3; otherwise align to 2**N-byte bounary. + +Thu Aug 6 12:10:39 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * read.c (s_fill): make the .fill size clamped error a warn and + fix bug where 0's were always placed. + + * config/tc-h8300.c: if a :8 is seen after an operand, fill top + two bytes of any constant with 0xff: + +Wed Aug 5 12:02:40 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * config/tc-m68k.c (md_pseudo_table): fix the .align thing + the right way; for just the 68k. Sun 3 .align is nbytes, not ptwo. + +Wed Aug 5 01:54:34 1992 John Gilmore (gnu at cygnus.com) + + * tc-m68k.c (try_index): Error if index scaling specified and + assembling for an older CPU than a 68020. + +Sat Aug 1 19:10:13 1992 Ken Raeburn (raeburn@cygnus.com) + + * config/tc-sparc.c (tc_aout_fix_to_chars): If pc-relative, take + fx_offset into account. + +Fri Jul 31 21:53:28 1992 Ken Raeburn (raeburn@cygnus.com) + + * configure.in (mips host): Accept "ultrix" with version number. + + * expr.c (floating_constant): Separate "=-" to avoid confusing + ancient or broken compilers. + + * config/tc-m68k.c (m68k_ip): Mismatch error could also indicate + processor/opcode mismatch, so reword the error message. + (md_assemble): If no CPU has been set (even if FPU/PMMU + characteristics have been), default to 68020. Don't need extra + quotes around error string. + +Fri Jul 31 12:26:34 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * read.c (potable): Revert sac's incorrect change made Jul 13. + Align really is supposed to be ptwo not nbytes. + +Mon Jul 20 02:51:59 1992 D. V. Henkel-Wallace (gumby@cygnus.com) + + * Makefile.in: _Do_ include libiberty. (from sef) + +Fri Jul 17 15:15:28 1992 Ken Raeburn (raeburn@cygnus.com) + + * expr.c (integer_constant): Handle "0f" and "0b" label references + properly. + +Thu Jul 16 08:20:17 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * write.c (fixup_segment): if relaxing, don't do anything. + * config/obj-bout.[ch] : maintain the a_relaxable file header info + * config/tc-i960.c: new option -linkrelax + +Mon Jul 13 14:11:36 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * expr.c (expr): allow SEG_BSS in expressions + * read.c (potable): align should be nbytes, not ptwo! + * write.c (write_object_file): extra glue for new bss attributes + (relax_segment): SEG_BSS is ok now + * config/tc-m68k.c (m68k_ip_op): can now parse more @( modes + +Mon Jul 6 17:09:32 1992 Steve Chamberlain (sac@cygnus.com) + + * obj-coffbfd.c (fill_section): mark .lit sections as STYP_LIT + +Mon Jun 1 16:20:22 1992 Michael Tiemann (tiemann@cygnus.com) + + * configure.in: recognize m680x0 as having sun3 emulation mode for + vxworks environment. + + +Tue Jun 30 20:25:54 1992 D. V. Henkel-Wallace (gumby@cygnus.com) + + * Makefile.in: Add program_suffix (parallel to program_prefix) + +Wed Jun 24 10:57:54 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * app.c (process_escape): new function to handle escapes the right + way, (do_scrub_next_char): use new function + * cond.c (s_ifdef): do ifdef/ifndef right + * read.c (s_fill): make the , expressions optional like the doc + says + * config/tc-h8300.[ch]: better warnings + +Tue Jun 9 07:54:54 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * subsegs.c (subsegs_begin): create bss0_frchainP in the same was + as data0_frchainP + + * write.c (write_object_file): various changes to handle data in + the BSS segment in much the same was as stuff in the DATA segment. + + * tc-m68k.c (m68kip): Fix typo so that only arch's >=68020 do + pcrel data stuff. (md_estimate_size_before_relax): when relaxing a + 68010 bxx into a bra+6 jmpxx, put the bytes of the jmp opcode into + the right place. (s_bss): Don't put .bss stuff into SEG_DATA, put + it into SEG_BSS + +Thu Jun 4 11:59:13 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * expr.c(expr): allow SEG_REGISTER in expressions. + * read.c(pseudo_set): register expressions can be the source of a + set. + * subsegs.c (subseg_new): Now -R forces all changes to SEG_DATA to + goto SEG_TEXT (if a.out) + * write.c (write_object_file): If a.out don't use the old way for + -R. + * config/obj-a.out (s_sect): complain if the user tries to use a + subsegment with a value which might interfere with out -R hackery. + * config/tc-m68k.c (m68k_reg_parse): lookup names in symbol table + rather than use ugly if tree. (init_regtable): insert register + names into symbol table. + +Tue Jun 2 16:47:09 1992 Steve Chamberlain (sac@cygnus.com) + + * write.c (write_object_file): keep the fix_tail clean, which + fixes a bug in -R where relocations were being lost. + +Mon Jun 1 16:20:22 1992 Michael Tiemann (tiemann@cygnus.com) + + * configure.in: recognize m680x0 as having sun3 emulation mode for + vxworks environment. + +Sun May 31 05:33:00 1992 david d `zoo' zuhn (zoo@cygnus.com) + + * configure.in: recognize m680x0 as an m68k + +Thu May 28 11:22:02 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * configure.in: Recognize sparclite as a sparc variant. + + * tc-sparc.c: Use new ARCHITECTURES_CONFLICT_P macro. Mention new + -Asparclite flag. + +Tue May 26 16:47:56 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * config/tc-a29k.c: lint + * listing.c, expr.c: patches from Andrew Smith + +Thu May 14 17:22:48 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * doc/Makefile.in: use m4 rather than gm4. + +Mon May 4 18:56:19 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * obj-coffbfd.c: use is a synonym for section, (do_relocs_for): + calc the base of relocs correctly. + * tc-a29k.c (parse_operand): allow expressions to be in any section. + +Mon Apr 27 13:13:31 1992 K. Richard Pixley (rich@cygnus.com) + + * as.c, write.c: use -K rather than -k for the broken word warning + option. + +Tue Apr 21 13:35:30 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: do not print recursion lines. + +Wed Apr 15 21:19:31 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: the tooldir copy of gas goes directly in tooldir. + +Tue Apr 14 14:50:22 1992 Ken Raeburn (Raeburn@Cygnus.COM) + + * write.c (write_object_file): For b.out format, round up section + start addresses to match required alignment. + +Thu Apr 9 05:45:29 1992 Ken Raeburn (Raeburn@Cygnus.COM) + + * Makefile.in (install): Install into $(tooldir)/bin, since that's + where gcc looks for it. + +Tue Apr 7 15:12:15 1992 Sean Eric Fagan (sef@cygnus.com) + + * Makefile.in: Changed some lines to be less confusing for some + makes. + + * input-file.c: Conditionalize on _IOFBF, not VMS. + + * read.c, write.c: Change a series of ifdef/elif to + ifdef/else/ifdef etc. + +Fri Mar 27 12:21:16 1992 K. Richard Pixley (rich@cygnus.com) + + * symbols.c (fb_label_init): fix sizeof to memset. + +Fri Mar 13 15:45:44 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: install the man page. + + * Makefile.in: pass down MAKEINFO explicitly on info. + + * doc/Makefile.in: use $(MAKEINFO) not makeinfo. + +Fri Mar 13 08:03:03 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * flonum-const.c: renamed flonum-konst.c to stop dos name + conflict. + +Thu Mar 12 04:42:38 1992 K. Richard Pixley (rich@cygnus.com) + + * tc-m68k.h, te-sun3.h: moved LOCAL_LABELS_FB definition from + tc-m68k.h to te-sun3.h. + +Wed Mar 11 23:32:42 1992 K. Richard Pixley (rich@cygnus.com) + + * configure.in: vxworks68 gets te-sun3.h. + + * expr.c: remove limitation that local_labels_dollar or + local_labels_fb must be < 10. + + * symbols.c: remove local_labels_dollar, replace with a function + interface for a sparse array. All users adjusted. + + * te-sun3.h: add LOCAL_LABELS_DOLLAR. + +Sat Mar 7 00:06:25 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * doc/Makefile.in: commented out line for building as-all.texinfo. + This is temporary. + + * doc/as.texinfo, doc/as-all.texinfo: added menu item hooks. + +Fri Mar 6 21:57:18 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: added check target. + +Tue Mar 3 15:45:56 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: added tooldir and program_prefix. + +Sun Mar 1 04:43:19 1992 Michael Tiemann (tiemann@cygnus.com) + + * write.{c,h} (fix_new): Make these declarations consistent. + +Sat Feb 29 13:59:10 1992 Michael Tiemann (tiemann@cygnus.com) + + * Makefile.in (strerror.o): Add rule so that broken Sun make can + work in subdirs. + +Wed Feb 26 19:26:28 1992 Steve Chamberlain (sac at thepub.cygnus.com) + + * read.c, obj-coffbfd.c : fix h8300 specific bit rot + + * expr.c (operand): if can't work out what sort of operand it is, + then look through FLT_CHARS for a hint. + +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. + + * doc/Makefile.in, doc/configure.in: removed traces of namesubdir, + -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced + copyrights to '92, changed some from Cygnus to FSF. + +Tue Feb 25 14:17:15 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * expr.c: If an expression is single comma, then return with + SEG_ABSENT rather than an error - since the sparc front end does + really strange things with things like fbge,a + + * as.h: include bfd.h if using many sections + * expr.c: LOCAL_LABELS_FB had been changed to lower case - so + local labels didn't work. + * listing.c (list_symbol_table): don't core dump when there's no + symbol there. + * write.c, write.h: call fix_new with the right number of args on + the H8. + * config/tc-h8300.[ch] : fix bugs reported by HMSI, and make + errors nices + +Sat Feb 22 12:26:28 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * app.c: MRI compatibility - allow single quote to start a string. + * as.c: fix typo recently introduced. + * as.h : Don't include aout/reloc.h - it's not right for COFF! + * expr.c: Much rewriting, to accomodate MRI syntax for + expressions. Also easier to read now. + * listing.c: Put back defuns + * read.c: modified to accept MRI syntax, put back listing pseudo + ops so that an assembler built with NO_LISTING ignores list ops + rather than pukes. + * write.c, write.h: fixs - only keep a reloc type in a fix if the target + machine is a SPARC or a 29K. + * config/obj-aout.c: added s_sect pseudo op + * config/obj-coffbfd.c: lints, set the filehdr flags right and + fill in the timestamp. + * config/obj-coffbfd.h: Since we don't include aout/reloc.h + anymore, define all the relocs which the tc- bit will use so we + can translate from them to the coff types. + * config/tc-a29k.c: reloc_type isn't ane enum any more + * config/tc-m68k.c: Added NO_RELOC definition. + +Fri Feb 21 06:21:07 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: put header files before C source for TAGS; remove + references to non-existent syscalls.h. + + * read.c, write.c subsegs.c: back out the .bss changes. + + * obj-aout.c: do not include stab.gnu.h if NO_LISTING. + + * tc-i860.c, a.out.gnu.h: move i860 relocs to a proper place. + + * a.out.h: removed. + +Fri Feb 21 01:08:48 1992 Minh Tran-Le (TRANLE@INTELLICORP.COM) + + * symbols.c (local_label_name): symbols now start with ^A. + + * read.c, subsegs.c, write.c obj-coff.c: added handling of + `.bss` pseudo op for unitialized data. The new gcc (1.37.9x) + generate these sections. .align: will use NOP_OPCODE or 0 + for padding. This is just for being nice to the + disassembler. + + * expr.c (operand): changed to generate local label "\001L0" + starting with a ^A so that it is recognized as a local label. + + * as.c (perform_an_assembly_pass): zero bss_fix_root, too. + + * tc-i386.c: tc-i386.c: added handling of the following opcodes: + i/o opcodes - inb, inw, outb and outw. string manipulation with + att syntax - scmp, slod, smov, ssca, ssto. + + * obj-coff.c: (for aix386) Moved the symbols .text, .data and .bss + to just after .file . + + In obj_crawl_symbol_chain() where it tries to put the external + symbols apart, with the condition: + (!S_IS_DEFINED(symbolP) && + !S_IS_DEBUG(symbolP) && + !SF_GET_STATICS(symbolP)) + it was moving too many symbols out. So I switch it back to the + condition: + (S_GET_STORAGE_CLASS(symbolP) == C_EXT && !SF_GET_FUNCTION(symbolP)) + + In obj_emit_relocations() added the conditional on KEEP_RELOC_INFO + so that we don't use the F_RELFLG which make the linker complain + that somebody has stripped the relocation info. + + Also, the AIX ld program require that the relocation table + is sorted by r_vaddr like the standard ATT assembler does. + + [he also changed the sizeof(struct ...)'s into the coff + style FOOSZ macros. I'm not sure this is right, but I can't + remember why. xoxorich.] + +Fri Feb 21 01:08:48 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in, configure.in, doc: use the doc. Build it, install + it, clean it, etc. + +Tue Feb 18 02:21:25 1992 K. Richard Pixley (rich at cygnus.com) + + * read.c: white space and comments only. + + * configure.in: use the new atof-ns32.c for ns32k. + + * write.c: comment change only. + + * tc-m88k.[hc]: pulled in from hack's unfinished work. These + aren't yet integrated. + + * tc-i860.[hc]: blew off the dust. Something must still be done + about conflicting relocation types. + + * tc-ns32k.c: Replaced previous tc_aout_fix_to_chars stub with the + real thing. + + * tc-i960.c, tc-sparc.c: white space and comments only. + + * tc-a29k.h: delete duplicate macro definition. + + * new file atof-ns32k.c copied from hack's last unreleased gas. + +Mon Feb 17 07:51:06 1992 K. Richard Pixley (rich at cygnus.com) + + * config/tc-ns32k.c: actually make tc_aout_fix_to_chars work + rather than abort. + + * nearly everything. flush ChangeLog, package as gas-1.92.1. + ChangeLog's prior to this are sketchy at best. I have logs. + They just aren't ChangeLogs. diff --git a/gnu/usr.bin/binutils/gas/Makefile.in b/gnu/usr.bin/binutils/gas/Makefile.in new file mode 100644 index 00000000000..805d5cc3baf --- /dev/null +++ b/gnu/usr.bin/binutils/gas/Makefile.in @@ -0,0 +1,545 @@ +# Makefile for GNU Assembler +# Copyright (C) 1987-1992, 1993 Free Software Foundation, Inc. + +# This file is part of GNU GAS. + +# GNU 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 2, or (at your option) +# any later version. + +# GNU 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 GNU GAS; see the file COPYING. If not, write to +# the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# The targets for external use include: +# all, doc, proto, install, uninstall, includes, TAGS, +# clean, mostlyclean, distclean, realclean, stage1, stage2, stage3, stage4. + +# Variables that exist for you to override. +# See below for how to change them for certain systems. + +VPATH = @srcdir@ +srcdir = @srcdir@ +srcroot = $(srcdir)/.. + +target_alias = @target_alias@ +prefix = @prefix@ + +program_transform_name = @program_transform_name@ +exec_prefix = @exec_prefix@ +bindir = $(exec_prefix)/bin +libdir = $(exec_prefix)/lib +tooldir = $(exec_prefix)/$(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 + +VERSION=2.6 + +SHELL = /bin/sh + +INSTALL = $${srcroot}/install.sh -c +INSTALL_PROGRAM = $(INSTALL) +INSTALL_DATA = $(INSTALL) +INSTALL_XFORM = $(INSTALL) -t='-e $(program_transform_name)' +INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1 + +DISTSTUFF= make-gas.com m68k-parse.c + +AR = ar +AR_FLAGS = qv +BISON = bison -y +BISONFLAGS = +MAKEINFO = makeinfo +TEXI2DVI = texi2dvi +RANLIB = ranlib +CC = @CC@ +CFLAGS = -g + +MAKEOVERRIDES= + +EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \ + echo $${rootme}/../expect/expect ; \ + else echo expect ; fi` + +FLAGS_TO_PASS = \ + "prefix=$(prefix)" \ + "exec_prefix=$(exec_prefix)" \ + "tooldir=$(tooldir)" \ + "AR=$(AR)" \ + "AR_FLAGS=$(AR_FLAGS)" \ + "CC=$(CC)" \ + "CFLAGS=$(CFLAGS)" \ + "RANLIB=$(RANLIB)" \ + "LOADLIBES=$(LOADLIBES)" \ + "LDFLAGS=$(LDFLAGS)" \ + "BISON=$(BISON)" \ + "LEX=$(LEX)" \ + "MAKEINFO=$(MAKEINFO)" \ + "INSTALL=$(INSTALL)" \ + "INSTALL_DATA=$(INSTALL_DATA)" \ + "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" + +RUNTEST = `if [ -f ${srcdir}/../dejagnu/runtest ] ; then \ + echo ${srcdir}/../dejagnu/runtest ; else echo runtest; \ + fi` +RUNTESTFLAGS= + +# Lists of files for various purposes. + +REAL_SOURCES = \ + $(srcdir)/app.c \ + $(srcdir)/as.c \ + $(srcdir)/atof-generic.c \ + $(srcdir)/bignum-copy.c \ + $(srcdir)/cond.c \ + $(srcdir)/expr.c \ + $(srcdir)/flonum-konst.c \ + $(srcdir)/flonum-copy.c \ + $(srcdir)/flonum-mult.c \ + $(srcdir)/frags.c \ + $(srcdir)/hash.c \ + $(srcdir)/input-file.c \ + $(srcdir)/input-scrub.c \ + $(srcdir)/literal.c \ + $(srcdir)/messages.c \ + $(srcdir)/output-file.c \ + $(srcdir)/read.c \ + $(srcdir)/subsegs.c \ + $(srcdir)/symbols.c \ + $(srcdir)/write.c \ + $(srcdir)/listing.c \ + $(srcdir)/ecoff.c \ + $(srcdir)/stabs.c + +# in an expedient order +LINKED_SOURCES = \ + targ-cpu.c \ + obj-format.c \ + atof-targ.c + +SOURCES = $(LINKED_SOURCES) $(REAL_SOURCES) + +REAL_HEADERS = \ + $(srcdir)/as.h \ + $(srcdir)/bignum.h \ + $(srcdir)/expr.h \ + $(srcdir)/flonum.h \ + $(srcdir)/frags.h \ + $(srcdir)/hash.h \ + $(srcdir)/input-file.h \ + $(srcdir)/listing.h \ + $(srcdir)/tc.h \ + $(srcdir)/obj.h \ + $(srcdir)/read.h \ + $(srcdir)/struc-symbol.h \ + $(srcdir)/subsegs.h \ + $(srcdir)/symbols.h \ + $(srcdir)/write.h \ + $(srcdir)/ecoff.h + +LINKED_HEADERS = \ + targ-env.h \ + targ-cpu.h \ + obj-format.h \ + atof-targ.h + +HEADERS = $(LINKED_HEADERS) $(REAL_HEADERS) + +TE_OBJS= + +# @target_frag@ + +OBJS = \ + targ-cpu.o \ + obj-format.o \ + atof-targ.o \ + app.o \ + as.o \ + atof-generic.o \ + bignum-copy.o \ + cond.o \ + expr.o \ + flonum-konst.o \ + flonum-copy.o \ + flonum-mult.o \ + frags.o \ + hash.o \ + input-file.o \ + input-scrub.o \ + literal.o \ + messages.o \ + output-file.o \ + read.o \ + subsegs.o \ + symbols.o \ + write.o \ + listing.o \ + ecoff.o \ + stabs.o \ + sb.o \ + macro.o \ + @extra_objects@ \ + $(TE_OBJS) + +GASPOBJS = \ + gasp.o \ + macro.o \ + sb.o \ + hash.o + +all: .gdbinit as.new gasp.new + @srcroot=`cd $(srcroot); pwd`; export srcroot; \ + (cd doc ; $(MAKE) $(FLAGS_TO_PASS) all) + +dvi info install-info clean-info: + @srcroot=`cd $(srcroot); pwd`; export srcroot; \ + (cd doc ; $(MAKE) $(FLAGS_TO_PASS) $@) + +make-gas.com: stamp-mk.com +stamp-mk.com: vmsconf.sh Makefile + sh $(srcdir)/vmsconf.sh $(OBJS) > new-make.com + $(srcdir)/../move-if-change new-make.com $(srcdir)/make-gas.com + touch stamp-mk.com + +# Now figure out from those variables how to compile and link. + +# This is the variable actually used when we compile. +ALL_CFLAGS = $(INTERNAL_CFLAGS) $(CROSS) $(CFLAGS) $(HDEFINES) $(TDEFINES) + +# How to link with both our special library facilities +# and the system's installed libraries. + +LIBS = @OPCODES_LIB@ @BFDLIB@ $(LOCAL_LOADLIBES) ../libiberty/libiberty.a + +# Specify the directories to be searched for header files. +# Both . and srcdir are used, in that order, +# so that tm.h and config.h will be found in the compilation +# subdirectory rather than in the source directory. +INCLUDES = -I. -I$(srcdir) -I../bfd -I$(srcdir)/config -I$(srcdir)/../include -I$(srcdir)/.. -I$(srcdir)/../bfd + +# Always use -I$(srcdir)/config when compiling. +.c.o: + $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $< + +# This tells GNU make version 3 not to export all the variables +# defined in this file into the environment. +.NOEXPORT: + +# Files to be copied away after each stage in building. +STAGESTUFF = *.o as.new gasp.new + +$(OBJS): @ALL_OBJ_DEPS@ + +as.new: $(OBJS) $(LIBS) + $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o as.new $(OBJS) $(LIBS) $(LOADLIBES) + +$(OBJS): config.h as.h targ-env.h obj-format.h targ-cpu.h flonum.h expr.h \ + struc-symbol.h write.h frags.h hash.h read.h symbols.h tc.h obj.h \ + listing.h bignum.h + +gasp.new: $(GASPOBJS) ../libiberty/libiberty.a + $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o gasp.new $(GASPOBJS) ../libiberty/libiberty.a $(LOADLIBES) + +installcheck: + @echo No installcheck target is available yet for the GNU assembler. + +site.exp: ./Makefile + @echo "Making a new config file..." + -@rm -f ./tmp? + @touch site.exp + -@mv site.exp site.bak + @echo "## these variables are automatically generated by make ##" > ./tmp0 + @echo "# Do not edit here. If you wish to override these values," >> ./tmp0 + @echo "# do so in the last section." >> ./tmp0 + @echo set host_os @host_os@ >> ./tmp0 + @echo set host_alias @host_alias@ >> ./tmp0 + @echo set host_cpu @host_cpu@ >> ./tmp0 + @echo set host_vendor @host_vendor@ >> ./tmp0 + @echo set target_os @target_os@ >> ./tmp0 + @echo set target_alias @target_alias@ >> ./tmp0 + @echo set target_cpu @target_cpu@ >> ./tmp0 + @echo set target_vendor @target_vendor@ >> ./tmp0 + @echo set host_triplet @host@ >> ./tmp0 + @echo set target_triplet @target@ >> ./tmp0 + @echo set target_canonical @target@ >> ./tmp0 + @echo set srcdir ${srcdir}/testsuite >> ./tmp0 + @echo set exec_prefix ${exec_prefix} >> ./tmp0 + @echo set objdir `pwd` >> ./tmp0 + @echo "## All variables above are generated by configure. Do Not Edit ##" >> ./tmp0 + @sed -e '1,/^## All variables above are.*##/ d' < site.bak >> ./tmp0 + @mv -f ./tmp0 site.exp + +check: site.exp + if [ -d testsuite ]; then \ + true; \ + else \ + mkdir testsuite; \ + fi + rm -f testsuite/site.exp + cp site.exp testsuite/site.exp + rootme=`pwd`; export rootme; \ + srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \ + cd testsuite; \ + EXPECT=${EXPECT} ; export EXPECT ; \ + if [ -f $${rootme}/../expect/expect ] ; then \ + TCL_LIBRARY=$${srcdir}/../tcl/library ; \ + export TCL_LIBRARY ; fi ; \ + $(RUNTEST) --tool gas --srcdir $${srcdir}/testsuite $(RUNTESTFLAGS) + +config.status: configure + if [ -r config.status ]; then \ + sh ./config.status --recheck ; \ + else \ + echo You must configure gas. Look at the INSTALL file for details. ; \ + exit 1 ; \ + fi + +config.h: config-stamp ; @true +config-stamp: Makefile conf + -rm -f config.new config-stamp + echo '/* config.h. Generated automatically by make. */' > config.new + echo '#ifndef GAS_VERSION' >> config.new + echo '#define GAS_VERSION "$(VERSION)"' >> config.new + echo '' >> config.new + cat conf >> config.new + echo '#endif /* GAS_VERSION */' >> config.new + $(srcdir)/../move-if-change config.new config.h + touch config-stamp + +# Compiling object files from source files. + +TARG_CPU_DEP_a29k = +TARG_CPU_DEP_alpha = +TARG_CPU_DEP_arm = +TARG_CPU_DEP_generic = +TARG_CPU_DEP_h8300 = $(srcdir)/../include/opcode/h8300.h +TARG_CPU_DEP_h8500 = $(srcdir)/../opcodes/h8500-opc.h +TARG_CPU_DEP_hppa = +TARG_CPU_DEP_i386 = $(srcdir)/../include/opcode/i386.h +TARG_CPU_DEP_i860 = +TARG_CPU_DEP_i960 = +TARG_CPU_DEP_m68k = $(srcdir)/../include/opcode/m68k.h \ + $(srcdir)/config/m68k-parse.h subsegs.h +TARG_CPU_DEP_m88k = $(srcdir)/config/m88k-opcode.h +TARG_CPU_DEP_mips = $(srcdir)/../include/opcode/mips.h +TARG_CPU_DEP_ns32k = +TARG_CPU_DEP_ppc = +TARG_CPU_DEP_sh = $(srcdir)/../opcodes/sh-opc.h +TARG_CPU_DEP_sparc = +TARG_CPU_DEP_tahoe = +TARG_CPU_DEP_vax = +TARG_CPU_DEP_w65 = $(srcdir)/../opcodes/w65-opc.h +TARG_CPU_DEP_z8k = $(srcdir)/../opcodes/z8k-opc.h + +gasp.o : gasp.c sb.h macro.h config.h +sb.o : sb.c sb.h config.h +macro.o : macro.c macro.h sb.h hash.h config.h +app.o : app.c write.h +as.o : as.c output-file.h write.h subsegs.h sb.h macro.h +atof-generic.o : atof-generic.c +bignum-copy.o : bignum-copy.c +cond.o : cond.c +debug.o : debug.c subsegs.h +expr.o : expr.c +flonum-konst.o : flonum-konst.c +flonum-copy.o : flonum-copy.c +flonum-mult.o : flonum-mult.c +frags.o : frags.c subsegs.h +hash.o : hash.c +input-file.o : input-file.c input-file.h +input-scrub.o : input-scrub.c input-file.h sb.h +listing.o : listing.c input-file.h subsegs.h +literal.o : literal.c subsegs.h +messages.o : messages.c +output-file.o : output-file.c output-file.h +read.o : read.c sb.h macro.h +subsegs.o : subsegs.c subsegs.h +symbols.o : symbols.c subsegs.h +write.o : write.c subsegs.h output-file.h +ecoff.o : ecoff.c ecoff.h \ + $(srcdir)/../include/coff/internal.h $(srcdir)/../include/coff/sym.h \ + $(srcdir)/../include/coff/ecoff.h \ + $(srcdir)/../include/coff/symconst.h \ + $(srcdir)/../include/aout/stab_gnu.h +stabs.o : stabs.c subsegs.h $(srcdir)/../include/aout/stab_gnu.h +atof-targ.o : atof-targ.c +obj-format.o : obj-format.c +targ-cpu.o : targ-cpu.c $(TARG_CPU_DEP_@target_cpu_type@) + +obj-elf.o : $(srcdir)/config/obj-elf.c + $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(srcdir)/config/obj-elf.c +obj-ecoff.o : $(srcdir)/config/obj-ecoff.c + $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(srcdir)/config/obj-ecoff.c + +e-mipself.o : $(srcdir)/config/e-mipself.c + $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(srcdir)/config/e-mipself.c +e-mipsecoff.o : $(srcdir)/config/e-mipsecoff.c + $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(srcdir)/config/e-mipsecoff.c + +# The m68k operand parser. + +m68k-parse.c: $(srcdir)/config/m68k-parse.y + $(BISON) $(BISONFLAGS) $(srcdir)/config/m68k-parse.y + mv -f y.tab.c m68k-parse.c +m68k-parse.o: m68k-parse.c $(srcdir)/config/m68k-parse.h + +# Remake the info files. + +doc: $(srcdir)/as.info + +$(srcdir)/as.info: $(srcdir)/doc/as.texinfo + @(cd doc; $(MAKE) $(FLAGS_TO_PASS) as.info; mv as.info $srcdir) + +diststuff: $(DISTSTUFF) info + +clean-here: + -rm -f $(STAGESTUFF) core stamp-mk.com + -rm -f testsuite/*.o testsuite/*.out \ + testsuite/gas.log testsuite/gas.sum testsuite/site.exp + +clean mostlyclean: clean-here + @cd doc ; $(MAKE) $(FLAGS_TO_PASS) $@ + +# Like clean but also delete the links made to configure gas. +distclean: clean-here + @cd doc ; $(MAKE) $(FLAGS_TO_PASS) $@ + -rm -f config.status Makefile targ-env.h targ-cpu.h \ + targ-cpu.c obj-format.h obj-format.c atof-targ.c TAGS \ + config-stamp config.h conf config.log config.cache .gdbinit \ + testsuite/Makefile testsuite/config.status +maintainer-clean realclean: clean distclean clean-info + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + -rm -rf $(DISTSTUFF) + +# Entry points `install', `includes' and `uninstall'. + +# Copy the files into directories where they will be run. +install: + srcroot=`cd $(srcroot); pwd`; export srcroot; \ + $(INSTALL_XFORM) as.new $(bindir)/as; \ + $(INSTALL_XFORM1) $(srcdir)/doc/as.1 $(man1dir)/as.1; \ + n=`echo as | sed '$(program_transform_name)'`; \ + if [ -d $(tooldir) ]; then \ + if [ -d $(tooldir)/bin ] ; then true ; else mkdir $(tooldir)/bin ; fi; \ + rm -f $(tooldir)/bin/as; \ + ln $(bindir)/$$n $(tooldir)/bin/as >/dev/null 2>/dev/null \ + || $(INSTALL_PROGRAM) as.new $(tooldir)/bin/as; \ + else true; fi + srcroot=`cd $(srcroot); pwd`; export srcroot; \ + $(INSTALL_XFORM) gasp.new $(bindir)/gasp + +# Cancel installation by deleting the installed files. +uninstall: + -n=`t='$(program_transform_name)'; echo as | sed $$t`; \ + rm -f $(bindir)/$$n; \ + rm -f $(mandir)/$$n.1 + -n=`t='$(program_transform_name)'; echo gasp | sed $$t`; \ + rm -f $(bindir)/$$n; \ + +# These exist for maintenance purposes. + +tags TAGS: force + etags $(REAL_HEADERS) $(REAL_SOURCES) $(srcdir)/config/*.[hc] $(srcdir)/README $(srcdir)/Makefile.in + +bootstrap: as.new force + $(MAKE) stage1 + rm -f stage && ln -s stage1 stage + $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new + $(MAKE) stage2 + rm -f stage && ln -s stage2 stage + $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new + $(MAKE) comparison against=stage2 + +bootstrap2: force + rm -f stage && ln -s stage1 stage + $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new + $(MAKE) stage2 + rm -f stage && ln -s stage2 stage + $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new + $(MAKE) comparison against=stage2 + +bootstrap3: force + rm -f stage && ln -s stage2 stage + $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new + $(MAKE) comparison against=stage2 + +# Copy the object files from a particular stage into a subdirectory. +stage1: force + -mkdir stage1 + -mv $(STAGESTUFF) stage1 + if [ -f stage1/as.new -a ! -f stage1/as ] ; then (cd stage1 ; ln -s as.new as) ; fi + +stage2: force + -mkdir stage2 + -mv $(STAGESTUFF) stage2 + if [ -f stage2/as.new -a ! -f stage2/as ] ; then (cd stage2 ; ln -s as.new as) ; fi + +stage3: force + -mkdir stage3 + -mv $(STAGESTUFF) stage3 + if [ -f stage3/as.new -a ! -f stage3/as ] ; then (cd stage3 ; ln -s as.new as) ; fi + +against=stage2 + +# This rule is derived from corresponding code in the Makefile.in for gcc. +# The "tail +16c" is to bypass headers which may include timestamps or +# temporary assembly file names. +comparison: force + x=0 ; \ + for file in *.o ; do \ + tail +16c ./$$file > tmp-foo1; \ + if tail +16c ${against}/$$file > tmp-foo2 2>/dev/null ; then \ + if cmp tmp-foo1 tmp-foo2 ; then \ + true ; \ + else \ + echo $$file differs ; \ + x=1 ; \ + fi ; \ + else true; fi ; \ + done ; \ + exit $$x + -rm -f tmp-foo* + +de-stage1: force + - (cd stage1 ; rm -f as ; mv -f * ..) + - rmdir stage1 + +de-stage2: force + - (cd stage2 ; rm -f as ; mv -f * ..) + - rmdir stage2 + +de-stage3: force + - (cd stage3 ; rm -f as ; mv -f * ..) + - rmdir stage3 + +#In GNU Make, ignore whether `stage*' exists. +.PHONY: stage1 stage2 stage3 stage4 clean mostlyclean realclean distclean +.PHONY: TAGS bootstrap + +force: + +Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag) \ + $(srcdir)/configure.in config.status conf.in + $(SHELL) ./config.status +.gdbinit: $(srcdir)/gdbinit.in config.status + $(SHELL) ./config.status diff --git a/gnu/usr.bin/binutils/gas/NEWS b/gnu/usr.bin/binutils/gas/NEWS new file mode 100644 index 00000000000..e2a59f777e8 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/NEWS @@ -0,0 +1,201 @@ +-*- text -*- + +Changes since 2.5: + +Gas now directly supports macros, without requiring GASP. + +Gas now has an MRI assembler compatibility mode. + +Added --defsym SYM=VALUE option. + +Added -mips4 support to MIPS assembler. + +Added PIC support to Solaris and SPARC SunOS 4 assembler. + +Changes since 2.3: + +Converted this directory to use an autoconf-generated configure script. + +ARM support, from Richard Earnshaw. + +Updated VMS support, from Pat Rankin, including considerably improved debugging +support. + +Support for the control registers in the 68060. + +Handles (ignores) a new directive ".this_GCC_requires_the_GNU_assembler", to +provide for possible future gcc changes, for targets where gas provides some +features not available in the native assembler. If the native assembler is +used, it should become obvious pretty quickly what the problem is. + +Usage message is available with "--help". + +The GNU Assembler Preprocessor (gasp) is included. (Actually, it was in 2.3 +also, but didn't get into the NEWS file.) + +Weak symbol support for a.out. + +A bug in the listing code which could cause an infinite loop has been fixed. +Bugs in listings when generating a COFF object file have also been fixed. + +Initial i386-svr4 PIC implementation from Eric Youngdale, based on code by Paul +Kranenburg. + +Improved Alpha support. Immediate constants can have a much larger range now. +Support for the 21164 has been contributed by Digital. + +Updated ns32k (pc532-mach, netbsd532) support from Ian Dall. + +Changes since 2.2: + +Mach i386 support, by David Mackenzie and Ken Raeburn. + +RS/6000 and PowerPC support by Ian Taylor. + +VMS command scripts (make-gas.com, config-gas.com) have been worked on a bit, +based on mail received from various people. The `-h#' option should work again +too. + +HP-PA work, by Jeff Law. Note, for the PA, gas-2.3 has been designed to work +with gdb-4.12 and gcc-2.6. As gcc-2.6 has not been released yet, a special +version of gcc-2.5.8 has been patched to work with gas-2.3. You can retrieve +this special version of gcc-2.5.8 via anonymous ftp from jaguar.cs.utah.edu +in the "dist" directory. + +Vax support in gas fixed for BSD, so it builds and seems to run a couple simple +tests okay. I haven't put it through extensive testing. (GNU make is +currently required for BSD 4.3 builds.) + +Support for the DEC Alpha, running OSF/1 (ECOFF format). The gas support is +based on code donated by CMU, which used an a.out-based format. I'm afraid the +alpha-a.out support is pretty badly mangled, and much of it removed; making it +work will require rewriting it as BFD support for the format anyways. + +Irix 5 support. + +The test suites have been fixed up a bit, so that they should work with a +couple different versions of expect and dejagnu. + +Symbols' values are now handled internally as expressions, permitting more +flexibility in evaluating them in some cases. Some details of relocation +handling have also changed, and simple constant pool management has been added, +to make the Alpha port easier. + +New option "--statistics" for printing out program run times. This is intended +to be used with the gcc "-Q" option, which prints out times spent in various +phases of compilation. (You should be able to get all of them printed out with +"gcc -Q -Wa,--statistics", I think.) + +---------------------------------------------------------------- + +Changes since 2.1: + +RS/6000 AIX and MIPS SGI Irix 5 support has been added. + +Configurations that are still in development (and therefore are convenient to +have listed in configure.in) still get rejected without a minor change to +gas/Makefile.in, so people not doing development work shouldn't get the +impression that support for such configurations is actually believed to be +reliable. + +The program name (usually "as") is printed when a fatal error message is +displayed. This should prevent some confusion about the source of occasional +messages about "internal errors". + +ELF support is falling into place. Support for the 386 should be working. +Support for SPARC Solaris is in. HPPA support from Utah is being integrated. + +Symbol values are maintained as expressions instead of being immediately boiled +down to add-symbol, sub-symbol, and constant. This permits slightly more +complex calculations involving symbols whose values are not alreadey known. + +DBX-style debugging info ("stabs") is now supported for COFF formats. +If any stabs directives are seen in the source, GAS will create two new +sections: a ".stab" and a ".stabstr" section. The format of the .stab +section is nearly identical to the a.out symbol format, and .stabstr is +its string table. For this to be useful, you must have configured GCC +to generate stabs (by defining DBX_DEBUGGING_INFO), and must have a GDB +that can use the stab sections (4.11 or later). + +LynxOS, on i386 and m68k platforms, is now supported. SPARC LynxOS +support is in progress. + +---------------------------------------------------------------- + +Changes for 2.1: + +Several small fixes for i386-aix (PS/2) support from Minh Tran-Le have been +incorporated, but not well tested yet. + +Altered the opcode table split for m68k; it should require less VM to compile +with gcc now. + +Some minor adjustments to add (Convergent Technologies') Miniframe support, +suggested by Ronald Cole. + +HPPA support (running OSF only, not HPUX) has been contributed by Utah. This +includes improved ELF support, which I've started adapting for SPARC Solaris +2.x. Integration isn't completely, so it probably won't work. + +HP9000/300 support, donated by HP, has been merged in. + +Ian Taylor has finished the MIPS ECOFF (Ultrix, Irix) support. + +Better error messages for unsupported configurations (e.g., hppa-hpux). + +Test suite framework is starting to become reasonable. + +---------------------------------------------------------------- + +Changes for 2.0: + +Mostly bug fixes. + +Some more merging of BFD and ELF code, but ELF still doesn't work. + +---------------------------------------------------------------- + +Changes for 1.94: + +BFD merge is partly done. Adventurous souls may try giving configure the +"--with-bfd-assembler" option. Currently, ELF format requires it, a.out format +accepts it; SPARC CPU accepts it. It's the default only for OS "elf" or +"solaris". (ELF isn't really supported yet. It needs work. I've got some +code from Utah for HP-PA ELF, and from DG for m88k ELF, but they're not fully +merged yet.) + +The 68K opcode table has been split in half. It should now compile under gcc +without consuming ridiculous amounts of memory. + +A couple data structures have been reduced in size. This should result in +saving a little bit of space at runtime. + +Support for MIPS, from OSF and Ralph Campbell, has been merged in. The OSF +code provided ROSE format support, which I haven't merged in yet. (I can make +it available, if anyone wants to try it out.) Ralph's code, for BSD 4.4, +supports a.out format. We don't have ECOFF support in just yet; it's coming. + +Support for the Hitachi H8/500 has been added. + +VMS host and target support should be working now, thanks chiefly to Eric +Youngdale. + +---------------------------------------------------------------- + +Changes for 1.93.01: + +For m68k, support for more processors has been added: 68040, CPU32, 68851. + +For i386, .align is now power-of-two; was number-of-bytes. + +For m68k, "%" is now accepted before register names. For COFF format, which +doesn't use underscore prefixes for C labels, it is required, so variable "a0" +can be distinguished from the register. + +Last public release was 1.38. Lots of configuration changes since then, lots +of new CPUs and formats, lots of bugs fixed. + + +Local variables: +fill-column: 79 +End: diff --git a/gnu/usr.bin/binutils/gas/NOTES b/gnu/usr.bin/binutils/gas/NOTES new file mode 100644 index 00000000000..b062909db12 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/NOTES @@ -0,0 +1,142 @@ +-*- text -*- + +PORTING: + +Sorry, no description of the interfaces is written up yet. Look at existing +back ends and work from there. + +New hosts: If your host system has a strange header file setup, create a +config/ho-foo.h file for it and include the appropriate header files or +definitions there. If your host has a broken compiler, or some broken macros +in header files, create a host-specific file and repair the damage there. +(See, for example, ho-rs6000.h. The "assert" macro on that system doesn't work +right, and a flag is set to rewrite an expression in tc-m68k.c that the native +compiler mis-compiles.) + +New target formats: Look at the BFD_ASSEMBLER code. The a.out code might be a +fair example. There are no "good" examples yet, unfortunately, nor any good +documentation of the changes. + +New target processors: Check first to see if the BFD_ASSEMBLER interface is +supported by the file format code you need to use. + +New environments: ??? + +DOCUMENTATION: + +The internals of gas need documenting. + +The documentation should also contain a "Trouble" section similar to gcc's +manual: real bugs, common problems, incompatibilities, etc. + +Anyone want to offer to maintain a man page? + +BFD CONVERSION: + +The "#ifdef BFD_ASSEMBLER" code is on its way in; the "#ifndef BFD_ASSEMBLER" +code is on its way out. The new code uses BFD data structures, and calls BFD +for anything that needs to be written to the output file. The old code did all +the writing itself, or in a couple of cases, used BFD as a slightly higher +level than stdio (i.e., bfd_seek, bfd_write -- these are not the preferred +interface). + +Because of this, some of this code is messy. Lots of ifdef's, and the +non-BFD_ASSEMBLER version often has multiple conditional tests inside it for +various processors or formats. As the various targets get converted over, +these will gradually go away. + +As of the moment I'm editing this file, only the "sun4" and "decstation-bsd" +targets can really use the BFD code. Other back ends still need merging or +touching up. + +TO DO: + +Remove DONTDEF code, commented-out code. + +Eliminate, as much as possible, anything not in config that is conditionalized +on a CPU, format, or environment. + +Merge COFF support into one version, supporting all the pseudo-ops used in +either versions now, but using BFD for high-level operations. (See second +following item.) Currently there are two versions (plus the new BFD code), +which support different features, and are used on different targets. + +Convert remaining a.out/b.out targets to using the BFD_ASSEMBLER code by +default. + +Finish conversion to using BFD for all object file writing. (This is the +BFD_ASSEMBLER code, not BFD or BFD_HEADERS.) VMS might be the tough one here, +since there's no BFD support for it at all yet. Eliminate the old code. Some +of this can be done target by target, so doing a target where the CPU or +format already supports BFD_ASSEMBLER mode may be easiest. + +Fix lots of uses of empty strings to use null pointers. Will improve +efficiency, and should make code clearer too. + +Clean up comments; lots of 'em are one previous maintainer griping about +another previous maintainer, unrelated to the code. (And with no names, +they're not so fun to read. :-) + +For sparc: "call 0" becomes "jmpl %g0,%l7", and similarly for absolute +addresses in -4096...4095. (Solaris assembler does this. No +relocation required, no absolute symbol needed.) For addresses +outside the range, for COFF, keep generating an absolute symbol to use +for relocs. + +Get Steve to document H8/500 stuff (and others). + +Improve test suite. Incorporate more reported net bugs, and non-confidential +Cygnus customer bugs, and anything else. + +Add support for i386/i486 16-bit mode, so operating system initialization code +doesn't require a separate assembler nor lots of `.byte' directives. + +See if it's more maintainable (and not too much of a performance loss) to use +a yacc grammar for parsing input. The lexer will have to be flexible, and the +grammar will have to contain any construct used on any platform, but it may be +easier to maintain, instead of having code in most of the back ends. + +PIC support. + +Torbjorn Granlund writes, regarding alpha .align: + + Please make sure the .align directive works as in digital's assembler. + They fill the space with a sequence of "bis $31,$31,$31;ldq_u $31,0($30)" + since these two instructions can dual-issue. Since .align is ued a lot by + gcc, it is an important optimization. + +Torbjorn Granlund writes, regarding i386/i486/pentium: + + In a new publication from Intel, "Optimization for Intel's 32 bit + Processors", they recommended code alignment on a 16 byte boundary if that + requires less than 8 bytes of fill instructions. The Pentium is not + affected by such alignment, the 386 wants alignment on a 4 byte boundary. + It is the 486 that is most helped by large alignment. + + Recommended nop instructions: + 1 byte: 90 xchg %eax,%eax + 2 bytes: 8b c0 movl %eax,%eax + 3 bytes: 8d 76 00 leal 0(%esi),%esi + 4 bytes: 8d 74 26 00 leal 0(%esi),%esi + 5 bytes: 8b c0 8d 76 00 movl %eax,%eax; leal 0(%esi),%esi + 6 bytes: 8d b6 00 00 00 00 leal 0(%esi),%esi + 7 bytes: 8d b4 26 00 00 00 00 leal 0(%esi),%esi + + Note that `leal 0(%esi),%esi' has a few different encodings... + + There are faster instructions for certain lengths, that are not true nops. + If you can determine that a register and the condition code is dead (by + scanning forwards for a register that is written before it is read, and + similar for cc) you can use a `incl reg' for a 3 times faster 1 cycle nop... + +(From old "NOTES" file to-do list, not really reviewed:) + +fix relocation types for i860, perhaps by adding a ref pointer to fixS? + +remove the ifdef's from fx_callj tests? + +space tighten sparc alignment? + +md_ => tc_ + +share b.out with a.out. diff --git a/gnu/usr.bin/binutils/gas/NOTES.config b/gnu/usr.bin/binutils/gas/NOTES.config new file mode 100644 index 00000000000..e12797d51c1 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/NOTES.config @@ -0,0 +1,52 @@ + + The GAS Configuration Plan + +Theory: + +The goal of the new configuration scheme is to bury all object format, +target processor, and host machine dependancies in object, target, and +host specific files. That is, to move all #ifdef's out of the gas +common code. + +Here's how it works. There is a .h and a .c file for each object file +format, a .h and a .c file for each target processor, and a .h for +each host. config.gas creates {sym}links in the current directory to +the appropriate files in the config directory. config.gas also serves +as a list of triplets {host, target, object-format} that have been +tested at one time or another. I also recommend that config.gas be +used to document triplet specific notes as to purpose of the triplet, +etc. + +Implementation: + +host.h is a {sym}link to .../config/xm-yourhost.h. It is intended to +be used to hide host compiler, system header file, and system library +differences between host machines. If your host needs actual c source +files, then either: these are generally useful functions, in which +case you should probably build a local library outside of the gas +source tree, or someone, perhaps me, is confused about what is needed +by different hosts. + +obj-format.h is a {sym}link to .../config/obj-something.h. It is intended + +All gas .c files include as.h. + +as.h #define's "gas", includes host.h, defines a number of gas +specific structures and types, and then includes tp.h, obj.h, and +target-environment.h. + +target-environment.h defines a target environment specific +preprocessor flag, eg, TE_SUN, and then includes obj-format.h. + +obj-format.h defines an object format specific preprocessor flag, eg, +OBJ_AOUT, OBJ_BOUT, OBJ_COFF, includes "target-processor.h", and then +defines the object specific macros, functions, types, and structures. + +target-processor.h + +target-processor. + +Porting: + +There appear to be four major types of ports; new hosts, new target +processors, new object file formats, and new target environments. diff --git a/gnu/usr.bin/binutils/gas/README b/gnu/usr.bin/binutils/gas/README new file mode 100644 index 00000000000..7a25d9a0844 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/README @@ -0,0 +1,295 @@ +-*- text -*- + + README for GAS + [cribbed largely from GDB's README file] + +A number of things have changed since version 1 and the wonderful world of gas +looks very different. There's still a lot of irrelevant garbage lying around +that will be cleaned up in time. Documentation is scarce, as are logs of the +changes made since the last gas release. My apologies, and I'll try to get +something useful. + +Unpacking and Installation - Summary +==================================== + +See ../binutils/README. + +Documentation +============= + +The GAS release includes texinfo source for its manual, which can be processed +into `info' or `dvi' forms. + +The DVI form is suitable for printing or displaying; the commands for doing +this vary from system to system. On many systems, `lpr -d' will print a DVI +file. On others, you may need to run a program such as `dvips' to convert the +DVI file into a form your system can print. + +If you wish to build the DVI file, you will need to have TeX installed on your +system. You can rebuild it by typing: + + cd gas-2.5/gas/doc + make as.dvi + +The Info form is viewable with the GNU Emacs `info' subsystem, or the +standalone `info' program, available as part of the GNU Texinfo distribution. +To build the info files, you will need the `makeinfo' program. Type: + + cd gas-2.5/gas/doc + make info + +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 GAS 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 GAS source directory +(`gas-2.5', for version 2.5). + + +`configure' options +=================== + + Here is a summary of the `configure' options and arguments that are +most often useful for building GAS. `configure' also has several other +options not listed here. + + configure [--help] + [--prefix=DIR] + [--srcdir=PATH] + [--norecursion] [--rm] + [--target=TARGET] HOST + [--with-OPTION] + [--enable-OPTION] + +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 implements the `VPATH' feature.* + Use this option to make configurations in directories separate + from the GAS 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 GAS for cross-assembling programs for the specified + TARGET. Without this option, GAS is configured to assemble .o files + that run on the same machine (HOST) as GAS itself. + + There is no convenient way to generate a list of all available + targets. + +`--enable-OPTION' + These flags tell the program or library being configured to + configure itself differently from the default for the specified + host/target combination. See below for a list of `--enable' + options recognized in the gas-2.5 distribution. + +`HOST ...' + Configure GAS 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 +GAS or its supporting libraries. + +The `--enable' options recognized by software in the gas-2.5 distribution are: + +`--enable-targets=...' + This causes one or more specified configurations to be added to those for + which BFD support is compiled. Currently gas cannot use any format other + than its compiled-in default, so this option is not very useful. + +`--enable-bfd-assembler' + This causes the assembler to use the new code being merged into it to use + BFD data structures internally, and use BFD for writing object files. + For most targets, this isn't supported yet. For most targets where it has + been done, it's already the default. So generally you won't need to use + this option. See `BFD CONVERSION' in the file `gas/NOTES'. + +Supported platforms +=================== + +At this point I believe gas to be ansi only code for most target cpu's. That +is, there should be relatively few, if any host system dependencies. So +porting (as a cross-assembler) to hosts not yet supported should be fairly +easy. Porting to a new target shouldn't be too tough if it's a variant of one +already supported. + +Native assembling should work on: + + sun3 + sun4 + 386bsd + bsd/386 + delta (m68k-sysv from Motorola) + delta88 (m88k-sysv from Motorola) + linux + m68k hpux 8.0 (hpux 7.0 may be a problem) + vax bsd, ultrix, vms + hp9000s300 + decstation + iris + miniframe (m68k-sysv from Convergent Technologies) + i386-aix (ps/2) + hppa (hpux 4.3bsd, osf1) + rs6000 + unixware + sco 3.2v4.2 + sparc solaris 2.3 + +For cross-assemblers, I believe hosting to work on any of the machines listed +above, plus: + + sun386i + at least some flavors of hpux (hpux 7.0 may be a problem) + most flavors of sysV + +I believe that gas as a cross-assembler can currently be targetted for: + + 386bsd + bsd/386 + decstation-bsd (a.out format, to be used in BSD 4.4) + ebmon29k + go32 (DOS on i386, with DJGPP -- old a.out version) + h8/300, h8/500 (Hitachi) + hp9000/300 + i386-aix (ps/2) + i960-coff + linux + mips ecoff (decstation-ultrix, iris, mips magnum, mips-idt-ecoff) + nindy960 + powerpc + sco386 + sun3 + sun4 + vax bsd or ultrix? + vms + vxworks68k + vxworks960 + z8000 (Zilog) + +MIPS ECOFF support has been added, but GAS will not run a C-style +preprocessor. If you want that, rename your file to have a ".S" suffix, and +run gcc on it. Or run "gcc -xassembler-with-cpp foo.s". + +Support for ELF should work now for sparc, hppa, i386. + +Support for ns32k, tahoe, i860, m88k may be suffering from bitrot. + +If you try out gas on some host or target not listed above, please let me know +the results, so I can update the list. + +Compiler Support Hacks +====================== + +The assembler has been modified to support a feature that is potentially +useful when assembling compiler output, but which may confuse assembly +language programmers. If assembler encounters a .word pseudo-op of the form +symbol1-symbol2 (the difference of two symbols), and the difference of those +two symbols will not fit in 16 bits, the assembler will create a branch around +a long jump to symbol1, and insert this into the output directly before the +next label: The .word will (instead of containing garbage, or giving an error +message) contain (the address of the long jump)-symbol2. This allows the +assembler to assemble jump tables that jump to locations very far away into +code that works properly. If the next label is more than 32K away from the +.word, you lose (silently); RMS claims this will never happen. If the -K +option is given, you will get a warning message when this happens. + + +REPORTING BUGS IN GAS +===================== + +Bugs in gas should be reported to bug-gnu-utils@prep.ai.mit.edu. They may be +cross-posted to bug-gcc if they affect the use of gas with gcc. They should +not be reported just to bug-gcc, since I don't read that list, and therefore +wouldn't see them. + +If you report a bug in GAS, please remember to include: + +A description of exactly what went wrong, and exactly what should have +happened instead. + +The type of machine (VAX, 68020, etc) and operating system (BSD, SunOS, DYNIX, +VMS, etc) GAS was running on. + +The configuration name(s) given to the "configure" script. The +"config.status" file should have this information. + +The options given to GAS at run time. + +The actual input file that caused the problem. + +It is silly to report a bug in GAS without including an input file for GAS. +Don't ask us to generate the file just because you made it from files you +think we have access to. + +1. You might be mistaken. +2. It might take us a lot of time to install things to regenerate that file. +3. We might get a different file from the one you got, and might not see any +bug. + +To save us these delays and uncertainties, always send the input file for the +program that failed. A smaller test case that demonstrates the problem is of +course preferable, but be sure it is a complete input file, and that it really +does demonstrate the problem; but if paring it down would cause large delays +in filing the bug report, don't bother. + +If the input file is very large, and you are on the internet, you may want to +make it avaliable for anonymous FTP instead of mailing it. If you do, include +instructions for FTP'ing it in your bug report. + +If you expect to be contributing a large number of test cases, it would be +helpful if you would look at the test suite included in the release (based on +the Deja Gnu testing framework, available from the usual ftp sites) and write +test cases to fit into that framework. This is certainly not required. diff --git a/gnu/usr.bin/binutils/gas/README-quirks b/gnu/usr.bin/binutils/gas/README-quirks new file mode 100644 index 00000000000..c9a3b05917a --- /dev/null +++ b/gnu/usr.bin/binutils/gas/README-quirks @@ -0,0 +1,7 @@ +* rcsid's should be conspicuously absent until someone explains to me + how to use them constructively without affecting diffs from remote + sites. If you can, then I will become an active supporter of + rcsid's. + +* "diff -u" patches preferred. "diff -c" patches accepted. All other + patches will be returned. diff --git a/gnu/usr.bin/binutils/gas/README-vms b/gnu/usr.bin/binutils/gas/README-vms new file mode 100644 index 00000000000..796c603b4f3 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/README-vms @@ -0,0 +1,248 @@ + This document explains a couple of things that are specific to VMS. +There are currently two "chapters", the first deals with cross-assembly +issues, and the second deals with the VMS debugger and GNU-CC. + + +*********************************************************************** +****************** Notes for Cross Assembly with VMS ****************** +*********************************************************************** + + If you wish to build gas on a non-VMS system to cross-assemble, +you should use: + +configure ${hosttype} -target=vms + +and then follow the usual procedure. The object files generated on +Unix will be correct from a binary point of view, but the real trick is +getting them to the VMS machine. The format of the object file is +a variable-length record, but each record contains binary data. gas +writes the records in the same format that VMS would expect, +namely a two-byte count followed by that number of bytes. + + If you try to copy the file to a VMS system using ftp, the ftp +protocol will screw up the file by looking for nulls (record terminator for +unix) and it will insert it's own record terminators at that point. This +will obviously corrupt the file. + + If you try to transfer the file with ftp in binary mode, the +file itself will not be corrupt, but VMS will think that the file contains +fixed-length records of 512 bytes. You can use the public-domain FILE +utility to change this with a command like: + +$FILE foo.o/type=variable + +If you do not have this utility available, the following program can be +used to perform this task: + + #include + + #define RME$C_SETRFM 1 + + struct FAB * fab; + + main(int argc, char * argv[]){ + int i, status; + fab = (struct FAB*) malloc(sizeof(struct FAB)); + *fab = cc$rms_fab; /* initialize FAB*/ + fab->fab$b_fac = FAB$M_PUT; + fab->fab$l_fop |= FAB$M_ESC; + fab->fab$l_ctx = RME$C_SETRFM; + fab->fab$w_ifi = 0; + for(i=1;ifab$l_fna = argv[i]; + fab->fab$b_fns = strlen(argv[i]); + status = sys$open(fab,0,0); + if((status & 7) != 1) lib$signal(status); + fab->fab$b_rfm = FAB$C_VAR; + status = sys$modify(fab,0,0); + if((status & 7) != 1) lib$signal(status); + status = sys$close(fab,0,0); + if((status & 7) != 1) lib$signal(status); + }; + } + + If you have NFS running on the VMS system, what you need to do +depends upon which NFS software you are running on the VMS system. There +are a number of different TCP/IP packages for VMS available, and only very +limited testing has been performed. In the tests that has been done so +far, the contents of the file will always be correct when transferring the +file via NFS, but the record attributes may or may not be correct. + + One proprietary TCP/IP/NFS package for VMS is known to +automatically fix the record attributes of the object file if you NFS mount +a unix disk from the VMS system, and if the file has a ".obj" extension on +the unix system. Other TCP/IP packages might do this for you as well, but +they have not been checked. + +No matter what method you use to get the file to the VMS system, it is +always a good idea to check to make sure that it is the correct type by +doing a "$dir/full" on the object file. The desired record attributes will +be "None". Undesirable record attributes will be "Stream-LF" or anything +else. + +Once you get the files on the VMS system, you can check their integrity +with the "$anal/obj" command. (Naturally at some point you should rename +the .o files to .obj). As far as the debugger is concerned, the records +will be correct, but the debugger will not be able to find the source files, +since it only has the file name, and not the full directory specification. +You must give the debugger some help by telling it which directories to +search for the individual files - once you have done this you should be +able to proceed normally. + + It is a good idea to use names for your files which will be valid +under VMS, since otherwise you will have no way of getting the debugger to +find the source file when deugging. + +The reason for this is that the object file normally contins specific +information that the debugger can use to positively identify a file, and if +you are assembling on a unix system this information simply does not exist +in a meaningful way. You must help the debugger by using the "SET FILE=" +command to tell the debugger where to look for source files. The debugger +records will be correct, except that the debugger will not be initially +able to find the source files. You can use the "SET FILE" command to tell +the debugger where to look for the source files. + +I have only tested this with a SVr4 i486 machine, and everything seems to +work OK, with the limited testing that I have done. Other machines may +or may not work. You should read the chapters on cross-compilers in the gcc +manual before fooling with this. Since gas does not need to do any floating +point arithmetic, the floating point constants that are generated here should +be correct - the only concern is with constant folding in the main compiler. +The range and precision of floats and doubles are similar on the 486 (with +a builtin 80387) and the VAX, although there is a factor of 2 to 4 +difference in the range. The double, as implemented on the 486, is quite +similar to the G_FLOAT on the VAX. + +*********************************************************************** +****************** Notes for using GNU CC with the VMS debugger******** +*********************************************************************** + + + 1) You should be aware that GNU-C, as with any other decent compiler, +will do things when optimization is turned on that you may not expect. +Sometimes intermediate results are not written to variables, if they are only +used in one place, and sometimes variables that are not used at all will not be +written to the symbol table. Also, parameters to inline functions are often +inaccessible. You can see the assembly code equivalent by using KP7 in the +debugger, and from this you can tell if in fact a variable should have the +value that you expect. You can find out if a variable lives withing a register +by doing a 'show symbol/addr'. + + 2) Overly complex data types, such as: + +int (*(*(*(*(*(* sarr6)[1])[1])[2])[3])[4])[5]; + +will not be debugged properly, since the debugging record overflows an internal +debugger buffer. gcc-as will convert these to *void as far as the debugger +symbol table is concerned, which will avoid any problems, and the assembler +will give you a message informing you that this has happened. + + 3) You must, of course, compile and link with /debug. If you link +without debug, you still get traceback table in the executable, but there is no +symbol table for variables. + + 4) Included in the patches to VMS.C are fixes to two bugs that are +unrelated to the changes that I have made. One of these made it impossible to +debug small programs sometimes, and the other caused the debugger to become +confused about which routine it was in, and give this incorrect info in +tracebacks. + + 5) If you are using the GNU-C++ compiler, you should modify the +compiler driver file GNU_CC:[000000]GCC.COM (or GXX.COM). If you have a +seperate GXX.COM, then you need to change one line in GXX.COM to: +$ if f$locate("D",p2) .ne. P2_Length then Debug = " ""-G0""" + Notice zero---> ^ +If you are using a GCC.COM that does both C and C++, add the following lines to +GCC.COM: + +$! +$! Use old style debugging records for VMS +$! +$ if (Debug.nes."" ).and. Plus then Debug = " ""-G0""" + +after the variables Plus and Debug are set. The reason for this, is that C++ +compiler by default generates debugging records that are more complex, +with many new syntactical elements that allow for the new features of the +language. The -G0 switch tells the C++ compiler to use the old style debugging +records. Until the debugger understands C++ there is not any point to try and +use the expanded syntax. + + 6) When you have nested scopes, i.e.: +main(){ + int i; + {int i; + {int i; +};};} +and you say "EXAM i" the debugger needs to figure out which variable you +actually want to reference. I have arranged things to define a block to the +debugger when you use brackets to enter a new scope, so in the example above, +the variables would be described as: +TEST\main\i +TEST\main\$0\i +TEST\main\$0\$0\i +At each level, the block name is a number with a dollar sign prefix, the +numbers start with 0 and count upward. When you say EXAM i, the debugger looks +at the current PC, and decides which block it is currently in. It works from +the innermost level outward until it finds a block that has the variable "i" +defined. You can always specify the scope explicitly. + + 7) With C++, there can be a lot of inline functions, and it would be +rather restrictive to force the user to debug the program by converting all of +the inline functions to normal functions. What I have done is to essentially +"add" (with the debugger) source lines from the include files that contain the +inline functions. Thus when you step into an inline function it appears as if +you have called the function, and you can examine variables and so forth. +There are several *very* important differences, however. First of all, since +there is no function call involved, you cannot step over the inline function +call - you always step into it. Secondly, since the same source lines are used +in many locations, there is a seperate copy of the source for *each* usage. +Without this, breakpoints do not work, since we must have a 1-to-1 mapping +between source lines and PC. + Since you cannot step over inline function calls, it can be a real pain +if you are not really interested in what is going on for that function call. +What I have done is to use the "-D" switch for the assembler to toggle the +following behavior. With the "-D" switch, all inline functions are included in +the object file, and you can debug everything. Without the "-D" switch +(default case with VMS implementation), inline functions are included *only* if +they did not come from system header files (i.e. from GNU_CC_INCLUDE: or +GNU_GXX_INCLUDE:). Thus, without the switch the user only debugs his/her own +inline functions, and not the system ones. (This is especially useful if you do +a lot of stream I/O in C++). This probably will not provide enough granularity +for many users, but for now this is still somewhat experimental, and I would +like to reflect upon it and get some feedback before I go any further. +Possible solutions include an interactive prompting, a logical name, or a new +command line option in gcc.c (which is then passed through somehow to the guts +of the assembler). + The inline functions from header files appear after the source code +for the source file. This has the advantage that the source file itself is +numbered with the same line numbers that you get with an editor. In addition, +the entire header file is not included, since the assembler makes a list of +the min and max source lines that are used, and only includes those lines from +the first to the last actually used. (It is easy to change it to include the +whole file). + + 8) When you are debugging C++ objects, the object "this" is refered to +as "$this". Actually, the compiler writes it as ".this", but the period is +not good for the debugger, so I have a routine to convert it to a $. (It +actually converts all periods to $, but only for variables, since this was +intended to allow us to access "this". + + 9) If you use the asm("...") keyword for global symbols, you will not +be able to see that symbol with the debugger. The reason is that there are two +records for the symbol stored in the data structures of the assembler. One +contains the info such as psect number and offset, and the other one contains +the information having to do with the data type of the variable. In order to +debug as symbol, you need to be able to coorelate these records, and the only +way to do this is by name. The record with the storage attributes will take +the name used in the asm directive, and the record that specifies the data type +has the actual variable name, and thus when you use the asm directive to change +a variable name, the symbol becomes invisible. + + 10) Older versions of the compiler ( GNU-C 1.37.92 and earlier) place +global constants in the text psect. This is unfortunate, since to the linker +this appears to be an entry point. I sent a patch to the compiler to RMS, +which will generate a .const section for these variables, and patched the +assembler to put these variables into a psect just like that for normal +variables, except that they are marked NOWRT. static constants are still +placed in the text psect, since there is no need for any external access. diff --git a/gnu/usr.bin/binutils/gas/README.coff b/gnu/usr.bin/binutils/gas/README.coff new file mode 100644 index 00000000000..46c61cda909 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/README.coff @@ -0,0 +1,79 @@ +The coff patches intend to do the following : + + . Generate coff files very compatible with vanilla linker. + . Understands coff debug directives. + +Here are the guidelines of the work I have done : + + . Encapsulate format dependent code in macros where it is possible. + . Where not possible differenciate with #ifdef + . try not to change the calling conventions of the existing functions. + I made one exception : symbol_new. I would be pleased to hear about + a better solution. (symbols.c) + . Extend the use of N_TYPE_seg seg_N_TYPE tables so that segments can + be manipulated without using their format dependent name. (subsegs.c) + . Write a function to parse the .def debug directives + . Write two small peaces of code to handle the .ln directive. + . In write.c try to move all the cross compilation specifics (md_..) to + format dependent files. + . Encapsulate the data structures using generic types, macros calls. + . Added too much code to resolve the complexity of the symbol table + generated. Most of the code deals with debug stuff. + . Create another makefile, shorter, cleaner. + . Create a config.gas shell script to mimic the gcc,gdb... configuration + mechanism. This reduce the complexity of the makefile. + . Isolate the format dependent code in two files + coff.c coff.h + aout.c aout.h + elf.c elf.h [ Not yet ;-] + . added a little stack management routine for coff in file stack.c + . isolate os specific flags in m- files + +If further development is planed on it is should solve the following problems : + + . Encapsulate DESC & OTHER tests in a macro call. I'm not aware + of their exact semantics. + . Clean up the seg_N_TYPE N_TYPE_seg naming scheme + . Try to remove as much reference to segment dependent names as possible + . Find a cleaner solution for symbol_new. + . Report the modifications on vax, ns32k, sparc machine dependent files. + To acheive this goal, search for \ conftest.c < conftest.out 2>&1 +if egrep yes conftest.out >/dev/null 2>&1; then + GCC=yes +else + GCC= +fi +rm -f conftest* +])dnl +dnl +dnl GAS_CHECK_DECL_NEEDED(name, typedefname, typedef, headers) +AC_DEFUN(GAS_CHECK_DECL_NEEDED,[ +AC_MSG_CHECKING(whether declaration is required for $1) +AC_CACHE_VAL(gas_cv_decl_needed_$1, +AC_TRY_LINK([$4], +[ +typedef $3; +$2 x; +x = ($2) $1; +], gas_cv_decl_needed_$1=no, gas_cv_decl_needed_$1=yes))dnl +AC_MSG_RESULT($gas_cv_decl_needed_$1) +test $gas_cv_decl_needed_$1 = no || { + ifelse(index($1,[$]),-1, + [AC_DEFINE([NEED_DECLARATION_]translit($1, [a-z], [A-Z]))], + [gas_decl_name_upcase=`echo $1 | tr '[a-z]' '[A-Z]'` + AC_DEFINE_UNQUOTED(NEED_DECLARATION_$gas_decl_name_upcase)]) +} +])dnl +dnl +dnl Some non-ANSI preprocessors botch requoting inside strings. That's bad +dnl enough, but on some of those systems, the assert macro relies on requoting +dnl working properly! +dnl GAS_WORKING_ASSERT +AC_DEFUN(GAS_WORKING_ASSERT, +[AC_MSG_CHECKING([for working assert macro]) +AC_CACHE_VAL(gas_cv_assert_ok, +AC_TRY_LINK([#include +#include ], [ +/* check for requoting problems */ +static int a, b, c, d; +static char *s; +assert (!strcmp(s, "foo bar baz quux")); +/* check for newline handling */ +assert (a == b + || c == d); +], gas_cv_assert_ok=yes, gas_cv_assert_ok=no))dnl +AC_MSG_RESULT($gas_cv_assert_ok) +test $gas_cv_assert_ok = yes || AC_DEFINE(BROKEN_ASSERT) +])dnl +dnl +dnl Since many Bourne shell implementations lack subroutines, use this +dnl hack to simplify the code in configure.in. +dnl GAS_UNIQ(listvar) +AC_DEFUN(GAS_UNIQ, +[_gas_uniq_list="[$]$1" +_gas_uniq_newlist="" +dnl Protect against empty input list. +for _gas_uniq_i in _gas_uniq_dummy [$]_gas_uniq_list ; do + case [$]_gas_uniq_i in + _gas_uniq_dummy) ;; + *) case " [$]_gas_uniq_newlist " in + *" [$]_gas_uniq_i "*) ;; + *) _gas_uniq_newlist="[$]_gas_uniq_newlist [$]_gas_uniq_i" ;; + esac ;; + esac +done +$1=[$]_gas_uniq_newlist +])dnl diff --git a/gnu/usr.bin/binutils/gas/app.c b/gnu/usr.bin/binutils/gas/app.c new file mode 100644 index 00000000000..794bcdd5649 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/app.c @@ -0,0 +1,1012 @@ +/* This is the Assembler Pre-Processor + Copyright (C) 1987, 1990, 1991, 1992, 1994 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 2, 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. */ + +/* Modified by Allen Wirfs-Brock, Instantiations Inc 2/90 */ +/* App, the assembler pre-processor. This pre-processor strips out excess + spaces, turns single-quoted characters into a decimal constant, and turns + # into a .line \n.file + pair. This needs better error-handling. */ + +#include +#include "as.h" /* For BAD_CASE() only */ + +#if (__STDC__ != 1) +#ifndef const +#define const /* empty */ +#endif +#endif + +static char lex[256]; +static const char symbol_chars[] = +"$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + +#define LEX_IS_SYMBOL_COMPONENT 1 +#define LEX_IS_WHITESPACE 2 +#define LEX_IS_LINE_SEPARATOR 3 +#define LEX_IS_COMMENT_START 4 +#define LEX_IS_LINE_COMMENT_START 5 +#define LEX_IS_TWOCHAR_COMMENT_1ST 6 +#define LEX_IS_TWOCHAR_COMMENT_2ND 7 +#define LEX_IS_STRINGQUOTE 8 +#define LEX_IS_COLON 9 +#define LEX_IS_NEWLINE 10 +#define LEX_IS_ONECHAR_QUOTE 11 +#define IS_SYMBOL_COMPONENT(c) (lex[c] == LEX_IS_SYMBOL_COMPONENT) +#define IS_WHITESPACE(c) (lex[c] == LEX_IS_WHITESPACE) +#define IS_LINE_SEPARATOR(c) (lex[c] == LEX_IS_LINE_SEPARATOR) +#define IS_COMMENT(c) (lex[c] == LEX_IS_COMMENT_START) +#define IS_LINE_COMMENT(c) (lex[c] == LEX_IS_LINE_COMMENT_START) +#define IS_NEWLINE(c) (lex[c] == LEX_IS_NEWLINE) + +static int process_escape PARAMS ((int)); + +/* FIXME-soon: The entire lexer/parser thingy should be + built statically at compile time rather than dynamically + each and every time the assembler is run. xoxorich. */ + +void +do_scrub_begin () +{ + const char *p; + + lex[' '] = LEX_IS_WHITESPACE; + lex['\t'] = LEX_IS_WHITESPACE; + lex['\n'] = LEX_IS_NEWLINE; + lex[';'] = LEX_IS_LINE_SEPARATOR; + lex[':'] = LEX_IS_COLON; + + if (! flag_mri) + { + lex['"'] = LEX_IS_STRINGQUOTE; + +#ifndef TC_HPPA + lex['\''] = LEX_IS_ONECHAR_QUOTE; +#endif + +#ifdef SINGLE_QUOTE_STRINGS + lex['\''] = LEX_IS_STRINGQUOTE; +#endif + } + + /* Note: if any other character can be LEX_IS_STRINGQUOTE, the loop + in state 5 of do_scrub_chars must be changed. */ + + /* Note that these override the previous defaults, e.g. if ';' is a + comment char, then it isn't a line separator. */ + for (p = symbol_chars; *p; ++p) + { + lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT; + } /* declare symbol characters */ + + for (p = comment_chars; *p; p++) + { + lex[(unsigned char) *p] = LEX_IS_COMMENT_START; + } /* declare comment chars */ + + for (p = line_comment_chars; *p; p++) + { + lex[(unsigned char) *p] = LEX_IS_LINE_COMMENT_START; + } /* declare line comment chars */ + + for (p = line_separator_chars; *p; p++) + { + lex[(unsigned char) *p] = LEX_IS_LINE_SEPARATOR; + } /* declare line separators */ + + /* Only allow slash-star comments if slash is not in use */ + if (lex['/'] == 0) + { + lex['/'] = LEX_IS_TWOCHAR_COMMENT_1ST; + } + /* FIXME-soon. This is a bad hack but otherwise, we can't do + c-style comments when '/' is a line comment char. xoxorich. */ + if (lex['*'] == 0) + { + lex['*'] = LEX_IS_TWOCHAR_COMMENT_2ND; + } + + if (flag_mri) + { + lex['\''] = LEX_IS_STRINGQUOTE; + lex[';'] = LEX_IS_COMMENT_START; + lex['*'] = LEX_IS_LINE_COMMENT_START; + /* The MRI documentation says '!' is LEX_IS_COMMENT_START, but + then it can't be used in an expression. */ + lex['!'] = LEX_IS_LINE_COMMENT_START; + } +} /* do_scrub_begin() */ + +/* Saved state of the scrubber */ +static int state; +static int old_state; +static char *out_string; +static char out_buf[20]; +static int add_newlines; +static char *saved_input; +static int saved_input_len; + +/* Data structure for saving the state of app across #include's. Note that + app is called asynchronously to the parsing of the .include's, so our + state at the time .include is interpreted is completely unrelated. + That's why we have to save it all. */ + +struct app_save + { + int state; + int old_state; + char *out_string; + char out_buf[sizeof (out_buf)]; + int add_newlines; + char *saved_input; + int saved_input_len; + }; + +char * +app_push () +{ + register struct app_save *saved; + + saved = (struct app_save *) xmalloc (sizeof (*saved)); + saved->state = state; + saved->old_state = old_state; + saved->out_string = out_string; + memcpy (saved->out_buf, out_buf, sizeof (out_buf)); + saved->add_newlines = add_newlines; + saved->saved_input = saved_input; + saved->saved_input_len = saved_input_len; + + /* do_scrub_begin() is not useful, just wastes time. */ + + state = 0; + saved_input = NULL; + + return (char *) saved; +} + +void +app_pop (arg) + char *arg; +{ + register struct app_save *saved = (struct app_save *) arg; + + /* There is no do_scrub_end (). */ + state = saved->state; + old_state = saved->old_state; + out_string = saved->out_string; + memcpy (out_buf, saved->out_buf, sizeof (out_buf)); + add_newlines = saved->add_newlines; + saved_input = saved->saved_input; + saved_input_len = saved->saved_input_len; + + free (arg); +} /* app_pop() */ + +/* @@ This assumes that \n &c are the same on host and target. This is not + necessarily true. */ +static int +process_escape (ch) + int ch; +{ + switch (ch) + { + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case '\'': + return '\''; + case '"': + return '\"'; + default: + return ch; + } +} + +/* This function is called to process input characters. The GET + parameter is used to retrieve more input characters. GET should + set its parameter to point to a buffer, and return the length of + the buffer; it should return 0 at end of file. The scrubbed output + characters are put into the buffer starting at TOSTART; the TOSTART + buffer is TOLEN bytes in length. The function returns the number + of scrubbed characters put into TOSTART. This will be TOLEN unless + end of file was seen. This function is arranged as a state + machine, and saves its state so that it may return at any point. + This is the way the old code used to work. */ + +int +do_scrub_chars (get, tostart, tolen) + int (*get) PARAMS ((char **)); + char *tostart; + int tolen; +{ + char *to = tostart; + char *toend = tostart + tolen; + char *from; + char *fromend; + int fromlen; + register int ch, ch2 = 0; + int not_cpp_line = 0; + + /*State 0: beginning of normal line + 1: After first whitespace on line (flush more white) + 2: After first non-white (opcode) on line (keep 1white) + 3: after second white on line (into operands) (flush white) + 4: after putting out a .line, put out digits + 5: parsing a string, then go to old-state + 6: putting out \ escape in a "d string. + 7: After putting out a .appfile, put out string. + 8: After putting out a .appfile string, flush until newline. + 9: After seeing symbol char in state 3 (keep 1white after symchar) + 10: After seeing whitespace in state 9 (keep white before symchar) + 11: After seeing a symbol character in state 0 (eg a label definition) + -1: output string in out_string and go to the state in old_state + -2: flush text until a '*' '/' is seen, then go to state old_state + */ + + /* I added states 9 and 10 because the MIPS ECOFF assembler uses + constructs like ``.loc 1 20''. This was turning into ``.loc + 120''. States 9 and 10 ensure that a space is never dropped in + between characters which could appear in a identifier. Ian + Taylor, ian@cygnus.com. + + I added state 11 so that something like "Lfoo add %r25,%r26,%r27" works + correctly on the PA (and any other target where colons are optional). + Jeff Law, law@cs.utah.edu. */ + + /* This macro gets the next input character. */ + +#define GET() \ + (from < fromend \ + ? *from++ \ + : ((saved_input != NULL \ + ? (free (saved_input), \ + saved_input = NULL, \ + 0) \ + : 0), \ + fromlen = (*get) (&from), \ + fromend = from + fromlen, \ + (fromlen == 0 \ + ? EOF \ + : *from++))) + + /* This macro pushes a character back on the input stream. */ + +#define UNGET(uch) (*--from = (uch)) + + /* This macro puts a character into the output buffer. If this + character fills the output buffer, this macro jumps to the label + TOFULL. We use this rather ugly approach because we need to + handle two different termination conditions: EOF on the input + stream, and a full output buffer. It would be simpler if we + always read in the entire input stream before processing it, but + I don't want to make such a significant change to the assembler's + memory usage. */ + +#define PUT(pch) \ + do \ + { \ + *to++ = (pch); \ + if (to >= toend) \ + goto tofull; \ + } \ + while (0) + + if (saved_input != NULL) + { + from = saved_input; + fromend = from + saved_input_len; + } + else + { + fromlen = (*get) (&from); + if (fromlen == 0) + return 0; + fromend = from + fromlen; + } + + while (1) + { + /* The cases in this switch end with continue, in order to + branch back to the top of this while loop and generate the + next output character in the appropriate state. */ + switch (state) + { + case -1: + ch = *out_string++; + if (*out_string == '\0') + { + state = old_state; + old_state = 3; + } + PUT (ch); + continue; + + case -2: + for (;;) + { + do + { + ch = GET (); + + if (ch == EOF) + { + as_warn ("end of file in comment"); + goto fromeof; + } + + if (ch == '\n') + PUT ('\n'); + } + while (ch != '*'); + + while ((ch = GET ()) == '*') + ; + + if (ch == EOF) + { + as_warn ("end of file in comment"); + goto fromeof; + } + + if (ch == '/') + break; + + UNGET (ch); + } + + state = old_state; + PUT (' '); + continue; + + case 4: + ch = GET (); + if (ch == EOF) + goto fromeof; + else if (ch >= '0' && ch <= '9') + PUT (ch); + else + { + while (ch != EOF && IS_WHITESPACE (ch)) + ch = GET (); + if (ch == '"') + { + UNGET (ch); + out_string = "\n\t.appfile "; + old_state = 7; + state = -1; + PUT (*out_string++); + } + else + { + while (ch != EOF && ch != '\n') + ch = GET (); + state = 0; + PUT (ch); + } + } + continue; + + case 5: + /* We are going to copy everything up to a quote character, + with special handling for a backslash. We try to + optimize the copying in the simple case without using the + GET and PUT macros. */ + { + char *s; + int len; + + for (s = from; s < fromend; s++) + { + ch = *s; + /* This condition must be changed if the type of any + other character can be LEX_IS_STRINGQUOTE. */ + if (ch == '\\' + || ch == '"' + || ch == '\'' + || ch == '\n') + break; + } + len = s - from; + if (len > toend - to) + len = toend - to; + if (len > 0) + { + memcpy (to, from, len); + to += len; + from += len; + } + } + + ch = GET (); + if (ch == EOF) + { + as_warn ("end of file in string: inserted '\"'"); + state = old_state; + UNGET ('\n'); + PUT ('"'); + } + else if (lex[ch] == LEX_IS_STRINGQUOTE) + { + state = old_state; + PUT (ch); + } +#ifndef NO_STRING_ESCAPES + else if (ch == '\\') + { + state = 6; + PUT (ch); + } +#endif + else if (flag_mri && ch == '\n') + { + /* Just quietly terminate the string. This permits lines like + bne label loop if we haven't reach end yet + */ + state = old_state; + UNGET (ch); + PUT ('\''); + } + else + { + PUT (ch); + } + continue; + + case 6: + state = 5; + ch = GET (); + switch (ch) + { + /* Handle strings broken across lines, by turning '\n' into + '\\' and 'n'. */ + case '\n': + UNGET ('n'); + add_newlines++; + PUT ('\\'); + continue; + + case '"': + case '\\': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': + case 'x': + case 'X': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + break; +#if defined(IGNORE_NONSTANDARD_ESCAPES) | defined(ONLY_STANDARD_ESCAPES) + default: + as_warn ("Unknown escape '\\%c' in string: Ignored", ch); + break; +#else /* ONLY_STANDARD_ESCAPES */ + default: + /* Accept \x as x for any x */ + break; +#endif /* ONLY_STANDARD_ESCAPES */ + + case EOF: + as_warn ("End of file in string: '\"' inserted"); + PUT ('"'); + continue; + } + PUT (ch); + continue; + + case 7: + ch = GET (); + state = 5; + old_state = 8; + if (ch == EOF) + goto fromeof; + PUT (ch); + continue; + + case 8: + do + ch = GET (); + while (ch != '\n' && ch != EOF); + if (ch == EOF) + goto fromeof; + state = 0; + PUT (ch); + continue; + } + + /* OK, we are somewhere in states 0 through 4 or 9 through 11 */ + + /* flushchar: */ + ch = GET (); + recycle: + if (ch == EOF) + { + if (state != 0) + { + as_warn ("end of file not at end of a line; newline inserted"); + state = 0; + PUT ('\n'); + } + goto fromeof; + } + + switch (lex[ch]) + { + case LEX_IS_WHITESPACE: + do + { + ch = GET (); + } + while (ch != EOF && IS_WHITESPACE (ch)); + if (ch == EOF) + goto fromeof; + + if (state == 0) + { + /* Preserve a single whitespace character at the + beginning of a line. */ + state = 1; + UNGET (ch); + PUT (' '); + break; + } + + if (IS_COMMENT (ch) + || ch == '/' + || IS_LINE_SEPARATOR (ch)) + { + /* cpp never outputs a leading space before the #, so + try to avoid being confused. */ + not_cpp_line = 1; + if (flag_mri) + { + /* In MRI mode, we keep these spaces. */ + UNGET (ch); + PUT (' '); + break; + } + goto recycle; + } + + /* If we're in state 2 or 11, we've seen a non-white + character followed by whitespace. If the next character + is ':', this is whitespace after a label name which we + normally must ignore. In MRI mode, though, spaces are + not permitted between the label and the colon. */ + if ((state == 2 || state == 11) + && lex[ch] == LEX_IS_COLON + && ! flag_mri) + { + state = 1; + PUT (ch); + break; + } + + switch (state) + { + case 0: + state++; + goto recycle; /* Punted leading sp */ + case 1: + /* We can arrive here if we leave a leading whitespace + character at the beginning of a line. */ + goto recycle; + case 2: + state = 3; + if (to + 1 < toend) + { + /* Optimize common case by skipping UNGET/GET. */ + PUT (' '); /* Sp after opco */ + goto recycle; + } + UNGET (ch); + PUT (' '); + break; + case 3: + if (flag_mri) + { + /* In MRI mode, we keep these spaces. */ + UNGET (ch); + PUT (' '); + break; + } + goto recycle; /* Sp in operands */ + case 9: + case 10: + if (flag_mri) + { + /* In MRI mode, we keep these spaces. */ + state = 3; + UNGET (ch); + PUT (' '); + break; + } + state = 10; /* Sp after symbol char */ + goto recycle; + case 11: + state = 1; + UNGET (ch); + PUT (' '); /* Sp after label definition. */ + break; + default: + BAD_CASE (state); + } + break; + + case LEX_IS_TWOCHAR_COMMENT_1ST: + ch2 = GET (); + if (ch2 != EOF && lex[ch2] == LEX_IS_TWOCHAR_COMMENT_2ND) + { + for (;;) + { + do + { + ch2 = GET (); + if (ch2 != EOF && IS_NEWLINE (ch2)) + add_newlines++; + } + while (ch2 != EOF && + (lex[ch2] != LEX_IS_TWOCHAR_COMMENT_2ND)); + + while (ch2 != EOF && + (lex[ch2] == LEX_IS_TWOCHAR_COMMENT_2ND)) + { + ch2 = GET (); + } + + if (ch2 == EOF + || lex[ch2] == LEX_IS_TWOCHAR_COMMENT_1ST) + break; + UNGET (ch); + } + if (ch2 == EOF) + as_warn ("end of file in multiline comment"); + + ch = ' '; + goto recycle; + } + else + { + if (ch2 != EOF) + UNGET (ch2); + if (state == 9 || state == 10) + state = 3; + PUT (ch); + } + break; + + case LEX_IS_STRINGQUOTE: + if (state == 10) + { + /* Preserve the whitespace in foo "bar" */ + UNGET (ch); + state = 3; + PUT (' '); + + /* PUT didn't jump out. We could just break, but we + know what will happen, so optimize a bit. */ + ch = GET (); + old_state = 3; + } + else if (state == 9) + old_state = 3; + else + old_state = state; + state = 5; + PUT (ch); + break; + +#ifndef IEEE_STYLE + case LEX_IS_ONECHAR_QUOTE: + if (state == 10) + { + /* Preserve the whitespace in foo 'b' */ + UNGET (ch); + state = 3; + PUT (' '); + break; + } + ch = GET (); + if (ch == EOF) + { + as_warn ("end of file after a one-character quote; \\0 inserted"); + ch = 0; + } + if (ch == '\\') + { + ch = GET (); + if (ch == EOF) + { + as_warn ("end of file in escape character"); + ch = '\\'; + } + else + ch = process_escape (ch); + } + sprintf (out_buf, "%d", (int) (unsigned char) ch); + + /* None of these 'x constants for us. We want 'x'. */ + if ((ch = GET ()) != '\'') + { +#ifdef REQUIRE_CHAR_CLOSE_QUOTE + as_warn ("Missing close quote: (assumed)"); +#else + if (ch != EOF) + UNGET (ch); +#endif + } + if (strlen (out_buf) == 1) + { + PUT (out_buf[0]); + break; + } + if (state == 9) + old_state = 3; + else + old_state = state; + state = -1; + out_string = out_buf; + PUT (*out_string++); + break; +#endif + + case LEX_IS_COLON: + if (state == 9 || state == 10) + state = 3; + else if (state != 3) + state = 1; + PUT (ch); + break; + + case LEX_IS_NEWLINE: + /* Roll out a bunch of newlines from inside comments, etc. */ + if (add_newlines) + { + --add_newlines; + UNGET (ch); + } + /* fall thru into... */ + + case LEX_IS_LINE_SEPARATOR: + state = 0; + PUT (ch); + break; + + case LEX_IS_LINE_COMMENT_START: + if (state == 0) /* Only comment at start of line. */ + { + /* FIXME-someday: The two character comment stuff was + badly thought out. On i386, we want '/' as line + comment start AND we want C style comments. hence + this hack. The whole lexical process should be + reworked. xoxorich. */ + if (ch == '/') + { + ch2 = GET (); + if (ch2 == '*') + { + state = -2; + break; + } + else + { + UNGET (ch2); + } + } /* bad hack */ + + if (ch != '#') + not_cpp_line = 1; + + do + { + ch = GET (); + } + while (ch != EOF && IS_WHITESPACE (ch)); + if (ch == EOF) + { + as_warn ("end of file in comment; newline inserted"); + PUT ('\n'); + break; + } + if (ch < '0' || ch > '9' || not_cpp_line) + { + /* Non-numerics: Eat whole comment line */ + while (ch != EOF && !IS_NEWLINE (ch)) + ch = GET (); + if (ch == EOF) + as_warn ("EOF in Comment: Newline inserted"); + state = 0; + PUT ('\n'); + break; + } + /* Numerics begin comment. Perhaps CPP `# 123 "filename"' */ + UNGET (ch); + old_state = 4; + state = -1; + out_string = "\t.appline "; + PUT (*out_string++); + break; + } + + /* We have a line comment character which is not at the + start of a line. If this is also a normal comment + character, fall through. Otherwise treat it as a default + character. */ + if (strchr (comment_chars, ch) == NULL + && (! flag_mri + || (ch != '!' && ch != '*'))) + goto de_fault; + if (flag_mri + && (ch == '!' || ch == '*') + && state != 1 + && state != 10) + goto de_fault; + /* Fall through. */ + case LEX_IS_COMMENT_START: + do + { + ch = GET (); + } + while (ch != EOF && !IS_NEWLINE (ch)); + if (ch == EOF) + as_warn ("end of file in comment; newline inserted"); + state = 0; + PUT ('\n'); + break; + + case LEX_IS_SYMBOL_COMPONENT: + if (state == 10) + { + /* This is a symbol character following another symbol + character, with whitespace in between. We skipped + the whitespace earlier, so output it now. */ + UNGET (ch); + state = 3; + PUT (' '); + break; + } + + if (state == 3) + state = 9; + + /* This is a common case. Quickly copy CH and all the + following symbol component or normal characters. */ + if (to + 1 < toend) + { + char *s; + int len; + + for (s = from; s < fromend; s++) + { + int type; + + ch2 = *s; + type = lex[ch2]; + if (type != 0 + && type != LEX_IS_SYMBOL_COMPONENT) + break; + } + if (s > from) + { + /* Handle the last character normally, for + simplicity. */ + --s; + } + len = s - from; + if (len > (toend - to) - 1) + len = (toend - to) - 1; + if (len > 0) + { + PUT (ch); + if (len > 8) + { + memcpy (to, from, len); + to += len; + from += len; + } + else + { + switch (len) + { + case 8: *to++ = *from++; + case 7: *to++ = *from++; + case 6: *to++ = *from++; + case 5: *to++ = *from++; + case 4: *to++ = *from++; + case 3: *to++ = *from++; + case 2: *to++ = *from++; + case 1: *to++ = *from++; + } + } + ch = GET (); + } + } + + /* Fall through. */ + default: + de_fault: + /* Some relatively `normal' character. */ + if (state == 0) + { + state = 11; /* Now seeing label definition */ + } + else if (state == 1) + { + state = 2; /* Ditto */ + } + else if (state == 9) + { + if (lex[ch] != LEX_IS_SYMBOL_COMPONENT) + state = 3; + } + else if (state == 10) + { + state = 3; + } + PUT (ch); + break; + } + } + + /*NOTREACHED*/ + + fromeof: + /* We have reached the end of the input. */ + return to - tostart; + + tofull: + /* The output buffer is full. Save any input we have not yet + processed. */ + if (fromend > from) + { + char *save; + + save = (char *) xmalloc (fromend - from); + memcpy (save, from, fromend - from); + if (saved_input != NULL) + free (saved_input); + saved_input = save; + saved_input_len = fromend - from; + } + else + { + if (saved_input != NULL) + { + free (saved_input); + saved_input = NULL; + } + } + return to - tostart; +} + +/* end of app.c */ diff --git a/gnu/usr.bin/binutils/gas/as.c b/gnu/usr.bin/binutils/gas/as.c new file mode 100644 index 00000000000..ec44c7e440d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/as.c @@ -0,0 +1,772 @@ +/* as.c - GAS main program. + Copyright (C) 1987, 1990, 1991, 1992, 1994 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 2, 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. */ + +/* + * Main program for AS; a 32-bit assembler of GNU. + * Understands command arguments. + * Has a few routines that don't fit in other modules because they + * are shared. + * + * + * bugs + * + * : initialisers + * Since no-one else says they will support them in future: I + * don't support them now. + * + */ + +#include "ansidecl.h" +#include "libiberty.h" + +#define COMMON + +#include "as.h" +#include "subsegs.h" +#include "output-file.h" +#include "sb.h" +#include "macro.h" + +static void perform_an_assembly_pass PARAMS ((int argc, char **argv)); +static int macro_expr PARAMS ((const char *, int, sb *, int *)); + +int listing; /* true if a listing is wanted */ + +static char *listing_filename = NULL; /* Name of listing file. */ + +/* Maximum level of macro nesting. */ + +int max_macro_nest = 100; + +char *myname; /* argv[0] */ +#ifdef BFD_ASSEMBLER +segT reg_section, expr_section; +segT text_section, data_section, bss_section; +#endif + +int chunksize = 5000; + +/* To monitor memory allocation more effectively, make this non-zero. + Then the chunk sizes for gas and bfd will be reduced. */ +int debug_memory = 0; + + +void +print_version_id () +{ + static int printed; + if (printed) + return; + printed = 1; + + fprintf (stderr, "GNU assembler version %s (%s)", GAS_VERSION, TARGET_ALIAS); +#ifdef BFD_ASSEMBLER + fprintf (stderr, ", using BFD version %s", BFD_VERSION); +#endif + fprintf (stderr, "\n"); +} + +void +show_usage (stream) + FILE *stream; +{ + fprintf (stream, "Usage: %s [option...] [asmfile...]\n", myname); + + fprintf (stream, "\ +Options:\n\ +-a[sub-option...] turn on listings\n\ + Sub-options [default hls]:\n\ + d omit debugging directives\n\ + h include high-level source\n\ + l include assembly\n\ + n omit forms processing\n\ + s include symbols\n\ + =file set listing file name (must be last sub-option)\n"); + fprintf (stream, "\ +-D produce assembler debugging messages\n\ +--defsym SYM=VAL define symbol SYM to given value\n\ +-f skip whitespace and comment preprocessing\n\ +--help show this message and exit\n\ +-I DIR add DIR to search list for .include directives\n\ +-J don't warn about signed overflow\n\ +-K warn when differences altered for long displacements\n\ +-L keep local symbols (starting with `L')\n"); + fprintf (stream, "\ +-M,--mri assemble in MRI compatibility mode\n\ +-nocpp ignored\n\ +-o OBJFILE name the object-file output OBJFILE (default a.out)\n\ +-R fold data section into text section\n\ +--statistics print maximum bytes and total seconds used\n\ +--version print assembler version number and exit\n\ +-W suppress warnings\n\ +-w ignored\n\ +-X ignored\n\ +-Z generate object file even after errors\n"); + + md_show_usage (stream); +} + +#ifdef USE_EMULATIONS +#define EMULATION_ENVIRON "AS_EMULATION" + +extern struct emulation mipsbelf, mipslelf, mipself; +extern struct emulation mipsbecoff, mipslecoff, mipsecoff; + +static const char *emulation_name; +static struct emulation *const emulations[] = { EMULATIONS }; +static const int n_emulations = sizeof (emulations) / sizeof (emulations[0]); + +static void +select_emulation_mode (argc, argv) + int argc; + char **argv; +{ + int i; + char *p, *em = 0; + + for (i = 1; i < argc; i++) + if (!strncmp ("--em", argv[i], 4)) + break; + + if (i == argc) + goto do_default; + + p = strchr (argv[i], '='); + if (p) + p++; + else + p = argv[i+1]; + + if (!p || !*p) + as_fatal ("missing emulation mode name"); + em = p; + + do_default: + if (em == 0) + em = getenv (EMULATION_ENVIRON); + if (em == 0) + em = DEFAULT_EMULATION; + + if (em) + { + for (i = 0; i < n_emulations; i++) + if (!strcmp (emulations[i]->name, em)) + break; + if (i == n_emulations) + as_fatal ("unrecognized emulation name `%s'", em); + this_emulation = emulations[i]; + } + else + this_emulation = emulations[0]; + + this_emulation->init (); +} + +const char * +default_emul_bfd_name () +{ + abort (); +} + +void +common_emul_init () +{ + this_format = this_emulation->format; + + if (this_emulation->leading_underscore == 2) + this_emulation->leading_underscore = this_format->dfl_leading_underscore; + + if (this_emulation->default_endian != 2) + target_big_endian = this_emulation->default_endian; + + if (this_emulation->fake_label_name == 0) + { + if (this_emulation->leading_underscore) + this_emulation->fake_label_name = "L0\001"; + else + /* What other parameters should we test? */ + this_emulation->fake_label_name = ".L0\001"; + } +} +#endif + +/* + * Since it is easy to do here we interpret the special arg "-" + * to mean "use stdin" and we set that argv[] pointing to "". + * After we have munged argv[], the only things left are source file + * name(s) and ""(s) denoting stdin. These file names are used + * (perhaps more than once) later. + * + * check for new machine-dep cmdline options in + * md_parse_option definitions in config/tc-*.c + */ + +void +parse_args (pargc, pargv) + int *pargc; + char ***pargv; +{ + int old_argc, new_argc; + char **old_argv, **new_argv; + + /* Starting the short option string with '-' is for programs that + 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. */ + + char *shortopts; + extern CONST char *md_shortopts; + static const char std_shortopts[] = + { + '-', 'J', +#ifndef WORKING_DOT_WORD + /* -K is not meaningful if .word is not being hacked. */ + 'K', +#endif + 'L', 'M', 'R', 'W', 'Z', 'f', 'a', ':', ':', 'D', 'I', ':', 'o', ':', +#ifndef VMS + /* -v takes an argument on VMS, so we don't make it a generic + option. */ + 'v', +#endif + 'w', 'X', + '\0' + }; + struct option *longopts; + extern struct option md_longopts[]; + extern size_t md_longopts_size; + static const struct option std_longopts[] = { +#define OPTION_HELP (OPTION_STD_BASE) + {"help", no_argument, NULL, OPTION_HELP}, + {"mri", no_argument, NULL, 'M'}, +#define OPTION_NOCPP (OPTION_STD_BASE + 1) + {"nocpp", no_argument, NULL, OPTION_NOCPP}, +#define OPTION_STATISTICS (OPTION_STD_BASE + 2) + {"statistics", no_argument, NULL, OPTION_STATISTICS}, +#define OPTION_VERSION (OPTION_STD_BASE + 3) + {"version", no_argument, NULL, OPTION_VERSION}, +#define OPTION_DUMPCONFIG (OPTION_STD_BASE + 4) + {"dump-config", no_argument, NULL, OPTION_DUMPCONFIG}, +#define OPTION_VERBOSE (OPTION_STD_BASE + 5) + {"verbose", no_argument, NULL, OPTION_VERBOSE}, +#define OPTION_EMULATION (OPTION_STD_BASE + 6) + {"emulation", required_argument, NULL, OPTION_EMULATION}, +#define OPTION_DEFSYM (OPTION_STD_BASE + 7) + {"defsym", required_argument, NULL, OPTION_DEFSYM} + }; + + /* Construct the option lists from the standard list and the + target dependent list. */ + shortopts = concat (std_shortopts, md_shortopts, (char *) NULL); + longopts = (struct option *) xmalloc (sizeof (std_longopts) + md_longopts_size); + memcpy (longopts, std_longopts, sizeof (std_longopts)); + memcpy ((char *) longopts + sizeof (std_longopts), + md_longopts, md_longopts_size); + + /* Make a local copy of the old argv. */ + old_argc = *pargc; + old_argv = *pargv; + + /* Initialize a new argv that contains no options. */ + new_argv = (char **) xmalloc (sizeof (char *) * (old_argc + 1)); + new_argv[0] = old_argv[0]; + new_argc = 1; + new_argv[new_argc] = NULL; + + while (1) + { + /* getopt_long_only is like getopt_long, but '-' as well as '--' can + indicate a long option. */ + int longind; + int optc = getopt_long_only (old_argc, old_argv, shortopts, longopts, + &longind); + + if (optc == -1) + break; + + switch (optc) + { + default: + /* md_parse_option should return 1 if it recognizes optc, + 0 if not. */ + if (md_parse_option (optc, optarg) != 0) + break; + /* `-v' isn't included in the general short_opts list, so check for + it explicity here before deciding we've gotten a bad argument. */ + if (optc == 'v') + { +#ifdef VMS + /* Telling getopt to treat -v's value as optional can result + in it picking up a following filename argument here. The + VMS code in md_parse_option can return 0 in that case, + but it has no way of pushing the filename argument back. */ + if (optarg && *optarg) + new_argv[new_argc++] = optarg, new_argv[new_argc] = NULL; + else +#else + case 'v': +#endif + case OPTION_VERBOSE: + print_version_id (); + break; + } + /*FALLTHRU*/ + + case '?': + exit (EXIT_FAILURE); + + case 1: /* File name. */ + if (!strcmp (optarg, "-")) + optarg = ""; + new_argv[new_argc++] = optarg; + new_argv[new_argc] = NULL; + break; + + case OPTION_HELP: + show_usage (stdout); + exit (EXIT_SUCCESS); + + case OPTION_NOCPP: + break; + + case OPTION_STATISTICS: + flag_print_statistics = 1; + break; + + case OPTION_VERSION: + print_version_id (); + exit (EXIT_SUCCESS); + + case OPTION_EMULATION: +#ifdef USE_EMULATIONS + if (strcmp (optarg, this_emulation->name)) + as_fatal ("multiple emulation names specified"); +#else + as_fatal ("emulations not handled in this configuration"); +#endif + break; + + case OPTION_DUMPCONFIG: + fprintf (stderr, "alias = %s\n", TARGET_ALIAS); + fprintf (stderr, "canonical = %s\n", TARGET_CANONICAL); + fprintf (stderr, "cpu-type = %s\n", TARGET_CPU); +#ifdef TARGET_OBJ_FORMAT + fprintf (stderr, "format = %s\n", TARGET_OBJ_FORMAT); +#endif +#ifdef TARGET_FORMAT + fprintf (stderr, "bfd-target = %s\n", TARGET_FORMAT); +#endif + exit (EXIT_SUCCESS); + + case OPTION_DEFSYM: + { + char *s; + long i; + symbolS *sym; + + for (s = optarg; *s != '\0' && *s != '='; s++) + ; + if (*s == '\0') + as_fatal ("bad defsym; format is --defsym name=value"); + *s++ = '\0'; + i = strtol (s, (char **) NULL, 0); + sym = symbol_new (optarg, absolute_section, (valueT) i, + &zero_address_frag); + symbol_table_insert (sym); + } + break; + + case 'J': + flag_signed_overflow_ok = 1; + break; + +#ifndef WORKING_DOT_WORD + case 'K': + flag_warn_displacement = 1; + break; +#endif + + case 'L': + flag_keep_locals = 1; + break; + + case 'M': + flag_mri = 1; + break; + + case 'R': + flag_readonly_data_in_text = 1; + break; + + case 'W': + flag_no_warnings = 1; + break; + + case 'Z': + flag_always_generate_output = 1; + break; + + case 'a': + if (optarg) + { + while (*optarg) + { + switch (*optarg) + { + case 'd': + listing |= LISTING_NODEBUG; + break; + case 'h': + listing |= LISTING_HLL; + break; + case 'l': + listing |= LISTING_LISTING; + break; + case 'n': + listing |= LISTING_NOFORM; + break; + case 's': + listing |= LISTING_SYMBOLS; + break; + case '=': + listing_filename = strdup (optarg + 1); + if (listing_filename == NULL) + as_fatal ("virtual memory exhausted"); + optarg += strlen (listing_filename); + break; + default: + as_fatal ("invalid listing option `%c'", *optarg); + break; + } + optarg++; + } + } + if (!listing) + listing = LISTING_DEFAULT; + break; + + case 'D': + /* DEBUG is implemented: it debugs different */ + /* things from other people's assemblers. */ + flag_debug = 1; + break; + + case 'f': + flag_no_comments = 1; + break; + + case 'I': + { /* Include file directory */ + char *temp = strdup (optarg); + if (!temp) + as_fatal ("virtual memory exhausted"); + add_include_dir (temp); + break; + } + + case 'o': + out_file_name = strdup (optarg); + if (!out_file_name) + as_fatal ("virtual memory exhausted"); + break; + + case 'w': + break; + + case 'X': + /* -X means treat warnings as errors */ + break; + } + } + + free (shortopts); + free (longopts); + + *pargc = new_argc; + *pargv = new_argv; +} + +int +main (argc, argv) + int argc; + char **argv; +{ + int macro_alternate; + int macro_strip_at; + int keep_it; + long start_time = get_run_time (); + + if (debug_memory) + { +#ifdef BFD_ASSEMBLER + extern long _bfd_chunksize; + _bfd_chunksize = 64; +#endif + chunksize = 64; + } + +#ifdef HOST_SPECIAL_INIT + HOST_SPECIAL_INIT (argc, argv); +#endif + + myname = argv[0]; + xmalloc_set_program_name (myname); + + START_PROGRESS (myname, 0); + +#ifndef OBJ_DEFAULT_OUTPUT_FILE_NAME +#define OBJ_DEFAULT_OUTPUT_FILE_NAME "a.out" +#endif + + out_file_name = OBJ_DEFAULT_OUTPUT_FILE_NAME; + + hex_init (); +#ifdef BFD_ASSEMBLER + bfd_init (); +#endif + +#ifdef USE_EMULATIONS + select_emulation_mode (argc, argv); +#endif + + PROGRESS (1); + symbol_begin (); + frag_init (); + subsegs_begin (); + read_begin (); + parse_args (&argc, &argv); + input_scrub_begin (); + expr_begin (); + + macro_alternate = 0; + macro_strip_at = 0; +#ifdef TC_I960 + macro_strip_at = flag_mri; +#endif +#ifdef TC_A29K + /* For compatibility with the AMD 29K family macro assembler + specification. */ + macro_alternate = 1; + macro_strip_at = 1; +#endif + + macro_init (macro_alternate, flag_mri, macro_strip_at, macro_expr); + + PROGRESS (1); + +#ifdef BFD_ASSEMBLER + output_file_create (out_file_name); + assert (stdoutput != 0); +#endif + +#ifdef tc_init_after_args + tc_init_after_args (); +#endif + + PROGRESS (1); + + perform_an_assembly_pass (argc, argv); /* Assemble it. */ + +#ifdef md_end + md_end (); +#endif + + if (seen_at_least_1_file () + && !((had_warnings () && flag_always_generate_output) + || had_errors () > 0)) + keep_it = 1; + else + keep_it = 0; + + if (keep_it) + write_object_file (); + +#ifndef NO_LISTING + listing_print (listing_filename); +#endif + +#ifndef OBJ_VMS /* does its own file handling */ +#ifndef BFD_ASSEMBLER + if (keep_it) +#endif + output_file_close (out_file_name); +#endif + + if (!keep_it) + unlink (out_file_name); + + input_scrub_end (); + + END_PROGRESS (myname); + + if (flag_print_statistics) + { + extern char **environ; +#ifdef HAVE_SBRK + char *lim = (char *) sbrk (0); +#endif + long run_time = get_run_time () - start_time; + + fprintf (stderr, "%s: total time in assembly: %ld.%06ld\n", + myname, run_time / 1000000, run_time % 1000000); +#ifdef HAVE_SBRK + fprintf (stderr, "%s: data size %ld\n", + myname, (long) (lim - (char *) &environ)); +#endif + } + + /* Use exit instead of return, because under VMS environments they + may not place the same interpretation on the value given. */ + if ((had_warnings () && flag_always_generate_output) + || had_errors () > 0) + exit (EXIT_FAILURE); + exit (EXIT_SUCCESS); +} + + +/* perform_an_assembly_pass() + * + * Here to attempt 1 pass over each input file. + * We scan argv[*] looking for filenames or exactly "" which is + * shorthand for stdin. Any argv that is NULL is not a file-name. + * We set need_pass_2 TRUE if, after this, we still have unresolved + * expressions of the form (unknown value)+-(unknown value). + * + * Note the un*x semantics: there is only 1 logical input file, but it + * may be a catenation of many 'physical' input files. + */ +static void +perform_an_assembly_pass (argc, argv) + int argc; + char **argv; +{ + int saw_a_file = 0; +#ifdef BFD_ASSEMBLER + flagword applicable; +#endif + + need_pass_2 = 0; + +#ifndef BFD_ASSEMBLER +#ifdef MANY_SEGMENTS + { + unsigned int i; + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + segment_info[i].fix_root = 0; + } + /* Create the three fixed ones */ + { + segT seg; + +#ifdef TE_APOLLO + seg = subseg_new (".wtext", 0); +#else + seg = subseg_new (".text", 0); +#endif + assert (seg == SEG_E0); + seg = subseg_new (".data", 0); + assert (seg == SEG_E1); + seg = subseg_new (".bss", 0); + assert (seg == SEG_E2); +#ifdef TE_APOLLO + create_target_segments (); +#endif + } + +#else /* not MANY_SEGMENTS */ + text_fix_root = NULL; + data_fix_root = NULL; + bss_fix_root = NULL; +#endif /* not MANY_SEGMENTS */ +#else /* BFD_ASSEMBLER */ + /* Create the standard sections, and those the assembler uses + internally. */ + text_section = subseg_new (".text", 0); + data_section = subseg_new (".data", 0); + bss_section = subseg_new (".bss", 0); + /* @@ FIXME -- we're setting the RELOC flag so that sections are assumed + to have relocs, otherwise we don't find out in time. */ + applicable = bfd_applicable_section_flags (stdoutput); + bfd_set_section_flags (stdoutput, text_section, + applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC + | SEC_CODE | SEC_READONLY)); + /* @@ FIXME -- SEC_CODE seems to mean code only, rather than code possibly.*/ + bfd_set_section_flags (stdoutput, data_section, + applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)); + bfd_set_section_flags (stdoutput, bss_section, applicable & SEC_ALLOC); + seg_info (bss_section)->bss = 1; + subseg_new (BFD_ABS_SECTION_NAME, 0); + subseg_new (BFD_UND_SECTION_NAME, 0); + reg_section = subseg_new ("*GAS `reg' section*", 0); + expr_section = subseg_new ("*GAS `expr' section*", 0); + +#endif /* BFD_ASSEMBLER */ + + subseg_set (text_section, 0); + + /* This may add symbol table entries, which requires having an open BFD, + and sections already created, in BFD_ASSEMBLER mode. */ + md_begin (); + + argv++; /* skip argv[0] */ + argc--; /* skip argv[0] */ + while (argc--) + { + if (*argv) + { /* Is it a file-name argument? */ + PROGRESS (1); + saw_a_file++; + /* argv->"" if stdin desired, else->filename */ + read_a_source_file (*argv); + } + argv++; /* completed that argv */ + } + if (!saw_a_file) + read_a_source_file (""); +} /* perform_an_assembly_pass() */ + +/* The interface between the macro code and gas expression handling. */ + +static int +macro_expr (emsg, idx, in, val) + const char *emsg; + int idx; + sb *in; + int *val; +{ + char *hold; + expressionS ex; + + sb_terminate (in); + + hold = input_line_pointer; + input_line_pointer = in->ptr + idx; + expression (&ex); + idx = input_line_pointer - in->ptr; + input_line_pointer = hold; + + if (ex.X_op != O_constant) + as_bad ("%s", emsg); + + *val = (int) ex.X_add_number; + + return idx; +} + +/* end of as.c */ diff --git a/gnu/usr.bin/binutils/gas/as.h b/gnu/usr.bin/binutils/gas/as.h new file mode 100644 index 00000000000..a7e1ebe9ab1 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/as.h @@ -0,0 +1,659 @@ +/* as.h - global header file + Copyright (C) 1987, 1990, 1991, 1992 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 2, 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. */ + +#ifndef GAS +#define GAS 1 +/* + * I think this stuff is largely out of date. xoxorich. + * + * CAPITALISED names are #defined. + * "lowercaseH" is #defined if "lowercase.h" has been #include-d. + * "lowercaseT" is a typedef of "lowercase" objects. + * "lowercaseP" is type "pointer to object of type 'lowercase'". + * "lowercaseS" is typedef struct ... lowercaseS. + * + * #define DEBUG to enable all the "know" assertion tests. + * #define SUSPECT when debugging hash code. + * #define COMMON as "extern" for all modules except one, where you #define + * COMMON as "". + * If TEST is #defined, then we are testing a module: #define COMMON as "". + */ + +#include "config.h" + +/* This is the code recommended in the autoconf documentation, almost + verbatim. If it doesn't work for you, let me know, and notify + djm@gnu.ai.mit.edu as well. */ +/* Added #undef for DJ Delorie. The right fix is to ensure that as.h + is included first, before even any system header files, in all files + that use it. KR 1994.11.03 */ +/* Added void* version for STDC case. This is to be compatible with + the declaration in bison.simple, used for m68k operand parsing. + --KR 1995.08.08 */ +/* Force void* decl for hpux. This is what Bison uses. --KR 1995.08.16 */ + +/* AIX requires this to be the first thing in the file. */ +#ifdef __GNUC__ +# undef alloca +# define alloca __builtin_alloca +#else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +# if !defined (__STDC__) && !defined (__hpux) +char *alloca (); +# else +void *alloca (); +# endif /* __STDC__, __hpux */ +# endif /* alloca */ +# endif /* _AIX */ +# endif /* HAVE_ALLOCA_H */ +#endif + +/* Now, tend to the rest of the configuration. */ + +/* System include files first... */ +#include +#include +#ifdef HAVE_STRING_H +#include +#else +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +/* for size_t, pid_t */ +#include +#endif + +/* Some systems do declare this, but this seems to be the universal + declaration, though the parameter type varies. (It ought to use + `const' but many systems prototype it without.) Include it here + for systems that don't declare it. If conflicts arise, just add + another autoconf test... */ +extern char *strdup (/* const char * */); + +#include +/* The first getopt value for machine-independent long options. + 150 isn't special; it's just an arbitrary non-ASCII char value. */ +#define OPTION_STD_BASE 150 +/* The first getopt value for machine-dependent long options. + 170 gives the standard options room to grow. */ +#define OPTION_MD_BASE 170 + +#ifdef DEBUG +#undef NDEBUG +#endif +#if !defined (__GNUC__) || __GNUC_MINOR__ <= 5 +#define __PRETTY_FUNCTION__ ((char*)0) +#endif +#if 0 + +/* Handle lossage with assert.h. */ +#ifndef BROKEN_ASSERT +#include +#else /* BROKEN_ASSERT */ +#ifndef NDEBUG +#define assert(p) ((p) ? 0 : (as_assert (__FILE__, __LINE__, __PRETTY_FUNCTION__), 0)) +#else +#define assert(p) ((p), 0) +#endif +#endif /* BROKEN_ASSERT */ + +#else + +#define assert(P) ((P) ? 0 : (as_assert (__FILE__, __LINE__, __PRETTY_FUNCTION__), 0)) +#undef abort +#define abort() as_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__) + +#endif + + +/* Now GNU header files... */ +#include +#ifdef BFD_ASSEMBLER +#include +#endif + +/* Define the standard progress macros. */ +#include + +/* This doesn't get taken care of anywhere. */ +#ifndef __MWERKS__ /* Metrowerks C chokes on the "defined (inline)" */ +#if !defined (__GNUC__) && !defined (inline) +#define inline +#endif +#endif /* !__MWERKS__ */ + +/* Other stuff from config.h. */ +#ifdef NEED_DECLARATION_MALLOC +extern PTR malloc (); +extern PTR realloc (); +#endif +#ifdef NEED_DECLARATION_FREE +extern void free (); +#endif +#ifdef NEED_DECLARATION_ERRNO +extern int errno; +#endif + +/* This is needed for VMS. */ +#if ! defined (HAVE_UNLINK) && defined (HAVE_REMOVE) +#define unlink remove +#endif + +/* Hack to make "gcc -Wall" not complain about obstack macros. */ +#if !defined (memcpy) && !defined (bcopy) +#define bcopy(src,dest,size) memcpy(dest,src,size) +#endif + +#ifdef BFD_ASSEMBLER +/* This one doesn't get declared, but we're using it anyways. This + should be fixed -- either it's part of the external interface or + it's not. */ +extern PTR bfd_alloc_by_size_t PARAMS ((bfd *abfd, size_t sz)); +#endif + +/* Make Saber happier on obstack.h. */ +#ifdef SABER +#undef __PTR_TO_INT +#define __PTR_TO_INT(P) ((int)(P)) +#undef __INT_TO_PTR +#define __INT_TO_PTR(P) ((char *)(P)) +#endif + +#ifndef __LINE__ +#define __LINE__ "unknown" +#endif /* __LINE__ */ + +#ifndef __FILE__ +#define __FILE__ "unknown" +#endif /* __FILE__ */ + +#ifndef __STDC__ +#ifndef const +#define const +#endif +#ifndef volatile +#define volatile +#endif +#endif /* ! __STDC__ */ + +#ifndef FOPEN_WB +#ifdef GO32 +#include "fopen-bin.h" +#else +#include "fopen-same.h" +#endif +#endif + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#endif + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free xfree + +#define xfree free + +#define BAD_CASE(val) \ +{ \ + as_fatal("Case value %ld unexpected at line %d of file \"%s\"\n", \ + (long) val, __LINE__, __FILE__); \ + } + +/* Version 2.1 of Solaris had problems with this declaration, but I + think that bug has since been fixed. If it causes problems on your + system, just delete it. */ +extern char *strstr (); + +#include "flonum.h" + +/* These are assembler-wide concepts */ + +#ifdef BFD_ASSEMBLER +extern bfd *stdoutput; +typedef bfd_vma addressT; +typedef bfd_signed_vma offsetT; +#else +typedef unsigned long addressT; +typedef long offsetT; +#endif + +/* Type of symbol value, etc. For use in prototypes. */ +typedef addressT valueT; + +#ifndef COMMON +#ifdef TEST +#define COMMON /* declare our COMMONs storage here. */ +#else +#define COMMON extern /* our commons live elswhere */ +#endif +#endif +/* COMMON now defined */ + +#ifdef DEBUG +#ifndef know +#define know(p) assert(p) /* Verify our assumptions! */ +#endif /* not yet defined */ +#else +#define know(p) /* know() checks are no-op.ed */ +#endif + +/* input_scrub.c */ + +/* + * Supplies sanitised buffers to read.c. + * Also understands printing line-number part of error messages. + */ + + +/* subsegs.c Sub-segments. Also, segment(=expression type)s.*/ + +#ifndef BFD_ASSEMBLER + +#ifdef MANY_SEGMENTS +#include "bfd.h" +#define N_SEGMENTS 10 +#define SEG_NORMAL(x) ((x) >= SEG_E0 && (x) <= SEG_E9) +#define SEG_LIST SEG_E0,SEG_E1,SEG_E2,SEG_E3,SEG_E4,SEG_E5,SEG_E6,SEG_E7,SEG_E8,SEG_E9 +#define SEG_TEXT SEG_E0 +#define SEG_DATA SEG_E1 +#define SEG_BSS SEG_E2 +#else +#define N_SEGMENTS 3 +#define SEG_NORMAL(x) ((x) == SEG_TEXT || (x) == SEG_DATA || (x) == SEG_BSS) +#define SEG_LIST SEG_TEXT,SEG_DATA,SEG_BSS +#endif + +typedef enum _segT + { + SEG_ABSOLUTE = 0, + SEG_LIST, + SEG_UNKNOWN, + SEG_GOOF, /* Only happens if AS has a logic error. */ + /* Invented so we don't crash printing */ + /* error message involving weird segment. */ + SEG_EXPR, /* Intermediate expression values. */ + SEG_DEBUG, /* Debug segment */ + SEG_NTV, /* Transfert vector preload segment */ + SEG_PTV, /* Transfert vector postload segment */ + SEG_REGISTER /* Mythical: a register-valued expression */ + } segT; + +#define SEG_MAXIMUM_ORDINAL (SEG_REGISTER) +#else +typedef asection *segT; +#define SEG_NORMAL(SEG) ((SEG) != absolute_section \ + && (SEG) != undefined_section \ + && (SEG) != reg_section \ + && (SEG) != expr_section) +#endif +typedef int subsegT; + +/* What subseg we are accreting now? */ +COMMON subsegT now_subseg; + +/* Segment our instructions emit to. */ +COMMON segT now_seg; + +#ifdef BFD_ASSEMBLER +#define segment_name(SEG) bfd_get_section_name (stdoutput, SEG) +#else +extern char const *const seg_name[]; +#define segment_name(SEG) seg_name[(int) (SEG)] +#endif + +#ifndef BFD_ASSEMBLER +extern int section_alignment[]; +#endif + +#ifdef BFD_ASSEMBLER +extern segT reg_section, expr_section; +/* Shouldn't these be eliminated someday? */ +extern segT text_section, data_section, bss_section; +#define absolute_section bfd_abs_section_ptr +#define undefined_section bfd_und_section_ptr +#else +#define reg_section SEG_REGISTER +#define expr_section SEG_EXPR +#define text_section SEG_TEXT +#define data_section SEG_DATA +#define bss_section SEG_BSS +#define absolute_section SEG_ABSOLUTE +#define undefined_section SEG_UNKNOWN +#endif + +/* relax() */ + +enum _relax_state + { + /* Variable chars to be repeated fr_offset times. + Fr_symbol unused. Used with fr_offset == 0 for a + constant length frag. */ + rs_fill = 1, + + /* Align: Fr_offset: power of 2. Variable chars: fill pattern. */ + rs_align, + + /* Align code: fr_offset: power of 2. Fill pattern is machine + specific, defaulting to all zeros. */ + rs_align_code, + + /* Org: Fr_offset, fr_symbol: address. 1 variable char: fill + character. */ + rs_org, + +#ifndef WORKING_DOT_WORD + /* JF: gunpoint */ + rs_broken_word, +#endif + + /* machine-specific relaxable (or similarly alterable) instruction */ + rs_machine_dependent, + + /* .space directive with expression operand that needs to be computed + later. Similar to rs_org, but different. + fr_symbol: operand + 1 variable char: fill character */ + rs_space + }; + +typedef enum _relax_state relax_stateT; + +/* This type is used in prototypes, so it can't be a type that will be + widened for argument passing. */ +typedef unsigned int relax_substateT; + +/* Enough bits for address, but still an integer type. + Could be a problem, cross-assembling for 64-bit machines. */ +typedef addressT relax_addressT; + + +/* frags.c */ + +/* + * A code fragment (frag) is some known number of chars, followed by some + * unknown number of chars. Typically the unknown number of chars is an + * instruction address whose size is yet unknown. We always know the greatest + * possible size the unknown number of chars may become, and reserve that + * much room at the end of the frag. + * Once created, frags do not change address during assembly. + * We chain the frags in (a) forward-linked list(s). The object-file address + * of the 1st char of a frag is generally not known until after relax(). + * Many things at assembly time describe an address by {object-file-address + * of a particular frag}+offset. + + BUG: it may be smarter to have a single pointer off to various different + notes for different frag kinds. See how code pans + */ +struct frag +{ + /* Object file address. */ + addressT fr_address; + /* Chain forward; ascending address order. Rooted in frch_root. */ + struct frag *fr_next; + + /* (Fixed) number of chars we know we have. May be 0. */ + offsetT fr_fix; + /* (Variable) number of chars after above. May be 0. */ + offsetT fr_var; + /* For variable-length tail. */ + struct symbol *fr_symbol; + /* For variable-length tail. */ + offsetT fr_offset; + /* Points to opcode low addr byte, for relaxation. */ + char *fr_opcode; + +#ifndef NO_LISTING + struct list_info_struct *line; +#endif + + /* What state is my tail in? */ + relax_stateT fr_type; + relax_substateT fr_subtype; + + /* Track the alignment and offset of the current frag. With this, + sometimes we can avoid creating new frags for .align directives. */ + unsigned short align_mask; + unsigned short align_offset; + + /* These are needed only on the NS32K machines. But since we don't + include targ-cpu.h until after this structure has been defined, + we can't really conditionalize it. This code should be + rearranged a bit to make that possible. + + In the meantime, if we get stuck like this with any other target, + create a union here. */ + char fr_pcrel_adjust, fr_bsr; + + /* Data begins here. */ + char fr_literal[1]; +}; + +#define SIZEOF_STRUCT_FRAG \ +((char *)zero_address_frag.fr_literal-(char *)&zero_address_frag) +/* We want to say fr_literal[0] above. */ + +typedef struct frag fragS; + +/* Current frag we are building. This frag is incomplete. It is, however, + included in frchain_now. The fr_fix field is bogus; instead, use: + obstack_next_free(&frags)-frag_now->fr_literal. */ +COMMON fragS *frag_now; +extern int frag_now_fix (); + +/* For foreign-segment symbol fixups. */ +COMMON fragS zero_address_frag; +/* For local common (N_BSS segment) fixups. */ +COMMON fragS bss_address_frag; + +/* main program "as.c" (command arguments etc) */ + +COMMON unsigned char flag_no_comments; /* -f */ +COMMON unsigned char flag_debug; /* -D */ +COMMON unsigned char flag_signed_overflow_ok; /* -J */ +#ifndef WORKING_DOT_WORD +COMMON unsigned char flag_warn_displacement; /* -K */ +#endif + +/* True if local symbols should be retained. */ +COMMON int flag_keep_locals; /* -L */ + +/* True if we are assembling using MRI syntax. */ +COMMON int flag_mri; + +/* Should the data section be made read-only and appended to the text + section? */ +COMMON unsigned char flag_readonly_data_in_text; /* -R */ + +/* True if warnings should be inhibited. */ +COMMON int flag_no_warnings; /* -W */ + +/* True if we should attempt to generate output even if non-fatal errors + are detected. */ +COMMON unsigned char flag_always_generate_output; /* -Z */ + +/* This is true if the assembler should output time and space usage. */ + +COMMON unsigned char flag_print_statistics; + +/* name of emitted object file */ +COMMON char *out_file_name; + +/* TRUE if we need a second pass. */ +COMMON int need_pass_2; + +/* TRUE if we should do no relaxing, and + leave lots of padding. */ +COMMON int linkrelax; + +/* TRUE if we should produce a listing. */ +extern int listing; + +/* Maximum level of macro nesting. */ +extern int max_macro_nest; + +/* Obstack chunk size. Keep large for efficient space use, make small to + increase malloc calls for monitoring memory allocation. */ +extern int chunksize; + +struct _pseudo_type + { + /* assembler mnemonic, lower case, no '.' */ + const char *poc_name; + /* Do the work */ + void (*poc_handler) PARAMS ((int)); + /* Value to pass to handler */ + int poc_val; + }; + +typedef struct _pseudo_type pseudo_typeS; + +/* Prefer varargs for non-ANSI compiler, since some will barf if the + ellipsis definition is used with a no-arguments declaration. */ +#if defined (HAVE_VARARGS_H) && !defined (__STDC__) +#undef HAVE_STDARG_H +#endif + +#if defined (HAVE_STDARG_H) +#define USE_STDARG +#endif +#if !defined (USE_STDARG) && defined (HAVE_VARARGS_H) +#define USE_VARARGS +#endif + +#ifdef USE_STDARG +#if __GNUC__ >= 2 +/* for use with -Wformat */ +#define PRINTF_LIKE(FCN) void FCN (const char *format, ...) \ + __attribute__ ((format (printf, 1, 2))) +#define PRINTF_WHERE_LIKE(FCN) void FCN (char *file, unsigned int line, \ + const char *format, ...) \ + __attribute__ ((format (printf, 3, 4))) +#else /* ANSI C with stdarg, but not GNU C */ +#define PRINTF_LIKE(FCN) void FCN PARAMS ((const char *format, ...)) +#define PRINTF_WHERE_LIKE(FCN) void FCN PARAMS ((char *file, \ + unsigned int line, \ + const char *format, ...)) +#endif +#else /* not using stdarg */ +#define PRINTF_LIKE(FCN) void FCN () +#define PRINTF_WHERE_LIKE(FCN) void FCN () +#endif + +PRINTF_LIKE (as_bad); +PRINTF_LIKE (as_fatal); +PRINTF_LIKE (as_tsktsk); +PRINTF_LIKE (as_warn); +PRINTF_WHERE_LIKE (as_bad_where); +PRINTF_WHERE_LIKE (as_warn_where); +void as_assert PARAMS ((const char *, int, const char *)); +void as_abort PARAMS ((const char *, int, const char *)); + +void fprint_value PARAMS ((FILE *file, addressT value)); +void sprint_value PARAMS ((char *buf, addressT value)); + +int had_errors PARAMS ((void)); +int had_warnings PARAMS ((void)); + +void print_version_id PARAMS ((void)); +char *app_push PARAMS ((void)); +char *atof_ieee PARAMS ((char *str, int what_kind, LITTLENUM_TYPE * words)); +char *input_scrub_include_file PARAMS ((char *filename, char *position)); +char *input_scrub_new_file PARAMS ((char *filename)); +char *input_scrub_next_buffer PARAMS ((char **bufp)); +PTR xmalloc PARAMS ((unsigned long size)); +PTR xrealloc PARAMS ((PTR ptr, unsigned long n)); +int do_scrub_chars PARAMS ((int (*get) (char **), char *to, int tolen)); +int gen_to_words PARAMS ((LITTLENUM_TYPE * words, int precision, + long exponent_bits)); +int had_err PARAMS ((void)); +int ignore_input PARAMS ((void)); +int seen_at_least_1_file PARAMS ((void)); +void app_pop PARAMS ((char *arg)); +void as_howmuch PARAMS ((FILE * stream)); +void as_perror PARAMS ((const char *gripe, const char *filename)); +void as_where PARAMS ((char **namep, unsigned int *linep)); +void bump_line_counters PARAMS ((void)); +void do_scrub_begin PARAMS ((void)); +void input_scrub_begin PARAMS ((void)); +void input_scrub_close PARAMS ((void)); +void input_scrub_end PARAMS ((void)); +void new_logical_line PARAMS ((char *fname, int line_number)); +void subsegs_begin PARAMS ((void)); +void subseg_change PARAMS ((segT seg, int subseg)); +segT subseg_new PARAMS ((const char *name, subsegT subseg)); +segT subseg_force_new PARAMS ((const char *name, subsegT subseg)); +void subseg_set PARAMS ((segT seg, subsegT subseg)); +#ifdef BFD_ASSEMBLER +segT subseg_get PARAMS ((const char *, int)); +#endif + +struct expressionS; +struct fix; +struct symbol; +struct relax_type; + +#ifdef BFD_ASSEMBLER +/* literal.c */ +valueT add_to_literal_pool PARAMS ((struct symbol *, valueT, segT, int)); +#endif + +#include "expr.h" /* Before targ-*.h */ + +/* this one starts the chain of target dependant headers */ +#include "targ-env.h" + +#include "struc-symbol.h" +#include "write.h" +#include "frags.h" +#include "hash.h" +#include "read.h" +#include "symbols.h" + +#include "tc.h" +#include "obj.h" + +#ifdef USE_EMULATIONS +#include "emul.h" +#endif +#include "listing.h" + +#ifndef LOCAL_LABELS_DOLLAR +#define LOCAL_LABELS_DOLLAR 0 +#endif + +#ifndef LOCAL_LABELS_FB +#define LOCAL_LABELS_FB 0 +#endif + +#endif /* GAS */ + +/* end of as.h */ diff --git a/gnu/usr.bin/binutils/gas/atof-generic.c b/gnu/usr.bin/binutils/gas/atof-generic.c new file mode 100644 index 00000000000..a78e9b640e5 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/atof-generic.c @@ -0,0 +1,635 @@ +/* atof_generic.c - turn a string of digits into a Flonum + Copyright (C) 1987, 1990, 1991, 1992 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 2, 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. */ + +#include +#include + +#include "as.h" + +#ifndef FALSE +#define FALSE (0) +#endif +#ifndef TRUE +#define TRUE (1) +#endif + +#ifdef TRACE +static void flonum_print PARAMS ((const FLONUM_TYPE *)); +#endif + +#define ASSUME_DECIMAL_MARK_IS_DOT + +/***********************************************************************\ + * * + * Given a string of decimal digits , with optional decimal * + * mark and optional decimal exponent (place value) of the * + * lowest_order decimal digit: produce a floating point * + * number. The number is 'generic' floating point: our * + * caller will encode it for a specific machine architecture. * + * * + * Assumptions * + * uses base (radix) 2 * + * this machine uses 2's complement binary integers * + * target flonums use " " " " * + * target flonums exponents fit in a long * + * * + \***********************************************************************/ + +/* + + Syntax: + + ::= + ::= '+' | '-' | {empty} + ::= + | + | + | + + ::= {empty} + | + + ::= | + ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + ::= {one character from "string_of_decimal_exponent_marks"} + ::= {one character from "string_of_decimal_marks"} + + */ + +int +atof_generic (address_of_string_pointer, + string_of_decimal_marks, + string_of_decimal_exponent_marks, + address_of_generic_floating_point_number) + /* return pointer to just AFTER number we read. */ + char **address_of_string_pointer; + /* At most one per number. */ + const char *string_of_decimal_marks; + const char *string_of_decimal_exponent_marks; + FLONUM_TYPE *address_of_generic_floating_point_number; +{ + int return_value; /* 0 means OK. */ + char *first_digit; + int number_of_digits_before_decimal; + int number_of_digits_after_decimal; + long decimal_exponent; + int number_of_digits_available; + char digits_sign_char; + + /* + * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent. + * It would be simpler to modify the string, but we don't; just to be nice + * to caller. + * We need to know how many digits we have, so we can allocate space for + * the digits' value. + */ + + char *p; + char c; + int seen_significant_digit; + +#ifdef ASSUME_DECIMAL_MARK_IS_DOT + assert (string_of_decimal_marks[0] == '.' + && string_of_decimal_marks[1] == 0); +#define IS_DECIMAL_MARK(c) ((c) == '.') +#else +#define IS_DECIMAL_MARK(c) (0 != strchr (string_of_decimal_marks, (c))) +#endif + + first_digit = *address_of_string_pointer; + c = *first_digit; + + if (c == '-' || c == '+') + { + digits_sign_char = c; + first_digit++; + } + else + digits_sign_char = '+'; + + switch (first_digit[0]) + { + case 'n': + case 'N': + if (!strncasecmp ("nan", first_digit, 3)) + { + address_of_generic_floating_point_number->sign = 0; + address_of_generic_floating_point_number->exponent = 0; + address_of_generic_floating_point_number->leader = + address_of_generic_floating_point_number->low; + *address_of_string_pointer = first_digit + 3; + return 0; + } + break; + + case 'i': + case 'I': + if (!strncasecmp ("inf", first_digit, 3)) + { + address_of_generic_floating_point_number->sign = + digits_sign_char == '+' ? 'P' : 'N'; + address_of_generic_floating_point_number->exponent = 0; + address_of_generic_floating_point_number->leader = + address_of_generic_floating_point_number->low; + + first_digit += 3; + if (!strncasecmp ("inity", first_digit, 5)) + first_digit += 5; + + *address_of_string_pointer = first_digit; + + return 0; + } + break; + } + + number_of_digits_before_decimal = 0; + number_of_digits_after_decimal = 0; + decimal_exponent = 0; + seen_significant_digit = 0; + for (p = first_digit; + (((c = *p) != '\0') + && (!c || !IS_DECIMAL_MARK (c)) + && (!c || !strchr (string_of_decimal_exponent_marks, c))); + p++) + { + if (isdigit (c)) + { + if (seen_significant_digit || c > '0') + { + ++number_of_digits_before_decimal; + seen_significant_digit = 1; + } + else + { + first_digit++; + } + } + else + { + break; /* p -> char after pre-decimal digits. */ + } + } /* For each digit before decimal mark. */ + +#ifndef OLD_FLOAT_READS + /* Ignore trailing 0's after the decimal point. The original code here + * (ifdef'd out) does not do this, and numbers like + * 4.29496729600000000000e+09 (2**31) + * come out inexact for some reason related to length of the digit + * string. + */ + if (c && IS_DECIMAL_MARK (c)) + { + int zeros = 0; /* Length of current string of zeros */ + + for (p++; (c = *p) && isdigit (c); p++) + { + if (c == '0') + { + zeros++; + } + else + { + number_of_digits_after_decimal += 1 + zeros; + zeros = 0; + } + } + } +#else + if (c && IS_DECIMAL_MARK (c)) + { + for (p++; + (((c = *p) != '\0') + && (!c || !strchr (string_of_decimal_exponent_marks, c))); + p++) + { + if (isdigit (c)) + { + /* This may be retracted below. */ + number_of_digits_after_decimal++; + + if ( /* seen_significant_digit || */ c > '0') + { + seen_significant_digit = TRUE; + } + } + else + { + if (!seen_significant_digit) + { + number_of_digits_after_decimal = 0; + } + break; + } + } /* For each digit after decimal mark. */ + } + + while (number_of_digits_after_decimal + && first_digit[number_of_digits_before_decimal + + number_of_digits_after_decimal] == '0') + --number_of_digits_after_decimal; +#endif + + if (flag_mri) + { + while (c == '_') + c = *++p; + } + if (c && strchr (string_of_decimal_exponent_marks, c)) + { + char digits_exponent_sign_char; + + c = *++p; + if (flag_mri) + { + while (c == '_') + c = *++p; + } + if (c && strchr ("+-", c)) + { + digits_exponent_sign_char = c; + c = *++p; + } + else + { + digits_exponent_sign_char = '+'; + } + + for (; (c); c = *++p) + { + if (isdigit (c)) + { + decimal_exponent = decimal_exponent * 10 + c - '0'; + /* + * BUG! If we overflow here, we lose! + */ + } + else + { + break; + } + } + + if (digits_exponent_sign_char == '-') + { + decimal_exponent = -decimal_exponent; + } + } + + *address_of_string_pointer = p; + + + + number_of_digits_available = + number_of_digits_before_decimal + number_of_digits_after_decimal; + return_value = 0; + if (number_of_digits_available == 0) + { + address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */ + address_of_generic_floating_point_number->leader + = -1 + address_of_generic_floating_point_number->low; + address_of_generic_floating_point_number->sign = digits_sign_char; + /* We have just concocted (+/-)0.0E0 */ + + } + else + { + int count; /* Number of useful digits left to scan. */ + + LITTLENUM_TYPE *digits_binary_low; + unsigned int precision; + unsigned int maximum_useful_digits; + unsigned int number_of_digits_to_use; + unsigned int more_than_enough_bits_for_digits; + unsigned int more_than_enough_littlenums_for_digits; + unsigned int size_of_digits_in_littlenums; + unsigned int size_of_digits_in_chars; + FLONUM_TYPE power_of_10_flonum; + FLONUM_TYPE digits_flonum; + + precision = (address_of_generic_floating_point_number->high + - address_of_generic_floating_point_number->low + + 1); /* Number of destination littlenums. */ + + /* Includes guard bits (two littlenums worth) */ +#if 0 /* The integer version below is very close, and it doesn't + require floating point support (which is currently buggy on + the Alpha). */ + maximum_useful_digits = (((double) (precision - 2)) + * ((double) (LITTLENUM_NUMBER_OF_BITS)) + / (LOG_TO_BASE_2_OF_10)) + + 2; /* 2 :: guard digits. */ +#else + maximum_useful_digits = (((precision - 2)) + * ( (LITTLENUM_NUMBER_OF_BITS)) + * 1000000 / 3321928) + + 2; /* 2 :: guard digits. */ +#endif + + if (number_of_digits_available > maximum_useful_digits) + { + number_of_digits_to_use = maximum_useful_digits; + } + else + { + number_of_digits_to_use = number_of_digits_available; + } + + /* Cast these to SIGNED LONG first, otherwise, on systems with + LONG wider than INT (such as Alpha OSF/1), unsignedness may + cause unexpected results. */ + decimal_exponent += ((long) number_of_digits_before_decimal + - (long) number_of_digits_to_use); + +#if 0 + more_than_enough_bits_for_digits + = ((((double) number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1); +#else + more_than_enough_bits_for_digits + = (number_of_digits_to_use * 3321928 / 1000000 + 1); +#endif + + more_than_enough_littlenums_for_digits + = (more_than_enough_bits_for_digits + / LITTLENUM_NUMBER_OF_BITS) + + 2; + + /* Compute (digits) part. In "12.34E56" this is the "1234" part. + Arithmetic is exact here. If no digits are supplied then this + part is a 0 valued binary integer. Allocate room to build up + the binary number as littlenums. We want this memory to + disappear when we leave this function. Assume no alignment + problems => (room for n objects) == n * (room for 1 + object). */ + + size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits; + size_of_digits_in_chars = size_of_digits_in_littlenums + * sizeof (LITTLENUM_TYPE); + + digits_binary_low = (LITTLENUM_TYPE *) + alloca (size_of_digits_in_chars); + + memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars); + + /* Digits_binary_low[] is allocated and zeroed. */ + + /* + * Parse the decimal digits as if * digits_low was in the units position. + * Emit a binary number into digits_binary_low[]. + * + * Use a large-precision version of: + * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit + */ + + for (p = first_digit, count = number_of_digits_to_use; count; p++, --count) + { + c = *p; + if (isdigit (c)) + { + /* + * Multiply by 10. Assume can never overflow. + * Add this digit to digits_binary_low[]. + */ + + long carry; + LITTLENUM_TYPE *littlenum_pointer; + LITTLENUM_TYPE *littlenum_limit; + + littlenum_limit = digits_binary_low + + more_than_enough_littlenums_for_digits + - 1; + + carry = c - '0'; /* char -> binary */ + + for (littlenum_pointer = digits_binary_low; + littlenum_pointer <= littlenum_limit; + littlenum_pointer++) + { + long work; + + work = carry + 10 * (long) (*littlenum_pointer); + *littlenum_pointer = work & LITTLENUM_MASK; + carry = work >> LITTLENUM_NUMBER_OF_BITS; + } + + if (carry != 0) + { + /* + * We have a GROSS internal error. + * This should never happen. + */ + as_fatal ("failed sanity check."); + } + } + else + { + ++count; /* '.' doesn't alter digits used count. */ + } + } + + + /* + * Digits_binary_low[] properly encodes the value of the digits. + * Forget about any high-order littlenums that are 0. + */ + while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0 + && size_of_digits_in_littlenums >= 2) + size_of_digits_in_littlenums--; + + digits_flonum.low = digits_binary_low; + digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1; + digits_flonum.leader = digits_flonum.high; + digits_flonum.exponent = 0; + /* + * The value of digits_flonum . sign should not be important. + * We have already decided the output's sign. + * We trust that the sign won't influence the other parts of the number! + * So we give it a value for these reasons: + * (1) courtesy to humans reading/debugging + * these numbers so they don't get excited about strange values + * (2) in future there may be more meaning attached to sign, + * and what was + * harmless noise may become disruptive, ill-conditioned (or worse) + * input. + */ + digits_flonum.sign = '+'; + + { + /* + * Compute the mantssa (& exponent) of the power of 10. + * If sucessful, then multiply the power of 10 by the digits + * giving return_binary_mantissa and return_binary_exponent. + */ + + LITTLENUM_TYPE *power_binary_low; + int decimal_exponent_is_negative; + /* This refers to the "-56" in "12.34E-56". */ + /* FALSE: decimal_exponent is positive (or 0) */ + /* TRUE: decimal_exponent is negative */ + FLONUM_TYPE temporary_flonum; + LITTLENUM_TYPE *temporary_binary_low; + unsigned int size_of_power_in_littlenums; + unsigned int size_of_power_in_chars; + + size_of_power_in_littlenums = precision; + /* Precision has a built-in fudge factor so we get a few guard bits. */ + + decimal_exponent_is_negative = decimal_exponent < 0; + if (decimal_exponent_is_negative) + { + decimal_exponent = -decimal_exponent; + } + + /* From now on: the decimal exponent is > 0. Its sign is separate. */ + + size_of_power_in_chars = size_of_power_in_littlenums + * sizeof (LITTLENUM_TYPE) + 2; + + power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars); + temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars); + memset ((char *) power_binary_low, '\0', size_of_power_in_chars); + *power_binary_low = 1; + power_of_10_flonum.exponent = 0; + power_of_10_flonum.low = power_binary_low; + power_of_10_flonum.leader = power_binary_low; + power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1; + power_of_10_flonum.sign = '+'; + temporary_flonum.low = temporary_binary_low; + temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1; + /* + * (power) == 1. + * Space for temporary_flonum allocated. + */ + + /* + * ... + * + * WHILE more bits + * DO find next bit (with place value) + * multiply into power mantissa + * OD + */ + { + int place_number_limit; + /* Any 10^(2^n) whose "n" exceeds this */ + /* value will fall off the end of */ + /* flonum_XXXX_powers_of_ten[]. */ + int place_number; + const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */ + + place_number_limit = table_size_of_flonum_powers_of_ten; + + multiplicand = (decimal_exponent_is_negative + ? flonum_negative_powers_of_ten + : flonum_positive_powers_of_ten); + + for (place_number = 1;/* Place value of this bit of exponent. */ + decimal_exponent;/* Quit when no more 1 bits in exponent. */ + decimal_exponent >>= 1, place_number++) + { + if (decimal_exponent & 1) + { + if (place_number > place_number_limit) + { + /* The decimal exponent has a magnitude so great + that our tables can't help us fragment it. + Although this routine is in error because it + can't imagine a number that big, signal an + error as if it is the user's fault for + presenting such a big number. */ + return_value = ERROR_EXPONENT_OVERFLOW; + /* quit out of loop gracefully */ + decimal_exponent = 0; + } + else + { +#ifdef TRACE + printf ("before multiply, place_number = %d., power_of_10_flonum:\n", + place_number); + + flonum_print (&power_of_10_flonum); + (void) putchar ('\n'); +#endif +#ifdef TRACE + printf ("multiplier:\n"); + flonum_print (multiplicand + place_number); + (void) putchar ('\n'); +#endif + flonum_multip (multiplicand + place_number, + &power_of_10_flonum, &temporary_flonum); +#ifdef TRACE + printf ("after multiply:\n"); + flonum_print (&temporary_flonum); + (void) putchar ('\n'); +#endif + flonum_copy (&temporary_flonum, &power_of_10_flonum); +#ifdef TRACE + printf ("after copy:\n"); + flonum_print (&power_of_10_flonum); + (void) putchar ('\n'); +#endif + } /* If this bit of decimal_exponent was computable.*/ + } /* If this bit of decimal_exponent was set. */ + } /* For each bit of binary representation of exponent */ +#ifdef TRACE + printf ("after computing power_of_10_flonum:\n"); + flonum_print (&power_of_10_flonum); + (void) putchar ('\n'); +#endif + } + + } + + /* + * power_of_10_flonum is power of ten in binary (mantissa) , (exponent). + * It may be the number 1, in which case we don't NEED to multiply. + * + * Multiply (decimal digits) by power_of_10_flonum. + */ + + flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number); + /* Assert sign of the number we made is '+'. */ + address_of_generic_floating_point_number->sign = digits_sign_char; + + } + return return_value; +} + +#ifdef TRACE +static void +flonum_print (f) + const FLONUM_TYPE *f; +{ + LITTLENUM_TYPE *lp; + char littlenum_format[10]; + sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2); +#define print_littlenum(LP) (printf (littlenum_format, LP)) + printf ("flonum @%p %c e%ld", f, f->sign, f->exponent); + if (f->low < f->high) + for (lp = f->high; lp >= f->low; lp--) + print_littlenum (*lp); + else + for (lp = f->low; lp <= f->high; lp++) + print_littlenum (*lp); + printf ("\n"); + fflush (stdout); +} +#endif + +/* end of atof_generic.c */ diff --git a/gnu/usr.bin/binutils/gas/bignum-copy.c b/gnu/usr.bin/binutils/gas/bignum-copy.c new file mode 100644 index 00000000000..2bffcbfea4c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/bignum-copy.c @@ -0,0 +1,80 @@ +/* bignum_copy.c - copy a bignum + Copyright (C) 1987, 1990, 1991, 1992 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 2, 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. */ + +#include "as.h" + +/* + * bignum_copy () + * + * Copy a bignum from in to out. + * If the output is shorter than the input, copy lower-order littlenums. + * Return 0 or the number of significant littlenums dropped. + * Assumes littlenum arrays are densely packed: no unused chars between + * the littlenums. Uses memcpy() to move littlenums, and wants to + * know length (in chars) of the input bignum. + */ + +/* void */ +int +bignum_copy (in, in_length, out, out_length) + register LITTLENUM_TYPE *in; + register int in_length; /* in sizeof(littlenum)s */ + register LITTLENUM_TYPE *out; + register int out_length; /* in sizeof(littlenum)s */ +{ + int significant_littlenums_dropped; + + if (out_length < in_length) + { + LITTLENUM_TYPE *p; /* -> most significant (non-zero) input + littlenum. */ + + memcpy ((void *) out, (void *) in, + (unsigned int) out_length << LITTLENUM_SHIFT); + for (p = in + in_length - 1; p >= in; --p) + { + if (*p) + break; + } + significant_littlenums_dropped = p - in - in_length + 1; + + if (significant_littlenums_dropped < 0) + { + significant_littlenums_dropped = 0; + } + } + else + { + memcpy ((char *) out, (char *) in, + (unsigned int) in_length << LITTLENUM_SHIFT); + + if (out_length > in_length) + { + memset ((char *) (out + in_length), + '\0', + (unsigned int) (out_length - in_length) << LITTLENUM_SHIFT); + } + + significant_littlenums_dropped = 0; + } + + return (significant_littlenums_dropped); +} /* bignum_copy() */ + +/* end of bignum-copy.c */ diff --git a/gnu/usr.bin/binutils/gas/bignum.h b/gnu/usr.bin/binutils/gas/bignum.h new file mode 100644 index 00000000000..e3b2f167998 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/bignum.h @@ -0,0 +1,52 @@ +/* bignum.h-arbitrary precision integers + Copyright (C) 1987, 1992 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 2, 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. */ + +/***********************************************************************\ + * * + * Arbitrary-precision integer arithmetic. * + * For speed, we work in groups of bits, even though this * + * complicates algorithms. * + * Each group of bits is called a 'littlenum'. * + * A bunch of littlenums representing a (possibly large) * + * integer is called a 'bignum'. * + * Bignums are >= 0. * + * * + \***********************************************************************/ + +#define LITTLENUM_NUMBER_OF_BITS (16) +#define LITTLENUM_RADIX (1 << LITTLENUM_NUMBER_OF_BITS) +#define LITTLENUM_MASK (0xFFFF) +#define LITTLENUM_SHIFT (1) +#define CHARS_PER_LITTLENUM (1 << LITTLENUM_SHIFT) +#ifndef BITS_PER_CHAR +#define BITS_PER_CHAR (8) +#endif + +typedef unsigned short LITTLENUM_TYPE; + +/* JF truncated this to get around a problem with GCC */ +#define LOG_TO_BASE_2_OF_10 (3.3219280948873623478703194294893901758651) +/* WARNING: I haven't checked that the trailing digits are correct! */ + +/* lengths are in sizeof(littlenum)s */ + +int bignum_copy PARAMS ((LITTLENUM_TYPE * in, int in_length, + LITTLENUM_TYPE * out, int out_length)); + +/* end of bignum.h */ diff --git a/gnu/usr.bin/binutils/gas/bit_fix.h b/gnu/usr.bin/binutils/gas/bit_fix.h new file mode 100644 index 00000000000..6a729a700c6 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/bit_fix.h @@ -0,0 +1,51 @@ +/* write.h + + Copyright (C) 1987, 1992 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 2, 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. */ + +/* The bit_fix was implemented to support machines that need variables + to be inserted in bitfields other than 1, 2 and 4 bytes. + Furthermore it gives us a possibillity to mask in bits in the symbol + when it's fixed in the objectcode and check the symbols limits. + + The or-mask is used to set the huffman bits in displacements for the + ns32k port. + The acbi, addqi, movqi, cmpqi instruction requires an assembler that + can handle bitfields. Ie handle an expression, evaluate it and insert + the result in an some bitfield. ( ex: 5 bits in a short field of a opcode) + */ + +#ifndef __bit_fix_h__ +#define __bit_fix_h__ + +struct bit_fix + { + int fx_bit_size; /* Length of bitfield */ + int fx_bit_offset; /* Bit offset to bitfield */ + long fx_bit_base; /* Where do we apply the bitfix. + If this is zero, default is assumed. */ + long fx_bit_base_adj; /* Adjustment of base */ + long fx_bit_max; /* Signextended max for bitfield */ + long fx_bit_min; /* Signextended min for bitfield */ + long fx_bit_add; /* Or mask, used for huffman prefix */ + }; +typedef struct bit_fix bit_fixS; + +#endif /* __bit_fix_h__ */ + +/* end of bit_fix.h */ diff --git a/gnu/usr.bin/binutils/gas/cond.c b/gnu/usr.bin/binutils/gas/cond.c new file mode 100644 index 00000000000..fd8161ab7ce --- /dev/null +++ b/gnu/usr.bin/binutils/gas/cond.c @@ -0,0 +1,368 @@ +/* cond.c - conditional assembly pseudo-ops, and .include + Copyright (C) 1990, 1991, 1992, 1993 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 2, 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. */ + +#include "as.h" + +#include "obstack.h" + +/* This is allocated to grow and shrink as .ifdef/.endif pairs are scanned. */ +struct obstack cond_obstack; + +struct file_line +{ + char *file; + unsigned int line; +}; /* file_line */ + +/* This is what we push and pop. */ +struct conditional_frame + { + struct file_line if_file_line; /* the source file & line number of the "if" */ + struct file_line else_file_line; /* the source file & line of the "else" */ + struct conditional_frame *previous_cframe; + int else_seen; /* have we seen an else yet? */ + int ignoring; /* if we are currently ignoring input. */ + int dead_tree; /* if a conditional at a higher level is ignoring input. */ + }; /* conditional_frame */ + +static void initialize_cframe PARAMS ((struct conditional_frame *cframe)); +static char *get_mri_string PARAMS ((int, int *)); + +static struct conditional_frame *current_cframe = NULL; + +void +s_ifdef (arg) + int arg; +{ + register char *name; /* points to name of symbol */ + register struct symbol *symbolP; /* Points to symbol */ + struct conditional_frame cframe; + + SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */ + name = input_line_pointer; + + if (!is_name_beginner (*name)) + { + as_bad ("invalid identifier for \".ifdef\""); + obstack_1grow (&cond_obstack, 0); + ignore_rest_of_line (); + } + else + { + char c; + + c = get_symbol_end (); + symbolP = symbol_find (name); + *input_line_pointer = c; + + initialize_cframe (&cframe); + cframe.ignoring = cframe.dead_tree || !((symbolP != 0) ^ arg); + current_cframe = ((struct conditional_frame *) + obstack_copy (&cond_obstack, &cframe, + sizeof (cframe))); + demand_empty_rest_of_line (); + } /* if a valid identifyer name */ +} /* s_ifdef() */ + +void +s_if (arg) + int arg; +{ + expressionS operand; + struct conditional_frame cframe; + int t; + char *stop = NULL; + char stopc; + + if (flag_mri) + stop = mri_comment_field (&stopc); + + SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */ + + if (current_cframe != NULL && current_cframe->ignoring) + { + operand.X_add_number = 0; + while (! is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + } + else + { + expression (&operand); + if (operand.X_op != O_constant) + as_bad ("non-constant expression in \".if\" statement"); + } + + switch ((operatorT) arg) + { + case O_eq: t = operand.X_add_number == 0; break; + case O_ne: t = operand.X_add_number != 0; break; + case O_lt: t = operand.X_add_number < 0; break; + case O_le: t = operand.X_add_number <= 0; break; + case O_ge: t = operand.X_add_number >= 0; break; + case O_gt: t = operand.X_add_number > 0; break; + default: + abort (); + } + + /* If the above error is signaled, this will dispatch + using an undefined result. No big deal. */ + initialize_cframe (&cframe); + cframe.ignoring = cframe.dead_tree || ! t; + current_cframe = ((struct conditional_frame *) + obstack_copy (&cond_obstack, &cframe, sizeof (cframe))); + + if (flag_mri) + mri_comment_end (stop, stopc); + + demand_empty_rest_of_line (); +} /* s_if() */ + +/* Get a string for the MRI IFC or IFNC pseudo-ops. */ + +static char * +get_mri_string (terminator, len) + int terminator; + int *len; +{ + char *ret; + char *s; + + SKIP_WHITESPACE (); + s = ret = input_line_pointer; + if (*input_line_pointer == '\'') + { + ++s; + ++input_line_pointer; + while (! is_end_of_line[(unsigned char) *input_line_pointer]) + { + *s++ = *input_line_pointer++; + if (s[-1] == '\'') + { + if (*input_line_pointer != '\'') + break; + ++input_line_pointer; + } + } + SKIP_WHITESPACE (); + } + else + { + while (*input_line_pointer != terminator + && ! is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + s = input_line_pointer; + while (s > ret && (s[-1] == ' ' || s[-1] == '\t')) + --s; + } + + *len = s - ret; + return ret; +} + +/* The MRI IFC and IFNC pseudo-ops. */ + +void +s_ifc (arg) + int arg; +{ + char *s1, *s2; + int len1, len2; + int res; + struct conditional_frame cframe; + + s1 = get_mri_string (',', &len1); + + if (*input_line_pointer != ',') + as_bad ("bad format for ifc or ifnc"); + else + ++input_line_pointer; + + s2 = get_mri_string (';', &len2); + + res = len1 == len2 && strncmp (s1, s2, len1) == 0; + + initialize_cframe (&cframe); + cframe.ignoring = cframe.dead_tree || ! (res ^ arg); + current_cframe = ((struct conditional_frame *) + obstack_copy (&cond_obstack, &cframe, sizeof (cframe))); +} + +void +s_endif (arg) + int arg; +{ + struct conditional_frame *hold; + + if (current_cframe == NULL) + { + as_bad ("\".endif\" without \".if\""); + } + else + { + hold = current_cframe; + current_cframe = current_cframe->previous_cframe; + obstack_free (&cond_obstack, hold); + } /* if one pop too many */ + + if (flag_mri) + { + while (! is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + } + + demand_empty_rest_of_line (); +} /* s_endif() */ + +void +s_else (arg) + int arg; +{ + if (current_cframe == NULL) + { + as_bad (".else without matching .if - ignored"); + + } + else if (current_cframe->else_seen) + { + as_bad ("duplicate \"else\" - ignored"); + as_bad_where (current_cframe->else_file_line.file, + current_cframe->else_file_line.line, + "here is the previous \"else\""); + as_bad_where (current_cframe->if_file_line.file, + current_cframe->if_file_line.line, + "here is the previous \"if\""); + } + else + { + as_where (¤t_cframe->else_file_line.file, + ¤t_cframe->else_file_line.line); + + if (!current_cframe->dead_tree) + { + current_cframe->ignoring = !current_cframe->ignoring; + } /* if not a dead tree */ + + current_cframe->else_seen = 1; + } /* if error else do it */ + + if (flag_mri) + { + while (! is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + } + + demand_empty_rest_of_line (); +} /* s_else() */ + +void +s_ifeqs (arg) + int arg; +{ + char *s1, *s2; + int len1, len2; + int res; + struct conditional_frame cframe; + + s1 = demand_copy_C_string (&len1); + + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + as_bad (".ifeqs syntax error"); + ignore_rest_of_line (); + return; + } + + ++input_line_pointer; + + s2 = demand_copy_C_string (&len2); + + res = len1 == len2 && strncmp (s1, s2, len1) == 0; + + initialize_cframe (&cframe); + cframe.ignoring = cframe.dead_tree || ! (res ^ arg); + current_cframe = ((struct conditional_frame *) + obstack_copy (&cond_obstack, &cframe, sizeof (cframe))); + + demand_empty_rest_of_line (); +} /* s_ifeqs() */ + +int +ignore_input () +{ + char *s; + + s = input_line_pointer; + +#ifndef MRI_MODE_NEEDS_PSEUDO_DOT +#define MRI_MODE_NEEDS_PSEUDO_DOT 0 +#endif + + if ((flag_mri && ! MRI_MODE_NEEDS_PSEUDO_DOT) +#ifdef NO_PSEUDO_DOT + || 1 +#endif + ) + { + if (s[-1] != '.') + --s; + } + else + { + if (s[-1] != '.') + return (current_cframe != NULL) && (current_cframe->ignoring); + } + + /* We cannot ignore certain pseudo ops. */ + if (((s[0] == 'i' + || s[0] == 'I') + && (!strncasecmp (s, "if", 2) + || !strncasecmp (s, "ifdef", 5) + || !strncasecmp (s, "ifndef", 6))) + || ((s[0] == 'e' + || s[0] == 'E') + && (!strncasecmp (s, "else", 4) + || !strncasecmp (s, "endif", 5) + || !strncasecmp (s, "endc", 4)))) + return 0; + + return (current_cframe != NULL) && (current_cframe->ignoring); +} /* ignore_input() */ + +static void +initialize_cframe (cframe) + struct conditional_frame *cframe; +{ + memset (cframe, 0, sizeof (*cframe)); + as_where (&cframe->if_file_line.file, + &cframe->if_file_line.line); + cframe->previous_cframe = current_cframe; + cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring; + + return; +} /* initialize_cframe() */ + +/* + * Local Variables: + * fill-column: 131 + * comment-column: 0 + * End: + */ + +/* end of cond.c */ diff --git a/gnu/usr.bin/binutils/gas/conf.in b/gnu/usr.bin/binutils/gas/conf.in new file mode 100644 index 00000000000..e1b803f587d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/conf.in @@ -0,0 +1,117 @@ +/* conf.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* If using the C implementation of alloca, define 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 + */ +#undef STACK_DIRECTION + +/* Should gas use high-level BFD interfaces? */ +#undef BFD_ASSEMBLER + +/* Some assert/preprocessor combinations are incapable of handling + certain kinds of constructs in the argument of assert. For example, + quoted strings (if requoting isn't done right) or newlines. */ +#undef BROKEN_ASSERT + +/* If we aren't doing cross-assembling, some operations can be optimized, + since byte orders and value sizes don't need to be adjusted. */ +#undef CROSS_COMPILE + +/* Some gas code wants to know these parameters. */ +#undef TARGET_ALIAS +#undef TARGET_CPU +#undef TARGET_CANONICAL +#undef TARGET_OS +#undef TARGET_VENDOR + +/* Sometimes the system header files don't declare malloc and realloc. */ +#undef NEED_DECLARATION_MALLOC + +/* Sometimes the system header files don't declare free. */ +#undef NEED_DECLARATION_FREE + +/* Sometimes errno.h doesn't declare errno itself. */ +#undef NEED_DECLARATION_ERRNO + +#undef MANY_SEGMENTS + +/* Needed only for sparc configuration */ +#undef sparcv9 + +/* Needed only for some configurations that can produce multiple output + formats. */ +#undef DEFAULT_EMULATION +#undef EMULATIONS +#undef USE_EMULATIONS +#undef OBJ_MAYBE_AOUT +#undef OBJ_MAYBE_BOUT +#undef OBJ_MAYBE_COFF +#undef OBJ_MAYBE_ECOFF +#undef OBJ_MAYBE_ELF +#undef OBJ_MAYBE_GENERIC +#undef OBJ_MAYBE_HP300 +#undef OBJ_MAYBE_IEEE +#undef OBJ_MAYBE_SOM +#undef OBJ_MAYBE_VMS + +/* Used for some of the COFF configurations, when the COFF code needs + to select something based on the CPU type before it knows it... */ +#undef I386COFF +#undef M68KCOFF +#undef M88KCOFF + +/* Define if you have the remove function. */ +#undef HAVE_REMOVE + +/* Define if you have the sbrk function. */ +#undef HAVE_SBRK + +/* Define if you have the unlink function. */ +#undef HAVE_UNLINK + +/* Define if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_VARARGS_H diff --git a/gnu/usr.bin/binutils/gas/config-gas.com b/gnu/usr.bin/binutils/gas/config-gas.com new file mode 100644 index 00000000000..2bfc5768533 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config-gas.com @@ -0,0 +1,169 @@ +$! +$! This file sets things up to build gas on a VMS system to generate object +$! files for a VMS system. We do not use the configure script, since we +$! do not have /bin/sh to execute it. +$! +$! If you are running this file, then obviously the host is vax-dec-vms. +$! [That's no longer obvious, but there's not much we can do about alpha yet.] +$! +$gas_host="vms" +$! +$cpu_type="vax" +$emulation="generic" +$obj_format="vms" +$atof="vax" +$! +$ DELETE = "delete/noConfirm" +$ ECHO = "write sys$output" +$! +$! Target specific information +$call link targ-cpu.c [.config]tc-'cpu_type'.c +$call link targ-cpu.h [.config]tc-'cpu_type'.h +$call link targ-env.h [.config]te-'emulation'.h +$! +$! Code to handle the object file format. +$call link obj-format.h [.config]obj-'obj_format'.h +$call link obj-format.c [.config]obj-'obj_format'.c +$! +$! Code to handle floating point. +$call link atof-targ.c [.config]atof-'atof'.c +$! +$! +$! Create the file version.opt, which helps identify the executable. +$! +$if f$trnlnm("IFILE$").nes."" then close/noLog ifile$ +$search Makefile.in "VERSION="/Exact/Output=config-gas-tmp.tmp +$open ifile$ config-gas-tmp.tmp +$read ifile$ line +$close ifile$ +$DELETE config-gas-tmp.tmp;* +$! Discard "VERSION=" and "\n" parts. +$ijk=f$locate("=",line)+1 +$line=f$extract(ijk,f$length(line)-ijk,line) +$! [what "\n" part?? this seems to be useless, but is benign] +$ijk=f$locate("\n",line) +$line=f$extract(0,ijk,line) +$! +$ if f$search("version.opt").nes."" then DELETE version.opt;* +$copy _NL: version.opt +$open/Append ifile$ version.opt +$write ifile$ "identification="+""""+line+"""" +$close ifile$ +$! +$! Now write config.h. +$! +$ if f$search("config.h").nes."" then DELETE config.h;* +$copy _NL: config.h +$open/Append ifile$ config.h +$write ifile$ "/* config.h. Generated by config-gas.com. */ +$write ifile$ "#ifndef GAS_VERSION" +$write ifile$ "#define GAS_VERSION """,line,"""" +$write ifile$ "#endif" +$write ifile$ "/*--*/" +$append [.config]vms-conf.h ifile$: +$close ifile$ +$ECHO "Created config.h." +$! +$! Check for, and possibly make, header file . +$! +$ if f$search("tmp-chk-h.*").nes."" then DELETE tmp-chk-h.*;* +$!can't use simple `#include HDR' with `gcc /Define="HDR="' +$!because the 2.6.[0-3] preprocessor handles it wrong (VMS-specific gcc bug) +$ create tmp-chk-h.c +int tmp_chk_h; /* guarantee non-empty output */ +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_UNIXIO_H +#include +#endif +#ifdef HAVE_UNIXLIB_H +#include +#endif +$ on warning then continue +$ CHECK = "call tmp_chk_h" +$ CHECK "HAVE_STDIO_H" +$ if .not.$status +$ then type sys$input: + +? could not compile . + Since gcc is not set up correctly, gas configuration cannot proceed. + +$ DELETE tmp-chk-h.c;* +$ exit %x002C +$ endif +$! +$ CHECK "HAVE_UNISTD_H" +$ if .not.$status +$ then +$ if f$trnlnm("HFILE$").nes."" then close/noLog hfile$ +$ CHECK "HAVE_UNIXIO_H" +$ got_unixio = ($status .and. 1) +$ CHECK "HAVE_UNIXLIB_H" +$ got_unixlib = ($status .and. 1) +$ create []unistd.h !with rudimentary contents +/* substitute for building gas */ +#ifndef UNISTD_H +#define UNISTD_H + +$ open/Append hfile$ []unistd.h +$ if got_unixio +$ then write hfile$ "#include " +$ else append sys$input: hfile$: +/* some of the routines normally prototyped in */ +extern int creat(), open(), close(), read(), write(); +extern int access(), dup(), dup2(), fstat(), stat(); +extern long lseek(); +$ endif +$ write hfile$ "" +$ if got_unixlib +$ then write hfile$ "#include " +$ else append sys$input: hfile$: +/* some of the routines normally prototyped in */ +extern char *sbrk(), *getcwd(), *cuserid(); +extern int brk(), chdir(), chmod(), chown(), mkdir(); +extern unsigned getuid(), umask(); +$ endif +$ append sys$input: hfile$: + +#endif /*UNISTD_H*/ +$ close hfile$ +$ ECHO "Created ""[]unistd.h""." +$ endif !gcc '#include ' failed +$ DELETE tmp-chk-h.c;* +$ +$tmp_chk_h: subroutine +$ set noOn +$ hname = f$edit("<" + (p1 - "HAVE_" - "_H") + ".h>","LOWERCASE") +$ write sys$output "Checking for ''hname'." +$ if f$search("tmp-chk-h.obj").nes."" then DELETE tmp-chk-h.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 +$ gcc /Include=([],[-.include]) /Define=("''p1'") tmp-chk-h.c +$!can't just check $status; gcc 2.6.[0-3] preprocessor doesn't set it correctly +$ ok = (($status.and.1).and.(f$search("tmp-chk-h.obj").nes."")) .or. %x10000000 +$ deassign sys$error !restore, more or less +$ deassign sys$output +$ if ok then DELETE tmp-chk-h.obj;* +$ exit ok +$ endsubroutine !tmp_chk_h +$ +$! +$! Done +$! +$ if f$search("config.status") .nes. "" then DELETE config.status;* +$ create config.status +Links are now set up for use with a vax running VMS. +$ type config.status +$exit +$! +$! +$link: +$subroutine +$ if f$search(p1).nes."" then DELETE 'p1';* +$ copy 'p2' 'p1' +$ ECHO "Copied ''f$edit(p2,"LOWERCASE")' to ''f$edit(p1,"LOWERCASE")'." +$endsubroutine diff --git a/gnu/usr.bin/binutils/gas/config/alpha-opcode.h b/gnu/usr.bin/binutils/gas/config/alpha-opcode.h new file mode 100644 index 00000000000..c2e562ed11d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/alpha-opcode.h @@ -0,0 +1,835 @@ +/* + * Mach Operating System + * Copyright (c) 1993 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 + * 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 the + * rights to redistribute these changes. + */ +/* + * HISTORY + * 5-Oct-93 Alessandro Forin (af) at Carnegie-Mellon University + * First checkin. + * + * Author: Alessandro Forin, Carnegie Mellon University + * Date: Jan 1993 + */ + +/* Table of opcodes for the alpha. + Copyright (C) 1989, 1994, 1995 Free Software Foundation, Inc. + Contributed 1993 by Carnegie Mellon University. + +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 alpha_opcode +{ + const char *name; + const unsigned int match; /* fixed encoding part of instruction */ + const int isa_float; + const char *args; +}; + +/* + All alpha 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: + 1 ra register + 2 rb register + 3 rc register + r same register for ra and rc + R same register for ra and rb + e fa floating point register. + f fb floating point register. + g fc floating point register. + I 26 bit immediate + l 16 low bits of immediate + h 16 high(er) bits of immediate [Never used. KR] + L 22 bit PC relative immediate. + i 14 bit immediate jmp/jsr/ret operand -- PC-rel or not, + dependent on opcode + b 8 bit literal, shifted left 13 bits (literal in `operate' fmt) + G Base-register GET at address, needs macro-expansion + P Base-register PUT at address, needs macro-expansion + Bn builtin macro + t twelve bit displacement + 8 eight bit index + +Syntactic elements + ( + ) base register in "offset(base)" addressing + , separator + +Builtin functions (look like macros to the programmer) + %br the current base register + la %r,A load the (64bit) address in register %r + li %r,N load the constant N in register %r +#if 0 + lo(A) low 16 bits of Address (relocatable) + uml(A) med-low 16 bits, unchanged + umh(A) med-high 16 bits, unchanged + uhi(A) high 16 bits, unchanged + ml(A) med-low, adjusted viz sign of lo(A) + mh(A) med-high, adjusted viz sign of ml(A) + hi(A) high, adjusted viz sign of mh(A) +#endif + +*/ + +/* 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 alpha_opcode alpha_opcodes[] = +{ + +{ "ldgp", 0x00000000, 0, "3,l(1)Ba" }, /* builtin */ +{ "setgp", 0x00000000, 0, "0(1)Bb" }, /* builtin */ + +{ "reml", 0x00000000, 0, "1,2,3B0" }, /* builtin */ +{ "divl", 0x00000000, 0, "1,2,3B1" }, /* builtin */ +{ "remq", 0x00000000, 0, "1,2,3B2" }, /* builtin */ +{ "divq", 0x00000000, 0, "1,2,3B3" }, /* builtin */ +{ "remlu", 0x00000000, 0, "1,2,3B4" }, /* builtin */ +{ "divlu", 0x00000000, 0, "1,2,3B5" }, /* builtin */ +{ "remqu", 0x00000000, 0, "1,2,3B6" }, /* builtin */ +{ "divqu", 0x00000000, 0, "1,2,3B7" }, /* builtin */ + +{ "lda", 0x20000000, 0, "1,l(2)" }, /* 6o+5a+5b+16d */ +{ "lda", 0x20000000, 0, "1,G" }, /* regbase macro */ +{ "ldi", 0x201F0000, 0, "1,l"}, /* ldi ra,lit == lda ra,lit(r31) */ +{ "ldah", 0x24000000, 0, "1,l(2)" }, +{ "ldah", 0x24000000, 0, "1,G" }, /* regbase macro */ +{ "lui", 0x241F0000, 0, "1,l"}, /* lui ra,lit == ldah ra,lit(r31) */ +{ "ldil", 0x20000000, 0, "1,G" }, /* macro */ +{ "ldiq", 0x20000000, 0, "1,G" }, /* (broken) macro */ + +{ "ldl", 0xa0000000, 0, "1,l(2)" }, +{ "ldl", 0xa0000000, 0, "1,G" }, /* regbase macro */ +{ "ldl_l", 0xa8000000, 0, "1,l(2)" }, +{ "ldl_l", 0xa8000000, 0, "1,G" }, /* regbase macro */ +{ "ldq", 0xa4000000, 0, "1,l(2)" }, +{ "ldq", 0xa4000000, 0, "1,G" }, /* regbase macro */ +{ "ldq_u", 0x2c000000, 0, "1,l(2)" }, +{ "ldq_u", 0x2c000000, 0, "1,G" }, /* regbase macro */ +{ "ldq_l", 0xac000000, 0, "1,l(2)" }, +{ "ldq_l", 0xac000000, 0, "1,G" }, /* regbase macro */ + +{ "stl", 0xb0000000, 0, "1,l(2)" }, +{ "stl", 0xb0000000, 0, "1,P" }, /* regbase macro */ +{ "stl_c", 0xb8000000, 0, "1,l(2)" }, +{ "stl_c", 0xb8000000, 0, "1,P" }, /* regbase macro */ +{ "stq", 0xb4000000, 0, "1,l(2)" }, +{ "stq", 0xb4000000, 0, "1,P" }, /* regbase macro */ +{ "stq_u", 0x3c000000, 0, "1,l(2)" }, +{ "stq_u", 0x3c000000, 0, "1,P" }, /* regbase macro */ +{ "stq_c", 0xbc000000, 0, "1,l(2)" }, +{ "stq_c", 0xbc000000, 0, "1,P" }, /* regbase macro */ + +{ "beq", 0xe4000000, 0, "1,L" }, /* 6o+5a+21d */ +{ "bne", 0xf4000000, 0, "1,L" }, +{ "blt", 0xe8000000, 0, "1,L" }, +{ "ble", 0xec000000, 0, "1,L" }, +{ "bgt", 0xfc000000, 0, "1,L" }, +{ "bge", 0xf8000000, 0, "1,L" }, +{ "blbc", 0xe0000000, 0, "1,L" }, +{ "blbs", 0xf0000000, 0, "1,L" }, + +{ "br", 0xc0000000, 0, "1,L" }, +{ "br", 0xc3e00000, 0, "L" }, /* macro: br zero,disp */ +{ "bsr", 0xd0000000, 0, "1,L" }, +{ "bsr", 0xd3500000, 0, "L" }, /* macro: bsr $ra,L */ + +{ "jmp", 0x68000000, 0, "1,(2),i" }, /* 6o+5a+5b+2A+14d */ +{ "jmp", 0x68000000, 0, "1,(2)" }, +{ "jmp", 0x68000000, 0, "1,Bc" }, +{ "jsr", 0x68004000, 0, "1,(2),i" }, +{ "jsr", 0x68004000, 0, "1,(2)" }, +{ "jsr", 0x68004000, 0, "1,Bc" }, /* macro: lda $pv,L;jsr .. */ +{ "ret", 0x68008000, 0, "1,(2),i" }, +{ "ret", 0x68008000, 0, "1,(2)" }, +{ "ret", 0x6bfa8000, 0, "" }, /* macro: ret zero,(ra) */ +{ "ret", 0x6be08000, 0, "(2)" }, /* macro: ret zero,(2) */ +{ "ret", 0x681a8000, 0, "1" }, /* macro: ret 1,(ra) */ +{ "jcr", 0x6800c000, 0, "1,(2)" }, +{ "jsr_coroutine", 0x6800c000, 0, "1,(2)" }, + +{ "addl", 0x40000000, 0, "1,2,3" }, /* 6o+5a+5b+4z+7f+5c */ +{ "addl", 0x40001000, 0, "1,b,3" }, /* 6o+5a+8n+1+7f+5c */ +{ "addl/v", 0x40000800, 0, "1,2,3" }, +{ "addl/v", 0x40001800, 0, "1,b,3" }, +{ "s4addl", 0x40000040, 0, "1,2,3" }, +{ "s4addl", 0x40001040, 0, "1,b,3" }, +{ "s8addl", 0x40000240, 0, "1,2,3" }, +{ "s8addl", 0x40001240, 0, "1,b,3" }, +{ "addq", 0x40000400, 0, "1,2,3" }, +{ "addq", 0x40001400, 0, "1,b,3" }, +{ "addq/v", 0x40000c00, 0, "1,2,3" }, + +{ "addq/v", 0x40001c00, 0, "1,b,3" }, +{ "s4addq", 0x40000440, 0, "1,2,3" }, +{ "s4addq", 0x40001440, 0, "1,b,3" }, +{ "s8addq", 0x40000640, 0, "1,2,3" }, +{ "s8addq", 0x40001640, 0, "1,b,3" }, +{ "cmpeq", 0x400005a0, 0, "1,2,3" }, +{ "cmpeq", 0x400015a0, 0, "1,b,3" }, +{ "cmplt", 0x400009a0, 0, "1,2,3" }, +{ "cmplt", 0x400019a0, 0, "1,b,3" }, +{ "cmple", 0x40000da0, 0, "1,2,3" }, +{ "cmple", 0x40001da0, 0, "1,b,3" }, +{ "cmpult", 0x400003a0, 0, "1,2,3" }, +{ "cmpult", 0x400013a0, 0, "1,b,3" }, +{ "cmpule", 0x400007a0, 0, "1,2,3" }, +{ "cmpule", 0x400017a0, 0, "1,b,3" }, +{ "subl", 0x40000120, 0, "1,2,3" }, +{ "subl", 0x40001120, 0, "1,b,3" }, +{ "subl/v", 0x40000920, 0, "1,2,3" }, +{ "subl/v", 0x40001920, 0, "1,b,3" }, +{ "s4subl", 0x40000160, 0, "1,2,3" }, +{ "s4subl", 0x40001160, 0, "1,b,3" }, +{ "s8subl", 0x40000360, 0, "1,2,3" }, +{ "s8subl", 0x40001360, 0, "1,b,3" }, +{ "subq", 0x40000520, 0, "1,2,3" }, +{ "subq", 0x40001520, 0, "1,b,3" }, +{ "subq/v", 0x40000d20, 0, "1,2,3" }, +{ "subq/v", 0x40001d20, 0, "1,b,3" }, +{ "s4subq", 0x40000560, 0, "1,2,3" }, +{ "s4subq", 0x40001560, 0, "1,b,3" }, +{ "s8subq", 0x40000760, 0, "1,2,3" }, +{ "s8subq", 0x40001760, 0, "1,b,3" }, +{ "cmpbge", 0x400001e0, 0, "1,2,3" }, +{ "cmpbge", 0x400011e0, 0, "1,b,3" }, + +{ "mull", 0x4c000000, 0, "1,2,3" }, +{ "mull", 0x4c001000, 0, "1,b,3" }, +{ "mull/v", 0x4c000800, 0, "1,2,3" }, +{ "mull/v", 0x4c001800, 0, "1,b,3" }, +{ "mulq", 0x4c000400, 0, "1,2,3" }, +{ "mulq", 0x4c001400, 0, "1,b,3" }, +{ "mulq/v", 0x4c000c00, 0, "1,2,3" }, +{ "mulq/v", 0x4c001c00, 0, "1,b,3" }, +{ "umulh", 0x4c000600, 0, "1,2,3" }, +{ "umulh", 0x4c001600, 0, "1,b,3" }, + +{ "clr", 0x47ff0400, 0, "3" }, /* macro: or zero,zero,rc */ +{ "negl", 0x43e00120, 0, "2,3" }, /* macro: subl zero,rb,rc */ +{ "negl_v", 0x43e00920, 0, "2,3" }, /* macro: subl_v zero,rb,rc */ +{ "negq", 0x43e00520, 0, "2,3" }, /* macro: subq zero,rb,rc */ +{ "negq_v", 0x43e00d20, 0, "2,3" }, /* macro: subq_v zero,rb,rc */ +{ "sextl", 0x43e00000, 0, "2,3" }, /* macro: addl zero,rb,rc */ + +{ "and", 0x44000000, 0, "1,2,3" }, +{ "and", 0x44001000, 0, "1,b,3" }, +{ "and", 0x44000000, 0, "r,2" }, /* macro: and ra,rb,ra */ +{ "and", 0x44001000, 0, "r,b" }, /* macro: and ra,#,ra */ +{ "or", 0x44000400, 0, "1,2,3" }, +{ "or", 0x44001400, 0, "1,b,3" }, +{ "or", 0x44000400, 0, "r,2" }, /* macro: or ra,rb,ra */ +{ "or", 0x44001400, 0, "r,b" }, /* macro: or ra,#,ra */ +{ "bis", 0x44000400, 0, "1,2,3" }, +{ "bis", 0x44001400, 0, "1,b,3" }, +{ "bis", 0x44000400, 0, "r,2" }, /* macro: or ra,rb,ra */ +{ "bis", 0x44001400, 0, "r,b" }, /* macro: or ra,#,ra */ +#if 0 /* The `b' handling doesn't seem to handle big constants right + now, and even if it did, this pattern would imply that the + constant should be produced and *then* moved into the + destination register, which is silly. Since the native + assembler doesn't support this instruction, don't even bother + trying to fix it. Just punt. */ +{ "movi", 0x47E01400, 0, "b,3"}, /* movi lit,rc == bis r31,lit,rc */ +#endif +{ "xor", 0x44000800, 0, "1,2,3" }, +{ "xor", 0x44001800, 0, "1,b,3" }, +{ "xor", 0x44000800, 0, "r,2" }, /* macro: ra,rb,ra */ +{ "xor", 0x44001800, 0, "r,b" }, /* macro: ra,#,ra */ +{ "andnot", 0x44000100, 0, "1,2,3" }, +{ "andnot", 0x44001100, 0, "1,b,3" }, +{ "andnot", 0x44000100, 0, "r,2" }, /* macro: ra,#,ra */ +{ "andnot", 0x44001100, 0, "r,b" }, /* macro: ra,#,ra */ +{ "bic", 0x44000100, 0, "1,2,3" }, +{ "bic", 0x44001100, 0, "1,b,3" }, +{ "bic", 0x44000100, 0, "r,2" }, /* macro: ra,#,ra */ +{ "bic", 0x44001100, 0, "r,b" }, /* macro: ra,#,ra */ +{ "ornot", 0x44000500, 0, "1,2,3" }, +{ "ornot", 0x44001500, 0, "1,b,3" }, +{ "ornot", 0x44000500, 0, "r,2" }, /* macro: ra,#,ra */ +{ "ornot", 0x44001500, 0, "r,b" }, /* macro: ra,#,ra */ +{ "not", 0x47e00500, 0, "2,3" }, /* macro: ornot zero,.. */ +{ "not", 0x47e01500, 0, "b,3" }, +{ "xornot", 0x44000900, 0, "1,2,3" }, +{ "xornot", 0x44001900, 0, "1,b,3" }, +{ "xornot", 0x44000900, 0, "r,2" }, /* macro: ra,#,ra */ +{ "xornot", 0x44001900, 0, "r,b" }, /* macro: ra,#,ra */ +{ "eqv", 0x44000900, 0, "1,2,3" }, +{ "eqv", 0x44001900, 0, "1,b,3" }, +{ "eqv", 0x44000900, 0, "r,2" }, /* macro: ra,#,ra */ +{ "eqv", 0x44001900, 0, "r,b" }, /* macro: ra,#,ra */ + +{ "cmoveq", 0x44000480, 0, "1,2,3" }, +{ "cmoveq", 0x44001480, 0, "1,b,3" }, +{ "cmovne", 0x440004c0, 0, "1,2,3" }, +{ "cmovne", 0x440014c0, 0, "1,b,3" }, +{ "cmovlt", 0x44000880, 0, "1,2,3" }, +{ "cmovlt", 0x44001880, 0, "1,b,3" }, +{ "cmovle", 0x44000c80, 0, "1,2,3" }, +{ "cmovle", 0x44001c80, 0, "1,b,3" }, +{ "cmovgt", 0x44000cc0, 0, "1,2,3" }, +{ "cmovgt", 0x44001cc0, 0, "1,b,3" }, +{ "cmovge", 0x440008c0, 0, "1,2,3" }, +{ "cmovge", 0x440018c0, 0, "1,b,3" }, +{ "cmovlbc", 0x440002c0, 0, "1,2,3" }, +{ "cmovlbc", 0x440012c0, 0, "1,b,3" }, +{ "cmovlbs", 0x44000280, 0, "1,2,3" }, +{ "cmovlbs", 0x44001280, 0, "1,b,3" }, + +{ "sll", 0x48000720, 0, "1,2,3" }, +{ "sll", 0x48001720, 0, "1,b,3" }, +{ "srl", 0x48000680, 0, "1,2,3" }, +{ "srl", 0x48001680, 0, "1,b,3" }, +{ "sra", 0x48000780, 0, "1,2,3" }, +{ "sra", 0x48001780, 0, "1,b,3" }, + +{ "extbl", 0x480000c0, 0, "1,2,3" }, +{ "extbl", 0x480010c0, 0, "1,b,3" }, +{ "extwl", 0x480002c0, 0, "1,2,3" }, +{ "extwl", 0x480012c0, 0, "1,b,3" }, +{ "extll", 0x480004c0, 0, "1,2,3" }, +{ "extll", 0x480014c0, 0, "1,b,3" }, +{ "extql", 0x480006c0, 0, "1,2,3" }, +{ "extql", 0x480016c0, 0, "1,b,3" }, +{ "extwh", 0x48000b40, 0, "1,2,3" }, +{ "extwh", 0x48001b40, 0, "1,b,3" }, +{ "extlh", 0x48000d40, 0, "1,2,3" }, +{ "extlh", 0x48001d40, 0, "1,b,3" }, +{ "extqh", 0x48000f40, 0, "1,2,3" }, +{ "extqh", 0x48001f40, 0, "1,b,3" }, +{ "insbl", 0x48000160, 0, "1,2,3" }, +{ "insbl", 0x48001160, 0, "1,b,3" }, +{ "inswl", 0x48000360, 0, "1,2,3" }, +{ "inswl", 0x48001360, 0, "1,b,3" }, +{ "insll", 0x48000560, 0, "1,2,3" }, +{ "insll", 0x48001560, 0, "1,b,3" }, +{ "insql", 0x48000760, 0, "1,2,3" }, +{ "insql", 0x48001760, 0, "1,b,3" }, +{ "inswh", 0x48000ae0, 0, "1,2,3" }, +{ "inswh", 0x48001ae0, 0, "1,b,3" }, +{ "inslh", 0x48000ce0, 0, "1,2,3" }, +{ "inslh", 0x48001ce0, 0, "1,b,3" }, +{ "insqh", 0x48000ee0, 0, "1,2,3" }, +{ "insqh", 0x48001ee0, 0, "1,b,3" }, +{ "mskbl", 0x48000040, 0, "1,2,3" }, +{ "mskbl", 0x48001040, 0, "1,b,3" }, +{ "mskwl", 0x48000240, 0, "1,2,3" }, +{ "mskwl", 0x48001240, 0, "1,b,3" }, +{ "mskll", 0x48000440, 0, "1,2,3" }, +{ "mskll", 0x48001440, 0, "1,b,3" }, +{ "mskql", 0x48000640, 0, "1,2,3" }, +{ "mskql", 0x48001640, 0, "1,b,3" }, +{ "mskwh", 0x48000a40, 0, "1,2,3" }, +{ "mskwh", 0x48001a40, 0, "1,b,3" }, +{ "msklh", 0x48000c40, 0, "1,2,3" }, +{ "msklh", 0x48001c40, 0, "1,b,3" }, +{ "mskqh", 0x48000e40, 0, "1,2,3" }, +{ "mskqh", 0x48001e40, 0, "1,b,3" }, +{ "zap", 0x48000600, 0, "1,2,3" }, +{ "zap", 0x48001600, 0, "1,b,3" }, +{ "zapnot", 0x48000620, 0, "1,2,3" }, +{ "zapnot", 0x48001620, 0, "1,b,3" }, + +/* + * Floating point instructions + */ +{ "ldf", 0x80000000, 1, "e,l(2)" }, /* 6o+5a+5b+16d */ +{ "ldf", 0x80000000, 1, "e,G" }, /* regbase macro */ +{ "ldg", 0x84000000, 1, "e,l(2)" }, +{ "ldg", 0x84000000, 1, "e,G" }, /* regbase macro */ +{ "lds", 0x88000000, 1, "e,l(2)" }, +{ "lds", 0x88000000, 1, "e,G" }, /* regbase macro */ +{ "ldt", 0x8c000000, 1, "e,l(2)" }, +{ "ldt", 0x8c000000, 1, "e,G" }, /* regbase macro */ +{ "stf", 0x90000000, 1, "e,l(2)" }, +{ "stf", 0x90000000, 1, "e,P" }, /* regbase macro */ +{ "stg", 0x94000000, 1, "e,l(2)" }, +{ "stg", 0x94000000, 1, "e,P" }, /* regbase macro */ +{ "sts", 0x98000000, 1, "e,l(2)" }, +{ "sts", 0x98000000, 1, "e,P" }, /* regbase macro */ +{ "stt", 0x9c000000, 1, "e,l(2)" }, +{ "stt", 0x9c000000, 1, "e,P" }, /* regbase macro */ +{ "ldif", 0x80000000, 1, "e,F" }, +{ "ldig", 0x84000000, 1, "e,F" }, +{ "ldis", 0x88000000, 1, "e,F" }, +{ "ldit", 0x8c000000, 1, "e,F" }, + +{ "fbeq", 0xc4000000, 1, "e,L" }, /* 6o+5a+21d */ +{ "fbne", 0xd4000000, 1, "e,L" }, +{ "fblt", 0xc8000000, 1, "e,L" }, +{ "fble", 0xcc000000, 1, "e,L" }, +{ "fbgt", 0xdc000000, 1, "e,L" }, +{ "fbge", 0xd8000000, 1, "e,L" }, + +/* All subsets (opcode 0x17) */ +{ "cpys", 0x5c000400, 1, "e,f,g" }, /* 6o+5a+5b+11f+5c */ +{ "cpysn", 0x5c000420, 1, "e,f,g" }, +{ "cpyse", 0x5c000440, 1, "e,f,g" }, + +{ "cvtlq", 0x5fe00200, 1, "f,g" }, +{ "cvtql", 0x5fe00600, 1, "f,g" }, +{ "cvtql/v", 0x5fe02600, 1, "f,g" }, +{ "cvtql/sv", 0x5fe06600, 1, "f,g" }, + +{ "fcmoveq", 0x5c000540, 1, "e,f,g" }, +{ "fcmovne", 0x5c000560, 1, "e,f,g" }, +{ "fcmovlt", 0x5c000580, 1, "e,f,g" }, +{ "fcmovle", 0x5c0005c0, 1, "e,f,g" }, +{ "fcmovgt", 0x5c0005e0, 1, "e,f,g" }, +{ "fcmovge", 0x5c0005a0, 1, "e,f,g" }, + +{ "mf_fpcr", 0x5c0004a0, 1, "E" }, +{ "mt_fpcr", 0x5c000480, 1, "E" }, + +/* Vax subset (opcode 0x15) */ +{ "addf", 0x54001000, 1, "e,f,g" }, +{ "addf/c", 0x54000000, 1, "e,f,g" }, +{ "addf/u", 0x54003000, 1, "e,f,g" }, +{ "addf/uc", 0x54002000, 1, "e,f,g" }, +{ "addf/s", 0x54009000, 1, "e,f,g" }, +{ "addf/sc", 0x54008000, 1, "e,f,g" }, +{ "addf/su", 0x5400b000, 1, "e,f,g" }, +{ "addf/suc", 0x5400a000, 1, "e,f,g" }, +{ "addg", 0x54001400, 1, "e,f,g" }, +{ "addg/c", 0x54000400, 1, "e,f,g" }, +{ "addg/u", 0x54003400, 1, "e,f,g" }, +{ "addg/uc", 0x54002400, 1, "e,f,g" }, +{ "addg/s", 0x54009400, 1, "e,f,g" }, +{ "addg/sc", 0x54008400, 1, "e,f,g" }, +{ "addg/su", 0x5400b400, 1, "e,f,g" }, +{ "addg/suc", 0x5400a400, 1, "e,f,g" }, +{ "subf", 0x54001020, 1, "e,f,g" }, +{ "subf/c", 0x54000020, 1, "e,f,g" }, +{ "subf/u", 0x54003020, 1, "e,f,g" }, +{ "subf/uc", 0x54002020, 1, "e,f,g" }, +{ "subf/s", 0x54009020, 1, "e,f,g" }, +{ "subf/sc", 0x54008020, 1, "e,f,g" }, +{ "subf/su", 0x5400b020, 1, "e,f,g" }, +{ "subf/suc", 0x5400a020, 1, "e,f,g" }, +{ "subg", 0x54001420, 1, "e,f,g" }, +{ "subg/c", 0x54000420, 1, "e,f,g" }, +{ "subg/u", 0x54003420, 1, "e,f,g" }, +{ "subg/uc", 0x54002420, 1, "e,f,g" }, +{ "subg/s", 0x54009420, 1, "e,f,g" }, +{ "subg/sc", 0x54008420, 1, "e,f,g" }, +{ "subg/su", 0x5400b420, 1, "e,f,g" }, +{ "subg/suc", 0x5400a420, 1, "e,f,g" }, + +{ "cmpgeq", 0x540014a0, 1, "e,f,g" }, +{ "cmpgeq/s", 0x540094a0, 1, "e,f,g" }, +{ "cmpglt", 0x540014c0, 1, "e,f,g" }, +{ "cmpglt/s", 0x540094c0, 1, "e,f,g" }, +{ "cmpgle", 0x540014e0, 1, "e,f,g" }, +{ "cmpgle/s", 0x540094e0, 1, "e,f,g" }, + +{ "cvtgq", 0x57e015e0, 1, "f,g" }, +{ "cvtgq/c", 0x57e005e0, 1, "f,g" }, +{ "cvtgq/v", 0x57e035e0, 1, "f,g" }, +{ "cvtgq/vc", 0x57e025e0, 1, "f,g" }, +{ "cvtgq/s", 0x57e095e0, 1, "f,g" }, +{ "cvtgq/sc", 0x57e085e0, 1, "f,g" }, +{ "cvtgq/sv", 0x57e0b5e0, 1, "f,g" }, +{ "cvtgq/svc", 0x57e0a5e0, 1, "f,g" }, +{ "cvtqf", 0x57e01780, 1, "f,g" }, +{ "cvtqf/c", 0x57e00780, 1, "f,g" }, +{ "cvtqf/s", 0x57e09780, 1, "f,g" }, +{ "cvtqf/sc", 0x57e08780, 1, "f,g" }, +{ "cvtqg", 0x57e017c0, 1, "f,g" }, +{ "cvtqg/c", 0x57e007c0, 1, "f,g" }, +{ "cvtqg/s", 0x57e097c0, 1, "f,g" }, +{ "cvtqg/sc", 0x57e087c0, 1, "f,g" }, +{ "cvtdg", 0x57e013c0, 1, "f,g" }, +{ "cvtdg/c", 0x57e003c0, 1, "f,g" }, +{ "cvtdg/u", 0x57e033c0, 1, "f,g" }, +{ "cvtdg/uc", 0x57e023c0, 1, "f,g" }, +{ "cvtdg/s", 0x57e093c0, 1, "f,g" }, +{ "cvtdg/sc", 0x57e083c0, 1, "f,g" }, +{ "cvtdg/su", 0x57e0b3c0, 1, "f,g" }, +{ "cvtdg/suc", 0x57e0a3c0, 1, "f,g" }, +{ "cvtgd", 0x57e015a0, 1, "f,g" }, +{ "cvtgd/c", 0x57e005a0, 1, "f,g" }, +{ "cvtgd/u", 0x57e035a0, 1, "f,g" }, +{ "cvtgd/uc", 0x57e025a0, 1, "f,g" }, +{ "cvtgd/s", 0x57e095a0, 1, "f,g" }, +{ "cvtgd/sc", 0x57e085a0, 1, "f,g" }, +{ "cvtgd/su", 0x57e0b5a0, 1, "f,g" }, +{ "cvtgd/suc", 0x57e0a5a0, 1, "f,g" }, +{ "cvtgf", 0x57e01580, 1, "f,g" }, +{ "cvtgf/c", 0x57e00580, 1, "f,g" }, +{ "cvtgf/u", 0x57e03580, 1, "f,g" }, +{ "cvtgf/uc", 0x57e02580, 1, "f,g" }, +{ "cvtgf/s", 0x57e09580, 1, "f,g" }, +{ "cvtgf/sc", 0x57e08580, 1, "f,g" }, +{ "cvtgf/su", 0x57e0b580, 1, "f,g" }, +{ "cvtgf/suc", 0x57e0a580, 1, "f,g" }, + +{ "divf", 0x54001060, 1, "e,f,g" }, +{ "divf/c", 0x54000060, 1, "e,f,g" }, +{ "divf/u", 0x54003060, 1, "e,f,g" }, +{ "divf/uc", 0x54002060, 1, "e,f,g" }, +{ "divf/s", 0x54009060, 1, "e,f,g" }, +{ "divf/sc", 0x54008060, 1, "e,f,g" }, +{ "divf/su", 0x5400b060, 1, "e,f,g" }, +{ "divf/suc", 0x5400a060, 1, "e,f,g" }, +{ "divg", 0x54001460, 1, "e,f,g" }, +{ "divg/c", 0x54000460, 1, "e,f,g" }, +{ "divg/u", 0x54003460, 1, "e,f,g" }, +{ "divg/uc", 0x54002460, 1, "e,f,g" }, +{ "divg/s", 0x54009460, 1, "e,f,g" }, +{ "divg/sc", 0x54008460, 1, "e,f,g" }, +{ "divg/su", 0x5400b460, 1, "e,f,g" }, +{ "divg/suc", 0x5400a460, 1, "e,f,g" }, +{ "mulf", 0x54001040, 1, "e,f,g" }, +{ "mulf/c", 0x54000040, 1, "e,f,g" }, +{ "mulf/u", 0x54003040, 1, "e,f,g" }, +{ "mulf/uc", 0x54002040, 1, "e,f,g" }, +{ "mulf/s", 0x54009040, 1, "e,f,g" }, +{ "mulf/sc", 0x54008040, 1, "e,f,g" }, +{ "mulf/su", 0x5400b040, 1, "e,f,g" }, +{ "mulf/suc", 0x5400a040, 1, "e,f,g" }, +{ "mulg", 0x54001440, 1, "e,f,g" }, +{ "mulg/c", 0x54000440, 1, "e,f,g" }, +{ "mulg/u", 0x54003440, 1, "e,f,g" }, +{ "mulg/uc", 0x54002440, 1, "e,f,g" }, +{ "mulg/s", 0x54009440, 1, "e,f,g" }, +{ "mulg/sc", 0x54008440, 1, "e,f,g" }, +{ "mulg/su", 0x5400b440, 1, "e,f,g" }, +{ "mulg/suc", 0x5400a440, 1, "e,f,g" }, + +/* IEEE subset (opcode 0x16) */ +{ "adds", 0x58001000, 1, "e,f,g" }, +{ "adds/c", 0x58000000, 1, "e,f,g" }, +{ "adds/m", 0x58000800, 1, "e,f,g" }, +{ "adds/d", 0x58001800, 1, "e,f,g" }, +{ "adds/u", 0x58003000, 1, "e,f,g" }, +{ "adds/uc", 0x58002000, 1, "e,f,g" }, +{ "adds/um", 0x58002800, 1, "e,f,g" }, +{ "adds/ud", 0x58003800, 1, "e,f,g" }, +{ "adds/su", 0x5800b000, 1, "e,f,g" }, +{ "adds/suc", 0x5800a000, 1, "e,f,g" }, +{ "adds/sum", 0x5800a800, 1, "e,f,g" }, +{ "adds/sud", 0x5800b800, 1, "e,f,g" }, +{ "adds/sui", 0x5800f000, 1, "e,f,g" }, +{ "adds/suic", 0x5800e000, 1, "e,f,g" }, +{ "adds/suim", 0x5800e800, 1, "e,f,g" }, +{ "adds/suid", 0x5800f800, 1, "e,f,g" }, +{ "addt", 0x58001400, 1, "e,f,g" }, +{ "addt/c", 0x58000400, 1, "e,f,g" }, +{ "addt/m", 0x58000c00, 1, "e,f,g" }, +{ "addt/d", 0x58001c00, 1, "e,f,g" }, +{ "addt/u", 0x58003400, 1, "e,f,g" }, +{ "addt/uc", 0x58002400, 1, "e,f,g" }, +{ "addt/um", 0x58002c00, 1, "e,f,g" }, +{ "addt/ud", 0x58003c00, 1, "e,f,g" }, +{ "addt/su", 0x5800b400, 1, "e,f,g" }, +{ "addt/suc", 0x5800a400, 1, "e,f,g" }, +{ "addt/sum", 0x5800ac00, 1, "e,f,g" }, +{ "addt/sud", 0x5800bc00, 1, "e,f,g" }, +{ "addt/sui", 0x5800f400, 1, "e,f,g" }, +{ "addt/suic", 0x5800e400, 1, "e,f,g" }, +{ "addt/suim", 0x5800ec00, 1, "e,f,g" }, +{ "addt/suid", 0x5800fc00, 1, "e,f,g" }, +{ "subs", 0x58001020, 1, "e,f,g" }, +{ "subs/c", 0x58000020, 1, "e,f,g" }, +{ "subs/m", 0x58000820, 1, "e,f,g" }, +{ "subs/d", 0x58001820, 1, "e,f,g" }, +{ "subs/u", 0x58003020, 1, "e,f,g" }, +{ "subs/uc", 0x58002020, 1, "e,f,g" }, +{ "subs/um", 0x58002820, 1, "e,f,g" }, +{ "subs/ud", 0x58003820, 1, "e,f,g" }, +{ "subs/su", 0x5800b020, 1, "e,f,g" }, +{ "subs/suc", 0x5800a020, 1, "e,f,g" }, +{ "subs/sum", 0x5800a820, 1, "e,f,g" }, +{ "subs/sud", 0x5800b820, 1, "e,f,g" }, +{ "subs/sui", 0x5800f020, 1, "e,f,g" }, +{ "subs/suic", 0x5800e020, 1, "e,f,g" }, +{ "subs/suim", 0x5800e820, 1, "e,f,g" }, +{ "subs/suid", 0x5800f820, 1, "e,f,g" }, +{ "subt", 0x58001420, 1, "e,f,g" }, +{ "subt/c", 0x58000420, 1, "e,f,g" }, +{ "subt/m", 0x58000c20, 1, "e,f,g" }, +{ "subt/d", 0x58001c20, 1, "e,f,g" }, +{ "subt/u", 0x58003420, 1, "e,f,g" }, +{ "subt/uc", 0x58002420, 1, "e,f,g" }, +{ "subt/um", 0x58002c20, 1, "e,f,g" }, +{ "subt/ud", 0x58003c20, 1, "e,f,g" }, +{ "subt/su", 0x5800b420, 1, "e,f,g" }, +{ "subt/suc", 0x5800a420, 1, "e,f,g" }, +{ "subt/sum", 0x5800ac20, 1, "e,f,g" }, +{ "subt/sud", 0x5800bc20, 1, "e,f,g" }, +{ "subt/sui", 0x5800f420, 1, "e,f,g" }, +{ "subt/suic", 0x5800e420, 1, "e,f,g" }, +{ "subt/suim", 0x5800ec20, 1, "e,f,g" }, +{ "subt/suid", 0x5800fc20, 1, "e,f,g" }, + +{ "cmpteq", 0x580014a0, 1, "e,f,g" }, +{ "cmpteq/su", 0x5800b4a0, 1, "e,f,g" }, +{ "cmptlt", 0x580014c0, 1, "e,f,g" }, +{ "cmptlt/su", 0x5800b4c0, 1, "e,f,g" }, +{ "cmptle", 0x580014e0, 1, "e,f,g" }, +{ "cmptle/su", 0x5800b4e0, 1, "e,f,g" }, +{ "cmptun", 0x58001480, 1, "e,f,g" }, +{ "cmptun/su", 0x5800b480, 1, "e,f,g" }, + +{ "cvttq", 0x5be015e0, 1, "f,g" }, +{ "cvttq/c", 0x5be005e0, 1, "f,g" }, +{ "cvttq/v", 0x5be035e0, 1, "f,g" }, +{ "cvttq/vc", 0x5be025e0, 1, "f,g" }, +{ "cvttq/sv", 0x5be0b5e0, 1, "f,g" }, +{ "cvttq/svc", 0x5be0a5e0, 1, "f,g" }, +{ "cvttq/svi", 0x5be0f5e0, 1, "f,g" }, +{ "cvttq/svic", 0x5be0e5e0, 1, "f,g" }, +{ "cvtqs", 0x5be01780, 1, "f,g" }, +{ "cvtqs/c", 0x5be00780, 1, "f,g" }, +{ "cvtqs/m", 0x5be00f80, 1, "f,g" }, +{ "cvtqs/d", 0x5be01f80, 1, "f,g" }, +{ "cvtqs/sui", 0x5be0f780, 1, "f,g" }, +{ "cvtqs/suic", 0x5be0e780, 1, "f,g" }, +{ "cvtqs/suim", 0x5be0ef80, 1, "f,g" }, +{ "cvtqs/suid", 0x5be0ff80, 1, "f,g" }, +{ "cvtqt", 0x5be017c0, 1, "f,g" }, +{ "cvtqt/c", 0x5be007c0, 1, "f,g" }, +{ "cvtqt/m", 0x5be00fc0, 1, "f,g" }, +{ "cvtqt/d", 0x5be01fc0, 1, "f,g" }, +{ "cvtqt/sui", 0x5be0f7c0, 1, "f,g" }, +{ "cvtqt/suic", 0x5be0e7c0, 1, "f,g" }, +{ "cvtqt/suim", 0x5be0efc0, 1, "f,g" }, +{ "cvtqt/suid", 0x5be0ffc0, 1, "f,g" }, +{ "cvtts", 0x5be01580, 1, "f,g" }, +{ "cvtts/c", 0x5be00580, 1, "f,g" }, +{ "cvtts/m", 0x5be00d80, 1, "f,g" }, +{ "cvtts/d", 0x5be01d80, 1, "f,g" }, +{ "cvtts/u", 0x5be03580, 1, "f,g" }, +{ "cvtts/uc", 0x5be02580, 1, "f,g" }, +{ "cvtts/um", 0x5be02d80, 1, "f,g" }, +{ "cvtts/ud", 0x5be03d80, 1, "f,g" }, +{ "cvtts/su", 0x5be0b580, 1, "f,g" }, +{ "cvtts/suc", 0x5be0a580, 1, "f,g" }, +{ "cvtts/sum", 0x5be0ad80, 1, "f,g" }, +{ "cvtts/sud", 0x5be0bd80, 1, "f,g" }, +{ "cvtts/sui", 0x5be0f580, 1, "f,g" }, +{ "cvtts/suic", 0x5be0e580, 1, "f,g" }, +{ "cvtts/suim", 0x5be0ed80, 1, "f,g" }, +{ "cvtts/suid", 0x5be0fd80, 1, "f,g" }, + +{ "divs", 0x58001060, 1, "e,f,g" }, +{ "divs/c", 0x58000060, 1, "e,f,g" }, +{ "divs/m", 0x58000860, 1, "e,f,g" }, +{ "divs/d", 0x58001860, 1, "e,f,g" }, +{ "divs/u", 0x58003060, 1, "e,f,g" }, +{ "divs/uc", 0x58002060, 1, "e,f,g" }, +{ "divs/um", 0x58002860, 1, "e,f,g" }, +{ "divs/ud", 0x58003860, 1, "e,f,g" }, +{ "divs/su", 0x5800b060, 1, "e,f,g" }, +{ "divs/suc", 0x5800a060, 1, "e,f,g" }, +{ "divs/sum", 0x5800a860, 1, "e,f,g" }, +{ "divs/sud", 0x5800b860, 1, "e,f,g" }, +{ "divs/sui", 0x5800f060, 1, "e,f,g" }, +{ "divs/suic", 0x5800e060, 1, "e,f,g" }, +{ "divs/suim", 0x5800e860, 1, "e,f,g" }, +{ "divs/suid", 0x5800f860, 1, "e,f,g" }, +{ "divt", 0x58001460, 1, "e,f,g" }, +{ "divt/c", 0x58000460, 1, "e,f,g" }, +{ "divt/m", 0x58000c60, 1, "e,f,g" }, +{ "divt/d", 0x58001c60, 1, "e,f,g" }, +{ "divt/u", 0x58003460, 1, "e,f,g" }, +{ "divt/uc", 0x58002460, 1, "e,f,g" }, +{ "divt/um", 0x58002c60, 1, "e,f,g" }, +{ "divt/ud", 0x58003c60, 1, "e,f,g" }, +{ "divt/su", 0x5800b460, 1, "e,f,g" }, +{ "divt/suc", 0x5800a460, 1, "e,f,g" }, +{ "divt/sum", 0x5800ac60, 1, "e,f,g" }, +{ "divt/sud", 0x5800bc60, 1, "e,f,g" }, +{ "divt/sui", 0x5800f460, 1, "e,f,g" }, +{ "divt/suic", 0x5800e460, 1, "e,f,g" }, +{ "divt/suim", 0x5800ec60, 1, "e,f,g" }, +{ "divt/suid", 0x5800fc60, 1, "e,f,g" }, +{ "muls", 0x58001040, 1, "e,f,g" }, +{ "muls/c", 0x58000040, 1, "e,f,g" }, +{ "muls/m", 0x58000840, 1, "e,f,g" }, +{ "muls/d", 0x58001840, 1, "e,f,g" }, +{ "muls/u", 0x58003040, 1, "e,f,g" }, +{ "muls/uc", 0x58002040, 1, "e,f,g" }, +{ "muls/um", 0x58002840, 1, "e,f,g" }, +{ "muls/ud", 0x58003840, 1, "e,f,g" }, +{ "muls/su", 0x5800b040, 1, "e,f,g" }, +{ "muls/suc", 0x5800a040, 1, "e,f,g" }, +{ "muls/sum", 0x5800a840, 1, "e,f,g" }, +{ "muls/sud", 0x5800b840, 1, "e,f,g" }, +{ "muls/sui", 0x5800f040, 1, "e,f,g" }, +{ "muls/suic", 0x5800e040, 1, "e,f,g" }, +{ "muls/suim", 0x5800e840, 1, "e,f,g" }, +{ "muls/suid", 0x5800f840, 1, "e,f,g" }, +{ "mult", 0x58001440, 1, "e,f,g" }, +{ "mult/c", 0x58000440, 1, "e,f,g" }, +{ "mult/m", 0x58000c40, 1, "e,f,g" }, +{ "mult/d", 0x58001c40, 1, "e,f,g" }, +{ "mult/u", 0x58003440, 1, "e,f,g" }, +{ "mult/uc", 0x58002440, 1, "e,f,g" }, +{ "mult/um", 0x58002c40, 1, "e,f,g" }, +{ "mult/ud", 0x58003c40, 1, "e,f,g" }, +{ "mult/su", 0x5800b440, 1, "e,f,g" }, +{ "mult/suc", 0x5800a440, 1, "e,f,g" }, +{ "mult/sum", 0x5800ac40, 1, "e,f,g" }, +{ "mult/sud", 0x5800bc40, 1, "e,f,g" }, +{ "mult/sui", 0x5800f440, 1, "e,f,g" }, +{ "mult/suic", 0x5800e440, 1, "e,f,g" }, +{ "mult/suim", 0x5800ec40, 1, "e,f,g" }, +{ "mult/suid", 0x5800fc40, 1, "e,f,g" }, + +/* + * Miscellaneous + */ +{ "pal", 0x00000000, 0, "I" }, /* 6o+26f */ +{ "call_pal", 0x00000000, 0, "I" }, /* alias */ +{ "bpt", 0x00000080, 0, "" }, +{ "chmk", 0x00000083, 0, "" }, +{ "imb", 0x00000086, 0, "" }, +{ "halt", 0x00000000, 0, "" }, +{ "draina", 0x00000002, 0, "" }, + +{ "draint", 0x60000000, 0, "" }, /* 6o+5a+5b+16d */ +{ "trapb", 0x60000000, 0, "" }, /* 6o+5a+5b+16d */ +{ "fetch", 0x60008000, 0, "0(2)" }, +{ "fetch_m", 0x6000a000, 0, "0(2)" }, +{ "mb", 0x60004000, 0, "" }, +{ "rpcc", 0x6000c000, 0, "1" }, +{ "rc", 0x6000e000, 0, "1" }, +{ "rs", 0x6000f000, 0, "1" }, + +/* + * PAL instructions + */ +{ "hw_ld", 0x6c000000, 0, "1,t(2)" }, +{ "hw_ld/p", 0x6c008000, 0, "1,t(2)" }, +{ "hw_ld/a", 0x6c004000, 0, "1,t(2)" }, +{ "hw_ld/r", 0x6c002000, 0, "1,t(2)" }, +{ "hw_ld/q", 0x6c001000, 0, "1,t(2)" }, +{ "hw_ld/pa", 0x6c00C000, 0, "1,t(2)" }, +{ "hw_ld/pr", 0x6c00A000, 0, "1,t(2)" }, +{ "hw_ld/pq", 0x6c009000, 0, "1,t(2)" }, +{ "hw_ld/ar", 0x6c006000, 0, "1,t(2)" }, +{ "hw_ld/aq", 0x6c005000, 0, "1,t(2)" }, +{ "hw_ld/rq", 0x6c003000, 0, "1,t(2)" }, +{ "hw_ld/par", 0x6c00e000, 0, "1,t(2)" }, +{ "hw_ld/paq", 0x6c00d000, 0, "1,t(2)" }, +{ "hw_ld/prq", 0x6c00b000, 0, "1,t(2)" }, +{ "hw_ld/arq", 0x6c007000, 0, "1,t(2)" }, +{ "hw_ld/parq", 0x6c00f000, 0, "1,t(2)" }, + +{ "hw_ldq", 0x6c001000, 0, "1,t(2)" }, /* ldq/ldl variants for Eric */ +{ "hw_ldq/p", 0x6c009000, 0, "1,t(2)" }, +{ "hw_ldq/a", 0x6c005000, 0, "1,t(2)" }, +{ "hw_ldq/r", 0x6c003000, 0, "1,t(2)" }, +{ "hw_ldq/pa", 0x6c00d000, 0, "1,t(2)" }, +{ "hw_ldq/pr", 0x6c00b000, 0, "1,t(2)" }, +{ "hw_ldq/ar", 0x6c007000, 0, "1,t(2)" }, +{ "hw_ldq/par", 0x6c00f000, 0, "1,t(2)" }, +{ "hw_ldl", 0x6c000000, 0, "1,t(2)" }, +{ "hw_ldl/p", 0x6c008000, 0, "1,t(2)" }, +{ "hw_ldl/a", 0x6c004000, 0, "1,t(2)" }, +{ "hw_ldl/r", 0x6c002000, 0, "1,t(2)" }, +{ "hw_ldl/pa", 0x6c00C000, 0, "1,t(2)" }, +{ "hw_ldl/pr", 0x6c00A000, 0, "1,t(2)" }, +{ "hw_ldl/ar", 0x6c006000, 0, "1,t(2)" }, +{ "hw_ldl/par", 0x6c00e000, 0, "1,t(2)" }, + +{ "hw_st/paq", 0x7c00c000, 0, "1,t(2)" }, +{ "hw_st/pa", 0x7c00b000, 0, "1,t(2)" }, +{ "hw_st/pq", 0x7c009000, 0, "1,t(2)" }, +{ "hw_st/aq", 0x7c005000, 0, "1,t(2)" }, +{ "hw_st/p", 0x7c008000, 0, "1,t(2)" }, +{ "hw_st/a", 0x7c004000, 0, "1,t(2)" }, +{ "hw_st/q", 0x7c001000, 0, "1,t(2)" }, +{ "hw_st", 0x7c000000, 0, "1,t(2)" }, + +{ "hw_stq/pa", 0x7c00c000, 0, "1,t(2)" }, /* stq/stl variants for Eric */ +{ "hw_stq/p", 0x7c009000, 0, "1,t(2)" }, +{ "hw_stq", 0x7c001000, 0, "1,t(2)" }, +{ "hw_stq/a", 0x7c005000, 0, "1,t(2)" }, +{ "hw_stl/pa", 0x7c00b000, 0, "1,t(2)" }, +{ "hw_stl/p", 0x7c008000, 0, "1,t(2)" }, +{ "hw_stl/a", 0x7c004000, 0, "1,t(2)" }, +{ "hw_stl", 0x7c000000, 0, "1,t(2)" }, + +{ "hw_mfpr/p", 0x64000080, 0, "R,3" }, +{ "hw_mfpr/a", 0x64000040, 0, "R,3" }, +{ "hw_mfpr/i", 0x64000020, 0, "R,3" }, +{ "hw_mfpr/pa", 0x640000c0, 0, "R,3" }, +{ "hw_mfpr/pi", 0x640000a0, 0, "R,3" }, +{ "hw_mfpr/ai", 0x64000060, 0, "R,3" }, +{ "hw_mfpr/pai",0x640000e0, 0, "R,3" }, +{ "hw_mfpr", 0x64000000, 0, "R,8" }, + +{ "hw_mtpr/p", 0x74000080, 0, "R,3" }, +{ "hw_mtpr/a", 0x74000040, 0, "R,3" }, +{ "hw_mtpr/i", 0x74000020, 0, "R,3" }, +{ "hw_mtpr/pa", 0x740000c0, 0, "R,3" }, +{ "hw_mtpr/pi", 0x740000a0, 0, "R,3" }, +{ "hw_mtpr/ai", 0x74000060, 0, "R,3" }, +{ "hw_mtpr/pai",0x740000e0, 0, "R,3" }, +{ "hw_mtpr", 0x74000000, 0, "R,8" }, + +{ "hw_rei", 0x7bff8000, 0, "" }, +/* + * More macros + */ +{ "nop", 0x47ff041f, 0, "" }, /* or zero,zero,zero */ +{ "mov", 0x47e00400, 0, "2,3" }, /* or zero,r2,r3 */ +}; + +#define NUMOPCODES ((sizeof alpha_opcodes)/(sizeof alpha_opcodes[0])) diff --git a/gnu/usr.bin/binutils/gas/config/aout_gnu.h b/gnu/usr.bin/binutils/gas/config/aout_gnu.h new file mode 100644 index 00000000000..badf9cb21c7 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/aout_gnu.h @@ -0,0 +1,455 @@ +/* This file is aout_gnu.h + + Copyright (C) 1987-1992 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 2, 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. */ + +#ifndef __A_OUT_GNU_H__ +#define __A_OUT_GNU_H__ + +/* There are two main flavours of a.out, one which uses the standard + relocations, and one which uses extended relocations. + + Today, the extended reloc uses are + TC_SPARC, TC_A29K + + each must define the enum reloc_type + +*/ + +#define USE_EXTENDED_RELOC (defined(TC_SPARC) || defined(TC_A29K)) + +#if defined(TC_SPARC) || defined(TC_A29K) +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_10, 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 + }; + +#endif /* TC_SPARC or TC_A29K */ + + +#define __GNU_EXEC_MACROS__ + +#ifndef __STRUCT_EXEC_OVERRIDE__ + +/* This is the layout on disk of a Unix V7, Berkeley, SunOS, Vax Ultrix + "struct exec". Don't assume that on this machine, the "struct exec" + will lay out the same sizes or alignments. */ + +struct exec_bytes + { + unsigned char a_info[4]; + unsigned char a_text[4]; + unsigned char a_data[4]; + unsigned char a_bss[4]; + unsigned char a_syms[4]; + unsigned char a_entry[4]; + unsigned char a_trsize[4]; + unsigned char a_drsize[4]; + }; + +/* How big the "struct exec" is on disk */ +#define EXEC_BYTES_SIZE (8 * 4) + +/* This is the layout in memory of a "struct exec" while we process it. */ + +struct exec +{ + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned a_text; /* length of text, in bytes */ + unsigned a_data; /* length of data, in bytes */ + unsigned a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned a_syms; /* length of symbol table data in file, in bytes */ + unsigned a_entry; /* start address */ + unsigned a_trsize; /* length of relocation info for text, in bytes */ + unsigned a_drsize; /* length of relocation info for data, in bytes */ +}; + +#endif /* __STRUCT_EXEC_OVERRIDE__ */ + +/* these go in the N_MACHTYPE field */ +/* These symbols could be defined by code from Suns...punt 'em */ +#undef M_UNKNOWN +#undef M_68010 +#undef M_68020 +#undef M_SPARC +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 sun's numbers */ + M_386 = 100, + M_29K = 101, + M_RS6000 = 102, /* IBM RS/6000 */ + /* HP/BSD formats */ + M_HP200 = 200, /* hp200 (68010) BSD binary */ + M_HP300 = 300, /* hp300 (68020+68881) BSD binary */ + M_HPUX23 = 0x020C /* hp200/300 HPUX binary */ + }; + +#define N_MAGIC(exec) ((exec).a_info & 0xffff) +#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) +#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff) +#define N_SET_INFO(exec, magic, type, flags) \ + ((exec).a_info = ((magic) & 0xffff) \ + | (((int)(type) & 0xff) << 16) \ + | (((flags) & 0xff) << 24)) +#define N_SET_MAGIC(exec, magic) \ + ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) + +#define N_SET_MACHTYPE(exec, machtype) \ + ((exec).a_info = \ + ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16)) + +#define N_SET_FLAGS(exec, flags) \ + ((exec).a_info = \ + ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24)) + +/* Code indicating object file or impure executable. */ +#ifndef OMAGIC +#define OMAGIC 0407 +#endif +/* Code indicating pure executable. */ +#define NMAGIC 0410 +/* Code indicating demand-paged executable. */ +#define ZMAGIC 0413 + +/* Virtual Address of text segment from the a.out file. For OMAGIC, + (almost always "unlinked .o's" these days), should be zero. + For linked files, should reflect reality if we know it. */ + +#ifndef N_TXTADDR +#define N_TXTADDR(x) (N_MAGIC(x)==OMAGIC? 0 : TEXT_START_ADDR) +#endif + +#ifndef N_BADMAG +#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ + && N_MAGIC(x) != NMAGIC \ + && N_MAGIC(x) != ZMAGIC) +#endif + +/* By default, segment size is constant. But on some machines, it can + be a function of the a.out header (e.g. machine type). */ +#ifndef N_SEGSIZE +#define N_SEGSIZE(x) SEGMENT_SIZE +#endif + +/* This complexity is for encapsulated COFF support */ +#ifndef _N_HDROFF +#define _N_HDROFF(x) (N_SEGSIZE(x) - sizeof (struct exec)) +#endif + +#ifndef N_TXTOFF +#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? \ + _N_HDROFF((x)) + sizeof (struct exec) : \ + sizeof (struct exec)) +#endif + + +#ifndef N_DATOFF +#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) +#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 + +/* Address of text segment in memory after it is loaded. */ +#ifndef N_TXTADDR +#define N_TXTADDR(x) 0 +#endif + +#ifndef N_DATADDR +#define N_DATADDR(x) \ + (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+(x).a_text) \ + : (N_SEGSIZE(x) + ((N_TXTADDR(x)+(x).a_text-1) & ~(N_SEGSIZE(x)-1)))) +#endif + +/* Address of bss segment in memory after it is loaded. */ +#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) + +struct nlist + { + union + { + char *n_name; + struct nlist *n_next; + long n_strx; + } + n_un; + unsigned char n_type; + char n_other; + short n_desc; + unsigned long n_value; + }; + +#define N_UNDF 0 +#define N_ABS 2 +#define N_TEXT 4 +#define N_DATA 6 +#define N_BSS 8 +#define N_COMM 0x12 /* common (visible in shared lib commons) */ +#define N_FN 0x1F /* File name of a .o file */ + +/* Note: N_EXT can only usefully be 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 +#define N_TYPE 036 +#define N_STAB 0340 + +/* The following type indicates the definition of a symbol as being + an indirect reference to another symbol. The other symbol + appears as an undefined reference, immediately following this symbol. + + Indirection is asymmetrical. The other symbol's value will be used + to satisfy requests for the indirect symbol, but not vice versa. + If the other symbol does not have a definition, libraries will + be searched to find a definition. */ + +#define N_INDR 0xa + +/* 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 + element's 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. */ + +/* 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. */ + +/* The following enum and struct were borrowed from SunOS's + /usr/include/sun4/a.out.h and extended to handle + other machines. It is currently used on SPARC and AMD 29000. + + reloc_ext_bytes is how it looks on disk. reloc_info_extended is + how we might process it on a native host. */ +#if USE_EXTENDED_RELOC + +struct reloc_ext_bytes + { + unsigned char r_address[4]; + unsigned char r_index[3]; + unsigned char r_bits[1]; + unsigned char r_addend[4]; + }; + + +#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 + +#define RELOC_EXT_SIZE 12 /* Bytes per relocation entry */ + +struct reloc_info_extended +{ + unsigned long r_address; + unsigned int r_index:24; +# define r_symbolnum r_index + unsigned r_extern:1; + unsigned:2; + /* RS/6000 compiler does not support enum bitfield + enum reloc_type r_type:5; */ + enum reloc_type r_type; + long int r_addend; +}; + +#else + +/* The standard, old-fashioned, Berkeley compatible relocation struct */ + + + +#ifdef TC_I860 +/* NOTE: three bits max, see struct reloc_info_i860.r_type */ +enum i860_reloc_type + { + NO_RELOC = 0, BRADDR, LOW0, LOW1, LOW2, LOW3, LOW4, SPLIT0, SPLIT1, SPLIT2, RELOC_32, + }; + +typedef enum i860_reloc_type reloc_type; + +/* NOTE: two bits max, see reloc_info_i860.r_type */ +enum highlow_type + { + NO_SPEC = 0, PAIR, HIGH, HIGHADJ, + }; + + +struct reloc_info_i860 +{ + unsigned long r_address; + /* + * Using bit fields here is a bad idea because the order is not portable. :-( + */ + unsigned int r_symbolnum:24; + unsigned int r_pcrel:1; + unsigned int r_extern:1; + /* combining the two field simplifies the argument passing in "new_fix()" */ + /* and is compatible with the existing Sparc #ifdef's */ + /* r_type: highlow_type - bits 5,4; reloc_type - bits 3-0 */ + unsigned int r_type:6; + long r_addend; +}; + +#endif /* TC_I860 */ + + +struct reloc_std_bytes + { + unsigned char r_address[4]; + unsigned char r_index[3]; + unsigned char r_bits[1]; + }; + +#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 8 /* Bytes per relocation entry */ + +#endif /* USE_EXTENDED_RELOC */ + +#ifndef CUSTOM_RELOC_FORMAT +struct relocation_info +{ + /* Address (within segment) to be relocated. */ + int r_address; + /* 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 file's 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. */ +#ifdef TC_NS32K + unsigned int r_bsr:1; + unsigned int r_disp:2; +#else + 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" */ +#endif /* TC_NS32K */ + /* unused */ + unsigned int r_pad:1; /* Padding -- set to zero */ +}; + +#endif /* CUSTOM_RELOC_FORMAT */ + +#endif /* __A_OUT_GNU_H__ */ + +/* end of aout_gnu.h */ diff --git a/gnu/usr.bin/binutils/gas/config/arm-big.mt b/gnu/usr.bin/binutils/gas/config/arm-big.mt new file mode 100644 index 00000000000..31e773a14d9 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/arm-big.mt @@ -0,0 +1 @@ +TDEFINES=-DTARGET_BYTES_BIG_ENDIAN diff --git a/gnu/usr.bin/binutils/gas/config/arm-lit.mt b/gnu/usr.bin/binutils/gas/config/arm-lit.mt new file mode 100644 index 00000000000..9e240e8166e --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/arm-lit.mt @@ -0,0 +1 @@ +TDEFINES=-DTARGET_BYTES_LITTLE_ENDIAN diff --git a/gnu/usr.bin/binutils/gas/config/atof-ieee.c b/gnu/usr.bin/binutils/gas/config/atof-ieee.c new file mode 100644 index 00000000000..b577cdfb3c2 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/atof-ieee.c @@ -0,0 +1,584 @@ +/* atof_ieee.c - turn a Flonum into an IEEE floating point number + Copyright (C) 1987, 1992 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 2, 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. */ + +#include "as.h" + +extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */ + +#ifndef NULL +#define NULL (0) +#endif + +extern const char EXP_CHARS[]; +/* Precision in LittleNums. */ +#define MAX_PRECISION (6) +#define F_PRECISION (2) +#define D_PRECISION (4) +#define X_PRECISION (6) +#define P_PRECISION (6) + +/* Length in LittleNums of guard bits. */ +#define GUARD (2) + +static const unsigned long mask[] = +{ + 0x00000000, + 0x00000001, + 0x00000003, + 0x00000007, + 0x0000000f, + 0x0000001f, + 0x0000003f, + 0x0000007f, + 0x000000ff, + 0x000001ff, + 0x000003ff, + 0x000007ff, + 0x00000fff, + 0x00001fff, + 0x00003fff, + 0x00007fff, + 0x0000ffff, + 0x0001ffff, + 0x0003ffff, + 0x0007ffff, + 0x000fffff, + 0x001fffff, + 0x003fffff, + 0x007fffff, + 0x00ffffff, + 0x01ffffff, + 0x03ffffff, + 0x07ffffff, + 0x0fffffff, + 0x1fffffff, + 0x3fffffff, + 0x7fffffff, + 0xffffffff, +}; + + +static int bits_left_in_littlenum; +static int littlenums_left; +static LITTLENUM_TYPE *littlenum_pointer; + +static int +next_bits (number_of_bits) + int number_of_bits; +{ + int return_value; + + if (!littlenums_left) + return (0); + if (number_of_bits >= bits_left_in_littlenum) + { + return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; + number_of_bits -= bits_left_in_littlenum; + return_value <<= number_of_bits; + + if (--littlenums_left) + { + bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; + --littlenum_pointer; + return_value |= (*littlenum_pointer >> bits_left_in_littlenum) & mask[number_of_bits]; + } + } + else + { + bits_left_in_littlenum -= number_of_bits; + return_value = mask[number_of_bits] & (*littlenum_pointer >> bits_left_in_littlenum); + } + return (return_value); +} + +/* Num had better be less than LITTLENUM_NUMBER_OF_BITS */ +static void +unget_bits (num) + int num; +{ + if (!littlenums_left) + { + ++littlenum_pointer; + ++littlenums_left; + bits_left_in_littlenum = num; + } + else if (bits_left_in_littlenum + num > LITTLENUM_NUMBER_OF_BITS) + { + bits_left_in_littlenum = num - (LITTLENUM_NUMBER_OF_BITS - bits_left_in_littlenum); + ++littlenum_pointer; + ++littlenums_left; + } + else + bits_left_in_littlenum += num; +} + +static void +make_invalid_floating_point_number (words) + LITTLENUM_TYPE *words; +{ + as_bad ("cannot create floating-point number"); + words[0] = (LITTLENUM_TYPE) ((unsigned) -1) >> 1; /* Zero the leftmost bit */ + words[1] = (LITTLENUM_TYPE) -1; + words[2] = (LITTLENUM_TYPE) -1; + words[3] = (LITTLENUM_TYPE) -1; + words[4] = (LITTLENUM_TYPE) -1; + words[5] = (LITTLENUM_TYPE) -1; +} + +/************************************************************************\ + * Warning: this returns 16-bit LITTLENUMs. It is up to the caller * + * to figure out any alignment problems and to conspire for the * + * bytes/word to be emitted in the right order. Bigendians beware! * + * * +\************************************************************************/ + +/* Note that atof-ieee always has X and P precisions enabled. it is up + to md_atof to filter them out if the target machine does not support + them. */ + +/* Returns pointer past text consumed. */ +char * +atof_ieee (str, what_kind, words) + char *str; /* Text to convert to binary. */ + char what_kind; /* 'd', 'f', 'g', 'h' */ + LITTLENUM_TYPE *words; /* Build the binary here. */ +{ + /* Extra bits for zeroed low-order bits. The 1st MAX_PRECISION are + zeroed, the last contain flonum bits. */ + static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; + char *return_value; + /* Number of 16-bit words in the format. */ + int precision; + long exponent_bits; + FLONUM_TYPE save_gen_flonum; + + /* We have to save the generic_floating_point_number because it + contains storage allocation about the array of LITTLENUMs where + the value is actually stored. We will allocate our own array of + littlenums below, but have to restore the global one on exit. */ + save_gen_flonum = generic_floating_point_number; + + return_value = str; + generic_floating_point_number.low = bits + MAX_PRECISION; + generic_floating_point_number.high = NULL; + generic_floating_point_number.leader = NULL; + generic_floating_point_number.exponent = 0; + generic_floating_point_number.sign = '\0'; + + /* Use more LittleNums than seems necessary: the highest flonum may + have 15 leading 0 bits, so could be useless. */ + + memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); + + switch (what_kind) + { + case 'f': + case 'F': + case 's': + case 'S': + precision = F_PRECISION; + exponent_bits = 8; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + precision = D_PRECISION; + exponent_bits = 11; + break; + + case 'x': + case 'X': + case 'e': + case 'E': + precision = X_PRECISION; + exponent_bits = 15; + break; + + case 'p': + case 'P': + + precision = P_PRECISION; + exponent_bits = -1; + break; + + default: + make_invalid_floating_point_number (words); + return (NULL); + } + + generic_floating_point_number.high + = generic_floating_point_number.low + precision - 1 + GUARD; + + if (atof_generic (&return_value, ".", EXP_CHARS, + &generic_floating_point_number)) + { + make_invalid_floating_point_number (words); + return (NULL); + } + gen_to_words (words, precision, exponent_bits); + + /* Restore the generic_floating_point_number's storage alloc (and + everything else). */ + generic_floating_point_number = save_gen_flonum; + + return return_value; +} + +/* Turn generic_floating_point_number into a real float/double/extended. */ +int +gen_to_words (words, precision, exponent_bits) + LITTLENUM_TYPE *words; + int precision; + long exponent_bits; +{ + int return_value = 0; + + long exponent_1; + long exponent_2; + long exponent_3; + long exponent_4; + int exponent_skippage; + LITTLENUM_TYPE word1; + LITTLENUM_TYPE *lp; + + if (generic_floating_point_number.low > generic_floating_point_number.leader) + { + /* 0.0e0 seen. */ + if (generic_floating_point_number.sign == '+') + words[0] = 0x0000; + else + words[0] = 0x8000; + memset (&words[1], '\0', sizeof (LITTLENUM_TYPE) * (precision - 1)); + return (return_value); + } + + /* NaN: Do the right thing */ + if (generic_floating_point_number.sign == 0) + { + if (precision == F_PRECISION) + { + words[0] = 0x7fff; + words[1] = 0xffff; + } + else + { + words[0] = 0x7fff; + words[1] = 0xffff; + words[2] = 0xffff; + words[3] = 0xffff; + } + return return_value; + } + else if (generic_floating_point_number.sign == 'P') + { + /* +INF: Do the right thing */ + if (precision == F_PRECISION) + { + words[0] = 0x7f80; + words[1] = 0; + } + else + { + words[0] = 0x7ff0; + words[1] = 0; + words[2] = 0; + words[3] = 0; + } + return (return_value); + } + else if (generic_floating_point_number.sign == 'N') + { + /* Negative INF */ + if (precision == F_PRECISION) + { + words[0] = 0xff80; + words[1] = 0x0; + } + else + { + words[0] = 0xfff0; + words[1] = 0x0; + words[2] = 0x0; + words[3] = 0x0; + } + return (return_value); + } + /* + * The floating point formats we support have: + * Bit 15 is sign bit. + * Bits 14:n are excess-whatever exponent. + * Bits n-1:0 (if any) are most significant bits of fraction. + * Bits 15:0 of the next word(s) are the next most significant bits. + * + * So we need: number of bits of exponent, number of bits of + * mantissa. + */ + bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; + littlenum_pointer = generic_floating_point_number.leader; + littlenums_left = (1 + + generic_floating_point_number.leader + - generic_floating_point_number.low); + /* Seek (and forget) 1st significant bit */ + for (exponent_skippage = 0; !next_bits (1); ++exponent_skippage);; + exponent_1 = (generic_floating_point_number.exponent + + generic_floating_point_number.leader + + 1 + - generic_floating_point_number.low); + /* Radix LITTLENUM_RADIX, point just higher than + generic_floating_point_number.leader. */ + exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; + /* Radix 2. */ + exponent_3 = exponent_2 - exponent_skippage; + /* Forget leading zeros, forget 1st bit. */ + exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2); + /* Offset exponent. */ + + lp = words; + + /* Word 1. Sign, exponent and perhaps high bits. */ + word1 = ((generic_floating_point_number.sign == '+') + ? 0 + : (1 << (LITTLENUM_NUMBER_OF_BITS - 1))); + + /* Assume 2's complement integers. */ + if (exponent_4 < 1 && exponent_4 >= -62) + { + int prec_bits; + int num_bits; + + unget_bits (1); + num_bits = -exponent_4; + prec_bits = LITTLENUM_NUMBER_OF_BITS * precision - (exponent_bits + 1 + num_bits); + if (precision == X_PRECISION && exponent_bits == 15) + prec_bits -= LITTLENUM_NUMBER_OF_BITS + 1; + + if (num_bits >= LITTLENUM_NUMBER_OF_BITS - exponent_bits) + { + /* Bigger than one littlenum */ + num_bits -= (LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits; + *lp++ = word1; + if (num_bits + exponent_bits + 1 >= precision * LITTLENUM_NUMBER_OF_BITS) + { + /* Exponent overflow */ + make_invalid_floating_point_number (words); + return (return_value); + } + if (precision == X_PRECISION && exponent_bits == 15) + { + *lp++ = 0; + *lp++ = 0; + num_bits -= LITTLENUM_NUMBER_OF_BITS - 1; + } + while (num_bits >= LITTLENUM_NUMBER_OF_BITS) + { + num_bits -= LITTLENUM_NUMBER_OF_BITS; + *lp++ = 0; + } + if (num_bits) + *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - (num_bits)); + } + else + { + if (precision == X_PRECISION && exponent_bits == 15) + { + *lp++ = word1; + *lp++ = 0; + if (num_bits == LITTLENUM_NUMBER_OF_BITS) + { + *lp++ = 0; + *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - 1); + } + else if (num_bits == LITTLENUM_NUMBER_OF_BITS - 1) + *lp++ = 0; + else + *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - 1 - num_bits); + num_bits = 0; + } + else + { + word1 |= next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - (exponent_bits + num_bits)); + *lp++ = word1; + } + } + while (lp < words + precision) + *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); + + /* Round the mantissa up, but don't change the number */ + if (next_bits (1)) + { + --lp; + if (prec_bits > LITTLENUM_NUMBER_OF_BITS) + { + int n = 0; + int tmp_bits; + + n = 0; + tmp_bits = prec_bits; + while (tmp_bits > LITTLENUM_NUMBER_OF_BITS) + { + if (lp[n] != (LITTLENUM_TYPE) - 1) + break; + --n; + tmp_bits -= LITTLENUM_NUMBER_OF_BITS; + } + if (tmp_bits > LITTLENUM_NUMBER_OF_BITS || (lp[n] & mask[tmp_bits]) != mask[tmp_bits]) + { + unsigned long carry; + + for (carry = 1; carry && (lp >= words); lp--) + { + carry = *lp + carry; + *lp = carry; + carry >>= LITTLENUM_NUMBER_OF_BITS; + } + } + } + else if ((*lp & mask[prec_bits]) != mask[prec_bits]) + lp++; + } + + return return_value; + } + else if (exponent_4 & ~mask[exponent_bits]) + { + /* + * Exponent overflow. Lose immediately. + */ + + /* + * We leave return_value alone: admit we read the + * number, but return a floating exception + * because we can't encode the number. + */ + make_invalid_floating_point_number (words); + return return_value; + } + else + { + word1 |= (exponent_4 << ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits)) + | next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits); + } + + *lp++ = word1; + + /* X_PRECISION is special: it has 16 bits of zero in the middle, + followed by a 1 bit. */ + if (exponent_bits == 15 && precision == X_PRECISION) + { + *lp++ = 0; + *lp++ = 1 << (LITTLENUM_NUMBER_OF_BITS) | next_bits (LITTLENUM_NUMBER_OF_BITS - 1); + } + + /* The rest of the words are just mantissa bits. */ + while (lp < words + precision) + *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); + + if (next_bits (1)) + { + unsigned long carry; + /* + * Since the NEXT bit is a 1, round UP the mantissa. + * The cunning design of these hidden-1 floats permits + * us to let the mantissa overflow into the exponent, and + * it 'does the right thing'. However, we lose if the + * highest-order bit of the lowest-order word flips. + * Is that clear? + */ + + /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) + Please allow at least 1 more bit in carry than is in a LITTLENUM. + We need that extra bit to hold a carry during a LITTLENUM carry + propagation. Another extra bit (kept 0) will assure us that we + don't get a sticky sign bit after shifting right, and that + permits us to propagate the carry without any masking of bits. + #endif */ + for (carry = 1, lp--; carry && (lp >= words); lp--) + { + carry = *lp + carry; + *lp = carry; + carry >>= LITTLENUM_NUMBER_OF_BITS; + } + if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) + { + /* We leave return_value alone: admit we read the + * number, but return a floating exception + * because we can't encode the number. + */ + *words &= ~(1 << (LITTLENUM_NUMBER_OF_BITS - 1)); + /* make_invalid_floating_point_number (words); */ + /* return return_value; */ + } + } + return (return_value); +} + +#if 0 /* unused */ +/* This routine is a real kludge. Someone really should do it better, + but I'm too lazy, and I don't understand this stuff all too well + anyway. (JF) */ +static void +int_to_gen (x) + long x; +{ + char buf[20]; + char *bufp; + + sprintf (buf, "%ld", x); + bufp = &buf[0]; + if (atof_generic (&bufp, ".", EXP_CHARS, &generic_floating_point_number)) + as_bad ("Error converting number to floating point (Exponent overflow?)"); +} +#endif + +#ifdef TEST +char * +print_gen (gen) + FLONUM_TYPE *gen; +{ + FLONUM_TYPE f; + LITTLENUM_TYPE arr[10]; + double dv; + float fv; + static char sbuf[40]; + + if (gen) + { + f = generic_floating_point_number; + generic_floating_point_number = *gen; + } + gen_to_words (&arr[0], 4, 11); + memcpy (&dv, &arr[0], sizeof (double)); + sprintf (sbuf, "%x %x %x %x %.14G ", arr[0], arr[1], arr[2], arr[3], dv); + gen_to_words (&arr[0], 2, 8); + memcpy (&fv, &arr[0], sizeof (float)); + sprintf (sbuf + strlen (sbuf), "%x %x %.12g\n", arr[0], arr[1], fv); + + if (gen) + { + generic_floating_point_number = f; + } + + return (sbuf); +} + +#endif + +/* end of atof-ieee.c */ diff --git a/gnu/usr.bin/binutils/gas/config/atof-tahoe.c b/gnu/usr.bin/binutils/gas/config/atof-tahoe.c new file mode 100644 index 00000000000..195ea2f9171 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/atof-tahoe.c @@ -0,0 +1,431 @@ + +/* atof_tahoe.c - turn a string into a Tahoe floating point number + Copyright (C) 1987 Free Software Foundation, Inc. + */ + +/* This is really a simplified version of atof_vax.c. I glommed it wholesale + and then shaved it down. I don't even know how it works. (Don't you find + my honesty refreshing? bowen@cs.Buffalo.EDU (Devon E Bowen) + + I don't allow uppercase letters in the precision descrpitors. Ie 'f' and + 'd' are allowed but 'F' and 'D' aren't */ + +#include "as.h" + +/* Precision in LittleNums. */ +#define MAX_PRECISION (4) +#define D_PRECISION (4) +#define F_PRECISION (2) + +/* Precision in chars. */ +#define D_PRECISION_CHARS (8) +#define F_PRECISION_CHARS (4) + +/* Length in LittleNums of guard bits. */ +#define GUARD (2) + +static const long int mask[] = +{ + 0x00000000, + 0x00000001, + 0x00000003, + 0x00000007, + 0x0000000f, + 0x0000001f, + 0x0000003f, + 0x0000007f, + 0x000000ff, + 0x000001ff, + 0x000003ff, + 0x000007ff, + 0x00000fff, + 0x00001fff, + 0x00003fff, + 0x00007fff, + 0x0000ffff, + 0x0001ffff, + 0x0003ffff, + 0x0007ffff, + 0x000fffff, + 0x001fffff, + 0x003fffff, + 0x007fffff, + 0x00ffffff, + 0x01ffffff, + 0x03ffffff, + 0x07ffffff, + 0x0fffffff, + 0x1fffffff, + 0x3fffffff, + 0x7fffffff, + 0xffffffff +}; + + +/* Shared between flonum_gen2tahoe and next_bits */ +static int bits_left_in_littlenum; +static LITTLENUM_TYPE *littlenum_pointer; +static LITTLENUM_TYPE *littlenum_end; + +#if __STDC__ == 1 + +int flonum_gen2tahoe (int format_letter, FLONUM_TYPE * f, LITTLENUM_TYPE * words); + +#else /* not __STDC__ */ + +int flonum_gen2tahoe (); + +#endif /* not __STDC__ */ + + +static int +next_bits (number_of_bits) + int number_of_bits; +{ + int return_value; + + if (littlenum_pointer < littlenum_end) + return 0; + if (number_of_bits >= bits_left_in_littlenum) + { + return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; + number_of_bits -= bits_left_in_littlenum; + return_value <<= number_of_bits; + bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; + littlenum_pointer--; + if (littlenum_pointer >= littlenum_end) + return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) & + mask[number_of_bits]; + } + else + { + bits_left_in_littlenum -= number_of_bits; + return_value = mask[number_of_bits] & + ((*littlenum_pointer) >> bits_left_in_littlenum); + } + return (return_value); +} + +static void +make_invalid_floating_point_number (words) + LITTLENUM_TYPE *words; +{ + *words = 0x8000; /* Floating Reserved Operand Code */ +} + +static int /* 0 means letter is OK. */ +what_kind_of_float (letter, precisionP, exponent_bitsP) + char letter; /* In: lowercase please. What kind of float? */ + int *precisionP; /* Number of 16-bit words in the float. */ + long int *exponent_bitsP; /* Number of exponent bits. */ +{ + int retval; /* 0: OK. */ + + retval = 0; + switch (letter) + { + case 'f': + *precisionP = F_PRECISION; + *exponent_bitsP = 8; + break; + + case 'd': + *precisionP = D_PRECISION; + *exponent_bitsP = 8; + break; + + default: + retval = 69; + break; + } + return (retval); +} + +/***********************************************************************\ +* * +* Warning: this returns 16-bit LITTLENUMs, because that is * +* what the VAX thinks in. It is up to the caller to figure * +* out any alignment problems and to conspire for the bytes/word * +* to be emitted in the right order. Bigendians beware! * +* * +\***********************************************************************/ + +char * /* Return pointer past text consumed. */ +atof_tahoe (str, what_kind, words) + char *str; /* Text to convert to binary. */ + char what_kind; /* 'd', 'f', 'g', 'h' */ + LITTLENUM_TYPE *words; /* Build the binary here. */ +{ + FLONUM_TYPE f; + LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; + /* Extra bits for zeroed low-order bits. */ + /* The 1st MAX_PRECISION are zeroed, */ + /* the last contain flonum bits. */ + char *return_value; + int precision; /* Number of 16-bit words in the format. */ + long int exponent_bits; + + return_value = str; + f.low = bits + MAX_PRECISION; + f.high = NULL; + f.leader = NULL; + f.exponent = NULL; + f.sign = '\0'; + + if (what_kind_of_float (what_kind, &precision, &exponent_bits)) + { + return_value = NULL; /* We lost. */ + make_invalid_floating_point_number (words); + } + if (return_value) + { + memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); + + /* Use more LittleNums than seems */ + /* necessary: the highest flonum may have */ + /* 15 leading 0 bits, so could be useless. */ + f.high = f.low + precision - 1 + GUARD; + + if (atof_generic (&return_value, ".", "eE", &f)) + { + make_invalid_floating_point_number (words); + return_value = NULL; /* we lost */ + } + else + { + if (flonum_gen2tahoe (what_kind, &f, words)) + { + return_value = NULL; + } + } + } + return (return_value); +} + +/* + * In: a flonum, a Tahoe floating point format. + * Out: a Tahoe floating-point bit pattern. + */ + +int /* 0: OK. */ +flonum_gen2tahoe (format_letter, f, words) + char format_letter; /* One of 'd' 'f'. */ + FLONUM_TYPE *f; + LITTLENUM_TYPE *words; /* Deliver answer here. */ +{ + LITTLENUM_TYPE *lp; + int precision; + long int exponent_bits; + int return_value; /* 0 == OK. */ + + return_value = what_kind_of_float (format_letter, &precision, &exponent_bits); + if (return_value != 0) + { + make_invalid_floating_point_number (words); + } + else + { + if (f->low > f->leader) + { + /* 0.0e0 seen. */ + memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision); + } + else + { + long int exponent_1; + long int exponent_2; + long int exponent_3; + long int exponent_4; + int exponent_skippage; + LITTLENUM_TYPE word1; + + /* JF: Deal with new Nan, +Inf and -Inf codes */ + if (f->sign != '-' && f->sign != '+') + { + make_invalid_floating_point_number (words); + return return_value; + } + /* + * All tahoe floating_point formats have: + * Bit 15 is sign bit. + * Bits 14:n are excess-whatever exponent. + * Bits n-1:0 (if any) are most significant bits of fraction. + * Bits 15:0 of the next word are the next most significant bits. + * And so on for each other word. + * + * So we need: number of bits of exponent, number of bits of + * mantissa. + */ + + bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; + littlenum_pointer = f->leader; + littlenum_end = f->low; + /* Seek (and forget) 1st significant bit */ + for (exponent_skippage = 0; + !next_bits (1); + exponent_skippage++) + { + } + exponent_1 = f->exponent + f->leader + 1 - f->low; + /* Radix LITTLENUM_RADIX, point just higher than f -> leader. */ + exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; + /* Radix 2. */ + exponent_3 = exponent_2 - exponent_skippage; + /* Forget leading zeros, forget 1st bit. */ + exponent_4 = exponent_3 + (1 << (exponent_bits - 1)); + /* Offset exponent. */ + + if (exponent_4 & ~mask[exponent_bits]) + { + /* + * Exponent overflow. Lose immediately. + */ + + make_invalid_floating_point_number (words); + + /* + * We leave return_value alone: admit we read the + * number, but return a floating exception + * because we can't encode the number. + */ + } + else + { + lp = words; + + /* Word 1. Sign, exponent and perhaps high bits. */ + /* Assume 2's complement integers. */ + word1 = ((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) + | ((f->sign == '+') ? 0 : 0x8000) + | next_bits (15 - exponent_bits); + *lp++ = word1; + + /* The rest of the words are just mantissa bits. */ + for (; lp < words + precision; lp++) + { + *lp = next_bits (LITTLENUM_NUMBER_OF_BITS); + } + + if (next_bits (1)) + { + /* + * Since the NEXT bit is a 1, round UP the mantissa. + * The cunning design of these hidden-1 floats permits + * us to let the mantissa overflow into the exponent, and + * it 'does the right thing'. However, we lose if the + * highest-order bit of the lowest-order word flips. + * Is that clear? + */ + + unsigned long int carry; + + /* + #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) + Please allow at least 1 more bit in carry than is in a LITTLENUM. + We need that extra bit to hold a carry during a LITTLENUM carry + propagation. Another extra bit (kept 0) will assure us that we + don't get a sticky sign bit after shifting right, and that + permits us to propagate the carry without any masking of bits. + #endif + */ + for (carry = 1, lp--; + carry && (lp >= words); + lp--) + { + carry = *lp + carry; + *lp = carry; + carry >>= LITTLENUM_NUMBER_OF_BITS; + } + + if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) + { + make_invalid_floating_point_number (words); + /* + * We leave return_value alone: admit we read the + * number, but return a floating exception + * because we can't encode the number. + */ + } + } /* if (we needed to round up) */ + } /* if (exponent overflow) */ + } /* if (0.0e0) */ + } /* if (float_type was OK) */ + return (return_value); +} + +/* + * md_atof() + * + * In: input_line_pointer -> the 1st character of a floating-point + * number. + * 1 letter denoting the type of statement that wants a + * binary floating point number returned. + * Address of where to build floating point literal. + * Assumed to be 'big enough'. + * Address of where to return size of literal (in chars). + * + * Out: Input_line_pointer -> of next char after floating number. + * Error message, or 0. + * Floating point literal. + * Number of chars we used for the literal. + */ + +char * +md_atof (what_statement_type, literalP, sizeP) + char what_statement_type; + char *literalP; + int *sizeP; +{ + LITTLENUM_TYPE words[MAX_PRECISION]; + register char kind_of_float; + register int number_of_chars; + register LITTLENUM_TYPE *littlenum_pointer; + + switch (what_statement_type) + { + case 'f': /* .ffloat */ + case 'd': /* .dfloat */ + kind_of_float = what_statement_type; + break; + + default: + kind_of_float = 0; + break; + }; + + if (kind_of_float) + { + register LITTLENUM_TYPE *limit; + + input_line_pointer = atof_tahoe (input_line_pointer, + kind_of_float, + words); + /* + * The atof_tahoe() builds up 16-bit numbers. + * Since the assembler may not be running on + * a different-endian machine, be very careful about + * converting words to chars. + */ + number_of_chars = (kind_of_float == 'f' ? F_PRECISION_CHARS : + (kind_of_float == 'd' ? D_PRECISION_CHARS : 0)); + know (number_of_chars <= MAX_PRECISION * sizeof (LITTLENUM_TYPE)); + limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE)); + for (littlenum_pointer = words; + littlenum_pointer < limit; + littlenum_pointer++) + { + md_number_to_chars (literalP, *littlenum_pointer, + sizeof (LITTLENUM_TYPE)); + literalP += sizeof (LITTLENUM_TYPE); + }; + } + else + { + number_of_chars = 0; + }; + + *sizeP = number_of_chars; + return kind_of_float ? 0 : "Bad call to md_atof()"; +} + +/* atof_tahoe.c */ diff --git a/gnu/usr.bin/binutils/gas/config/atof-vax.c b/gnu/usr.bin/binutils/gas/config/atof-vax.c new file mode 100644 index 00000000000..2b814fb38db --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/atof-vax.c @@ -0,0 +1,510 @@ +/* atof_vax.c - turn a Flonum into a VAX floating point number + Copyright (C) 1987, 1992 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 2, 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. */ + +#include "as.h" + +/* Precision in LittleNums. */ +#define MAX_PRECISION (8) +#define H_PRECISION (8) +#define G_PRECISION (4) +#define D_PRECISION (4) +#define F_PRECISION (2) + +/* Length in LittleNums of guard bits. */ +#define GUARD (2) + +int flonum_gen2vax PARAMS ((int format_letter, FLONUM_TYPE * f, + LITTLENUM_TYPE * words)); + +/* Number of chars in flonum type 'letter'. */ +int +atof_vax_sizeof (letter) + char letter; +{ + int return_value; + + /* + * Permitting uppercase letters is probably a bad idea. + * Please use only lower-cased letters in case the upper-cased + * ones become unsupported! + */ + switch (letter) + { + case 'f': + case 'F': + return_value = 4; + break; + + case 'd': + case 'D': + case 'g': + case 'G': + return_value = 8; + break; + + case 'h': + case 'H': + return_value = 16; + break; + + default: + return_value = 0; + break; + } + return (return_value); +} /* atof_vax_sizeof */ + +static const long mask[] = +{ + 0x00000000, + 0x00000001, + 0x00000003, + 0x00000007, + 0x0000000f, + 0x0000001f, + 0x0000003f, + 0x0000007f, + 0x000000ff, + 0x000001ff, + 0x000003ff, + 0x000007ff, + 0x00000fff, + 0x00001fff, + 0x00003fff, + 0x00007fff, + 0x0000ffff, + 0x0001ffff, + 0x0003ffff, + 0x0007ffff, + 0x000fffff, + 0x001fffff, + 0x003fffff, + 0x007fffff, + 0x00ffffff, + 0x01ffffff, + 0x03ffffff, + 0x07ffffff, + 0x0fffffff, + 0x1fffffff, + 0x3fffffff, + 0x7fffffff, + 0xffffffff +}; + + +/* Shared between flonum_gen2vax and next_bits */ +static int bits_left_in_littlenum; +static LITTLENUM_TYPE *littlenum_pointer; +static LITTLENUM_TYPE *littlenum_end; + +static int +next_bits (number_of_bits) + int number_of_bits; +{ + int return_value; + + if (littlenum_pointer < littlenum_end) + return 0; + if (number_of_bits >= bits_left_in_littlenum) + { + return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; + number_of_bits -= bits_left_in_littlenum; + return_value <<= number_of_bits; + bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; + littlenum_pointer--; + if (littlenum_pointer >= littlenum_end) + return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) & mask[number_of_bits]; + } + else + { + bits_left_in_littlenum -= number_of_bits; + return_value = mask[number_of_bits] & ((*littlenum_pointer) >> bits_left_in_littlenum); + } + return (return_value); +} + +static void +make_invalid_floating_point_number (words) + LITTLENUM_TYPE *words; +{ + *words = 0x8000; /* Floating Reserved Operand Code */ +} + +static int /* 0 means letter is OK. */ +what_kind_of_float (letter, precisionP, exponent_bitsP) + char letter; /* In: lowercase please. What kind of float? */ + int *precisionP; /* Number of 16-bit words in the float. */ + long *exponent_bitsP; /* Number of exponent bits. */ +{ + int retval; /* 0: OK. */ + + retval = 0; + switch (letter) + { + case 'f': + *precisionP = F_PRECISION; + *exponent_bitsP = 8; + break; + + case 'd': + *precisionP = D_PRECISION; + *exponent_bitsP = 8; + break; + + case 'g': + *precisionP = G_PRECISION; + *exponent_bitsP = 11; + break; + + case 'h': + *precisionP = H_PRECISION; + *exponent_bitsP = 15; + break; + + default: + retval = 69; + break; + } + return (retval); +} + +/***********************************************************************\ + * * + * Warning: this returns 16-bit LITTLENUMs, because that is * + * what the VAX thinks in. It is up to the caller to figure * + * out any alignment problems and to conspire for the bytes/word * + * to be emitted in the right order. Bigendians beware! * + * * + \***********************************************************************/ + +char * /* Return pointer past text consumed. */ +atof_vax (str, what_kind, words) + char *str; /* Text to convert to binary. */ + char what_kind; /* 'd', 'f', 'g', 'h' */ + LITTLENUM_TYPE *words; /* Build the binary here. */ +{ + FLONUM_TYPE f; + LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; + /* Extra bits for zeroed low-order bits. */ + /* The 1st MAX_PRECISION are zeroed, */ + /* the last contain flonum bits. */ + char *return_value; + int precision; /* Number of 16-bit words in the format. */ + long exponent_bits; + + return_value = str; + f.low = bits + MAX_PRECISION; + f.high = NULL; + f.leader = NULL; + f.exponent = 0; + f.sign = '\0'; + + if (what_kind_of_float (what_kind, &precision, &exponent_bits)) + { + return_value = NULL; /* We lost. */ + make_invalid_floating_point_number (words); + } + + if (return_value) + { + memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); + + /* Use more LittleNums than seems */ + /* necessary: the highest flonum may have */ + /* 15 leading 0 bits, so could be useless. */ + f.high = f.low + precision - 1 + GUARD; + + if (atof_generic (&return_value, ".", "eE", &f)) + { + make_invalid_floating_point_number (words); + return_value = NULL; /* we lost */ + } + else + { + if (flonum_gen2vax (what_kind, &f, words)) + { + return_value = NULL; + } + } + } + return (return_value); +} /* atof_vax() */ + +/* + * In: a flonum, a vax floating point format. + * Out: a vax floating-point bit pattern. + */ + +int /* 0: OK. */ +flonum_gen2vax (format_letter, f, words) + char format_letter; /* One of 'd' 'f' 'g' 'h'. */ + FLONUM_TYPE *f; + LITTLENUM_TYPE *words; /* Deliver answer here. */ +{ + LITTLENUM_TYPE *lp; + int precision; + long exponent_bits; + int return_value; /* 0 == OK. */ + + return_value = what_kind_of_float (format_letter, &precision, &exponent_bits); + + if (return_value != 0) + { + make_invalid_floating_point_number (words); + } + else + { + if (f->low > f->leader) + { + /* 0.0e0 seen. */ + memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision); + } + else + { + long exponent_1; + long exponent_2; + long exponent_3; + long exponent_4; + int exponent_skippage; + LITTLENUM_TYPE word1; + + /* JF: Deal with new Nan, +Inf and -Inf codes */ + if (f->sign != '-' && f->sign != '+') + { + make_invalid_floating_point_number (words); + return return_value; + } + /* + * All vaxen floating_point formats (so far) have: + * Bit 15 is sign bit. + * Bits 14:n are excess-whatever exponent. + * Bits n-1:0 (if any) are most significant bits of fraction. + * Bits 15:0 of the next word are the next most significant bits. + * And so on for each other word. + * + * All this to be compatible with a KF11?? (Which is still faster + * than lots of vaxen I can think of, but it also has higher + * maintenance costs ... sigh). + * + * So we need: number of bits of exponent, number of bits of + * mantissa. + */ + +#ifdef NEVER /******* This zeroing seems redundant - Dean 3may86 **********/ + /* + * No matter how few bits we got back from the atof() + * routine, add enough zero littlenums so the rest of the + * code won't run out of "significant" bits in the mantissa. + */ + { + LITTLENUM_TYPE *ltp; + for (ltp = f->leader + 1; + ltp <= f->low + precision; + ltp++) + { + *ltp = 0; + } + } +#endif + + bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; + littlenum_pointer = f->leader; + littlenum_end = f->low; + /* Seek (and forget) 1st significant bit */ + for (exponent_skippage = 0; + !next_bits (1); + exponent_skippage++);; + + exponent_1 = f->exponent + f->leader + 1 - f->low; + /* Radix LITTLENUM_RADIX, point just higher than f->leader. */ + exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; + /* Radix 2. */ + exponent_3 = exponent_2 - exponent_skippage; + /* Forget leading zeros, forget 1st bit. */ + exponent_4 = exponent_3 + (1 << (exponent_bits - 1)); + /* Offset exponent. */ + + if (exponent_4 & ~mask[exponent_bits]) + { + /* + * Exponent overflow. Lose immediately. + */ + + make_invalid_floating_point_number (words); + + /* + * We leave return_value alone: admit we read the + * number, but return a floating exception + * because we can't encode the number. + */ + } + else + { + lp = words; + + /* Word 1. Sign, exponent and perhaps high bits. */ + /* Assume 2's complement integers. */ + word1 = (((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) + | ((f->sign == '+') ? 0 : 0x8000) + | next_bits (15 - exponent_bits)); + *lp++ = word1; + + /* The rest of the words are just mantissa bits. */ + for (; lp < words + precision; lp++) + { + *lp = next_bits (LITTLENUM_NUMBER_OF_BITS); + } + + if (next_bits (1)) + { + /* + * Since the NEXT bit is a 1, round UP the mantissa. + * The cunning design of these hidden-1 floats permits + * us to let the mantissa overflow into the exponent, and + * it 'does the right thing'. However, we lose if the + * highest-order bit of the lowest-order word flips. + * Is that clear? + */ + + unsigned long carry; + + /* + #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) + Please allow at least 1 more bit in carry than is in a LITTLENUM. + We need that extra bit to hold a carry during a LITTLENUM carry + propagation. Another extra bit (kept 0) will assure us that we + don't get a sticky sign bit after shifting right, and that + permits us to propagate the carry without any masking of bits. + #endif + */ + for (carry = 1, lp--; + carry && (lp >= words); + lp--) + { + carry = *lp + carry; + *lp = carry; + carry >>= LITTLENUM_NUMBER_OF_BITS; + } + + if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) + { + make_invalid_floating_point_number (words); + /* + * We leave return_value alone: admit we read the + * number, but return a floating exception + * because we can't encode the number. + */ + } + } /* if (we needed to round up) */ + } /* if (exponent overflow) */ + } /* if (0.0e0) */ + } /* if (float_type was OK) */ + return (return_value); +} /* flonum_gen2vax() */ + + +/* JF this used to be in vax.c but this looks like a better place for it */ + +/* + * md_atof() + * + * In: input_line_pointer->the 1st character of a floating-point + * number. + * 1 letter denoting the type of statement that wants a + * binary floating point number returned. + * Address of where to build floating point literal. + * Assumed to be 'big enough'. + * Address of where to return size of literal (in chars). + * + * Out: Input_line_pointer->of next char after floating number. + * Error message, or 0. + * Floating point literal. + * Number of chars we used for the literal. + */ + +#define MAXIMUM_NUMBER_OF_LITTLENUMS (8) /* For .hfloats. */ + +char * +md_atof (what_statement_type, literalP, sizeP) + char what_statement_type; + char *literalP; + int *sizeP; +{ + LITTLENUM_TYPE words[MAXIMUM_NUMBER_OF_LITTLENUMS]; + register char kind_of_float; + register int number_of_chars; + register LITTLENUM_TYPE *littlenumP; + + switch (what_statement_type) + { + case 'F': /* .float */ + case 'f': /* .ffloat */ + kind_of_float = 'f'; + break; + + case 'D': /* .double */ + case 'd': /* .dfloat */ + kind_of_float = 'd'; + break; + + case 'g': /* .gfloat */ + kind_of_float = 'g'; + break; + + case 'h': /* .hfloat */ + kind_of_float = 'h'; + break; + + default: + kind_of_float = 0; + break; + }; + + if (kind_of_float) + { + register LITTLENUM_TYPE *limit; + + input_line_pointer = atof_vax (input_line_pointer, + kind_of_float, + words); + /* + * The atof_vax() builds up 16-bit numbers. + * Since the assembler may not be running on + * a little-endian machine, be very careful about + * converting words to chars. + */ + number_of_chars = atof_vax_sizeof (kind_of_float); + know (number_of_chars <= MAXIMUM_NUMBER_OF_LITTLENUMS * sizeof (LITTLENUM_TYPE)); + limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE)); + for (littlenumP = words; littlenumP < limit; littlenumP++) + { + md_number_to_chars (literalP, *littlenumP, sizeof (LITTLENUM_TYPE)); + literalP += sizeof (LITTLENUM_TYPE); + }; + } + else + { + number_of_chars = 0; + }; + + *sizeP = number_of_chars; + return kind_of_float ? 0 : "Bad call to md_atof()"; +} + +/* end of atof-vax.c */ diff --git a/gnu/usr.bin/binutils/gas/config/e-mipsecoff.c b/gnu/usr.bin/binutils/gas/config/e-mipsecoff.c new file mode 100644 index 00000000000..c2efde49ce4 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/e-mipsecoff.c @@ -0,0 +1,34 @@ +#include "as.h" +#include "emul.h" + +static const char * +mipsecoff_bfd_name () +{ + abort (); +} + +#define emul_bfd_name mipsecoff_bfd_name +#define emul_format &ecoff_format_ops + +#define emul_name "mipsbecoff" +#define emul_struct_name mipsbecoff +#define emul_default_endian 1 +#include "emul-target.h" + +#undef emul_name +#undef emul_struct_name +#undef emul_default_endian + +#define emul_name "mipslecoff" +#define emul_struct_name mipslecoff +#define emul_default_endian 0 +#include "emul-target.h" + +#undef emul_name +#undef emul_struct_name +#undef emul_default_endian + +#define emul_name "mipsecoff" +#define emul_struct_name mipsecoff +#define emul_default_endian 2 +#include "emul-target.h" diff --git a/gnu/usr.bin/binutils/gas/config/e-mipself.c b/gnu/usr.bin/binutils/gas/config/e-mipself.c new file mode 100644 index 00000000000..d16cf7adef7 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/e-mipself.c @@ -0,0 +1,34 @@ +#include "as.h" +#include "emul.h" + +static const char * +mipself_bfd_name () +{ + abort (); +} + +#define emul_bfd_name mipself_bfd_name +#define emul_format &elf_format_ops + +#define emul_name "mipsbelf" +#define emul_struct_name mipsbelf +#define emul_default_endian 1 +#include "emul-target.h" + +#undef emul_name +#undef emul_struct_name +#undef emul_default_endian + +#define emul_name "mipslelf" +#define emul_struct_name mipslelf +#define emul_default_endian 0 +#include "emul-target.h" + +#undef emul_name +#undef emul_struct_name +#undef emul_default_endian + +#define emul_name "mipself" +#define emul_struct_name mipself +#define emul_default_endian 2 +#include "emul-target.h" diff --git a/gnu/usr.bin/binutils/gas/config/go32.cfg b/gnu/usr.bin/binutils/gas/config/go32.cfg new file mode 100644 index 00000000000..4059395da8e --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/go32.cfg @@ -0,0 +1,93 @@ +/* config.h for go32 */ + +#define I386COFF 1 + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* If using the C implementation of alloca, define 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 + */ +#undef STACK_DIRECTION + +/* Should gas use high-level BFD interfaces? */ +#undef BFD_ASSEMBLER + +/* If we aren't doing cross-assembling, some operations can be optimized, + since byte orders and value sizes don't need to be adjusted. */ +#undef CROSS_COMPILE + +/* Some gas code wants to know these parameters. */ +#define TARGET_ALIAS "i386" +#define TARGET_CPU "i386" +#define TARGET_CANONICAL "i386-i386" +#define TARGET_OS "djgpp" +#define TARGET_VENDOR "djgpp" + +/* Some operating systems, for example DOS, require the use of "wb" mode when + opening a binary file for writing. If only "w" is used, the file will not + be correct. However, some other systems reject such a mode. This indicates + which ../include/fopen-*.h header file we want to include, so that we can + get macros that'll do the right thing for this system. */ +#define WANT_FOPEN_BIN 1 + +/* Sometimes the system header files don't declare malloc and realloc. */ +#undef NEED_DECLARATION_MALLOC + +/* Sometimes the system header files don't declare free. */ +#undef NEED_DECLARATION_FREE + +/* Sometimes errno.h doesn't declare errno itself. */ +#undef NEED_DECLARATION_ERRNO + +#define MANY_SEGMENTS 1 + +/* Needed only for sparc configuration */ +#undef sparcv9 + +/* Define if you have the remove function. */ +#define HAVE_REMOVE 1 + +/* Define if you have the unlink function. */ +#define HAVE_UNLINK 1 + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +#undef HAVE_VARARGS_H diff --git a/gnu/usr.bin/binutils/gas/config/i386coff.mt b/gnu/usr.bin/binutils/gas/config/i386coff.mt new file mode 100644 index 00000000000..efda8336518 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/i386coff.mt @@ -0,0 +1 @@ +TDEFINES=-DI386COFF diff --git a/gnu/usr.bin/binutils/gas/config/m68k-parse.h b/gnu/usr.bin/binutils/gas/config/m68k-parse.h new file mode 100644 index 00000000000..532f56263d0 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/m68k-parse.h @@ -0,0 +1,261 @@ +/* m68k-parse.h -- header file for m68k assembler + Copyright (C) 1987, 91, 92, 93, 94, 1995 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 2, 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. */ + +#ifndef M68K_PARSE_H +#define M68K_PARSE_H + +/* This header file defines things which are shared between the + operand parser in m68k.y and the m68k assembler proper in + tc-m68k.c. */ + +/* The various m68k registers. */ + +/* DATA and ADDR have to be contiguous, so that reg-DATA gives + 0-7==data reg, 8-15==addr reg for operands that take both types. + + We don't use forms like "ADDR0 = ADDR" here because this file is + likely to be used on an Apollo, and the broken Apollo compiler + gives an `undefined variable' error if we do that, according to + troy@cbme.unsw.edu.au. */ + +#define DATA DATA0 +#define ADDR ADDR0 +#define SP ADDR7 +#define BAD BAD0 +#define BAC BAC0 + +enum m68k_register +{ + DATA0 = 1, /* 1- 8 == data registers 0-7 */ + DATA1, + DATA2, + DATA3, + DATA4, + DATA5, + DATA6, + DATA7, + + ADDR0, + ADDR1, + ADDR2, + ADDR3, + ADDR4, + ADDR5, + ADDR6, + ADDR7, + + FP0, /* Eight FP registers */ + FP1, + FP2, + FP3, + FP4, + FP5, + FP6, + FP7, + + COP0, /* Co-processor #0-#7 */ + COP1, + COP2, + COP3, + COP4, + COP5, + COP6, + COP7, + + PC, /* Program counter */ + ZPC, /* Hack for Program space, but 0 addressing */ + SR, /* Status Reg */ + CCR, /* Condition code Reg */ + + /* These have to be grouped together for the movec instruction to work. */ + USP, /* User Stack Pointer */ + ISP, /* Interrupt stack pointer */ + SFC, + DFC, + CACR, + VBR, + CAAR, + MSP, + ITT0, + ITT1, + DTT0, + DTT1, + MMUSR, + TC, + SRP, + URP, + BUSCR, /* 68060 added these */ + PCR, +#define last_movec_reg PCR + /* end of movec ordering constraints */ + + FPI, + FPS, + FPC, + + DRP, /* 68851 or 68030 MMU regs */ + CRP, + CAL, + VAL, + SCC, + AC, + BAD0, + BAD1, + BAD2, + BAD3, + BAD4, + BAD5, + BAD6, + BAD7, + BAC0, + BAC1, + BAC2, + BAC3, + BAC4, + BAC5, + BAC6, + BAC7, + PSR, /* aka MMUSR on 68030 (but not MMUSR on 68040) + and ACUSR on 68ec030 */ + PCSR, + + IC, /* instruction cache token */ + DC, /* data cache token */ + NC, /* no cache token */ + BC, /* both caches token */ + + TT0, /* 68030 access control unit regs */ + TT1, + + ZDATA0, /* suppressed data registers. */ + ZDATA1, + ZDATA2, + ZDATA3, + ZDATA4, + ZDATA5, + ZDATA6, + ZDATA7, + + ZADDR0, /* suppressed address registers. */ + ZADDR1, + ZADDR2, + ZADDR3, + ZADDR4, + ZADDR5, + ZADDR6, + ZADDR7, +}; + +/* Size information. */ + +enum m68k_size +{ + /* Unspecified. */ + SIZE_UNSPEC, + + /* Byte. */ + SIZE_BYTE, + + /* Word (2 bytes). */ + SIZE_WORD, + + /* Longword (4 bytes). */ + SIZE_LONG +}; + +/* The structure used to hold information about an index register. */ + +struct m68k_indexreg +{ + /* The index register itself. */ + enum m68k_register reg; + + /* The size to use. */ + enum m68k_size size; + + /* The value to scale by. */ + int scale; +}; + +/* The structure used to hold information about an expression. */ + +struct m68k_exp +{ + /* The size to use. */ + enum m68k_size size; + + /* The expression itself. */ + expressionS exp; +}; + +/* The operand modes. */ + +enum m68k_operand_type +{ + IMMED = 1, + ABSL, + DREG, + AREG, + FPREG, + CONTROL, + AINDR, + AINC, + ADEC, + DISP, + BASE, + POST, + PRE, + REGLST +}; + +/* The structure used to hold a parsed operand. */ + +struct m68k_op +{ + /* The type of operand. */ + enum m68k_operand_type mode; + + /* The main register. */ + enum m68k_register reg; + + /* The register mask for mode REGLST. */ + unsigned long mask; + + /* An error message. */ + const char *error; + + /* The index register. */ + struct m68k_indexreg index; + + /* The displacement. */ + struct m68k_exp disp; + + /* The outer displacement. */ + struct m68k_exp odisp; +}; + +#endif /* ! defined (M68K_PARSE_H) */ + +/* The parsing function. */ + +extern int m68k_ip_op PARAMS ((char *, struct m68k_op *)); + +/* Whether register prefixes are optional. */ +extern int flag_reg_prefix_optional; diff --git a/gnu/usr.bin/binutils/gas/config/m68k-parse.y b/gnu/usr.bin/binutils/gas/config/m68k-parse.y new file mode 100644 index 00000000000..c6da9db8c67 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/m68k-parse.y @@ -0,0 +1,982 @@ +/* m68k.y -- bison grammar for m68k operand parsing + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Ken Raeburn and Ian Lance Taylor, Cygnus Support + + 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 2, 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. */ + +/* This file holds a bison grammar to parse m68k operands. The m68k + has a complicated operand syntax, and gas supports two main + variations of it. Using a grammar is probably overkill, but at + least it makes clear exactly what we do support. */ + +%{ + +#include "as.h" +#include "tc-m68k.h" +#include "m68k-parse.h" + +/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, + etc), as well as gratuitiously global symbol names 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 m68k_maxdepth +#define yyparse m68k_parse +#define yylex m68k_lex +#define yyerror m68k_error +#define yylval m68k_lval +#define yychar m68k_char +#define yydebug m68k_debug +#define yypact m68k_pact +#define yyr1 m68k_r1 +#define yyr2 m68k_r2 +#define yydef m68k_def +#define yychk m68k_chk +#define yypgo m68k_pgo +#define yyact m68k_act +#define yyexca m68k_exca +#define yyerrflag m68k_errflag +#define yynerrs m68k_nerrs +#define yyps m68k_ps +#define yypv m68k_pv +#define yys m68k_s +#define yy_yys m68k_yys +#define yystate m68k_state +#define yytmp m68k_tmp +#define yyv m68k_v +#define yy_yyv m68k_yyv +#define yyval m68k_val +#define yylloc m68k_lloc +#define yyreds m68k_reds /* With YYDEBUG defined */ +#define yytoks m68k_toks /* With YYDEBUG defined */ +#define yylhs m68k_yylhs +#define yylen m68k_yylen +#define yydefred m68k_yydefred +#define yydgoto m68k_yydgoto +#define yysindex m68k_yysindex +#define yyrindex m68k_yyrindex +#define yygindex m68k_yygindex +#define yytable m68k_yytable +#define yycheck m68k_yycheck + +#ifndef YYDEBUG +#define YYDEBUG 1 +#endif + +/* Internal functions. */ + +static enum m68k_register m68k_reg_parse PARAMS ((char **)); +static int yylex PARAMS (()); +static void yyerror PARAMS ((const char *)); + +/* The parser sets fields pointed to by this global variable. */ +static struct m68k_op *op; + +%} + +%union +{ + struct m68k_indexreg indexreg; + enum m68k_register reg; + struct m68k_exp exp; + unsigned long mask; + int onereg; +} + +%token DR AR FPR FPCR LPC ZAR ZDR LZPC CREG +%token INDEXREG +%token EXPR + +%type zireg zdireg +%type zadr zdr apc zapc zpc optzapc optczapc +%type optcexpr optexprc +%type reglist ireglist reglistpair +%type reglistreg + +%% + +/* An operand. */ + +operand: + generic_operand + | motorola_operand + | mit_operand + ; + +/* A generic operand. */ + +generic_operand: + DR + { + op->mode = DREG; + op->reg = $1; + } + | AR + { + op->mode = AREG; + op->reg = $1; + } + | FPR + { + op->mode = FPREG; + op->reg = $1; + } + | FPCR + { + op->mode = CONTROL; + op->reg = $1; + } + | CREG + { + op->mode = CONTROL; + op->reg = $1; + } + | EXPR + { + op->mode = ABSL; + op->disp = $1; + } + | '#' EXPR + { + op->mode = IMMED; + op->disp = $2; + } + | '&' EXPR + { + op->mode = IMMED; + op->disp = $2; + } + | reglist + { + op->mode = REGLST; + op->mask = $1; + } + ; + +/* An operand in Motorola syntax. This includes MRI syntax as well, + which may or may not be different in that it permits commutativity + of index and base registers, and permits an offset expression to + appear inside or outside of the parentheses. */ + +motorola_operand: + '(' AR ')' + { + op->mode = AINDR; + op->reg = $2; + } + | '(' AR ')' '+' + { + op->mode = AINC; + op->reg = $2; + } + | '-' '(' AR ')' + { + op->mode = ADEC; + op->reg = $3; + } + | '(' EXPR ',' zapc ')' + { + op->reg = $4; + op->disp = $2; + if (($4 >= ZADDR0 && $4 <= ZADDR7) + || $4 == ZPC) + op->mode = BASE; + else + op->mode = DISP; + } + | EXPR '(' zapc ')' + { + op->reg = $3; + op->disp = $1; + if (($3 >= ZADDR0 && $3 <= ZADDR7) + || $3 == ZPC) + op->mode = BASE; + else + op->mode = DISP; + } + | '(' LPC ')' + { + op->mode = DISP; + op->reg = $2; + } + | '(' ZAR ')' + { + op->mode = BASE; + op->reg = $2; + } + | '(' LZPC ')' + { + op->mode = BASE; + op->reg = $2; + } + | '(' EXPR ',' zapc ',' zireg ')' + { + op->mode = BASE; + op->reg = $4; + op->disp = $2; + op->index = $6; + } + | '(' EXPR ',' zapc ',' zpc ')' + { + if ($4 == PC || $4 == ZPC) + yyerror ("syntax error"); + op->mode = BASE; + op->reg = $6; + op->disp = $2; + op->index.reg = $4; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + } + | '(' EXPR ',' zdireg optczapc ')' + { + op->mode = BASE; + op->reg = $5; + op->disp = $2; + op->index = $4; + } + | EXPR '(' zapc ',' zireg ')' + { + op->mode = BASE; + op->reg = $3; + op->disp = $1; + op->index = $5; + } + | '(' zapc ',' zireg ')' + { + op->mode = BASE; + op->reg = $2; + op->index = $4; + } + | EXPR '(' zapc ',' zpc ')' + { + if ($3 == PC || $3 == ZPC) + yyerror ("syntax error"); + op->mode = BASE; + op->reg = $5; + op->disp = $1; + op->index.reg = $3; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + } + | '(' zapc ',' zpc ')' + { + if ($2 == PC || $2 == ZPC) + yyerror ("syntax error"); + op->mode = BASE; + op->reg = $4; + op->index.reg = $2; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + } + | EXPR '(' zdireg optczapc ')' + { + op->mode = BASE; + op->reg = $4; + op->disp = $1; + op->index = $3; + } + | '(' zdireg optczapc ')' + { + op->mode = BASE; + op->reg = $3; + op->index = $2; + } + | '(' '[' EXPR optczapc ']' ',' zireg optcexpr ')' + { + op->mode = POST; + op->reg = $4; + op->disp = $3; + op->index = $7; + op->odisp = $8; + } + | '(' '[' EXPR optczapc ']' optcexpr ')' + { + op->mode = POST; + op->reg = $4; + op->disp = $3; + op->odisp = $6; + } + | '(' '[' zapc ']' ',' zireg optcexpr ')' + { + op->mode = POST; + op->reg = $3; + op->index = $6; + op->odisp = $7; + } + | '(' '[' zapc ']' optcexpr ')' + { + op->mode = POST; + op->reg = $3; + op->odisp = $5; + } + | '(' '[' EXPR ',' zapc ',' zireg ']' optcexpr ')' + { + op->mode = PRE; + op->reg = $5; + op->disp = $3; + op->index = $7; + op->odisp = $9; + } + | '(' '[' zapc ',' zireg ']' optcexpr ')' + { + op->mode = PRE; + op->reg = $3; + op->index = $5; + op->odisp = $7; + } + | '(' '[' EXPR ',' zapc ',' zpc ']' optcexpr ')' + { + if ($5 == PC || $5 == ZPC) + yyerror ("syntax error"); + op->mode = PRE; + op->reg = $7; + op->disp = $3; + op->index.reg = $5; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + op->odisp = $9; + } + | '(' '[' zapc ',' zpc ']' optcexpr ')' + { + if ($3 == PC || $3 == ZPC) + yyerror ("syntax error"); + op->mode = PRE; + op->reg = $5; + op->index.reg = $3; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + op->odisp = $7; + } + | '(' '[' optexprc zdireg optczapc ']' optcexpr ')' + { + op->mode = PRE; + op->reg = $5; + op->disp = $3; + op->index = $4; + op->odisp = $7; + } + ; + +/* An operand in MIT syntax. */ + +mit_operand: + optzapc '@' + { + /* We use optzapc to avoid a shift/reduce conflict. */ + if ($1 < ADDR0 || $1 > ADDR7) + yyerror ("syntax error"); + op->mode = AINDR; + op->reg = $1; + } + | optzapc '@' '+' + { + /* We use optzapc to avoid a shift/reduce conflict. */ + if ($1 < ADDR0 || $1 > ADDR7) + yyerror ("syntax error"); + op->mode = AINC; + op->reg = $1; + } + | optzapc '@' '-' + { + /* We use optzapc to avoid a shift/reduce conflict. */ + if ($1 < ADDR0 || $1 > ADDR7) + yyerror ("syntax error"); + op->mode = ADEC; + op->reg = $1; + } + | optzapc '@' '(' EXPR ')' + { + op->reg = $1; + op->disp = $4; + if (($1 >= ZADDR0 && $1 <= ZADDR7) + || $1 == ZPC) + op->mode = BASE; + else + op->mode = DISP; + } + | optzapc '@' '(' optexprc zireg ')' + { + op->mode = BASE; + op->reg = $1; + op->disp = $4; + op->index = $5; + } + | optzapc '@' '(' EXPR ')' '@' '(' optexprc zireg ')' + { + op->mode = POST; + op->reg = $1; + op->disp = $4; + op->index = $9; + op->odisp = $8; + } + | optzapc '@' '(' EXPR ')' '@' '(' EXPR ')' + { + op->mode = POST; + op->reg = $1; + op->disp = $4; + op->odisp = $8; + } + | optzapc '@' '(' optexprc zireg ')' '@' '(' EXPR ')' + { + op->mode = PRE; + op->reg = $1; + op->disp = $4; + op->index = $5; + op->odisp = $9; + } + ; + +/* An index register, possibly suppressed, which need not have a size + or scale. */ + +zireg: + INDEXREG + | zadr + { + $$.reg = $1; + $$.size = SIZE_UNSPEC; + $$.scale = 1; + } + ; + +/* A register which may be an index register, but which may not be an + address register. This nonterminal is used to avoid ambiguity when + trying to parse something like (0,d5,a6) as compared to (0,a6,d5). */ + +zdireg: + INDEXREG + | zdr + { + $$.reg = $1; + $$.size = SIZE_UNSPEC; + $$.scale = 1; + } + ; + +/* An address or data register, or a suppressed address or data + register. */ + +zadr: + zdr + | AR + | ZAR + ; + +/* A data register which may be suppressed. */ + +zdr: + DR + | ZDR + ; + +/* Either an address register or the PC. */ + +apc: + AR + | LPC + ; + +/* Either an address register, or the PC, or a suppressed address + register, or a suppressed PC. */ + +zapc: + apc + | LZPC + | ZAR + ; + +/* An optional zapc. */ + +optzapc: + /* empty */ + { + $$ = ZADDR0; + } + | zapc + ; + +/* The PC, optionally suppressed. */ + +zpc: + LPC + | LZPC + ; + +/* ',' zapc when it may be omitted. */ + +optczapc: + /* empty */ + { + $$ = ZADDR0; + } + | ',' zapc + { + $$ = $2; + } + ; + +/* ',' EXPR when it may be omitted. */ + +optcexpr: + /* empty */ + { + $$.exp.X_op = O_absent; + $$.size = SIZE_UNSPEC; + } + | ',' EXPR + { + $$ = $2; + } + ; + +/* EXPR ',' when it may be omitted. */ + +optexprc: + /* empty */ + { + $$.exp.X_op = O_absent; + $$.size = SIZE_UNSPEC; + } + | EXPR ',' + { + $$ = $1; + } + ; + +/* A register list for the movem instruction. */ + +reglist: + reglistpair + | reglistpair '/' ireglist + { + $$ = $1 | $3; + } + | reglistreg '/' ireglist + { + $$ = (1 << $1) | $3; + } + ; + +/* We use ireglist when we know we are looking at a reglist, and we + can safely reduce a simple register to reglistreg. If we permitted + reglist to reduce to reglistreg, it would be ambiguous whether a + plain register were a DREG/AREG/FPREG or a REGLST. */ + +ireglist: + reglistreg + { + $$ = 1 << $1; + } + | reglistpair + | reglistpair '/' ireglist + { + $$ = $1 | $3; + } + | reglistreg '/' ireglist + { + $$ = (1 << $1) | $3; + } + ; + +reglistpair: + reglistreg '-' reglistreg + { + $$ = (1 << ($3 + 1)) - 1 - ((1 << $1) - 1); + } + ; + +reglistreg: + DR + { + $$ = $1 - DATA0; + } + | AR + { + $$ = $1 - ADDR0 + 8; + } + | FPR + { + $$ = $1 - FP0 + 16; + } + | FPCR + { + if ($1 == FPI) + $$ = 24; + else if ($1 == FPS) + $$ = 25; + else + $$ = 26; + } + ; + +%% + +/* The string to parse is stored here, and modified by yylex. */ + +static char *str; + +/* The original string pointer. */ + +static char *strorig; + +/* If *CCP could be a register, return the register number and advance + *CCP. Otherwise don't change *CCP, and return 0. */ + +static enum m68k_register +m68k_reg_parse (ccp) + register char **ccp; +{ + char *start = *ccp; + char c; + char *p; + symbolS *symbolp; + + if (flag_reg_prefix_optional) + { + if (*start == REGISTER_PREFIX) + start++; + p = start; + } + else + { + if (*start != REGISTER_PREFIX) + return 0; + p = start + 1; + } + + if (! is_name_beginner (*p)) + return 0; + + p++; + while (is_part_of_name (*p) && *p != '.' && *p != ':' && *p != '*') + p++; + + c = *p; + *p = 0; + symbolp = symbol_find (start); + *p = c; + + if (symbolp != NULL && S_GET_SEGMENT (symbolp) == reg_section) + { + *ccp = p; + return S_GET_VALUE (symbolp); + } + + /* In MRI mode, something like foo.bar can be equated to a register + name. */ + while (flag_mri && c == '.') + { + ++p; + while (is_part_of_name (*p) && *p != '.' && *p != ':' && *p != '*') + p++; + c = *p; + *p = '\0'; + symbolp = symbol_find (start); + *p = c; + if (symbolp != NULL && S_GET_SEGMENT (symbolp) == reg_section) + { + *ccp = p; + return S_GET_VALUE (symbolp); + } + } + + return 0; +} + +/* The lexer. */ + +static int +yylex () +{ + enum m68k_register reg; + char *s; + int parens; + int c = 0; + char *hold; + + if (*str == ' ') + ++str; + + if (*str == '\0') + return 0; + + /* Various special characters are just returned directly. */ + switch (*str) + { + case '#': + case '&': + case ',': + case ')': + case '/': + case '@': + case '[': + case ']': + return *str++; + case '+': + /* It so happens that a '+' can only appear at the end of an + operand. If it appears anywhere else, it must be a unary + plus on an expression. */ + if (str[1] == '\0') + return *str++; + break; + case '-': + /* A '-' can only appear in -(ar), rn-rn, or ar@-. If it + appears anywhere else, it must be a unary minus on an + expression. */ + if (str[1] == '\0') + return *str++; + s = str + 1; + if (*s == '(') + ++s; + if (m68k_reg_parse (&s) != 0) + return *str++; + break; + case '(': + /* A '(' can only appear in `(reg)', `(expr,...', `([', `@(', or + `)('. If it appears anywhere else, it must be starting an + expression. */ + if (str[1] == '[' + || (str > strorig + && (str[-1] == '@' + || str[-1] == ')'))) + return *str++; + s = str + 1; + if (m68k_reg_parse (&s) != 0) + return *str++; + /* Check for the case of '(expr,...' by scanning ahead. If we + find a comma outside of balanced parentheses, we return '('. + If we find an unbalanced right parenthesis, then presumably + the '(' really starts an expression. */ + parens = 0; + for (s = str + 1; *s != '\0'; s++) + { + if (*s == '(') + ++parens; + else if (*s == ')') + { + if (parens == 0) + break; + --parens; + } + else if (*s == ',' && parens == 0) + { + /* A comma can not normally appear in an expression, so + this is a case of '(expr,...'. */ + return *str++; + } + } + } + + /* See if it's a register. */ + + reg = m68k_reg_parse (&str); + if (reg != 0) + { + int ret; + + yylval.reg = reg; + + if (reg >= DATA0 && reg <= DATA7) + ret = DR; + else if (reg >= ADDR0 && reg <= ADDR7) + ret = AR; + else if (reg >= FP0 && reg <= FP7) + return FPR; + else if (reg == FPI + || reg == FPS + || reg == FPC) + return FPCR; + else if (reg == PC) + return LPC; + else if (reg >= ZDATA0 && reg <= ZDATA7) + ret = ZDR; + else if (reg >= ZADDR0 && reg <= ZADDR7) + ret = ZAR; + else if (reg == ZPC) + return LZPC; + else + return CREG; + + /* If we get here, we have a data or address register. We + must check for a size or scale; if we find one, we must + return INDEXREG. */ + + s = str; + + if (*s != '.' && *s != ':' && *s != '*') + return ret; + + yylval.indexreg.reg = reg; + + if (*s != '.' && *s != ':') + yylval.indexreg.size = SIZE_UNSPEC; + else + { + ++s; + switch (*s) + { + case 'w': + case 'W': + yylval.indexreg.size = SIZE_WORD; + ++s; + break; + case 'l': + case 'L': + yylval.indexreg.size = SIZE_LONG; + ++s; + break; + default: + yyerror ("illegal size specification"); + yylval.indexreg.size = SIZE_UNSPEC; + break; + } + } + + if (*s != '*' && *s != ':') + yylval.indexreg.scale = 1; + else + { + ++s; + switch (*s) + { + case '1': + case '2': + case '4': + case '8': + yylval.indexreg.scale = *s - '0'; + ++s; + break; + default: + yyerror ("illegal scale specification"); + yylval.indexreg.scale = 1; + break; + } + } + + str = s; + + return INDEXREG; + } + + /* It must be an expression. Before we call expression, we need to + look ahead to see if there is a size specification. We must do + that first, because otherwise foo.l will be treated as the symbol + foo.l, rather than as the symbol foo with a long size + specification. The grammar requires that all expressions end at + the end of the operand, or with ',', '(', ']', ')'. */ + + parens = 0; + for (s = str; *s != '\0'; s++) + { + if (*s == '(') + { + if (parens == 0 + && s > str + && (s[-1] == ')' || isalnum ((unsigned char) s[-1]))) + break; + ++parens; + } + else if (*s == ')') + { + if (parens == 0) + break; + --parens; + } + else if (parens == 0 + && (*s == ',' || *s == ']')) + break; + } + + yylval.exp.size = SIZE_UNSPEC; + if (s <= str + 2 + || (s[-2] != '.' && s[-2] != ':')) + s = NULL; + else + { + switch (s[-1]) + { + case 's': + case 'S': + case 'b': + case 'B': + yylval.exp.size = SIZE_BYTE; + break; + case 'w': + case 'W': + yylval.exp.size = SIZE_WORD; + break; + case 'l': + case 'L': + yylval.exp.size = SIZE_LONG; + break; + default: + s = NULL; + break; + } + if (yylval.exp.size != SIZE_UNSPEC) + { + c = s[-2]; + s[-2] = '\0'; + } + } + + hold = input_line_pointer; + input_line_pointer = str; + expression (&yylval.exp.exp); + str = input_line_pointer; + input_line_pointer = hold; + + if (s != NULL) + { + s[-2] = c; + str = s; + } + + return EXPR; +} + +/* Parse an m68k operand. This is the only function which is called + from outside this file. */ + +int +m68k_ip_op (s, oparg) + char *s; + struct m68k_op *oparg; +{ + memset (oparg, 0, sizeof *oparg); + oparg->error = NULL; + oparg->index.reg = ZDATA0; + oparg->index.scale = 1; + oparg->disp.exp.X_op = O_absent; + oparg->odisp.exp.X_op = O_absent; + + str = strorig = s; + op = oparg; + + return yyparse (); +} + +/* The error handler. */ + +static void +yyerror (s) + const char *s; +{ + op->error = s; +} diff --git a/gnu/usr.bin/binutils/gas/config/m68kcoff.mt b/gnu/usr.bin/binutils/gas/config/m68kcoff.mt new file mode 100644 index 00000000000..0d07eb178d1 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/m68kcoff.mt @@ -0,0 +1 @@ +TDEFINES=-DM68KCOFF diff --git a/gnu/usr.bin/binutils/gas/config/m88k-opcode.h b/gnu/usr.bin/binutils/gas/config/m88k-opcode.h new file mode 100644 index 00000000000..27464bc0fc9 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/m88k-opcode.h @@ -0,0 +1,559 @@ +/* m88k-opcode.h -- Instruction information for the Motorola 88000 + Contributed by Devon Bowen of Buffalo University + and Torbjorn Granlund of the Swedish Institute of Computer Science. + Copyright (C) 1989, 1990, 1991 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. */ + +#if !defined(__STDC__) && !defined(const) +#define const +#endif + +/* + Character codes for op_spec field below. + Reserved for self-matching: [ ] , + + d = GRF Destination register (21:5) + x = XRF register prefix. Makes next d, 1, or 2, match an extended register. + 1 = Source register 1 (16:5) + 2 = Source register 2 (0:5) + 3 = Both source registers (same value) (0:5 and 16:5) + I = IMM16 (0:16) + b = bit field spec. (0:10) + p = 16 bit pc displ. (0:16) + P = 26 bit pc displ. (0:26) + B = bb0/bb1 condition (21:5) + M = bcnd condition (21:5) + f = fcr (5:6) + c = cr (5:6) + V = VEC9 (0:9) + o = O6 field of "prot" insn (10:7) + ? = Give warning for this insn/operand combination + */ + +/* instruction descriptor structure */ + +struct m88k_opcode +{ + unsigned int opcode; + char *name; + char *op_spec; +}; + +/* and introducing... the Motorola 88100 and 88110 instruction sets... */ + +/* By default, include the 88110 instructions. */ +#define MC88110 + +#if defined (MC88110) +#define _MC88100(OPCODE,MNEM,OP_SPEC) +#define _MC88110(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC}, +#else +#define _MC88100(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC}, +#define _MC88110(OPCODE,MNEM,OP_SPEC) +#endif + +#define _MC88xxx(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC}, + +/* Equal mnemonics must be adjacent. + More specific operand specification must go before more general. + For example, "d,1,2" must go before "d,1,I" as a register for s2 + would otherwise be considered a variable name. */ + +static struct m88k_opcode m88k_opcodes[] = +{ + /* Opcode Mnemonic Opspec */ + + _MC88xxx (0xf4007000, "add", "d,1,2") + _MC88xxx (0x70000000, "add", "d,1,I") + _MC88xxx (0xf4007200, "add.ci", "d,1,2") + _MC88xxx (0xf4007300, "add.cio", "d,1,2") + _MC88xxx (0xf4007100, "add.co", "d,1,2") + _MC88xxx (0xf4006000, "addu", "d,1,2") + _MC88xxx (0x60000000, "addu", "d,1,I") + _MC88xxx (0xf4006200, "addu.ci", "d,1,2") + _MC88xxx (0xf4006300, "addu.cio", "d,1,2") + _MC88xxx (0xf4006100, "addu.co", "d,1,2") + _MC88xxx (0xf4004000, "and", "d,1,2") + _MC88xxx (0x40000000, "and", "d,1,I") + _MC88xxx (0xf4004400, "and.c", "d,1,2") + _MC88xxx (0x44000000, "and.u", "d,1,I") + _MC88xxx (0xd0000000, "bb0", "B,1,p") + _MC88xxx (0xd4000000, "bb0.n", "B,1,p") + _MC88xxx (0xd8000000, "bb1", "B,1,p") + _MC88xxx (0xdc000000, "bb1.n", "B,1,p") + _MC88xxx (0xe8000000, "bcnd", "M,1,p") + _MC88xxx (0xec000000, "bcnd.n", "M,1,p") + _MC88xxx (0xc0000000, "br", "P") + _MC88xxx (0xc4000000, "br.n", "P") + _MC88xxx (0xc8000000, "bsr", "P") + _MC88xxx (0xcc000000, "bsr.n", "P") + _MC88xxx (0xf4008000, "clr", "d,1,2") + _MC88xxx (0xf0008000, "clr", "d,1,b") + _MC88xxx (0xf4007c00, "cmp", "d,1,2") + _MC88xxx (0x7c000000, "cmp", "d,1,I") + _MC88xxx (0xf4007800, "div", "d,1,2") + _MC88xxx (0x78000000, "div", "d,1,I") + _MC88xxx (0xf4007800, "divs", "d,1,2") + _MC88xxx (0x78000000, "divs", "d,1,I") + _MC88110 (0xf4006900, "divu.d", "d,1,2") + _MC88xxx (0xf4006800, "divu", "d,1,2") + _MC88xxx (0x68000000, "divu", "d,1,I") + _MC88xxx (0xf4009000, "ext", "d,1,2") + _MC88xxx (0xf0009000, "ext", "d,1,b") + _MC88xxx (0xf4009800, "extu", "d,1,2") + _MC88xxx (0xf0009800, "extu", "d,1,b") + _MC88xxx (0x84002800, "fadd.sss", "d,1,2") + _MC88110 (0x8400a800, "fadd.sss", "xd,x1,x2") + _MC88xxx (0x84002880, "fadd.ssd", "d,1,2") + _MC88110 (0x8400a820, "fadd.ssd", "xd,x1,x2") + _MC88110 (0x8400a840, "fadd.ssx", "xd,x1,x2") + _MC88xxx (0x84002a00, "fadd.sds", "d,1,2") + _MC88110 (0x8400a880, "fadd.sds", "xd,x1,x2") + _MC88xxx (0x84002a80, "fadd.sdd", "d,1,2") + _MC88110 (0x8400a8a0, "fadd.sdd", "xd,x1,x2") + _MC88110 (0x8400a8c0, "fadd.sdx", "xd,x1,x2") + _MC88110 (0x8400a900, "fadd.sxs", "xd,x1,x2") + _MC88110 (0x8400a920, "fadd.sxd", "xd,x1,x2") + _MC88110 (0x8400a940, "fadd.sxx", "xd,x1,x2") + _MC88xxx (0x84002820, "fadd.dss", "d,1,2") + _MC88110 (0x8400aa00, "fadd.dss", "xd,x1,x2") + _MC88xxx (0x840028a0, "fadd.dsd", "d,1,2") + _MC88110 (0x8400aa20, "fadd.dsd", "xd,x1,x2") + _MC88110 (0x8400aa40, "fadd.dsx", "xd,x1,x2") + _MC88xxx (0x84002a20, "fadd.dds", "d,1,2") + _MC88110 (0x8400aa80, "fadd.dds", "xd,x1,x2") + _MC88xxx (0x84002aa0, "fadd.ddd", "d,1,2") + _MC88110 (0x8400aaa0, "fadd.ddd", "xd,x1,x2") + _MC88110 (0x8400aac0, "fadd.ddx", "xd,x1,x2") + _MC88110 (0x8400ab00, "fadd.dxs", "xd,x1,x2") + _MC88110 (0x8400ab20, "fadd.dxd", "xd,x1,x2") + _MC88110 (0x8400ab40, "fadd.dxx", "xd,x1,x2") + _MC88110 (0x8400ac00, "fadd.xss", "xd,x1,x2") + _MC88110 (0x8400ac20, "fadd.xsd", "xd,x1,x2") + _MC88110 (0x8400ac40, "fadd.xsx", "xd,x1,x2") + _MC88110 (0x8400ac80, "fadd.xds", "xd,x1,x2") + _MC88110 (0x8400aca0, "fadd.xdd", "xd,x1,x2") + _MC88110 (0x8400acc0, "fadd.xdx", "xd,x1,x2") + _MC88110 (0x8400ad00, "fadd.xxs", "xd,x1,x2") + _MC88110 (0x8400ad20, "fadd.xxd", "xd,x1,x2") + _MC88110 (0x8400ad40, "fadd.xxx", "xd,x1,x2") + _MC88xxx (0x84003a80, "fcmp.sdd", "d,1,2") + _MC88110 (0x8400ba80, "fcmp.sdd", "d,x1,x2") + _MC88xxx (0x84003a00, "fcmp.sds", "d,1,2") + _MC88110 (0x8400ba00, "fcmp.sds", "d,x1,x2") + _MC88110 (0x8400bb00, "fcmp.sdx", "d,x1,x2") + _MC88xxx (0x84003880, "fcmp.ssd", "d,1,2") + _MC88110 (0x8400b880, "fcmp.ssd", "d,x1,x2") + _MC88xxx (0x84003800, "fcmp.sss", "d,1,2") + _MC88110 (0x8400b800, "fcmp.sss", "d,x1,x2") + _MC88110 (0x8400b900, "fcmp.ssx", "d,x1,x2") + _MC88110 (0x8400bc80, "fcmp.sxd", "d,x1,x2") + _MC88110 (0x8400bc00, "fcmp.sxs", "d,x1,x2") + _MC88110 (0x8400bd00, "fcmp.sxx", "d,x1,x2") + _MC88110 (0x84003aa0, "fcmpu.sdd", "d,1,2") + _MC88110 (0x8400baa0, "fcmpu.sdd", "d,x1,x2") + _MC88110 (0x84003a20, "fcmpu.sds", "d,1,2") + _MC88110 (0x8400ba20, "fcmpu.sds", "d,x1,x2") + _MC88110 (0x8400bb20, "fcmpu.sdx", "d,x1,x2") + _MC88110 (0x840038a0, "fcmpu.ssd", "d,1,2") + _MC88110 (0x8400b8a0, "fcmpu.ssd", "d,x1,x2") + _MC88110 (0x84003820, "fcmpu.sss", "d,1,2") + _MC88110 (0x8400b820, "fcmpu.sss", "d,x1,x2") + _MC88110 (0x8400b920, "fcmpu.ssx", "d,x1,x2") + _MC88110 (0x8400bca0, "fcmpu.sxd", "d,x1,x2") + _MC88110 (0x8400bc20, "fcmpu.sxs", "d,x1,x2") + _MC88110 (0x8400bd20, "fcmpu.sxx", "d,x1,x2") + _MC88110 (0x84000880, "fcvt.ds", "d,2") + _MC88110 (0x84008880, "fcvt.ds", "xd,x2") + _MC88110 (0x840088c0, "fcvt.dx", "xd,x2") + _MC88110 (0x84000820, "fcvt.sd", "d,2") + _MC88110 (0x84008820, "fcvt.sd", "xd,x2") + _MC88110 (0x84008840, "fcvt.sx", "xd,x2") + _MC88110 (0x84008920, "fcvt.xd", "xd,x2") + _MC88110 (0x84008900, "fcvt.xs", "xd,x2") + _MC88xxx (0x84007000, "fdiv.sss", "d,1,2") + _MC88110 (0x8400f000, "fdiv.sss", "xd,x1,x2") + _MC88xxx (0x84007080, "fdiv.ssd", "d,1,2") + _MC88110 (0x8400f020, "fdiv.ssd", "xd,x1,x2") + _MC88110 (0x8400f040, "fdiv.ssx", "xd,x1,x2") + _MC88xxx (0x84007200, "fdiv.sds", "d,1,2") + _MC88110 (0x8400f080, "fdiv.sds", "xd,x1,x2") + _MC88xxx (0x84007280, "fdiv.sdd", "d,1,2") + _MC88110 (0x8400f0a0, "fdiv.sdd", "xd,x1,x2") + _MC88110 (0x8400f0c0, "fdiv.sdx", "xd,x1,x2") + _MC88110 (0x8400f100, "fdiv.sxs", "xd,x1,x2") + _MC88110 (0x8400f120, "fdiv.sxd", "xd,x1,x2") + _MC88110 (0x8400f140, "fdiv.sxx", "xd,x1,x2") + _MC88xxx (0x84007020, "fdiv.dss", "d,1,2") + _MC88110 (0x8400f200, "fdiv.dss", "xd,x1,x2") + _MC88xxx (0x840070a0, "fdiv.dsd", "d,1,2") + _MC88110 (0x8400f220, "fdiv.dsd", "xd,x1,x2") + _MC88110 (0x8400f240, "fdiv.dsx", "xd,x1,x2") + _MC88xxx (0x84007220, "fdiv.dds", "d,1,2") + _MC88110 (0x8400f280, "fdiv.dds", "xd,x1,x2") + _MC88xxx (0x840072a0, "fdiv.ddd", "d,1,2") + _MC88110 (0x8400f2a0, "fdiv.ddd", "xd,x1,x2") + _MC88110 (0x8400f2c0, "fdiv.ddx", "xd,x1,x2") + _MC88110 (0x8400f300, "fdiv.dxs", "xd,x1,x2") + _MC88110 (0x8400f320, "fdiv.dxd", "xd,x1,x2") + _MC88110 (0x8400f340, "fdiv.dxx", "xd,x1,x2") + _MC88110 (0x8400f400, "fdiv.xss", "xd,x1,x2") + _MC88110 (0x8400f420, "fdiv.xsd", "xd,x1,x2") + _MC88110 (0x8400f440, "fdiv.xsx", "xd,x1,x2") + _MC88110 (0x8400f480, "fdiv.xds", "xd,x1,x2") + _MC88110 (0x8400f4a0, "fdiv.xdd", "xd,x1,x2") + _MC88110 (0x8400f4c0, "fdiv.xdx", "xd,x1,x2") + _MC88110 (0x8400f500, "fdiv.xxs", "xd,x1,x2") + _MC88110 (0x8400f520, "fdiv.xxd", "xd,x1,x2") + _MC88110 (0x8400f540, "fdiv.xxx", "xd,x1,x2") + _MC88xxx (0xf400ec00, "ff0", "d,2") + _MC88xxx (0xf400e800, "ff1", "d,2") + _MC88xxx (0x80004800, "fldcr", "d,f") + _MC88xxx (0x84002020, "flt.ds", "d,2") + _MC88110 (0x84002220, "flt.ds", "xd,2") + _MC88xxx (0x84002000, "flt.ss", "d,2") + _MC88110 (0x84002200, "flt.ss", "xd,2") + _MC88110 (0x84002240, "flt.xs", "xd,2") + _MC88xxx (0x84000000, "fmul.sss", "d,1,2") + _MC88110 (0x84008000, "fmul.sss", "xd,x1,x2") + _MC88xxx (0x84000080, "fmul.ssd", "d,1,2") + _MC88110 (0x84008020, "fmul.ssd", "xd,x1,x2") + _MC88110 (0x84008040, "fmul.ssx", "xd,x1,x2") + _MC88xxx (0x84000200, "fmul.sds", "d,1,2") + _MC88110 (0x84008080, "fmul.sds", "xd,x1,x2") + _MC88xxx (0x84000280, "fmul.sdd", "d,1,2") + _MC88110 (0x840080a0, "fmul.sdd", "xd,x1,x2") + _MC88110 (0x840080c0, "fmul.sdx", "xd,x1,x2") + _MC88110 (0x84008100, "fmul.sxs", "xd,x1,x2") + _MC88110 (0x84008120, "fmul.sxd", "xd,x1,x2") + _MC88110 (0x84008140, "fmul.sxx", "xd,x1,x2") + _MC88xxx (0x84000020, "fmul.dss", "d,1,2") + _MC88110 (0x84008200, "fmul.dss", "xd,x1,x2") + _MC88xxx (0x840000a0, "fmul.dsd", "d,1,2") + _MC88110 (0x84008220, "fmul.dsd", "xd,x1,x2") + _MC88110 (0x84008240, "fmul.dsx", "xd,x1,x2") + _MC88xxx (0x84000220, "fmul.dds", "d,1,2") + _MC88110 (0x84008280, "fmul.dds", "xd,x1,x2") + _MC88xxx (0x840002a0, "fmul.ddd", "d,1,2") + _MC88110 (0x840082a0, "fmul.ddd", "xd,x1,x2") + _MC88110 (0x840082c0, "fmul.ddx", "xd,x1,x2") + _MC88110 (0x84008300, "fmul.dxs", "xd,x1,x2") + _MC88110 (0x84008320, "fmul.dxd", "xd,x1,x2") + _MC88110 (0x84008340, "fmul.dxx", "xd,x1,x2") + _MC88110 (0x84008400, "fmul.xss", "xd,x1,x2") + _MC88110 (0x84008420, "fmul.xsd", "xd,x1,x2") + _MC88110 (0x84008440, "fmul.xsx", "xd,x1,x2") + _MC88110 (0x84008480, "fmul.xds", "xd,x1,x2") + _MC88110 (0x840084a0, "fmul.xdd", "xd,x1,x2") + _MC88110 (0x840084c0, "fmul.xdx", "xd,x1,x2") + _MC88110 (0x84008500, "fmul.xxs", "xd,x1,x2") + _MC88110 (0x84008520, "fmul.xxd", "xd,x1,x2") + _MC88110 (0x84008540, "fmul.xxx", "xd,x1,x2") + _MC88110 (0x840078a0, "fsqrt.dd", "d,2") + _MC88110 (0x8400f8a0, "fsqrt.dd", "xd,x2") + _MC88110 (0x84007880, "fsqrt.ds", "d,2") + _MC88110 (0x8400f880, "fsqrt.ds", "xd,x2") + _MC88110 (0x8400f8c0, "fsqrt.dx", "xd,x2") + _MC88110 (0x84007820, "fsqrt.sd", "d,2") + _MC88110 (0x8400f820, "fsqrt.sd", "xd,x2") + _MC88110 (0x84007800, "fsqrt.ss", "d,2") + _MC88110 (0x8400f800, "fsqrt.ss", "xd,x2") + _MC88110 (0x8400f840, "fsqrt.sx", "xd,x2") + _MC88110 (0x8400f920, "fsqrt.xd", "xd,x2") + _MC88110 (0x8400f900, "fsqrt.xs", "xd,x2") + _MC88110 (0x8400f940, "fsqrt.xx", "xd,x2") + _MC88xxx (0x80008800, "fstcr", "3,f") + _MC88xxx (0x84003000, "fsub.sss", "d,1,2") + _MC88110 (0x8400b000, "fsub.sss", "xd,x1,x2") + _MC88xxx (0x84003080, "fsub.ssd", "d,1,2") + _MC88110 (0x8400b020, "fsub.ssd", "xd,x1,x2") + _MC88110 (0x8400b040, "fsub.ssx", "xd,x1,x2") + _MC88xxx (0x84003200, "fsub.sds", "d,1,2") + _MC88110 (0x8400b080, "fsub.sds", "xd,x1,x2") + _MC88xxx (0x84003280, "fsub.sdd", "d,1,2") + _MC88110 (0x8400b0a0, "fsub.sdd", "xd,x1,x2") + _MC88110 (0x8400b0c0, "fsub.sdx", "xd,x1,x2") + _MC88110 (0x8400b100, "fsub.sxs", "xd,x1,x2") + _MC88110 (0x8400b120, "fsub.sxd", "xd,x1,x2") + _MC88110 (0x8400b140, "fsub.sxx", "xd,x1,x2") + _MC88xxx (0x84003020, "fsub.dss", "d,1,2") + _MC88110 (0x8400b200, "fsub.dss", "xd,x1,x2") + _MC88xxx (0x840030a0, "fsub.dsd", "d,1,2") + _MC88110 (0x8400b220, "fsub.dsd", "xd,x1,x2") + _MC88110 (0x8400b240, "fsub.dsx", "xd,x1,x2") + _MC88xxx (0x84003220, "fsub.dds", "d,1,2") + _MC88110 (0x8400b280, "fsub.dds", "xd,x1,x2") + _MC88xxx (0x840032a0, "fsub.ddd", "d,1,2") + _MC88110 (0x8400b2a0, "fsub.ddd", "xd,x1,x2") + _MC88110 (0x8400b2c0, "fsub.ddx", "xd,x1,x2") + _MC88110 (0x8400b300, "fsub.dxs", "xd,x1,x2") + _MC88110 (0x8400b320, "fsub.dxd", "xd,x1,x2") + _MC88110 (0x8400b340, "fsub.dxx", "xd,x1,x2") + _MC88110 (0x8400b400, "fsub.xss", "xd,x1,x2") + _MC88110 (0x8400b420, "fsub.xsd", "xd,x1,x2") + _MC88110 (0x8400b440, "fsub.xsx", "xd,x1,x2") + _MC88110 (0x8400b480, "fsub.xds", "xd,x1,x2") + _MC88110 (0x8400b4a0, "fsub.xdd", "xd,x1,x2") + _MC88110 (0x8400b4c0, "fsub.xdx", "xd,x1,x2") + _MC88110 (0x8400b500, "fsub.xxs", "xd,x1,x2") + _MC88110 (0x8400b520, "fsub.xxd", "xd,x1,x2") + _MC88110 (0x8400b540, "fsub.xxx", "xd,x1,x2") + _MC88xxx (0x8000c800, "fxcr", "d,3,f") + _MC88xxx (0x8400fc01, "illop1", "") + _MC88xxx (0x8400fc02, "illop2", "") + _MC88xxx (0x8400fc03, "illop3", "") + _MC88xxx (0x84004880, "int.sd", "d,2") + _MC88110 (0x8400c880, "int.sd", "d,x2") + _MC88xxx (0x84004800, "int.ss", "d,2") + _MC88110 (0x8400c800, "int.ss", "d,x2") + _MC88110 (0x8400c900, "int.sx", "d,x2") + _MC88xxx (0xf400c000, "jmp", "2") + _MC88xxx (0xf400c400, "jmp.n", "2") + _MC88xxx (0xf400c800, "jsr", "2") + _MC88xxx (0xf400cc00, "jsr.n", "2") + _MC88xxx (0xf4001400, "ld", "d,1,2") + _MC88xxx (0xf4001600, "ld", "d,1[2]") + _MC88xxx (0x14000000, "ld", "d,1,I") + _MC88110 (0xf0001600, "ld", "xd,1[2]") + _MC88110 (0xf0001400, "ld", "xd,1,2") + _MC88110 (0x04000000, "ld", "xd,1,I") + _MC88xxx (0xf4001e00, "ld.b", "d,1[2]") + _MC88xxx (0xf4001c00, "ld.b", "d,1,2") + _MC88xxx (0x1c000000, "ld.b", "d,1,I") + _MC88xxx (0xf4001d00, "ld.b.usr", "d,1,2") + _MC88xxx (0xf4001f00, "ld.b.usr", "d,1[2]") + _MC88xxx (0xf4000e00, "ld.bu", "d,1[2]") + _MC88xxx (0xf4000c00, "ld.bu", "d,1,2") + _MC88xxx (0x0c000000, "ld.bu", "d,1,I") + _MC88xxx (0xf4000d00, "ld.bu.usr", "d,1,2") + _MC88xxx (0xf4000f00, "ld.bu.usr", "d,1[2]") + _MC88xxx (0xf4001200, "ld.d", "d,1[2]") + _MC88xxx (0xf4001000, "ld.d", "d,1,2") + _MC88xxx (0x10000000, "ld.d", "d,1,I") + _MC88110 (0xf0001200, "ld.d", "xd,1[2]") + _MC88110 (0xf0001000, "ld.d", "xd,1,2") + _MC88110 (0x00000000, "ld.d", "xd,1,I") + _MC88xxx (0xf4001100, "ld.d.usr", "d,1,2") + _MC88xxx (0xf4001300, "ld.d.usr", "d,1[2]") + _MC88110 (0xf0001100, "ld.d.usr", "xd,1,2") + _MC88110 (0xf0001300, "ld.d.usr", "xd,1[2]") + _MC88xxx (0xf4001a00, "ld.h", "d,1[2]") + _MC88xxx (0xf4001800, "ld.h", "d,1,2") + _MC88xxx (0x18000000, "ld.h", "d,1,I") + _MC88xxx (0xf4001900, "ld.h.usr", "d,1,2") + _MC88xxx (0xf4001b00, "ld.h.usr", "d,1[2]") + _MC88xxx (0xf4000a00, "ld.hu", "d,1[2]") + _MC88xxx (0xf4000800, "ld.hu", "d,1,2") + _MC88xxx (0x08000000, "ld.hu", "d,1,I") + _MC88xxx (0xf4000900, "ld.hu.usr", "d,1,2") + _MC88xxx (0xf4000b00, "ld.hu.usr", "d,1[2]") + _MC88xxx (0xf4001500, "ld.usr", "d,1,2") + _MC88xxx (0xf4001700, "ld.usr", "d,1[2]") + _MC88110 (0xf0001500, "ld.usr", "xd,1,2") + _MC88110 (0xf0001700, "ld.usr", "xd,1[2]") + _MC88110 (0xf0001a00, "ld.x", "xd,1[2]") + _MC88110 (0xf0001800, "ld.x", "xd,1,2") + _MC88110 (0x3c000000, "ld.x", "xd,1,I") + _MC88110 (0xf0001900, "ld.x.usr", "xd,1,2") + _MC88110 (0xf0001b00, "ld.x.usr", "xd,1[2]") + _MC88xxx (0xf4003600, "lda", "d,1[2]") + _MC88xxx (0xf4006000, "lda", "?d,1,2") /* Output addu */ + _MC88xxx (0x60000000, "lda", "?d,1,I") /* Output addu */ + _MC88xxx (0xf4006000, "lda.b", "?d,1[2]") /* Output addu */ + _MC88xxx (0xf4006000, "lda.b", "?d,1,2") /* Output addu */ + _MC88xxx (0x60000000, "lda.b", "?d,1,I") /* Output addu */ + _MC88xxx (0xf4003200, "lda.d", "d,1[2]") + _MC88xxx (0xf4006000, "lda.d", "?d,1,2") /* Output addu */ + _MC88xxx (0x60000000, "lda.d", "?d,1,I") /* Output addu */ + _MC88110 (0xf4003e00, "lda.x", "d,1[2]") + _MC88xxx (0xf4003a00, "lda.h", "d,1[2]") + _MC88xxx (0xf4006000, "lda.h", "?d,1,2") /* Output addu */ + _MC88xxx (0x60000000, "lda.h", "?d,1,I") /* Output addu */ + _MC88xxx (0x80004000, "ldcr", "d,c") + _MC88xxx (0xf400a000, "mak", "d,1,2") + _MC88xxx (0xf000a000, "mak", "d,1,b") + _MC88xxx (0x48000000, "mask", "d,1,I") + _MC88xxx (0x4c000000, "mask.u", "d,1,I") + _MC88110 (0x8400c000, "mov.s", "d,x2") + _MC88110 (0x84004200, "mov.s", "xd,2") + _MC88110 (0x8400c080, "mov.d", "d,x2") + _MC88110 (0x84004280, "mov.d", "xd,2") + _MC88110 (0x8400c300, "mov", "xd,x2") + _MC88xxx (0xf4006c00, "mul", "d,1,2") + _MC88xxx (0x6c000000, "mul", "d,1,I") + _MC88xxx (0xf4006e00, "muls", "d,1,2") + _MC88xxx (0x6c000000, "muls", "d,1,I") + _MC88xxx (0xf4006c00, "mulu", "d,1,2") /* synonym for mul */ + _MC88xxx (0x6c000000, "mulu", "d,1,I") /* synonym for mul */ + _MC88110 (0xf4006d00, "mulu.d", "d,1,2") + _MC88xxx (0x84005080, "nint.sd", "d,2") + _MC88110 (0x8400d080, "nint.sd", "d,x2") + _MC88xxx (0x84005000, "nint.ss", "d,2") + _MC88110 (0x8400d000, "nint.ss", "d,x2") + _MC88110 (0x8400d100, "nint.sx", "d,x2") + _MC88xxx (0xf4005800, "or", "d,1,2") + _MC88xxx (0x58000000, "or", "d,1,I") + _MC88xxx (0xf4005c00, "or.c", "d,1,2") + _MC88xxx (0x5c000000, "or.u", "d,1,I") + _MC88110 (0x88002020, "padd.b", "d,1,2") + _MC88110 (0x88002040, "padd.h", "d,1,2") + _MC88110 (0x88002060, "padd", "d,1,2") + _MC88110 (0x880020a0, "padds.u.b", "d,1,2") + _MC88110 (0x880020c0, "padds.u.h", "d,1,2") + _MC88110 (0x880020e0, "padds.u", "d,1,2") + _MC88110 (0x88002120, "padds.us.b", "d,1,2") + _MC88110 (0x88002140, "padds.us.h", "d,1,2") + _MC88110 (0x88002160, "padds.us", "d,1,2") + _MC88110 (0x880021a0, "padds.s.b", "d,1,2") + _MC88110 (0x880021c0, "padds.s.h", "d,1,2") + _MC88110 (0x880021e0, "padds.s", "d,1,2") + _MC88110 (0x88003860, "pcmp", "d,1,2") + _MC88110 (0x88000000, "pmul", "d,1,2") + _MC88110 (0x88006420, "ppack.32.b", "d,1,2") + _MC88110 (0x88006240, "ppack.16.h", "d,1,2") + _MC88110 (0x88006440, "ppack.32.h", "d,1,2") + _MC88110 (0x88006160, "ppack.8", "d,1,2") + _MC88110 (0x88006260, "ppack.16", "d,1,2") + _MC88110 (0x88006460, "ppack.32", "d,1,2") + _MC88110 (0x88007800, "prot", "d,1,2") + _MC88110 (0x88007000, "prot", "d,1,o") + _MC88110 (0x88003020, "psub.b", "d,1,2") + _MC88110 (0x88003040, "psub.h", "d,1,2") + _MC88110 (0x88003060, "psub", "d,1,2") + _MC88110 (0x880030a0, "psubs.u.b", "d,1,2") + _MC88110 (0x880030c0, "psubs.u.h", "d,1,2") + _MC88110 (0x880030e0, "psubs.u", "d,1,2") + _MC88110 (0x88003120, "psubs.us.b", "d,1,2") + _MC88110 (0x88003140, "psubs.us.h", "d,1,2") + _MC88110 (0x88003160, "psubs.us", "d,1,2") + _MC88110 (0x880031a0, "psubs.s.b", "d,1,2") + _MC88110 (0x880031c0, "psubs.s.h", "d,1,2") + _MC88110 (0x880031e0, "psubs.s", "d,1,2") + _MC88110 (0x88006800, "punpk.n", "d,1") + _MC88110 (0x88006820, "punpk.b", "d,1") + _MC88110 (0x88006840, "punpk.h", "d,1") + _MC88xxx (0xf400a800, "rot", "d,1,2") + _MC88xxx (0xf000a800, "rot", "d,1,b") + _MC88xxx (0xf400fc00, "rte", "") + _MC88xxx (0xf4008800, "set", "d,1,2") + _MC88xxx (0xf0008800, "set", "d,1,b") + _MC88xxx (0xf4002600, "st", "d,1[2]") + _MC88xxx (0xf4002400, "st", "d,1,2") + _MC88xxx (0x24000000, "st", "d,1,I") + _MC88110 (0xf0002600, "st", "xd,1[2]") + _MC88110 (0xf0002400, "st", "xd,1,2") + _MC88110 (0x34000000, "st", "xd,1,I") + _MC88xxx (0xf4002e00, "st.b", "d,1[2]") + _MC88xxx (0xf4002c00, "st.b", "d,1,2") + _MC88xxx (0x2c000000, "st.b", "d,1,I") + _MC88xxx (0xf4002d00, "st.b.usr", "d,1,2") + _MC88xxx (0xf4002f00, "st.b.usr", "d,1[2]") + _MC88110 (0xf4002d80, "st.b.usr.wt", "d,1,2") + _MC88110 (0xf4002f80, "st.b.usr.wt", "d,1[2]") + _MC88110 (0xf4002c80, "st.b.wt", "d,1,2") + _MC88110 (0xf4002e80, "st.b.wt", "d,1[2]") + _MC88xxx (0xf4002200, "st.d", "d,1[2]") + _MC88xxx (0xf4002000, "st.d", "d,1,2") + _MC88xxx (0x20000000, "st.d", "d,1,I") + _MC88110 (0xf0002200, "st.d", "xd,1[2]") + _MC88110 (0xf0002000, "st.d", "xd,1,2") + _MC88110 (0x30000000, "st.d", "xd,1,I") + _MC88xxx (0xf4002100, "st.d.usr", "d,1,2") + _MC88xxx (0xf4002300, "st.d.usr", "d,1[2]") + _MC88110 (0xf0002100, "st.d.usr", "xd,1,2") + _MC88110 (0xf0002300, "st.d.usr", "xd,1[2]") + _MC88110 (0xf4002180, "st.d.usr.wt", "d,1,2") + _MC88110 (0xf4002380, "st.d.usr.wt", "d,1[2]") + _MC88110 (0xf0002180, "st.d.usr.wt", "xd,1,2") + _MC88110 (0xf0002380, "st.d.usr.wt", "xd,1[2]") + _MC88110 (0xf4002080, "st.d.wt", "d,1,2") + _MC88110 (0xf4002280, "st.d.wt", "d,1[2]") + _MC88110 (0xf0002080, "st.d.wt", "xd,1,2") + _MC88110 (0xf0002280, "st.d.wt", "xd,1[2]") + _MC88xxx (0xf4002a00, "st.h", "d,1[2]") + _MC88xxx (0xf4002800, "st.h", "d,1,2") + _MC88xxx (0x28000000, "st.h", "d,1,I") + _MC88xxx (0xf4002900, "st.h.usr", "d,1,2") + _MC88xxx (0xf4002b00, "st.h.usr", "d,1[2]") + _MC88110 (0xf4002980, "st.h.usr.wt", "d,1,2") + _MC88110 (0xf4002b80, "st.h.usr.wt", "d,1[2]") + _MC88110 (0xf4002880, "st.h.wt", "d,1,2") + _MC88110 (0xf4002a80, "st.h.wt", "d,1[2]") + _MC88xxx (0xf4002500, "st.usr", "d,1,2") + _MC88xxx (0xf4002700, "st.usr", "d,1[2]") + _MC88110 (0xf0002500, "st.usr", "xd,1,2") + _MC88110 (0xf0002700, "st.usr", "xd,1[2]") + _MC88110 (0xf4002580, "st.usr.wt", "d,1,2") + _MC88110 (0xf4002780, "st.usr.wt", "d,1[2]") + _MC88110 (0xf0002580, "st.usr.wt", "xd,1,2") + _MC88110 (0xf0002780, "st.usr.wt", "xd,1[2]") + _MC88110 (0xf4002480, "st.wt", "d,1,2") + _MC88110 (0xf4002680, "st.wt", "d,1[2]") + _MC88110 (0xf0002480, "st.wt", "xd,1,2") + _MC88110 (0xf0002680, "st.wt", "xd,1[2]") + _MC88110 (0xf0002a00, "st.x", "xd,1[2]") + _MC88110 (0xf0002800, "st.x", "xd,1,2") + _MC88110 (0x38000000, "st.x", "xd,1,I") + _MC88110 (0xf0002900, "st.x.usr", "xd,1,2") + _MC88110 (0xf0002b00, "st.x.usr", "xd,1[2]") + _MC88110 (0xf0002980, "st.x.usr.wt", "xd,1,2") + _MC88110 (0xf0002b80, "st.x.usr.wt", "xd,1[2]") + _MC88110 (0xf0002880, "st.x.wt", "xd,1,2") + _MC88110 (0xf0002a80, "st.x.wt", "xd,1[2]") + _MC88xxx (0x80008000, "stcr", "3,c") + _MC88xxx (0xf4007400, "sub", "d,1,2") + _MC88xxx (0x74000000, "sub", "d,1,I") + _MC88xxx (0xf4007600, "sub.ci", "d,1,2") + _MC88xxx (0xf4007700, "sub.cio", "d,1,2") + _MC88xxx (0xf4007500, "sub.co", "d,1,2") + _MC88xxx (0xf4006400, "subu", "d,1,2") + _MC88xxx (0x64000000, "subu", "d,1,I") + _MC88xxx (0xf4006600, "subu.ci", "d,1,2") + _MC88xxx (0xf4006700, "subu.cio", "d,1,2") + _MC88xxx (0xf4006500, "subu.co", "d,1,2") + _MC88xxx (0xf000d000, "tb0", "B,1,V") + _MC88xxx (0xf000d800, "tb1", "B,1,V") + _MC88xxx (0xf400f800, "tbnd", "1,2") + _MC88xxx (0xf8000000, "tbnd", "1,I") + _MC88xxx (0xf000e800, "tcnd", "M,1,V") + _MC88xxx (0x84005880, "trnc.sd", "d,2") + _MC88110 (0x8400d880, "trnc.sd", "d,x2") + _MC88xxx (0x84005800, "trnc.ss", "d,2") + _MC88110 (0x8400d800, "trnc.ss", "d,x2") + _MC88110 (0x8400d900, "trnc.sx", "d,x2") + _MC88xxx (0x8000c000, "xcr", "d,3,c") + _MC88xxx (0xf4000600, "xmem", "d,1[2]") + _MC88xxx (0xf4000400, "xmem", "d,1,2") + _MC88100 (0x04000000, "xmem", "?d,1,I") + _MC88xxx (0xf4000200, "xmem.bu", "d,1[2]") + _MC88xxx (0xf4000000, "xmem.bu", "d,1,2") + _MC88100 (0x00000000, "xmem.bu", "?d,1,I") + _MC88xxx (0xf4000300, "xmem.bu.usr", "d,1[2]") + _MC88xxx (0xf4000100, "xmem.bu.usr", "d,1,2") + _MC88100 (0x00000100, "xmem.bu.usr", "?d,1,I") + _MC88xxx (0xf4000700, "xmem.usr", "d,1[2]") + _MC88xxx (0xf4000500, "xmem.usr", "d,1,2") + _MC88100 (0x04000100, "xmem.usr", "?d,1,I") + _MC88xxx (0xf4005000, "xor", "d,1,2") + _MC88xxx (0x50000000, "xor", "d,1,I") + _MC88xxx (0xf4005400, "xor.c", "d,1,2") + _MC88xxx (0x54000000, "xor.u", "d,1,I") + _MC88xxx (0x00000000, "", 0) +}; + +#define NUMOPCODES ((sizeof m88k_opcodes)/(sizeof m88k_opcodes[0])) diff --git a/gnu/usr.bin/binutils/gas/config/m88kcoff.mt b/gnu/usr.bin/binutils/gas/config/m88kcoff.mt new file mode 100644 index 00000000000..474f6a01ebe --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/m88kcoff.mt @@ -0,0 +1 @@ +TDEFINES=-DM88KCOFF diff --git a/gnu/usr.bin/binutils/gas/config/mips-big.mt b/gnu/usr.bin/binutils/gas/config/mips-big.mt new file mode 100644 index 00000000000..31e773a14d9 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/mips-big.mt @@ -0,0 +1 @@ +TDEFINES=-DTARGET_BYTES_BIG_ENDIAN diff --git a/gnu/usr.bin/binutils/gas/config/mips-lit.mt b/gnu/usr.bin/binutils/gas/config/mips-lit.mt new file mode 100644 index 00000000000..9e240e8166e --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/mips-lit.mt @@ -0,0 +1 @@ +TDEFINES=-DTARGET_BYTES_LITTLE_ENDIAN diff --git a/gnu/usr.bin/binutils/gas/config/obj-aout.c b/gnu/usr.bin/binutils/gas/config/obj-aout.c new file mode 100644 index 00000000000..0a460646dfb --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-aout.c @@ -0,0 +1,558 @@ +/* a.out object file format + Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995 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 2, +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. */ + +#include "as.h" +#ifdef BFD_ASSEMBLER +#undef NO_RELOC +#include "aout/aout64.h" +#endif +#include "obstack.h" + +#ifndef BFD_ASSEMBLER +/* in: segT out: N_TYPE bits */ +const short seg_N_TYPE[] = +{ + N_ABS, + N_TEXT, + N_DATA, + N_BSS, + N_UNDF, /* unknown */ + N_UNDF, /* error */ + N_UNDF, /* expression */ + N_UNDF, /* debug */ + N_UNDF, /* ntv */ + N_UNDF, /* ptv */ + N_REGISTER, /* register */ +}; + +const segT N_TYPE_seg[N_TYPE + 2] = +{ /* N_TYPE == 0x1E = 32-2 */ + SEG_UNKNOWN, /* N_UNDF == 0 */ + SEG_GOOF, + SEG_ABSOLUTE, /* N_ABS == 2 */ + SEG_GOOF, + SEG_TEXT, /* N_TEXT == 4 */ + SEG_GOOF, + SEG_DATA, /* N_DATA == 6 */ + SEG_GOOF, + SEG_BSS, /* N_BSS == 8 */ + SEG_GOOF, + SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, + SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, + SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, + SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */ + SEG_GOOF, +}; +#endif + +static void obj_aout_line PARAMS ((int)); +static void obj_aout_weak PARAMS ((int)); + +const pseudo_typeS obj_pseudo_table[] = +{ + {"line", obj_aout_line, 0}, /* source code line number */ + {"ln", obj_aout_line, 0}, /* coff line number that we use anyway */ + + {"weak", obj_aout_weak, 0}, /* mark symbol as weak. */ + + /* coff debug pseudos (ignored) */ + {"def", s_ignore, 0}, + {"dim", s_ignore, 0}, + {"endef", s_ignore, 0}, + {"ident", s_ignore, 0}, + {"line", s_ignore, 0}, + {"ln", s_ignore, 0}, + {"scl", s_ignore, 0}, + {"size", s_ignore, 0}, + {"tag", s_ignore, 0}, + {"type", s_ignore, 0}, + {"val", s_ignore, 0}, + {"version", s_ignore, 0}, + + {"optim", s_ignore, 0}, /* For sun386i cc (?) */ + + /* other stuff */ + {"ABORT", s_abort, 0}, + + {NULL} /* end sentinel */ +}; /* obj_pseudo_table */ + + +#ifdef BFD_ASSEMBLER + +void +obj_aout_frob_symbol (sym, punt) + symbolS *sym; + int *punt; +{ + flagword flags; + asection *sec; + int desc, type, other; + + flags = sym->bsym->flags; + desc = S_GET_DESC (sym); + type = S_GET_TYPE (sym); + other = S_GET_OTHER (sym); + sec = sym->bsym->section; + + /* Only frob simple symbols this way right now. */ + if (! (type & ~ (N_TYPE | N_EXT))) + { + if (type == (N_UNDF | N_EXT) + && sec == &bfd_abs_section) + sym->bsym->section = sec = bfd_und_section_ptr; + + if ((type & N_TYPE) != N_INDR + && (type & N_TYPE) != N_SETA + && (type & N_TYPE) != N_SETT + && (type & N_TYPE) != N_SETD + && (type & N_TYPE) != N_SETB + && type != N_WARNING + && (sec == &bfd_abs_section + || sec == &bfd_und_section)) + return; + if (flags & BSF_EXPORT) + type |= N_EXT; + + switch (type & N_TYPE) + { + case N_SETA: + case N_SETT: + case N_SETD: + case N_SETB: + /* Set the debugging flag for constructor symbols so that + BFD leaves them alone. */ + sym->bsym->flags |= BSF_DEBUGGING; + + /* You can't put a common symbol in a set. The way a set + element works is that the symbol has a definition and a + name, and the linker adds the definition to the set of + that name. That does not work for a common symbol, + because the linker can't tell which common symbol the + user means. FIXME: Using as_bad here may be + inappropriate, since the user may want to force a + particular type without regard to the semantics of sets; + on the other hand, we certainly don't want anybody to be + mislead into thinking that their code will work. */ + if (S_IS_COMMON (sym)) + as_bad ("Attempt to put a common symbol into set %s", + S_GET_NAME (sym)); + /* Similarly, you can't put an undefined symbol in a set. */ + else if (! S_IS_DEFINED (sym)) + as_bad ("Attempt to put an undefined symbol into set %s", + S_GET_NAME (sym)); + + break; + case N_INDR: + /* Put indirect symbols in the indirect section. */ + sym->bsym->section = bfd_ind_section_ptr; + sym->bsym->flags |= BSF_INDIRECT; + if (type & N_EXT) + { + sym->bsym->flags |= BSF_EXPORT; + sym->bsym->flags &=~ BSF_LOCAL; + } + break; + case N_WARNING: + /* Mark warning symbols. */ + sym->bsym->flags |= BSF_WARNING; + break; + } + } + else + { + sym->bsym->flags |= BSF_DEBUGGING; + } + + S_SET_TYPE (sym, type); + + /* Double check weak symbols. */ + if (sym->bsym->flags & BSF_WEAK) + { + if (S_IS_COMMON (sym)) + as_bad ("Symbol `%s' can not be both weak and common", + S_GET_NAME (sym)); + } +} + +void +obj_aout_frob_file () +{ + /* Relocation processing may require knowing the VMAs of the sections. + Since writing to a section will cause the BFD back end to compute the + VMAs, fake it out here.... */ + bfd_byte b = 0; + boolean x = true; + if (bfd_section_size (stdoutput, text_section) != 0) + { + x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0, + (bfd_size_type) 1); + } + else if (bfd_section_size (stdoutput, data_section) != 0) + { + x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0, + (bfd_size_type) 1); + } + assert (x == true); +} + +#else + +/* Relocation. */ + +/* + * emit_relocations() + * + * Crawl along a fixS chain. Emit the segment's relocations. + */ +void +obj_emit_relocations (where, fixP, segment_address_in_file) + char **where; + fixS *fixP; /* Fixup chain for this segment. */ + relax_addressT segment_address_in_file; +{ + for (; fixP; fixP = fixP->fx_next) + if (fixP->fx_done == 0) + { + tc_aout_fix_to_chars (*where, fixP, segment_address_in_file); + *where += md_reloc_size; + } +} + +#ifndef obj_header_append +/* Aout file generation & utilities */ +void +obj_header_append (where, headers) + char **where; + object_headers *headers; +{ + tc_headers_hook (headers); + +#ifdef CROSS_COMPILE + md_number_to_chars (*where, headers->header.a_info, sizeof (headers->header.a_info)); + *where += sizeof (headers->header.a_info); + md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text)); + *where += sizeof (headers->header.a_text); + md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data)); + *where += sizeof (headers->header.a_data); + md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss)); + *where += sizeof (headers->header.a_bss); + md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms)); + *where += sizeof (headers->header.a_syms); + md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry)); + *where += sizeof (headers->header.a_entry); + md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize)); + *where += sizeof (headers->header.a_trsize); + md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize)); + *where += sizeof (headers->header.a_drsize); + +#else /* CROSS_COMPILE */ + + append (where, (char *) &headers->header, sizeof (headers->header)); +#endif /* CROSS_COMPILE */ + +} +#endif + +void +obj_symbol_to_chars (where, symbolP) + char **where; + symbolS *symbolP; +{ + md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP))); + md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP))); + md_number_to_chars ((char *) &(symbolP->sy_symbol.n_value), S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value)); + + append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type)); +} + +void +obj_emit_symbols (where, symbol_rootP) + char **where; + symbolS *symbol_rootP; +{ + symbolS *symbolP; + + /* Emit all symbols left in the symbol chain. */ + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + { + /* Used to save the offset of the name. It is used to point + to the string in memory but must be a file offset. */ + register char *temp; + + temp = S_GET_NAME (symbolP); + S_SET_OFFSET (symbolP, symbolP->sy_name_offset); + + /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */ + if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP)) + S_SET_EXTERNAL (symbolP); + + /* Adjust the type of a weak symbol. */ + if (S_GET_WEAK (symbolP)) + { + switch (S_GET_TYPE (symbolP)) + { + case N_UNDF: S_SET_TYPE (symbolP, N_WEAKU); break; + case N_ABS: S_SET_TYPE (symbolP, N_WEAKA); break; + case N_TEXT: S_SET_TYPE (symbolP, N_WEAKT); break; + case N_DATA: S_SET_TYPE (symbolP, N_WEAKD); break; + case N_BSS: S_SET_TYPE (symbolP, N_WEAKB); break; + default: as_bad ("%s: bad type for weak symbol", temp); break; + } + } + + obj_symbol_to_chars (where, symbolP); + S_SET_NAME (symbolP, temp); + } +} + +#endif /* ! BFD_ASSEMBLER */ + +static void +obj_aout_line (ignore) + int ignore; +{ + /* Assume delimiter is part of expression. + BSD4.2 as fails with delightful bug, so we + are not being incompatible here. */ + new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); + demand_empty_rest_of_line (); +} /* obj_aout_line() */ + +/* Handle .weak. This is a GNU extension. */ + +static void +obj_aout_weak (ignore) + int ignore; +{ + char *name; + int c; + symbolS *symbolP; + + do + { + name = input_line_pointer; + c = get_symbol_end (); + symbolP = symbol_find_or_make (name); + *input_line_pointer = c; + SKIP_WHITESPACE (); + S_SET_WEAK (symbolP); + if (c == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + if (*input_line_pointer == '\n') + c = '\n'; + } + } + while (c == ','); + demand_empty_rest_of_line (); +} + +void +obj_read_begin_hook () +{ +} + +#ifndef BFD_ASSEMBLER + +void +obj_crawl_symbol_chain (headers) + object_headers *headers; +{ + symbolS *symbolP; + symbolS **symbolPP; + int symbol_number = 0; + + tc_crawl_symbol_chain (headers); + + symbolPP = &symbol_rootP; /*->last symbol chain link. */ + while ((symbolP = *symbolPP) != NULL) + { + if (symbolP->sy_mri_common) + { + if (S_IS_EXTERNAL (symbolP)) + as_bad ("%s: global symbols not supported in common sections", + S_GET_NAME (symbolP)); + *symbolPP = symbol_next (symbolP); + continue; + } + + if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA)) + { + S_SET_SEGMENT (symbolP, SEG_TEXT); + } /* if pusing data into text */ + + resolve_symbol_value (symbolP); + + /* OK, here is how we decide which symbols go out into the brave + new symtab. Symbols that do are: + + * symbols with no name (stabd's?) + * symbols with debug info in their N_TYPE + + Symbols that don't are: + * symbols that are registers + * symbols with \1 as their 3rd character (numeric labels) + * "local labels" as defined by S_LOCAL_NAME(name) if the -L + switch was passed to gas. + + All other symbols are output. We complain if a deleted + symbol was marked external. */ + + + if (!S_IS_REGISTER (symbolP) + && (!S_GET_NAME (symbolP) + || S_IS_DEBUG (symbolP) + || !S_IS_DEFINED (symbolP) + || S_IS_EXTERNAL (symbolP) + || (S_GET_NAME (symbolP)[0] != '\001' + && (flag_keep_locals || !S_LOCAL_NAME (symbolP))))) + { + symbolP->sy_number = symbol_number++; + + /* The + 1 after strlen account for the \0 at the + end of each string */ + if (!S_IS_STABD (symbolP)) + { + /* Ordinary case. */ + symbolP->sy_name_offset = string_byte_count; + string_byte_count += strlen (S_GET_NAME (symbolP)) + 1; + } + else /* .Stabd case. */ + symbolP->sy_name_offset = 0; + symbolPP = &(symbol_next (symbolP)); + } + else + { + if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP)) + /* This warning should never get triggered any more. + Well, maybe if you're doing twisted things with + register names... */ + { + as_bad ("Local symbol %s never defined.", decode_local_label_name (S_GET_NAME (symbolP))); + } /* oops. */ + + /* Unhook it from the chain */ + *symbolPP = symbol_next (symbolP); + } /* if this symbol should be in the output */ + } /* for each symbol */ + + H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number); +} + +/* + * Find strings by crawling along symbol table chain. + */ + +void +obj_emit_strings (where) + char **where; +{ + symbolS *symbolP; + +#ifdef CROSS_COMPILE + /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ + md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count)); + *where += sizeof (string_byte_count); +#else /* CROSS_COMPILE */ + append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count)); +#endif /* CROSS_COMPILE */ + + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + { + if (S_GET_NAME (symbolP)) + append (&next_object_file_charP, S_GET_NAME (symbolP), + (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); + } /* walk symbol chain */ +} + +#ifndef AOUT_VERSION +#define AOUT_VERSION 0 +#endif + +void +obj_pre_write_hook (headers) + object_headers *headers; +{ + H_SET_DYNAMIC (headers, 0); + H_SET_VERSION (headers, AOUT_VERSION); + H_SET_MACHTYPE (headers, AOUT_MACHTYPE); + tc_aout_pre_write_hook (headers); +} + +void +DEFUN_VOID (s_sect) +{ + /* Strip out the section name */ + char *section_name; + char *section_name_end; + char c; + + unsigned int len; + unsigned int exp; + char *save; + + section_name = input_line_pointer; + c = get_symbol_end (); + section_name_end = input_line_pointer; + + len = section_name_end - section_name; + input_line_pointer++; + save = input_line_pointer; + + SKIP_WHITESPACE (); + if (c == ',') + { + exp = get_absolute_expression (); + } + else if (*input_line_pointer == ',') + { + input_line_pointer++; + exp = get_absolute_expression (); + } + else + { + input_line_pointer = save; + exp = 0; + } + if (exp >= 1000) + { + as_bad ("subsegment index too high"); + } + + if (strcmp (section_name, ".text") == 0) + { + subseg_set (SEG_TEXT, (subsegT) exp); + } + + if (strcmp (section_name, ".data") == 0) + { + if (flag_readonly_data_in_text) + subseg_set (SEG_TEXT, (subsegT) exp + 1000); + else + subseg_set (SEG_DATA, (subsegT) exp); + } + + *section_name_end = c; +} + +#endif /* ! BFD_ASSEMBLER */ + +/* end of obj-aout.c */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-aout.h b/gnu/usr.bin/binutils/gas/config/obj-aout.h new file mode 100644 index 00000000000..7f88e337bf1 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-aout.h @@ -0,0 +1,230 @@ +/* obj-aout.h, a.out object file format for gas, the assembler. + Copyright (C) 1989, 1990, 1991, 1992, 1993 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 2, + 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. */ + +/* Tag to validate a.out object file format processing */ +#define OBJ_AOUT 1 + +#include "targ-cpu.h" + +#ifdef BFD_ASSEMBLER + +#include "bfd/libaout.h" + +#define OUTPUT_FLAVOR bfd_target_aout_flavour + +#else /* ! BFD_ASSEMBLER */ + +#ifndef VMS +#include "aout_gnu.h" /* Needed to define struct nlist. Sigh. */ +#else +#include "a_out.h" +#endif + +#ifndef AOUT_MACHTYPE +#define AOUT_MACHTYPE 0 +#endif /* AOUT_MACHTYPE */ + +extern const short seg_N_TYPE[]; +extern const segT N_TYPE_seg[]; + +#ifndef DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE +#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC) +#endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */ + +#endif /* ! BFD_ASSEMBLER */ + +/* SYMBOL TABLE */ +/* Symbol table entry data type */ + +typedef struct nlist obj_symbol_type; /* Symbol table entry */ + +/* Symbol table macros and constants */ + +#ifdef BFD_ASSEMBLER + +#define S_SET_OTHER(S,V) (aout_symbol((S)->bsym)->other = (V)) +#define S_SET_TYPE(S,T) (aout_symbol((S)->bsym)->type = (T)) +#define S_SET_DESC(S,D) (aout_symbol((S)->bsym)->desc = (D)) +#define S_GET_OTHER(S) (aout_symbol((S)->bsym)->other) +#define S_GET_TYPE(S) (aout_symbol((S)->bsym)->type) +#define S_GET_DESC(S) (aout_symbol((S)->bsym)->desc) + +asection *text_section, *data_section, *bss_section; + +#define obj_frob_symbol(S,PUNT) obj_aout_frob_symbol (S, &PUNT) +#define obj_frob_file() obj_aout_frob_file () +extern void obj_aout_frob_symbol PARAMS ((struct symbol *, int *)); +extern void obj_aout_frob_file PARAMS ((void)); + +#define obj_sec_sym_ok_for_reloc(SEC) (1) + +#else + +/* We use the sy_obj field to record whether a symbol is weak. */ +#define OBJ_SYMFIELD_TYPE char + +/* + * Macros to extract information from a symbol table entry. + * This syntaxic indirection allows independence regarding a.out or coff. + * The argument (s) of all these macros is a pointer to a symbol table entry. + */ + +/* True if the symbol is external */ +#define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT) + +/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */ +#define S_IS_DEFINED(s) ((S_GET_TYPE(s) != N_UNDF) || (S_GET_OTHER(s) != 0) || (S_GET_DESC(s) != 0)) + +#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER) + +/* True if a debug special symbol entry */ +#define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB) +/* True if a symbol is local symbol name */ +/* A symbol name whose name begin with ^A is a gas internal pseudo symbol + nameless symbols come from .stab directives. */ +#define S_IS_LOCAL(s) (S_GET_NAME(s) && \ + !S_IS_DEBUG(s) && \ + (S_GET_NAME(s)[0] == '\001' || \ + (S_LOCAL_NAME(s) && !flag_keep_locals))) +/* True if a symbol is not defined in this file */ +#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT) +/* True if the symbol has been generated because of a .stabd directive */ +#define S_IS_STABD(s) (S_GET_NAME(s) == (char *)0) + +/* Accessors */ +/* The name of the symbol */ +#define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name) +/* The pointer to the string table */ +#define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx) +/* The type of the symbol */ +#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE) +/* The numeric value of the segment */ +#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)]) +/* The n_other expression value */ +#define S_GET_OTHER(s) ((s)->sy_symbol.n_other) +/* The n_desc expression value */ +#define S_GET_DESC(s) ((s)->sy_symbol.n_desc) +/* Whether the symbol is weak. */ +#define S_GET_WEAK(s) ((s)->sy_obj) + +/* Modifiers */ +/* Assume that a symbol cannot be simultaneously in more than on segment */ +/* set segment */ +#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg)) +/* The symbol is external */ +#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT) +/* The symbol is not external */ +#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT) +/* Set the name of the symbol */ +#define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v)) +/* Set the offset in the string table */ +#define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v)) +/* Set the n_type field */ +#define S_SET_TYPE(s,t) ((s)->sy_symbol.n_type = (t)) +/* Set the n_other expression value */ +#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v)) +/* Set the n_desc expression value */ +#define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v)) +/* Mark the symbol as weak. This causes n_type to be adjusted when + the symbol is written out. */ +#define S_SET_WEAK(s) ((s)->sy_obj = 1) + +/* File header macro and type definition */ + +#define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE(h) \ + + H_GET_TEXT_SIZE(h) \ + + H_GET_DATA_SIZE(h) \ + + H_GET_SYMBOL_TABLE_SIZE(h) \ + + H_GET_TEXT_RELOCATION_SIZE(h) \ + + H_GET_DATA_RELOCATION_SIZE(h) \ + + H_GET_STRING_SIZE(h)) + +#define H_GET_HEADER_SIZE(h) (EXEC_BYTES_SIZE) +#define H_GET_TEXT_SIZE(h) ((h)->header.a_text) +#define H_GET_DATA_SIZE(h) ((h)->header.a_data) +#define H_GET_BSS_SIZE(h) ((h)->header.a_bss) +#define H_GET_TEXT_RELOCATION_SIZE(h) ((h)->header.a_trsize) +#define H_GET_DATA_RELOCATION_SIZE(h) ((h)->header.a_drsize) +#define H_GET_SYMBOL_TABLE_SIZE(h) ((h)->header.a_syms) +#define H_GET_ENTRY_POINT(h) ((h)->header.a_entry) +#define H_GET_STRING_SIZE(h) ((h)->string_table_size) +#define H_GET_LINENO_SIZE(h) (0) + +#define H_GET_DYNAMIC(h) ((h)->header.a_info >> 31) +#define H_GET_VERSION(h) (((h)->header.a_info >> 24) & 0x7f) +#define H_GET_MACHTYPE(h) (((h)->header.a_info >> 16) & 0xff) +#define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info & 0xffff) + +#define H_SET_DYNAMIC(h,v) ((h)->header.a_info = (((v) << 31) \ + | (H_GET_VERSION(h) << 24) \ + | (H_GET_MACHTYPE(h) << 16) \ + | (H_GET_MAGIC_NUMBER(h)))) + +#define H_SET_VERSION(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \ + | ((v) << 24) \ + | (H_GET_MACHTYPE(h) << 16) \ + | (H_GET_MAGIC_NUMBER(h)))) + +#define H_SET_MACHTYPE(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \ + | (H_GET_VERSION(h) << 24) \ + | ((v) << 16) \ + | (H_GET_MAGIC_NUMBER(h)))) + +#define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \ + | (H_GET_VERSION(h) << 24) \ + | (H_GET_MACHTYPE(h) << 16) \ + | ((v)))) + +#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v))) +#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v))) +#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v))) + +#define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\ + H_SET_DATA_RELOCATION_SIZE((h),(d))) + +#define H_SET_TEXT_RELOCATION_SIZE(h,v) ((h)->header.a_trsize = (v)) +#define H_SET_DATA_RELOCATION_SIZE(h,v) ((h)->header.a_drsize = (v)) +#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * 12) + +#define H_SET_ENTRY_POINT(h,v) ((h)->header.a_entry = (v)) +#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) + +typedef struct + { + struct exec header; /* a.out header */ + long string_table_size; /* names + '\0' + sizeof(int) */ + } + +object_headers; + +/* line numbering stuff. */ +#define OBJ_EMIT_LINENO(a, b, c) {;} + +struct fix; +void tc_aout_fix_to_chars PARAMS ((char *where, struct fix *fixP, relax_addressT segment_address)); + +#endif + +#define obj_symbol_new_hook(s) {;} + +#define EMIT_SECTION_SYMBOLS 0 + +#define AOUT_STABS + +/* end of obj-aout.h */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-bout.c b/gnu/usr.bin/binutils/gas/config/obj-bout.c new file mode 100644 index 00000000000..ba7cadc370d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-bout.c @@ -0,0 +1,330 @@ +/* b.out object file format + Copyright (C) 1989, 1990, 1991, 1992 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 2, + 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. */ + +#include "as.h" +#include "obstack.h" +const short /* in: segT out: N_TYPE bits */ + seg_N_TYPE[] = +{ + N_ABS, + N_TEXT, + N_DATA, + N_BSS, + N_UNDF, /* unknown */ + N_UNDF, /* error */ + N_UNDF, /* expression */ + N_UNDF, /* debug */ + N_UNDF, /* ntv */ + N_UNDF, /* ptv */ + N_REGISTER, /* register */ +}; + +const segT N_TYPE_seg[N_TYPE + 2] = +{ /* N_TYPE == 0x1E = 32-2 */ + SEG_UNKNOWN, /* N_UNDF == 0 */ + SEG_GOOF, + SEG_ABSOLUTE, /* N_ABS == 2 */ + SEG_GOOF, + SEG_TEXT, /* N_TEXT == 4 */ + SEG_GOOF, + SEG_DATA, /* N_DATA == 6 */ + SEG_GOOF, + SEG_BSS, /* N_BSS == 8 */ + SEG_GOOF, + SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, + SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, + SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, + SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */ + SEG_GOOF, +}; + +static void obj_bout_line PARAMS ((int)); + +const pseudo_typeS obj_pseudo_table[] = +{ + {"line", obj_bout_line, 0}, /* source code line number */ + +/* coff debugging directives. Currently ignored silently */ + {"def", s_ignore, 0}, + {"dim", s_ignore, 0}, + {"endef", s_ignore, 0}, + {"ln", s_ignore, 0}, + {"scl", s_ignore, 0}, + {"size", s_ignore, 0}, + {"tag", s_ignore, 0}, + {"type", s_ignore, 0}, + {"val", s_ignore, 0}, + +/* other stuff we don't handle */ + {"ABORT", s_ignore, 0}, + {"ident", s_ignore, 0}, + + {NULL} /* end sentinel */ +}; /* obj_pseudo_table */ + +/* Relocation. */ + +/* + * emit_relocations() + * + * Crawl along a fixS chain. Emit the segment's relocations. + */ +void +obj_emit_relocations (where, fixP, segment_address_in_file) + char **where; + fixS *fixP; /* Fixup chain for this segment. */ + relax_addressT segment_address_in_file; +{ + for (; fixP; fixP = fixP->fx_next) + { + if (fixP->fx_done == 0 + || fixP->fx_r_type != NO_RELOC) + { + tc_bout_fix_to_chars (*where, fixP, segment_address_in_file); + *where += sizeof (struct relocation_info); + } /* if there's a symbol */ + } /* for each fixup */ + +} /* emit_relocations() */ + +/* Aout file generation & utilities */ + +/* Convert a lvalue to machine dependent data */ +void +obj_header_append (where, headers) + char **where; + object_headers *headers; +{ + /* Always leave in host byte order */ + + headers->header.a_talign = section_alignment[SEG_TEXT]; + + if (headers->header.a_talign < 2) + { + headers->header.a_talign = 2; + } /* force to at least 2 */ + + headers->header.a_dalign = section_alignment[SEG_DATA]; + headers->header.a_balign = section_alignment[SEG_BSS]; + + headers->header.a_tload = 0; + headers->header.a_dload = md_section_align (SEG_DATA, H_GET_TEXT_SIZE (headers)); + + headers->header.a_relaxable = linkrelax; + +#ifdef CROSS_COMPILE + md_number_to_chars (*where, headers->header.a_magic, sizeof (headers->header.a_magic)); + *where += sizeof (headers->header.a_magic); + md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text)); + *where += sizeof (headers->header.a_text); + md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data)); + *where += sizeof (headers->header.a_data); + md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss)); + *where += sizeof (headers->header.a_bss); + md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms)); + *where += sizeof (headers->header.a_syms); + md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry)); + *where += sizeof (headers->header.a_entry); + md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize)); + *where += sizeof (headers->header.a_trsize); + md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize)); + *where += sizeof (headers->header.a_drsize); + md_number_to_chars (*where, headers->header.a_tload, sizeof (headers->header.a_tload)); + *where += sizeof (headers->header.a_tload); + md_number_to_chars (*where, headers->header.a_dload, sizeof (headers->header.a_dload)); + *where += sizeof (headers->header.a_dload); + md_number_to_chars (*where, headers->header.a_talign, sizeof (headers->header.a_talign)); + *where += sizeof (headers->header.a_talign); + md_number_to_chars (*where, headers->header.a_dalign, sizeof (headers->header.a_dalign)); + *where += sizeof (headers->header.a_dalign); + md_number_to_chars (*where, headers->header.a_balign, sizeof (headers->header.a_balign)); + *where += sizeof (headers->header.a_balign); + md_number_to_chars (*where, headers->header.a_relaxable, sizeof (headers->header.a_relaxable)); + *where += sizeof (headers->header.a_relaxable); +#else /* ! CROSS_COMPILE */ + append (where, (char *) &headers->header, sizeof (headers->header)); +#endif /* ! CROSS_COMPILE */ +} /* a_header_append() */ + +void +obj_symbol_to_chars (where, symbolP) + char **where; + symbolS *symbolP; +{ + md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP))); + md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP))); + md_number_to_chars ((char *) &symbolP->sy_symbol.n_value, S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value)); + + append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type)); +} /* obj_symbol_to_chars() */ + +void +obj_emit_symbols (where, symbol_rootP) + char **where; + symbolS *symbol_rootP; +{ + symbolS *symbolP; + + /* + * Emit all symbols left in the symbol chain. + */ + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + { + /* Used to save the offset of the name. It is used to point + to the string in memory but must be a file offset. */ + char *temp; + + temp = S_GET_NAME (symbolP); + S_SET_OFFSET (symbolP, symbolP->sy_name_offset); + + /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */ + if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP)) + S_SET_EXTERNAL (symbolP); + + obj_symbol_to_chars (where, symbolP); + S_SET_NAME (symbolP, temp); + } +} /* emit_symbols() */ + +void +obj_symbol_new_hook (symbolP) + symbolS *symbolP; +{ + S_SET_OTHER (symbolP, 0); + S_SET_DESC (symbolP, 0); +} + +static void +obj_bout_line (ignore) + int ignore; +{ + /* Assume delimiter is part of expression. */ + /* BSD4.2 as fails with delightful bug, so we */ + /* are not being incompatible here. */ + new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); + demand_empty_rest_of_line (); +} /* obj_bout_line() */ + +void +obj_read_begin_hook () +{ +} + +void +obj_crawl_symbol_chain (headers) + object_headers *headers; +{ + symbolS **symbolPP; + symbolS *symbolP; + int symbol_number = 0; + + tc_crawl_symbol_chain (headers); + + symbolPP = &symbol_rootP; /*->last symbol chain link. */ + while ((symbolP = *symbolPP) != NULL) + { + if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA)) + { + S_SET_SEGMENT (symbolP, SEG_TEXT); + } /* if pusing data into text */ + + resolve_symbol_value (symbolP); + + /* OK, here is how we decide which symbols go out into the + brave new symtab. Symbols that do are: + + * symbols with no name (stabd's?) + * symbols with debug info in their N_TYPE + + Symbols that don't are: + * symbols that are registers + * symbols with \1 as their 3rd character (numeric labels) + * "local labels" as defined by S_LOCAL_NAME(name) + if the -L switch was passed to gas. + + All other symbols are output. We complain if a deleted + symbol was marked external. */ + + + if (1 + && !S_IS_REGISTER (symbolP) + && (!S_GET_NAME (symbolP) + || S_IS_DEBUG (symbolP) +#ifdef TC_I960 + /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */ + || !S_IS_DEFINED (symbolP) + || S_IS_EXTERNAL (symbolP) +#endif /* TC_I960 */ + || (S_GET_NAME (symbolP)[0] != '\001' && (flag_keep_locals || !S_LOCAL_NAME (symbolP))))) + { + symbolP->sy_number = symbol_number++; + + /* The + 1 after strlen account for the \0 at the + end of each string */ + if (!S_IS_STABD (symbolP)) + { + /* Ordinary case. */ + symbolP->sy_name_offset = string_byte_count; + string_byte_count += strlen (S_GET_NAME (symbolP)) + 1; + } + else /* .Stabd case. */ + symbolP->sy_name_offset = 0; + symbolPP = &(symbol_next (symbolP)); + } + else + { + if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP)) + { + as_bad ("Local symbol %s never defined", S_GET_NAME (symbolP)); + } /* oops. */ + + /* Unhook it from the chain */ + *symbolPP = symbol_next (symbolP); + } /* if this symbol should be in the output */ + } /* for each symbol */ + + H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number); +} + +/* + * Find strings by crawling along symbol table chain. + */ + +void +obj_emit_strings (where) + char **where; +{ + symbolS *symbolP; + +#ifdef CROSS_COMPILE + /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ + md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count)); + *where += sizeof (string_byte_count); +#else /* CROSS_COMPILE */ + append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count)); +#endif /* CROSS_COMPILE */ + + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + { + if (S_GET_NAME (symbolP)) + append (where, S_GET_NAME (symbolP), (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); + } /* walk symbol chain */ +} + +/* end of obj-bout.c */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-bout.h b/gnu/usr.bin/binutils/gas/config/obj-bout.h new file mode 100644 index 00000000000..959ab942f8a --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-bout.h @@ -0,0 +1,308 @@ +/* b.out object file format + Copyright (C) 1989, 1990, 1991, 1992 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 2, + 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, Cambridge, MA + 02139, USA. */ + +/* + * This file is a modified version of 'a.out.h'. It is to be used in all GNU + * tools modified to support the i80960 b.out format (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 OBJ_BOUT 1 + +#define OUTPUT_FLAVOR bfd_target_aout_flavour + +#include "targ-cpu.h" + +#define OBJ_DEFAULT_OUTPUT_FILE_NAME "b.out" + +extern const short seg_N_TYPE[]; +extern const segT N_TYPE_seg[]; + +#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 */ + +#ifndef DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE +#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (BMAGIC) +#endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */ + +/* 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 exec + { + /* Standard stuff */ + unsigned long a_magic; /* Identifies this as a b.out file */ + unsigned long a_text; /* Length of text */ + unsigned long a_data; /* Length of data */ + unsigned long a_bss; /* Length of runtime uninitialized data area */ + unsigned long a_syms; /* Length of symbol table */ + unsigned long a_entry; /* Runtime start address */ + unsigned long a_trsize; /* Length of text relocation info */ + unsigned long a_drsize; /* Length of data relocation info */ + + /* Added for i960 */ + unsigned long a_tload; /* Text runtime load address */ + unsigned long 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 */ + unsigned char a_relaxable; /* Contains enough info to relax */ + }; + +#define N_BADMAG(x) (((x).a_magic)!=BMAGIC) +#define N_TXTOFF(x) ( sizeof(struct exec) ) +#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) +#define N_TROFF(x) ( N_DATOFF(x) + (x).a_data ) +#define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize ) +#define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize ) +#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) + +/* 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; + }; + +typedef struct nlist obj_symbol_type; + +/* 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 */ + +#ifndef CUSTOM_RELOC_FORMAT +struct relocation_info + { + int r_address; /* File address of item to be relocated */ + unsigned + r_index:24, /* Index of symbol 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 + * 2 => 4 bytes -- only value used for i960 + */ + 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' */ + nuthin:1; /* Unused */ + }; + +#endif /* CUSTOM_RELOC_FORMAT */ + +/* + * Macros to extract information from a symbol table entry. + * This syntaxic indirection allows independence regarding a.out or coff. + * The argument (s) of all these macros is a pointer to a symbol table entry. + */ + +/* Predicates */ +/* True if the symbol is external */ +#define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT) + +/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */ +#define S_IS_DEFINED(s) ((S_GET_TYPE(s) != N_UNDF) || (S_GET_DESC(s) != 0)) +#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER) + +/* True if a debug special symbol entry */ +#define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB) +/* True if a symbol is local symbol name */ +/* A symbol name whose name begin with ^A is a gas internal pseudo symbol + nameless symbols come from .stab directives. */ +#define S_IS_LOCAL(s) (S_GET_NAME(s) && \ + !S_IS_DEBUG(s) && \ + (S_GET_NAME(s)[0] == '\001' || \ + (S_LOCAL_NAME(s) && !flag_keep_locals))) +/* True if a symbol is not defined in this file */ +#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT) +/* True if the symbol has been generated because of a .stabd directive */ +#define S_IS_STABD(s) (S_GET_NAME(s) == NULL) + +/* Accessors */ +/* The name of the symbol */ +#define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name) +/* The pointer to the string table */ +#define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx) +/* The type of the symbol */ +#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE) +/* The numeric value of the segment */ +#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)]) +/* The n_other expression value */ +#define S_GET_OTHER(s) ((s)->sy_symbol.n_other) +/* The n_desc expression value */ +#define S_GET_DESC(s) ((s)->sy_symbol.n_desc) + +/* Modifiers */ +/* Assume that a symbol cannot be simultaneously in more than on segment */ +/* set segment */ +#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg)) +/* The symbol is external */ +#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT) +/* The symbol is not external */ +#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT) +/* Set the name of the symbol */ +#define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v)) +/* Set the offset in the string table */ +#define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v)) +/* Set the n_other expression value */ +#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v)) +/* Set the n_desc expression value */ +#define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v)) +/* Set the n_type value */ +#define S_SET_TYPE(s,v) ((s)->sy_symbol.n_type = (v)) + +/* File header macro and type definition */ + +#define H_GET_FILE_SIZE(h) (sizeof(struct exec) + \ + H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ + H_GET_SYMBOL_TABLE_SIZE(h) + \ + H_GET_TEXT_RELOCATION_SIZE(h) + \ + H_GET_DATA_RELOCATION_SIZE(h) + \ + (h)->string_table_size) + +#define H_GET_HEADER_SIZE(h) (sizeof(struct exec)) +#define H_GET_TEXT_SIZE(h) ((h)->header.a_text) +#define H_GET_DATA_SIZE(h) ((h)->header.a_data) +#define H_GET_BSS_SIZE(h) ((h)->header.a_bss) +#define H_GET_TEXT_RELOCATION_SIZE(h) ((h)->header.a_trsize) +#define H_GET_DATA_RELOCATION_SIZE(h) ((h)->header.a_drsize) +#define H_GET_SYMBOL_TABLE_SIZE(h) ((h)->header.a_syms) +#define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info) +#define H_GET_ENTRY_POINT(h) ((h)->header.a_entry) +#define H_GET_STRING_SIZE(h) ((h)->string_table_size) +#define H_GET_LINENO_SIZE(h) (0) + +#ifdef EXEC_MACHINE_TYPE +#define H_GET_MACHINE_TYPE(h) ((h)->header.a_machtype) +#endif /* EXEC_MACHINE_TYPE */ +#ifdef EXEC_VERSION +#define H_GET_VERSION(h) ((h)->header.a_version) +#endif /* EXEC_VERSION */ + +#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = (v)) +#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = (v)) +#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = (v)) + +#define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\ + H_SET_DATA_RELOCATION_SIZE((h),(d))) + +#define H_SET_TEXT_RELOCATION_SIZE(h,v) ((h)->header.a_trsize = (v)) +#define H_SET_DATA_RELOCATION_SIZE(h,v) ((h)->header.a_drsize = (v)) +#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * \ + sizeof(struct nlist)) + +#define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_magic = (v)) + +#define H_SET_ENTRY_POINT(h,v) ((h)->header.a_entry = (v)) +#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) +#ifdef EXEC_MACHINE_TYPE +#define H_SET_MACHINE_TYPE(h,v) ((h)->header.a_machtype = (v)) +#endif /* EXEC_MACHINE_TYPE */ +#ifdef EXEC_VERSION +#define H_SET_VERSION(h,v) ((h)->header.a_version = (v)) +#endif /* EXEC_VERSION */ + +typedef struct + { + struct exec header; /* a.out header */ + long string_table_size; /* names + '\0' + sizeof(int) */ + } + +object_headers; + +/* unused hooks. */ +#define OBJ_EMIT_LINENO(a, b, c) {;} +#define obj_pre_write_hook(a) {;} + +#if __STDC__ +struct fix; +#endif +extern void tc_aout_fix_to_chars PARAMS ((char *where, + struct fix *fixP, + relax_addressT segment_address)); +extern void tc_bout_fix_to_chars PARAMS ((char *where, + struct fix *fixP, + relax_addressT segment_address)); + +#define AOUT_STABS + +/* end of obj-bout.h */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-coff.c b/gnu/usr.bin/binutils/gas/config/obj-coff.c new file mode 100644 index 00000000000..2757bb69d04 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-coff.c @@ -0,0 +1,4070 @@ +/* coff object file format + Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. + + This file is part of GAS. + + 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 2, 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. */ + +#include "as.h" +#include "obstack.h" +#include "subsegs.h" + +/* I think this is probably always correct. */ +#ifndef KEEP_RELOC_INFO +#define KEEP_RELOC_INFO +#endif + + +/* structure used to keep the filenames which + are too long around so that we can stick them + into the string table */ +struct filename_list +{ + char *filename; + struct filename_list *next; +}; + +static struct filename_list *filename_list_head; +static struct filename_list *filename_list_tail; + +const char *s_get_name PARAMS ((symbolS * s)); +static symbolS *def_symbol_in_progress; + + +/* stack stuff */ +typedef struct + { + unsigned long chunk_size; + unsigned long element_size; + unsigned long size; + char *data; + unsigned long pointer; + } +stack; + +static stack * +stack_init (chunk_size, element_size) + unsigned long chunk_size; + unsigned long element_size; +{ + stack *st; + + st = (stack *) malloc (sizeof (stack)); + if (!st) + return 0; + st->data = malloc (chunk_size); + if (!st->data) + { + free (st); + return 0; + } + st->pointer = 0; + st->size = chunk_size; + st->chunk_size = chunk_size; + st->element_size = element_size; + return st; +} + +#if 0 +/* Not currently used. */ +static void +stack_delete (st) + stack *st; +{ + free (st->data); + free (st); +} +#endif + +static char * +stack_push (st, element) + stack *st; + char *element; +{ + if (st->pointer + st->element_size >= st->size) + { + st->size += st->chunk_size; + if ((st->data = xrealloc (st->data, st->size)) == (char *) 0) + return (char *) 0; + } + memcpy (st->data + st->pointer, element, st->element_size); + st->pointer += st->element_size; + return st->data + st->pointer; +} + +static char * +stack_pop (st) + stack *st; +{ + if (st->pointer < st->element_size) + { + st->pointer = 0; + return (char *) 0; + } + st->pointer -= st->element_size; + return st->data + st->pointer; +} + +/* + * Maintain a list of the tagnames of the structres. + */ + +static struct hash_control *tag_hash; + +static void +tag_init () +{ + tag_hash = hash_new (); +} + +static void +tag_insert (name, symbolP) + const char *name; + symbolS *symbolP; +{ + const char *error_string; + + if ((error_string = hash_jam (tag_hash, name, (char *) symbolP))) + { + as_fatal ("Inserting \"%s\" into structure table failed: %s", + name, error_string); + } +} + +static symbolS * +tag_find (name) + char *name; +{ +#ifdef STRIP_UNDERSCORE + if (*name == '_') + name++; +#endif /* STRIP_UNDERSCORE */ + return (symbolS *) hash_find (tag_hash, name); +} + +static symbolS * +tag_find_or_make (name) + char *name; +{ + symbolS *symbolP; + + if ((symbolP = tag_find (name)) == NULL) + { + symbolP = symbol_new (name, undefined_section, + 0, &zero_address_frag); + + tag_insert (S_GET_NAME (symbolP), symbolP); +#ifdef BFD_ASSEMBLER + symbol_table_insert (symbolP); +#endif + } /* not found */ + + return symbolP; +} + + + +#ifdef BFD_ASSEMBLER + +static void SA_SET_SYM_TAGNDX PARAMS ((symbolS *, symbolS *)); + +#define GET_FILENAME_STRING(X) \ +((char*)(&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1]) + +/* @@ Ick. */ +static segT +fetch_coff_debug_section () +{ + static segT debug_section; + if (!debug_section) + { + CONST asymbol *s; + s = bfd_make_debug_symbol (stdoutput, (char *) 0, 0); + assert (s != 0); + debug_section = s->section; + } + return debug_section; +} + +void +SA_SET_SYM_ENDNDX (sym, val) + symbolS *sym; + symbolS *val; +{ + combined_entry_type *entry, *p; + + entry = &coffsymbol (sym->bsym)->native[1]; + p = coffsymbol (val->bsym)->native; + entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p; + entry->fix_end = 1; +} + +static void +SA_SET_SYM_TAGNDX (sym, val) + symbolS *sym; + symbolS *val; +{ + combined_entry_type *entry, *p; + + entry = &coffsymbol (sym->bsym)->native[1]; + p = coffsymbol (val->bsym)->native; + entry->u.auxent.x_sym.x_tagndx.p = p; + entry->fix_tag = 1; +} + +static int +S_GET_DATA_TYPE (sym) + symbolS *sym; +{ + return coffsymbol (sym->bsym)->native->u.syment.n_type; +} + +int +S_SET_DATA_TYPE (sym, val) + symbolS *sym; + int val; +{ + coffsymbol (sym->bsym)->native->u.syment.n_type = val; + return val; +} + +int +S_GET_STORAGE_CLASS (sym) + symbolS *sym; +{ + return coffsymbol (sym->bsym)->native->u.syment.n_sclass; +} + +int +S_SET_STORAGE_CLASS (sym, val) + symbolS *sym; + int val; +{ + coffsymbol (sym->bsym)->native->u.syment.n_sclass = val; + return val; +} + +/* Merge a debug symbol containing debug information into a normal symbol. */ + +void +c_symbol_merge (debug, normal) + symbolS *debug; + symbolS *normal; +{ + S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug)); + S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug)); + + if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal)) + /* take the most we have */ + S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug)); + + if (S_GET_NUMBER_AUXILIARY (debug) > 0) + { + /* Move all the auxiliary information. */ + /* @@ How many fields do we want to preserve? Would it make more + sense to pick and choose those we want to copy? Should look + into this further.... [raeburn:19920512.2209EST] */ + alent *linenos; + linenos = coffsymbol (normal->bsym)->lineno; + memcpy ((char *) &coffsymbol (normal->bsym)->native, + (char *) &coffsymbol (debug->bsym)->native, + S_GET_NUMBER_AUXILIARY(debug) * AUXESZ); + coffsymbol (normal->bsym)->lineno = linenos; + } + + /* Move the debug flags. */ + SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug)); +} + +static symbolS *previous_file_symbol; +void +c_dot_file_symbol (filename) + char *filename; +{ + symbolS *symbolP; + + symbolP = symbol_new (filename, bfd_abs_section_ptr, 0, &zero_address_frag); + + S_SET_STORAGE_CLASS (symbolP, C_FILE); + S_SET_NUMBER_AUXILIARY (symbolP, 1); + + symbolP->bsym->flags = BSF_DEBUGGING; + +#ifndef NO_LISTING + { + extern int listing; + if (listing) + { + listing_source_file (filename); + } + } +#endif + + S_SET_VALUE (symbolP, (long) previous_file_symbol); + + previous_file_symbol = symbolP; + + /* Make sure that the symbol is first on the symbol chain */ + if (symbol_rootP != symbolP) + { + if (symbolP == symbol_lastP) + { + symbol_lastP = symbol_lastP->sy_previous; + } /* if it was the last thing on the list */ + + symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); + symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP); + symbol_rootP = symbolP; + } /* if not first on the list */ +} + +/* + * Build a 'section static' symbol. + */ + +char * +c_section_symbol (name, value, length, nreloc, nlnno) + char *name; + long value; + long length; + unsigned short nreloc; + unsigned short nlnno; +{ + symbolS *symbolP; + + symbolP = symbol_new (name, + (name[1] == 't' + ? text_section + : name[1] == 'd' + ? data_section + : bss_section), + value, + &zero_address_frag); + + S_SET_STORAGE_CLASS (symbolP, C_STAT); + S_SET_NUMBER_AUXILIARY (symbolP, 1); + + SA_SET_SCN_SCNLEN (symbolP, length); + SA_SET_SCN_NRELOC (symbolP, nreloc); + SA_SET_SCN_NLINNO (symbolP, nlnno); + + SF_SET_STATICS (symbolP); + + return (char *) symbolP; +} + +/* Line number handling */ + +struct line_no { + struct line_no *next; + fragS *frag; + alent l; +}; + +int coff_line_base; + +/* Symbol of last function, which we should hang line#s off of. */ +static symbolS *line_fsym; + +#define in_function() (line_fsym != 0) +#define clear_function() (line_fsym = 0) +#define set_function(F) (line_fsym = (F), coff_add_linesym (F)) + + +void +obj_symbol_new_hook (symbolP) + symbolS *symbolP; +{ + char underscore = 0; /* Symbol has leading _ */ + + { + long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type); + char *s = (char *) bfd_alloc_by_size_t (stdoutput, sz); + memset (s, 0, sz); + coffsymbol (symbolP->bsym)->native = (combined_entry_type *) s; + } + S_SET_DATA_TYPE (symbolP, T_NULL); + S_SET_STORAGE_CLASS (symbolP, 0); + S_SET_NUMBER_AUXILIARY (symbolP, 0); + + if (S_IS_STRING (symbolP)) + SF_SET_STRING (symbolP); + if (!underscore && S_IS_LOCAL (symbolP)) + SF_SET_LOCAL (symbolP); +} + + +/* + * Handle .ln directives. + */ + +static symbolS *current_lineno_sym; +static struct line_no *line_nos; +/* @@ Blindly assume all .ln directives will be in the .text section... */ +int coff_n_line_nos; + +static void +add_lineno (frag, offset, num) + fragS *frag; + int offset; + int num; +{ + struct line_no *new_line = (struct line_no *) bfd_alloc_by_size_t (stdoutput, + sizeof (struct line_no)); + if (!current_lineno_sym) + { + abort (); + } + new_line->next = line_nos; + new_line->frag = frag; + new_line->l.line_number = num; + new_line->l.u.offset = offset; + line_nos = new_line; + coff_n_line_nos++; +} + +void +coff_add_linesym (sym) + symbolS *sym; +{ + if (line_nos) + { + coffsymbol (current_lineno_sym->bsym)->lineno = (alent *) line_nos; + coff_n_line_nos++; + line_nos = 0; + } + current_lineno_sym = sym; +} + +static void +obj_coff_ln (appline) + int appline; +{ + int l; + + if (! appline && def_symbol_in_progress != NULL) + { + as_warn (".ln pseudo-op inside .def/.endef: ignored."); + demand_empty_rest_of_line (); + return; + } + + l = get_absolute_expression (); + if (!appline) + { + add_lineno (frag_now, frag_now_fix (), l); + } + +#ifndef NO_LISTING + { + extern int listing; + + if (listing) + { + if (! appline) + l += coff_line_base - 1; + listing_source_line (l); + } + } +#endif + + demand_empty_rest_of_line (); +} + +/* + * def() + * + * Handle .def directives. + * + * One might ask : why can't we symbol_new if the symbol does not + * already exist and fill it with debug information. Because of + * the C_EFCN special symbol. It would clobber the value of the + * function symbol before we have a chance to notice that it is + * a C_EFCN. And a second reason is that the code is more clear this + * way. (at least I think it is :-). + * + */ + +#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';') +#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ + *input_line_pointer == '\t') \ + input_line_pointer++; + +static void +obj_coff_def (what) + int what; +{ + char name_end; /* Char after the end of name */ + char *symbol_name; /* Name of the debug symbol */ + char *symbol_name_copy; /* Temporary copy of the name */ + unsigned int symbol_name_length; + + if (def_symbol_in_progress != NULL) + { + as_warn (".def pseudo-op used inside of .def/.endef: ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + SKIP_WHITESPACES (); + + symbol_name = input_line_pointer; +#ifdef STRIP_UNDERSCORE + if (symbol_name[0] == '_' && symbol_name[1] != 0) + symbol_name++; +#endif /* STRIP_UNDERSCORE */ + + name_end = get_symbol_end (); + symbol_name_length = strlen (symbol_name); + symbol_name_copy = xmalloc (symbol_name_length + 1); + strcpy (symbol_name_copy, symbol_name); + + /* Initialize the new symbol */ + def_symbol_in_progress = symbol_make (symbol_name_copy); + def_symbol_in_progress->sy_frag = &zero_address_frag; + S_SET_VALUE (def_symbol_in_progress, 0); + + if (S_IS_STRING (def_symbol_in_progress)) + SF_SET_STRING (def_symbol_in_progress); + + *input_line_pointer = name_end; + + demand_empty_rest_of_line (); +} + +unsigned int dim_index; + +static void +obj_coff_endef (ignore) + int ignore; +{ + symbolS *symbolP; + /* DIM BUG FIX sac@cygnus.com */ + dim_index = 0; + if (def_symbol_in_progress == NULL) + { + as_warn (".endef pseudo-op used outside of .def/.endef: ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + /* Set the section number according to storage class. */ + switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) + { + case C_STRTAG: + case C_ENTAG: + case C_UNTAG: + SF_SET_TAG (def_symbol_in_progress); + /* intentional fallthrough */ + case C_FILE: + case C_TPDEF: + SF_SET_DEBUG (def_symbol_in_progress); + S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ()); + break; + + case C_EFCN: + SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ + /* intentional fallthrough */ + case C_BLOCK: + SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */ + /* intentional fallthrough */ + case C_FCN: + { + CONST char *name; + S_SET_SEGMENT (def_symbol_in_progress, text_section); + + name = bfd_asymbol_name (def_symbol_in_progress->bsym); + if (name[1] == 'b' && name[2] == 'f') + { + if (! in_function ()) + as_warn ("`%s' symbol without preceding function", name); +/* SA_SET_SYM_LNNO (def_symbol_in_progress, 12345);*/ + /* Will need relocating */ + SF_SET_PROCESS (def_symbol_in_progress); + clear_function (); + } + } + break; + +#ifdef C_AUTOARG + case C_AUTOARG: +#endif /* C_AUTOARG */ + case C_AUTO: + case C_REG: + case C_MOS: + case C_MOE: + case C_MOU: + case C_ARG: + case C_REGPARM: + case C_FIELD: + case C_EOS: + SF_SET_DEBUG (def_symbol_in_progress); + S_SET_SEGMENT (def_symbol_in_progress, absolute_section); + break; + + case C_EXT: + case C_STAT: + case C_LABEL: + /* Valid but set somewhere else (s_comm, s_lcomm, colon) */ + break; + + case C_USTATIC: + case C_EXTDEF: + case C_ULABEL: + as_warn ("unexpected storage class %d", + S_GET_STORAGE_CLASS (def_symbol_in_progress)); + break; + } /* switch on storage class */ + + /* Now that we have built a debug symbol, try to find if we should + merge with an existing symbol or not. If a symbol is C_EFCN or + SEG_ABSOLUTE or untagged SEG_DEBUG it never merges. */ + + /* Two cases for functions. Either debug followed by definition or + definition followed by debug. For definition first, we will + merge the debug symbol into the definition. For debug first, the + lineno entry MUST point to the definition function or else it + will point off into space when obj_crawl_symbol_chain() merges + the debug symbol into the real symbol. Therefor, let's presume + the debug symbol is a real function reference. */ + + /* FIXME-SOON If for some reason the definition label/symbol is + never seen, this will probably leave an undefined symbol at link + time. */ + + if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN + || (!strcmp (bfd_get_section_name (stdoutput, + S_GET_SEGMENT (def_symbol_in_progress)), + "*DEBUG*") + && !SF_GET_TAG (def_symbol_in_progress)) + || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section + || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL) + { + if (def_symbol_in_progress != symbol_lastP) + symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, + &symbol_lastP); + } + else + { + /* This symbol already exists, merge the newly created symbol + into the old one. This is not mandatory. The linker can + handle duplicate symbols correctly. But I guess that it save + a *lot* of space if the assembly file defines a lot of + symbols. [loic] */ + + /* The debug entry (def_symbol_in_progress) is merged into the + previous definition. */ + + c_symbol_merge (def_symbol_in_progress, symbolP); + /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */ + def_symbol_in_progress = symbolP; + + if (SF_GET_FUNCTION (def_symbol_in_progress) + || SF_GET_TAG (def_symbol_in_progress)) + { + /* For functions, and tags, the symbol *must* be where the + debug symbol appears. Move the existing symbol to the + current place. */ + /* If it already is at the end of the symbol list, do nothing */ + if (def_symbol_in_progress != symbol_lastP) + { + symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); + symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); + } + } + } + + if (SF_GET_TAG (def_symbol_in_progress) + && symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL) + { + tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress); + } + + if (SF_GET_FUNCTION (def_symbol_in_progress)) + { + know (sizeof (def_symbol_in_progress) <= sizeof (long)); + set_function (def_symbol_in_progress); + SF_SET_PROCESS (def_symbol_in_progress); + + if (symbolP == NULL) + { + /* That is, if this is the first time we've seen the + function... */ + symbol_table_insert (def_symbol_in_progress); + } /* definition follows debug */ + } /* Create the line number entry pointing to the function being defined */ + + def_symbol_in_progress = NULL; + demand_empty_rest_of_line (); +} + +static void +obj_coff_dim (ignore) + int ignore; +{ + int dim_index; + + if (def_symbol_in_progress == NULL) + { + as_warn (".dim pseudo-op used outside of .def/.endef: ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); + + for (dim_index = 0; dim_index < DIMNUM; dim_index++) + { + SKIP_WHITESPACES (); + SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index, + get_absolute_expression ()); + + switch (*input_line_pointer) + { + case ',': + input_line_pointer++; + break; + + default: + as_warn ("badly formed .dim directive ignored"); + /* intentional fallthrough */ + case '\n': + case ';': + dim_index = DIMNUM; + break; + } + } + + demand_empty_rest_of_line (); +} + +static void +obj_coff_line (ignore) + int ignore; +{ + int this_base; + + if (def_symbol_in_progress == NULL) + { + /* Probably stabs-style line? */ + obj_coff_ln (0); + return; + } + + this_base = get_absolute_expression (); + if (!strcmp (".bf", S_GET_NAME (def_symbol_in_progress))) + coff_line_base = this_base; + + S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); + SA_SET_SYM_LNNO (def_symbol_in_progress, coff_line_base); + + demand_empty_rest_of_line (); + +#ifndef NO_LISTING + if (strcmp (".bf", S_GET_NAME (def_symbol_in_progress)) == 0) + { + extern int listing; + + if (listing) + listing_source_line ((unsigned int) coff_line_base); + } +#endif +} + +static void +obj_coff_size (ignore) + int ignore; +{ + if (def_symbol_in_progress == NULL) + { + as_warn (".size pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); + SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ()); + demand_empty_rest_of_line (); +} + +static void +obj_coff_scl (ignore) + int ignore; +{ + if (def_symbol_in_progress == NULL) + { + as_warn (".scl pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ()); + demand_empty_rest_of_line (); +} + +static void +obj_coff_tag (ignore) + int ignore; +{ + char *symbol_name; + char name_end; + + if (def_symbol_in_progress == NULL) + { + as_warn (".tag pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } + + S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); + symbol_name = input_line_pointer; + name_end = get_symbol_end (); + + /* Assume that the symbol referred to by .tag is always defined. + This was a bad assumption. I've added find_or_make. xoxorich. */ + SA_SET_SYM_TAGNDX (def_symbol_in_progress, + tag_find_or_make (symbol_name)); + if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L) + { + as_warn ("tag not found for .tag %s", symbol_name); + } /* not defined */ + + SF_SET_TAGGED (def_symbol_in_progress); + *input_line_pointer = name_end; + + demand_empty_rest_of_line (); +} + +static void +obj_coff_type (ignore) + int ignore; +{ + if (def_symbol_in_progress == NULL) + { + as_warn (".type pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ()); + + if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) && + S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF) + { + SF_SET_FUNCTION (def_symbol_in_progress); + } /* is a function */ + + demand_empty_rest_of_line (); +} + +static void +obj_coff_val (ignore) + int ignore; +{ + if (def_symbol_in_progress == NULL) + { + as_warn (".val pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + if (is_name_beginner (*input_line_pointer)) + { + char *symbol_name = input_line_pointer; + char name_end = get_symbol_end (); + + if (!strcmp (symbol_name, ".")) + { + def_symbol_in_progress->sy_frag = frag_now; + S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); + /* If the .val is != from the .def (e.g. statics) */ + } + else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) + { + def_symbol_in_progress->sy_value.X_op = O_symbol; + def_symbol_in_progress->sy_value.X_add_symbol = + symbol_find_or_make (symbol_name); + def_symbol_in_progress->sy_value.X_op_symbol = NULL; + def_symbol_in_progress->sy_value.X_add_number = 0; + + /* If the segment is undefined when the forward reference is + resolved, then copy the segment id from the forward + symbol. */ + SF_SET_GET_SEGMENT (def_symbol_in_progress); + } + /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */ + *input_line_pointer = name_end; + } + else + { + S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ()); + } /* if symbol based */ + + demand_empty_rest_of_line (); +} + +void +obj_read_begin_hook () +{ + /* These had better be the same. Usually 18 bytes. */ +#ifndef BFD_HEADERS + know (sizeof (SYMENT) == sizeof (AUXENT)); + know (SYMESZ == AUXESZ); +#endif + tag_init (); +} + + +symbolS *coff_last_function; + +void +coff_frob_symbol (symp, punt) + symbolS *symp; + int *punt; +{ + static symbolS *last_tagP; + static stack *block_stack; + static symbolS *set_end; + symbolS *next_set_end = NULL; + + if (symp == &abs_symbol) + { + *punt = 1; + return; + } + + if (current_lineno_sym) + coff_add_linesym ((symbolS *) 0); + + if (!block_stack) + block_stack = stack_init (512, sizeof (symbolS*)); + + if (!S_IS_DEFINED (symp) && S_GET_STORAGE_CLASS (symp) != C_STAT) + S_SET_STORAGE_CLASS (symp, C_EXT); + + if (!SF_GET_DEBUG (symp)) + { + symbolS *real; + if (!SF_GET_LOCAL (symp) + && (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP)) + && real != symp) + { + c_symbol_merge (symp, real); + *punt = 1; + } + if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp)) + { + assert (S_GET_VALUE (symp) == 0); + S_SET_EXTERNAL (symp); + } + else if (S_GET_STORAGE_CLASS (symp) == C_NULL) + { + if (S_GET_SEGMENT (symp) == text_section + && symp != seg_info (text_section)->sym) + S_SET_STORAGE_CLASS (symp, C_LABEL); + else + S_SET_STORAGE_CLASS (symp, C_STAT); + } + if (SF_GET_PROCESS (symp)) + { + if (S_GET_STORAGE_CLASS (symp) == C_BLOCK) + { + if (!strcmp (S_GET_NAME (symp), ".bb")) + stack_push (block_stack, (char *) &symp); + else + { + symbolS *begin; + begin = *(symbolS **) stack_pop (block_stack); + if (begin == 0) + as_warn ("mismatched .eb"); + else + next_set_end = begin; + } + } + if (coff_last_function == 0 && SF_GET_FUNCTION (symp)) + { + union internal_auxent *auxp; + coff_last_function = symp; + if (S_GET_NUMBER_AUXILIARY (symp) < 1) + S_SET_NUMBER_AUXILIARY (symp, 1); + auxp = &coffsymbol (symp->bsym)->native[1].u.auxent; + memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0, + sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen)); + } + if (S_GET_STORAGE_CLASS (symp) == C_EFCN) + { + if (coff_last_function == 0) + as_fatal ("C_EFCN symbol out of scope"); + SA_SET_SYM_FSIZE (coff_last_function, + (long) (S_GET_VALUE (symp) + - S_GET_VALUE (coff_last_function))); + next_set_end = coff_last_function; + coff_last_function = 0; + } + } + else if (SF_GET_TAG (symp)) + last_tagP = symp; + else if (S_GET_STORAGE_CLASS (symp) == C_EOS) + next_set_end = last_tagP; + else if (S_GET_STORAGE_CLASS (symp) == C_FILE) + { + if (S_GET_VALUE (symp)) + { + S_SET_VALUE ((symbolS *) S_GET_VALUE (symp), 0xdeadbeef); + S_SET_VALUE (symp, 0); + } + } + if (S_IS_EXTERNAL (symp)) + S_SET_STORAGE_CLASS (symp, C_EXT); + else if (SF_GET_LOCAL (symp)) + *punt = 1; + + if (SF_GET_FUNCTION (symp)) + symp->bsym->flags |= BSF_FUNCTION; + + /* more ... */ + } + +#ifdef OBJ_XCOFF + /* This is pretty horrible, but we have to set *punt correctly in + order to call SA_SET_SYM_ENDNDX correctly. */ + if (! symp->sy_used_in_reloc + && ((symp->bsym->flags & BSF_SECTION_SYM) != 0 + || (! S_IS_EXTERNAL (symp) + && ! symp->sy_tc.output + && S_GET_STORAGE_CLASS (symp) != C_FILE))) + *punt = 1; +#endif + + if (set_end != (symbolS *) NULL + && ! *punt) + { + SA_SET_SYM_ENDNDX (set_end, symp); + set_end = NULL; + } + + if (next_set_end != NULL + && ! *punt) + set_end = next_set_end; + + if (coffsymbol (symp->bsym)->lineno) + { + int i; + struct line_no *lptr; + alent *l; + + lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno; + for (i = 0; lptr; lptr = lptr->next) + i++; + lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno; + + /* We need i entries for line numbers, plus 1 for the first + entry which BFD will override, plus 1 for the last zero + entry (a marker for BFD). */ + l = (alent *) bfd_alloc_by_size_t (stdoutput, (i + 2) * sizeof (alent)); + coffsymbol (symp->bsym)->lineno = l; + l[i + 1].line_number = 0; + l[i + 1].u.sym = NULL; + for (; i > 0; i--) + { + if (lptr->frag) + lptr->l.u.offset += lptr->frag->fr_address; + l[i] = lptr->l; + lptr = lptr->next; + } + } +} + +void +coff_adjust_section_syms (abfd, sec, x) + bfd *abfd; + asection *sec; + PTR x; +{ + symbolS *secsym; + segment_info_type *seginfo = seg_info (sec); + int nlnno, nrelocs = 0; + + /* RS/6000 gas creates a .debug section manually in ppc_frob_file in + tc-ppc.c. Do not get confused by it. */ + if (seginfo == NULL) + return; + + if (!strcmp (sec->name, ".text")) + nlnno = coff_n_line_nos; + else + nlnno = 0; + { + /* @@ Hope that none of the fixups expand to more than one reloc + entry... */ + fixS *fixp = seginfo->fix_root; + while (fixp) + { + fixp = fixp->fx_next; + nrelocs++; + } + } + if (bfd_get_section_size_before_reloc (sec) == 0 + && nrelocs == 0 && nlnno == 0) + return; + secsym = section_symbol (sec); + SA_SET_SCN_NRELOC (secsym, nrelocs); + SA_SET_SCN_NLINNO (secsym, nlnno); +} + +void +coff_frob_file () +{ + bfd_map_over_sections (stdoutput, coff_adjust_section_syms, (char*) 0); +} + +/* + * implement the .section pseudo op: + * .section name {, "flags"} + * ^ ^ + * | +--- optional flags: 'b' for bss + * | 'i' for info + * +-- section name 'l' for lib + * 'n' for noload + * 'o' for over + * 'w' for data + * 'd' (apparently m88k for data) + * 'x' for text + * But if the argument is not a quoted string, treat it as a + * subsegment number. + */ + +void +obj_coff_section (ignore) + int ignore; +{ + /* Strip out the section name */ + char *section_name; + char c; + char *name; + unsigned int exp; + flagword flags; + asection *sec; + + if (flag_mri) + { + char type; + + s_mri_sect (&type); + return; + } + + section_name = input_line_pointer; + c = get_symbol_end (); + + name = xmalloc (input_line_pointer - section_name + 1); + strcpy (name, section_name); + + *input_line_pointer = c; + + SKIP_WHITESPACE (); + + exp = 0; + flags = SEC_NO_FLAGS; + + if (*input_line_pointer == ',') + { + ++input_line_pointer; + SKIP_WHITESPACE (); + if (*input_line_pointer != '"') + exp = get_absolute_expression (); + else + { + ++input_line_pointer; + while (*input_line_pointer != '"' + && ! is_end_of_line[(unsigned char) *input_line_pointer]) + { + switch (*input_line_pointer) + { + case 'b': flags |= SEC_ALLOC; flags &=~ SEC_LOAD; break; + case 'n': flags &=~ SEC_LOAD; break; + case 'd': + case 'w': flags &=~ SEC_READONLY; break; + case 'x': flags |= SEC_CODE; break; + + case 'i': /* STYP_INFO */ + case 'l': /* STYP_LIB */ + case 'o': /* STYP_OVER */ + as_warn ("unsupported section attribute '%c'", + *input_line_pointer); + break; + + default: + as_warn("unknown section attribute '%c'", + *input_line_pointer); + break; + } + ++input_line_pointer; + } + if (*input_line_pointer == '"') + ++input_line_pointer; + } + } + + sec = subseg_new (name, (subsegT) exp); + + if (flags != SEC_NO_FLAGS) + { + if (! bfd_set_section_flags (stdoutput, sec, flags)) + as_warn ("error setting flags for \"%s\": %s", + bfd_section_name (stdoutput, sec), + bfd_errmsg (bfd_get_error ())); + } +} + +void +coff_adjust_symtab () +{ + if (symbol_rootP == NULL + || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) + { + assert (previous_file_symbol == 0); + c_dot_file_symbol ("fake"); + } +} + +void +coff_frob_section (sec) + segT sec; +{ + segT strsec; + char *strname, *p; + fragS *fragp; + bfd_vma size, n_entries, mask; + + /* The COFF back end in BFD requires that all section sizes be + rounded up to multiples of the corresponding section alignments. + Seems kinda silly to me, but that's the way it is. */ + size = bfd_get_section_size_before_reloc (sec); + mask = ((bfd_vma) 1 << (bfd_vma) sec->alignment_power) - 1; + if (size & mask) + { + size = (size + mask) & ~mask; + bfd_set_section_size (stdoutput, sec, size); + } + + /* If the section size is non-zero, the section symbol needs an aux + entry associated with it, indicating the size. We don't know + all the values yet; coff_frob_symbol will fill them in later. */ + if (size) + { + symbolS *secsym = section_symbol (sec); + + S_SET_STORAGE_CLASS (secsym, C_STAT); + S_SET_NUMBER_AUXILIARY (secsym, 1); + SF_SET_STATICS (secsym); + SA_SET_SCN_SCNLEN (secsym, size); + } + + /* @@ these should be in a "stabs.h" file, or maybe as.h */ +#ifndef STAB_SECTION_NAME +#define STAB_SECTION_NAME ".stab" +#endif +#ifndef STAB_STRING_SECTION_NAME +#define STAB_STRING_SECTION_NAME ".stabstr" +#endif + if (strcmp (STAB_STRING_SECTION_NAME, sec->name)) + return; + + strsec = sec; + sec = subseg_get (STAB_SECTION_NAME, 0); + /* size is already rounded up, since other section will be listed first */ + size = bfd_get_section_size_before_reloc (strsec); + + n_entries = bfd_get_section_size_before_reloc (sec) / 12 - 1; + + /* Find first non-empty frag. It should be large enough. */ + fragp = seg_info (sec)->frchainP->frch_root; + while (fragp && fragp->fr_fix == 0) + fragp = fragp->fr_next; + assert (fragp != 0 && fragp->fr_fix >= 12); + + /* Store the values. */ + p = fragp->fr_literal; + bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6); + bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8); +} + +void +obj_coff_init_stab_section (seg) + segT seg; +{ + char *file; + char *p; + char *stabstr_name; + unsigned int stroff; + + /* Make space for this first symbol. */ + p = frag_more (12); + /* Zero it out. */ + memset (p, 0, 12); + as_where (&file, (unsigned int *) NULL); + stabstr_name = (char *) alloca (strlen (seg->name) + 4); + strcpy (stabstr_name, seg->name); + strcat (stabstr_name, "str"); + stroff = get_stab_string_offset (file, stabstr_name); + know (stroff == 1); + md_number_to_chars (p, stroff, 4); +} + +#ifdef DEBUG +/* for debugging */ +const char * +s_get_name (s) + symbolS *s; +{ + return ((s == NULL) ? "(NULL)" : S_GET_NAME (s)); +} + +void +symbol_dump () +{ + symbolS *symbolP; + + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + { + printf("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n", + (unsigned long) symbolP, + S_GET_NAME(symbolP), + (long) S_GET_DATA_TYPE(symbolP), + S_GET_STORAGE_CLASS(symbolP), + (int) S_GET_SEGMENT(symbolP)); + } +} + +#endif /* DEBUG */ + +#else /* not BFD_ASSEMBLER */ + +#include "frags.h" +/* This is needed because we include internal bfd things. */ +#include + +#include "libbfd.h" +#include "libcoff.h" + +/* The NOP_OPCODE is for the alignment fill value. Fill with nop so + that we can stick sections together without causing trouble. */ +#ifndef NOP_OPCODE +#define NOP_OPCODE 0x00 +#endif + +/* The zeroes if symbol name is longer than 8 chars */ +#define S_SET_ZEROES(s,v) ((s)->sy_symbol.ost_entry.n_zeroes = (v)) + +#define MIN(a,b) ((a) < (b)? (a) : (b)) +/* This vector is used to turn an internal segment into a section # + suitable for insertion into a coff symbol table + */ + +const short seg_N_TYPE[] = +{ /* in: segT out: N_TYPE bits */ + C_ABS_SECTION, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + C_UNDEF_SECTION, /* SEG_UNKNOWN */ + C_UNDEF_SECTION, /* SEG_GOOF */ + C_UNDEF_SECTION, /* SEG_EXPR */ + C_DEBUG_SECTION, /* SEG_DEBUG */ + C_NTV_SECTION, /* SEG_NTV */ + C_PTV_SECTION, /* SEG_PTV */ + C_REGISTER_SECTION, /* SEG_REGISTER */ +}; + +int function_lineoff = -1; /* Offset in line#s where the last function + started (the odd entry for line #0) */ + +static symbolS *last_line_symbol; + +/* Add 4 to the real value to get the index and compensate the + negatives. This vector is used by S_GET_SEGMENT to turn a coff + section number into a segment number +*/ +static symbolS *previous_file_symbol; +void c_symbol_merge (); +static int line_base; + +symbolS *c_section_symbol (); +bfd *abfd; + +static void fixup_segment PARAMS ((segment_info_type *segP, + segT this_segment_type)); + + +static void fixup_mdeps PARAMS ((fragS *, + object_headers *, + segT)); + + +static void fill_section PARAMS ((bfd * abfd, + object_headers *, + unsigned long *)); + + +static int c_line_new PARAMS ((symbolS * symbol, long paddr, + int line_number, + fragS * frag)); + + +static void w_symbols PARAMS ((bfd * abfd, char *where, + symbolS * symbol_rootP)); + +static void adjust_stab_section PARAMS ((bfd *abfd, segT seg)); + +static void obj_coff_lcomm PARAMS ((int)); +static void obj_coff_text PARAMS ((int)); +static void obj_coff_data PARAMS ((int)); +static void obj_coff_bss PARAMS ((int)); +static void obj_coff_ident PARAMS ((int)); +void obj_coff_section PARAMS ((int)); + +/* Section stuff + + We allow more than just the standard 3 sections, infact, we allow + 10 sections, (though the usual three have to be there). + + This structure performs the mappings for us: + +*/ + +#define N_SEG 32 +typedef struct +{ + segT seg_t; + int i; +} seg_info_type; + +static const seg_info_type seg_info_off_by_4[N_SEG] = +{ + {SEG_PTV, }, + {SEG_NTV, }, + {SEG_DEBUG, }, + {SEG_ABSOLUTE, }, + {SEG_UNKNOWN, }, + {SEG_E0}, + {SEG_E1}, + {SEG_E2}, + {SEG_E3}, + {SEG_E4}, + {SEG_E5}, + {SEG_E6}, + {SEG_E7}, + {SEG_E8}, + {SEG_E9}, + {(segT)15}, + {(segT)16}, + {(segT)17}, + {(segT)18}, + {(segT)19}, + {(segT)20}, + {(segT)0}, + {(segT)0}, + {(segT)0}, + {SEG_REGISTER} +}; + + + +#define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4]) + +static relax_addressT +relax_align (address, alignment) + relax_addressT address; + long alignment; +{ + relax_addressT mask; + relax_addressT new_address; + + mask = ~((~0) << alignment); + new_address = (address + mask) & (~mask); + return (new_address - address); +} + + +segT +s_get_segment (x) + symbolS * x; +{ + return SEG_INFO_FROM_SECTION_NUMBER (x->sy_symbol.ost_entry.n_scnum).seg_t; +} + + + +/* calculate the size of the frag chain and fill in the section header + to contain all of it, also fill in the addr of the sections */ +static unsigned int +size_section (abfd, idx) + bfd * abfd; + unsigned int idx; +{ + + unsigned int size = 0; + fragS *frag = segment_info[idx].frchainP->frch_root; + while (frag) + { + size = frag->fr_address; + if (frag->fr_address != size) + { + fprintf (stderr, "Out of step\n"); + size = frag->fr_address; + } + + switch (frag->fr_type) + { +#ifdef TC_COFF_SIZEMACHDEP + case rs_machine_dependent: + size += TC_COFF_SIZEMACHDEP (frag); + break; +#endif + case rs_space: + assert (frag->fr_symbol == 0); + case rs_fill: + case rs_org: + size += frag->fr_fix; + size += frag->fr_offset * frag->fr_var; + break; + case rs_align: + size += frag->fr_fix; + size += relax_align (size, frag->fr_offset); + break; + default: + BAD_CASE (frag->fr_type); + break; + } + frag = frag->fr_next; + } + segment_info[idx].scnhdr.s_size = size; + return size; +} + + +static unsigned int +count_entries_in_chain (idx) + unsigned int idx; +{ + unsigned int nrelocs; + fixS *fixup_ptr; + + /* Count the relocations */ + fixup_ptr = segment_info[idx].fix_root; + nrelocs = 0; + while (fixup_ptr != (fixS *) NULL) + { + if (TC_COUNT_RELOC (fixup_ptr)) + { +#ifdef TC_A29K + if (fixup_ptr->fx_r_type == RELOC_CONSTH) + nrelocs += 2; + else + nrelocs++; +#else + nrelocs++; +#endif + } + + fixup_ptr = fixup_ptr->fx_next; + } + return nrelocs; +} + +/* output all the relocations for a section */ +void +do_relocs_for (abfd, h, file_cursor) + bfd * abfd; + object_headers * h; + unsigned long *file_cursor; +{ + unsigned int nrelocs; + unsigned int idx; + unsigned long reloc_start = *file_cursor; + + for (idx = SEG_E0; idx < SEG_E9; idx++) + { + if (segment_info[idx].scnhdr.s_name[0]) + { + struct external_reloc *ext_ptr; + struct external_reloc *external_reloc_vec; + unsigned int external_reloc_size; + unsigned int base = segment_info[idx].scnhdr.s_paddr; + fixS *fix_ptr = segment_info[idx].fix_root; + nrelocs = count_entries_in_chain (idx); + + if (nrelocs) + /* Bypass this stuff if no relocs. This also incidentally + avoids a SCO bug, where free(malloc(0)) tends to crash. */ + { + external_reloc_size = nrelocs * RELSZ; + external_reloc_vec = + (struct external_reloc *) malloc (external_reloc_size); + + ext_ptr = external_reloc_vec; + + /* Fill in the internal coff style reloc struct from the + internal fix list. */ + while (fix_ptr) + { + struct internal_reloc intr; + + /* Only output some of the relocations */ + if (TC_COUNT_RELOC (fix_ptr)) + { +#ifdef TC_RELOC_MANGLE + TC_RELOC_MANGLE (&segment_info[idx], fix_ptr, &intr, + base); + +#else + symbolS *dot; + symbolS *symbol_ptr = fix_ptr->fx_addsy; + + intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr); + intr.r_vaddr = + base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where; + +#ifdef TC_KEEP_FX_OFFSET + intr.r_offset = fix_ptr->fx_offset; +#else + intr.r_offset = 0; +#endif + + /* Turn the segment of the symbol into an offset. */ + if (symbol_ptr) + { + dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot; + if (dot) + { + intr.r_symndx = dot->sy_number; + } + else + { + intr.r_symndx = symbol_ptr->sy_number; + } + + } + else + { + intr.r_symndx = -1; + } +#endif + + (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr); + ext_ptr++; + +#if defined(TC_A29K) + + /* The 29k has a special kludge for the high 16 bit + reloc. Two relocations are emited, R_IHIHALF, + and R_IHCONST. The second one doesn't contain a + symbol, but uses the value for offset. */ + + if (intr.r_type == R_IHIHALF) + { + /* now emit the second bit */ + intr.r_type = R_IHCONST; + intr.r_symndx = fix_ptr->fx_addnumber; + (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr); + ext_ptr++; + } +#endif + } + + fix_ptr = fix_ptr->fx_next; + } + + /* Write out the reloc table */ + bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size, + abfd); + free (external_reloc_vec); + + /* Fill in section header info. */ + segment_info[idx].scnhdr.s_relptr = *file_cursor; + *file_cursor += external_reloc_size; + segment_info[idx].scnhdr.s_nreloc = nrelocs; + } + else + { + /* No relocs */ + segment_info[idx].scnhdr.s_relptr = 0; + } + } + } + /* Set relocation_size field in file headers */ + H_SET_RELOCATION_SIZE (h, *file_cursor - reloc_start, 0); +} + + +/* run through a frag chain and write out the data to go with it, fill + in the scnhdrs with the info on the file postions +*/ +static void +fill_section (abfd, h, file_cursor) + bfd * abfd; + object_headers *h; + unsigned long *file_cursor; +{ + + unsigned int i; + unsigned int paddr = 0; + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + unsigned int offset = 0; + struct internal_scnhdr *s = &(segment_info[i].scnhdr); + + PROGRESS (1); + + if (s->s_name[0]) + { + fragS *frag = segment_info[i].frchainP->frch_root; + char *buffer; + + if (s->s_size == 0) + s->s_scnptr = 0; + else + { + buffer = xmalloc (s->s_size); + s->s_scnptr = *file_cursor; + } + know (s->s_paddr == paddr); + + if (strcmp (s->s_name, ".text") == 0) + s->s_flags |= STYP_TEXT; + else if (strcmp (s->s_name, ".data") == 0) + s->s_flags |= STYP_DATA; + else if (strcmp (s->s_name, ".bss") == 0) + { + s->s_scnptr = 0; + s->s_flags |= STYP_BSS; + + /* @@ Should make the i386 and a29k coff targets define + COFF_NOLOAD_PROBLEM, and have only one test here. */ +#ifndef TC_I386 +#ifndef TC_A29K +#ifndef COFF_NOLOAD_PROBLEM + /* Apparently the SVR3 linker (and exec syscall) and UDI + mondfe progrem are confused by noload sections. */ + s->s_flags |= STYP_NOLOAD; +#endif +#endif +#endif + } + else if (strcmp (s->s_name, ".lit") == 0) + s->s_flags = STYP_LIT | STYP_TEXT; + else if (strcmp (s->s_name, ".init") == 0) + s->s_flags |= STYP_TEXT; + else if (strcmp (s->s_name, ".fini") == 0) + s->s_flags |= STYP_TEXT; + else if (strncmp (s->s_name, ".comment", 8) == 0) + s->s_flags |= STYP_INFO; + + while (frag) + { + unsigned int fill_size; + switch (frag->fr_type) + { + case rs_machine_dependent: + if (frag->fr_fix) + { + memcpy (buffer + frag->fr_address, + frag->fr_literal, + (unsigned int) frag->fr_fix); + offset += frag->fr_fix; + } + + break; + case rs_space: + assert (frag->fr_symbol == 0); + case rs_fill: + case rs_align: + case rs_org: + if (frag->fr_fix) + { + memcpy (buffer + frag->fr_address, + frag->fr_literal, + (unsigned int) frag->fr_fix); + offset += frag->fr_fix; + } + + fill_size = frag->fr_var; + if (fill_size && frag->fr_offset > 0) + { + unsigned int count; + unsigned int off = frag->fr_fix; + for (count = frag->fr_offset; count; count--) + { + if (fill_size + frag->fr_address + off <= s->s_size) + { + memcpy (buffer + frag->fr_address + off, + frag->fr_literal + frag->fr_fix, + fill_size); + off += fill_size; + offset += fill_size; + } + } + } + break; + case rs_broken_word: + break; + default: + abort (); + } + frag = frag->fr_next; + } + + if (s->s_size != 0) + { + if (s->s_scnptr != 0) + { + bfd_write (buffer, s->s_size, 1, abfd); + *file_cursor += s->s_size; + } + free (buffer); + } + paddr += s->s_size; + } + } +} + +/* Coff file generation & utilities */ + +static void +coff_header_append (abfd, h) + bfd * abfd; + object_headers * h; +{ + unsigned int i; + char buffer[1000]; + char buffero[1000]; + + bfd_seek (abfd, 0, 0); + +#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER + H_SET_MAGIC_NUMBER (h, COFF_MAGIC); + H_SET_VERSION_STAMP (h, 0); + H_SET_ENTRY_POINT (h, 0); + H_SET_TEXT_START (h, segment_info[SEG_E0].frchainP->frch_root->fr_address); + H_SET_DATA_START (h, segment_info[SEG_E1].frchainP->frch_root->fr_address); + H_SET_SIZEOF_OPTIONAL_HEADER (h, bfd_coff_swap_aouthdr_out(abfd, &h->aouthdr, + buffero)); +#else /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */ + H_SET_SIZEOF_OPTIONAL_HEADER (h, 0); +#endif /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */ + + i = bfd_coff_swap_filehdr_out (abfd, &h->filehdr, buffer); + + bfd_write (buffer, i, 1, abfd); + bfd_write (buffero, H_GET_SIZEOF_OPTIONAL_HEADER (h), 1, abfd); + + for (i = SEG_E0; i < SEG_E9; i++) + { + if (segment_info[i].scnhdr.s_name[0]) + { + unsigned int size = + bfd_coff_swap_scnhdr_out (abfd, + &(segment_info[i].scnhdr), + buffer); + if (size == 0) + as_bad ("bfd_coff_swap_scnhdr_out failed"); + bfd_write (buffer, size, 1, abfd); + } + } +} + + +char * +symbol_to_chars (abfd, where, symbolP) + bfd * abfd; + char *where; + symbolS * symbolP; +{ + unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux; + unsigned int i; + valueT val; + + /* Turn any symbols with register attributes into abs symbols */ + if (S_GET_SEGMENT (symbolP) == reg_section) + { + S_SET_SEGMENT (symbolP, absolute_section); + } + /* At the same time, relocate all symbols to their output value */ + + val = (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr + + S_GET_VALUE (symbolP)); + + S_SET_VALUE (symbolP, val); + + symbolP->sy_symbol.ost_entry.n_value = val; + + where += bfd_coff_swap_sym_out (abfd, &symbolP->sy_symbol.ost_entry, + where); + + for (i = 0; i < numaux; i++) + { + where += bfd_coff_swap_aux_out (abfd, + &symbolP->sy_symbol.ost_auxent[i], + S_GET_DATA_TYPE (symbolP), + S_GET_STORAGE_CLASS (symbolP), + i, numaux, where); + } + return where; + +} + +void +obj_symbol_new_hook (symbolP) + symbolS *symbolP; +{ + char underscore = 0; /* Symbol has leading _ */ + + /* Effective symbol */ + /* Store the pointer in the offset. */ + S_SET_ZEROES (symbolP, 0L); + S_SET_DATA_TYPE (symbolP, T_NULL); + S_SET_STORAGE_CLASS (symbolP, 0); + S_SET_NUMBER_AUXILIARY (symbolP, 0); + /* Additional information */ + symbolP->sy_symbol.ost_flags = 0; + /* Auxiliary entries */ + memset ((char *) &symbolP->sy_symbol.ost_auxent[0], 0, AUXESZ); + + if (S_IS_STRING (symbolP)) + SF_SET_STRING (symbolP); + if (!underscore && S_IS_LOCAL (symbolP)) + SF_SET_LOCAL (symbolP); +} + +/* + * Handle .ln directives. + */ + +static void +obj_coff_ln (appline) + int appline; +{ + int l; + + if (! appline && def_symbol_in_progress != NULL) + { + as_warn (".ln pseudo-op inside .def/.endef: ignored."); + demand_empty_rest_of_line (); + return; + } /* wrong context */ + + l = get_absolute_expression (); + c_line_new (0, frag_now_fix (), l, frag_now); +#ifndef NO_LISTING + { + extern int listing; + + if (listing) + { + if (! appline) + l += line_base - 1; + listing_source_line ((unsigned int) l); + } + + } +#endif + demand_empty_rest_of_line (); +} + +/* + * def() + * + * Handle .def directives. + * + * One might ask : why can't we symbol_new if the symbol does not + * already exist and fill it with debug information. Because of + * the C_EFCN special symbol. It would clobber the value of the + * function symbol before we have a chance to notice that it is + * a C_EFCN. And a second reason is that the code is more clear this + * way. (at least I think it is :-). + * + */ + +#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';') +#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ + *input_line_pointer == '\t') \ + input_line_pointer++; + +static void +obj_coff_def (what) + int what; +{ + char name_end; /* Char after the end of name */ + char *symbol_name; /* Name of the debug symbol */ + char *symbol_name_copy; /* Temporary copy of the name */ + unsigned int symbol_name_length; + + if (def_symbol_in_progress != NULL) + { + as_warn (".def pseudo-op used inside of .def/.endef: ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + SKIP_WHITESPACES (); + + def_symbol_in_progress = (symbolS *) obstack_alloc (¬es, sizeof (*def_symbol_in_progress)); + memset (def_symbol_in_progress, 0, sizeof (*def_symbol_in_progress)); + + symbol_name = input_line_pointer; + name_end = get_symbol_end (); + symbol_name_length = strlen (symbol_name); + symbol_name_copy = xmalloc (symbol_name_length + 1); + strcpy (symbol_name_copy, symbol_name); + + /* Initialize the new symbol */ +#ifdef STRIP_UNDERSCORE + S_SET_NAME (def_symbol_in_progress, (*symbol_name_copy == '_' + ? symbol_name_copy + 1 + : symbol_name_copy)); +#else /* STRIP_UNDERSCORE */ + S_SET_NAME (def_symbol_in_progress, symbol_name_copy); +#endif /* STRIP_UNDERSCORE */ + /* free(symbol_name_copy); */ + def_symbol_in_progress->sy_name_offset = (unsigned long) ~0; + def_symbol_in_progress->sy_number = ~0; + def_symbol_in_progress->sy_frag = &zero_address_frag; + S_SET_VALUE (def_symbol_in_progress, 0); + + if (S_IS_STRING (def_symbol_in_progress)) + SF_SET_STRING (def_symbol_in_progress); + + *input_line_pointer = name_end; + + demand_empty_rest_of_line (); +} + +unsigned int dim_index; + + +static void +obj_coff_endef (ignore) + int ignore; +{ + symbolS *symbolP = 0; + /* DIM BUG FIX sac@cygnus.com */ + dim_index = 0; + if (def_symbol_in_progress == NULL) + { + as_warn (".endef pseudo-op used outside of .def/.endef: ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + /* Set the section number according to storage class. */ + switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) + { + case C_STRTAG: + case C_ENTAG: + case C_UNTAG: + SF_SET_TAG (def_symbol_in_progress); + /* intentional fallthrough */ + case C_FILE: + case C_TPDEF: + SF_SET_DEBUG (def_symbol_in_progress); + S_SET_SEGMENT (def_symbol_in_progress, SEG_DEBUG); + break; + + case C_EFCN: + SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ + /* intentional fallthrough */ + case C_BLOCK: + SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */ + /* intentional fallthrough */ + case C_FCN: + S_SET_SEGMENT (def_symbol_in_progress, SEG_E0); + + if (strcmp (S_GET_NAME (def_symbol_in_progress), ".bf") == 0) + { /* .bf */ + if (function_lineoff < 0) + { + fprintf (stderr, "`.bf' symbol without preceding function\n"); + } /* missing function symbol */ + SA_GET_SYM_LNNOPTR (last_line_symbol) = function_lineoff; + + SF_SET_PROCESS (last_line_symbol); + function_lineoff = -1; + } + /* Value is always set to . */ + def_symbol_in_progress->sy_frag = frag_now; + S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); + break; + +#ifdef C_AUTOARG + case C_AUTOARG: +#endif /* C_AUTOARG */ + case C_AUTO: + case C_REG: + case C_MOS: + case C_MOE: + case C_MOU: + case C_ARG: + case C_REGPARM: + case C_FIELD: + case C_EOS: + SF_SET_DEBUG (def_symbol_in_progress); + S_SET_SEGMENT (def_symbol_in_progress, absolute_section); + break; + + case C_EXT: + case C_STAT: + case C_LABEL: + /* Valid but set somewhere else (s_comm, s_lcomm, colon) */ + break; + + case C_USTATIC: + case C_EXTDEF: + case C_ULABEL: + as_warn ("unexpected storage class %d", S_GET_STORAGE_CLASS (def_symbol_in_progress)); + break; + } /* switch on storage class */ + + /* Now that we have built a debug symbol, try to find if we should + merge with an existing symbol or not. If a symbol is C_EFCN or + absolute_section or untagged SEG_DEBUG it never merges. We also + don't merge labels, which are in a different namespace, nor + symbols which have not yet been defined since they are typically + unique, nor do we merge tags with non-tags. */ + + /* Two cases for functions. Either debug followed by definition or + definition followed by debug. For definition first, we will + merge the debug symbol into the definition. For debug first, the + lineno entry MUST point to the definition function or else it + will point off into space when crawl_symbols() merges the debug + symbol into the real symbol. Therefor, let's presume the debug + symbol is a real function reference. */ + + /* FIXME-SOON If for some reason the definition label/symbol is + never seen, this will probably leave an undefined symbol at link + time. */ + + if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN + || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL + || (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG + && !SF_GET_TAG (def_symbol_in_progress)) + || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section + || def_symbol_in_progress->sy_value.X_op != O_constant + || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL + || (SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))) + { + symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, + &symbol_lastP); + } + else + { + /* This symbol already exists, merge the newly created symbol + into the old one. This is not mandatory. The linker can + handle duplicate symbols correctly. But I guess that it save + a *lot* of space if the assembly file defines a lot of + symbols. [loic] */ + + /* The debug entry (def_symbol_in_progress) is merged into the + previous definition. */ + + c_symbol_merge (def_symbol_in_progress, symbolP); + /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */ + def_symbol_in_progress = symbolP; + + if (SF_GET_FUNCTION (def_symbol_in_progress) + || SF_GET_TAG (def_symbol_in_progress)) + { + /* For functions, and tags, the symbol *must* be where the + debug symbol appears. Move the existing symbol to the + current place. */ + /* If it already is at the end of the symbol list, do nothing */ + if (def_symbol_in_progress != symbol_lastP) + { + symbol_remove (def_symbol_in_progress, &symbol_rootP, + &symbol_lastP); + symbol_append (def_symbol_in_progress, symbol_lastP, + &symbol_rootP, &symbol_lastP); + } /* if not already in place */ + } /* if function */ + } /* normal or mergable */ + + if (SF_GET_TAG (def_symbol_in_progress) + && symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL) + { + tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress); + } + + if (SF_GET_FUNCTION (def_symbol_in_progress)) + { + know (sizeof (def_symbol_in_progress) <= sizeof (long)); + function_lineoff + = c_line_new (def_symbol_in_progress, 0, 0, &zero_address_frag); + + SF_SET_PROCESS (def_symbol_in_progress); + + if (symbolP == NULL) + { + /* That is, if this is the first time we've seen the + function... */ + symbol_table_insert (def_symbol_in_progress); + } /* definition follows debug */ + } /* Create the line number entry pointing to the function being defined */ + + def_symbol_in_progress = NULL; + demand_empty_rest_of_line (); +} + +static void +obj_coff_dim (ignore) + int ignore; +{ + int dim_index; + + if (def_symbol_in_progress == NULL) + { + as_warn (".dim pseudo-op used outside of .def/.endef: ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); + + for (dim_index = 0; dim_index < DIMNUM; dim_index++) + { + SKIP_WHITESPACES (); + SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index, + get_absolute_expression ()); + + switch (*input_line_pointer) + { + case ',': + input_line_pointer++; + break; + + default: + as_warn ("badly formed .dim directive ignored"); + /* intentional fallthrough */ + case '\n': + case ';': + dim_index = DIMNUM; + break; + } + } + + demand_empty_rest_of_line (); +} + +static void +obj_coff_line (ignore) + int ignore; +{ + int this_base; + const char *name; + + if (def_symbol_in_progress == NULL) + { + obj_coff_ln (0); + return; + } + + name = S_GET_NAME (def_symbol_in_progress); + this_base = get_absolute_expression (); + + /* Only .bf symbols indicate the use of a new base line number; the + line numbers associated with .ef, .bb, .eb are relative to the + start of the containing function. */ + if (!strcmp (".bf", name)) + { +#if 0 /* XXX Can we ever have line numbers going backwards? */ + if (this_base > line_base) +#endif + { + line_base = this_base; + } + +#ifndef NO_LISTING + { + extern int listing; + if (listing) + { + listing_source_line ((unsigned int) line_base); + } + } +#endif + } + + S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); + SA_SET_SYM_LNNO (def_symbol_in_progress, this_base); + + demand_empty_rest_of_line (); +} + +static void +obj_coff_size (ignore) + int ignore; +{ + if (def_symbol_in_progress == NULL) + { + as_warn (".size pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); + SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ()); + demand_empty_rest_of_line (); +} + +static void +obj_coff_scl (ignore) + int ignore; +{ + if (def_symbol_in_progress == NULL) + { + as_warn (".scl pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ()); + demand_empty_rest_of_line (); +} + +static void +obj_coff_tag (ignore) + int ignore; +{ + char *symbol_name; + char name_end; + + if (def_symbol_in_progress == NULL) + { + as_warn (".tag pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } + + S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); + symbol_name = input_line_pointer; + name_end = get_symbol_end (); + + /* Assume that the symbol referred to by .tag is always defined. + This was a bad assumption. I've added find_or_make. xoxorich. */ + SA_SET_SYM_TAGNDX (def_symbol_in_progress, + (long) tag_find_or_make (symbol_name)); + if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L) + { + as_warn ("tag not found for .tag %s", symbol_name); + } /* not defined */ + + SF_SET_TAGGED (def_symbol_in_progress); + *input_line_pointer = name_end; + + demand_empty_rest_of_line (); +} + +static void +obj_coff_type (ignore) + int ignore; +{ + if (def_symbol_in_progress == NULL) + { + as_warn (".type pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ()); + + if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) && + S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF) + { + SF_SET_FUNCTION (def_symbol_in_progress); + } /* is a function */ + + demand_empty_rest_of_line (); +} + +static void +obj_coff_val (ignore) + int ignore; +{ + if (def_symbol_in_progress == NULL) + { + as_warn (".val pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line (); + return; + } /* if not inside .def/.endef */ + + if (is_name_beginner (*input_line_pointer)) + { + char *symbol_name = input_line_pointer; + char name_end = get_symbol_end (); + + if (!strcmp (symbol_name, ".")) + { + def_symbol_in_progress->sy_frag = frag_now; + S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); + /* If the .val is != from the .def (e.g. statics) */ + } + else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) + { + def_symbol_in_progress->sy_value.X_op = O_symbol; + def_symbol_in_progress->sy_value.X_add_symbol = + symbol_find_or_make (symbol_name); + def_symbol_in_progress->sy_value.X_op_symbol = NULL; + def_symbol_in_progress->sy_value.X_add_number = 0; + + /* If the segment is undefined when the forward reference is + resolved, then copy the segment id from the forward + symbol. */ + SF_SET_GET_SEGMENT (def_symbol_in_progress); + + /* FIXME: gcc can generate address expressions + here in unusual cases (search for "obscure" + in sdbout.c). We just ignore the offset + here, thus generating incorrect debugging + information. We ignore the rest of the + line just below. */ + } + /* Otherwise, it is the name of a non debug symbol and + its value will be calculated later. */ + *input_line_pointer = name_end; + + /* FIXME: this is to avoid an error message in the + FIXME case mentioned just above. */ + while (! is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + } + else + { + S_SET_VALUE (def_symbol_in_progress, + (valueT) get_absolute_expression ()); + } /* if symbol based */ + + demand_empty_rest_of_line (); +} + +void +obj_read_begin_hook () +{ + /* These had better be the same. Usually 18 bytes. */ +#ifndef BFD_HEADERS + know (sizeof (SYMENT) == sizeof (AUXENT)); + know (SYMESZ == AUXESZ); +#endif + tag_init (); +} + +/* This function runs through the symbol table and puts all the + externals onto another chain */ + +/* The chain of globals. */ +symbolS *symbol_globalP; +symbolS *symbol_global_lastP; + +/* The chain of externals */ +symbolS *symbol_externP; +symbolS *symbol_extern_lastP; + +stack *block_stack; +symbolS *last_functionP; +symbolS *last_tagP; + +static unsigned int +yank_symbols () +{ + symbolS *symbolP; + unsigned int symbol_number = 0; + unsigned int last_file_symno = 0; + + struct filename_list *filename_list_scan = filename_list_head; + + for (symbolP = symbol_rootP; + symbolP; + symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP) + { + if (symbolP->sy_mri_common) + { + if (S_GET_STORAGE_CLASS (symbolP) == C_EXT) + as_bad ("%s: global symbols not supported in common sections", + S_GET_NAME (symbolP)); + symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); + continue; + } + + if (!SF_GET_DEBUG (symbolP)) + { + /* Debug symbols do not need all this rubbish */ + symbolS *real_symbolP; + + /* L* and C_EFCN symbols never merge. */ + if (!SF_GET_LOCAL (symbolP) + && S_GET_STORAGE_CLASS (symbolP) != C_LABEL + && symbolP->sy_value.X_op == O_constant + && (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP)) + && real_symbolP != symbolP) + { + /* FIXME-SOON: where do dups come from? + Maybe tag references before definitions? xoxorich. */ + /* Move the debug data from the debug symbol to the + real symbol. Do NOT do the oposite (i.e. move from + real symbol to debug symbol and remove real symbol from the + list.) Because some pointers refer to the real symbol + whereas no pointers refer to the debug symbol. */ + c_symbol_merge (symbolP, real_symbolP); + /* Replace the current symbol by the real one */ + /* The symbols will never be the last or the first + because : 1st symbol is .file and 3 last symbols are + .text, .data, .bss */ + symbol_remove (real_symbolP, &symbol_rootP, &symbol_lastP); + symbol_insert (real_symbolP, symbolP, &symbol_rootP, &symbol_lastP); + symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); + symbolP = real_symbolP; + } /* if not local but dup'd */ + + if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_E1)) + { + S_SET_SEGMENT (symbolP, SEG_E0); + } /* push data into text */ + + resolve_symbol_value (symbolP); + + if (S_GET_STORAGE_CLASS (symbolP) == C_NULL) + { + if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP)) + { + S_SET_EXTERNAL (symbolP); + } + else if (S_GET_SEGMENT (symbolP) == SEG_E0) + { + S_SET_STORAGE_CLASS (symbolP, C_LABEL); + } + else + { + S_SET_STORAGE_CLASS (symbolP, C_STAT); + } + } + + /* Mainly to speed up if not -g */ + if (SF_GET_PROCESS (symbolP)) + { + /* Handle the nested blocks auxiliary info. */ + if (S_GET_STORAGE_CLASS (symbolP) == C_BLOCK) + { + if (!strcmp (S_GET_NAME (symbolP), ".bb")) + stack_push (block_stack, (char *) &symbolP); + else + { /* .eb */ + register symbolS *begin_symbolP; + begin_symbolP = *(symbolS **) stack_pop (block_stack); + if (begin_symbolP == (symbolS *) 0) + as_warn ("mismatched .eb"); + else + SA_SET_SYM_ENDNDX (begin_symbolP, symbol_number + 2); + } + } + /* If we are able to identify the type of a function, and we + are out of a function (last_functionP == 0) then, the + function symbol will be associated with an auxiliary + entry. */ + if (last_functionP == (symbolS *) 0 && + SF_GET_FUNCTION (symbolP)) + { + last_functionP = symbolP; + + if (S_GET_NUMBER_AUXILIARY (symbolP) < 1) + { + S_SET_NUMBER_AUXILIARY (symbolP, 1); + } /* make it at least 1 */ + + /* Clobber possible stale .dim information. */ +#if 0 + /* Iffed out by steve - this fries the lnnoptr info too */ + bzero (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen, + sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen)); +#endif + } + /* The C_FCN doesn't need any additional information. I + don't even know if this is needed for sdb. But the + standard assembler generates it, so... */ + if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN) + { + if (last_functionP == (symbolS *) 0) + as_fatal ("C_EFCN symbol out of scope"); + SA_SET_SYM_FSIZE (last_functionP, + (long) (S_GET_VALUE (symbolP) - + S_GET_VALUE (last_functionP))); + SA_SET_SYM_ENDNDX (last_functionP, symbol_number); + last_functionP = (symbolS *) 0; + } + } + } + else if (SF_GET_TAG (symbolP)) + { + /* First descriptor of a structure must point to + the first slot after the structure description. */ + last_tagP = symbolP; + + } + else if (S_GET_STORAGE_CLASS (symbolP) == C_EOS) + { + /* +2 take in account the current symbol */ + SA_SET_SYM_ENDNDX (last_tagP, symbol_number + 2); + } + else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE) + { + /* If the filename was too long to fit in the + auxent, put it in the string table */ + if (SA_GET_FILE_FNAME_ZEROS (symbolP) == 0) + { + SA_SET_FILE_FNAME_OFFSET (symbolP, string_byte_count); + string_byte_count += strlen (filename_list_scan->filename) + 1; + filename_list_scan = filename_list_scan->next; + } + if (S_GET_VALUE (symbolP)) + { + S_SET_VALUE (symbolP, last_file_symno); + last_file_symno = symbol_number; + } /* no one points at the first .file symbol */ + } /* if debug or tag or eos or file */ + + /* We must put the external symbols apart. The loader + does not bomb if we do not. But the references in + the endndx field for a .bb symbol are not corrected + if an external symbol is removed between .bb and .be. + I.e in the following case : + [20] .bb endndx = 22 + [21] foo external + [22] .be + ld will move the symbol 21 to the end of the list but + endndx will still be 22 instead of 21. */ + + + if (SF_GET_LOCAL (symbolP)) + { + /* remove C_EFCN and LOCAL (L...) symbols */ + /* next pointer remains valid */ + symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); + + } + else if (!S_IS_DEFINED (symbolP) + && !S_IS_DEBUG (symbolP) + && !SF_GET_STATICS (symbolP) && + S_GET_STORAGE_CLASS (symbolP) == C_EXT) + { /* C_EXT && !SF_GET_FUNCTION(symbolP)) */ + /* if external, Remove from the list */ + symbolS *hold = symbol_previous (symbolP); + + symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); + symbol_clear_list_pointers (symbolP); + symbol_append (symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP); + symbolP = hold; + } + else if (! S_IS_DEBUG (symbolP) + && ! SF_GET_STATICS (symbolP) + && ! SF_GET_FUNCTION (symbolP) + && S_GET_STORAGE_CLASS (symbolP) == C_EXT) + { + symbolS *hold = symbol_previous (symbolP); + + /* The O'Reilly COFF book says that defined global symbols + come at the end of the symbol table, just before + undefined global symbols. */ + + symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); + symbol_clear_list_pointers (symbolP); + symbol_append (symbolP, symbol_global_lastP, &symbol_globalP, + &symbol_global_lastP); + symbolP = hold; + } + else + { + if (SF_GET_STRING (symbolP)) + { + symbolP->sy_name_offset = string_byte_count; + string_byte_count += strlen (S_GET_NAME (symbolP)) + 1; + } + else + { + symbolP->sy_name_offset = 0; + } /* fix "long" names */ + + symbolP->sy_number = symbol_number; + symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP); + } /* if local symbol */ + } /* traverse the symbol list */ + return symbol_number; + +} + + +static unsigned int +glue_symbols (head, tail) + symbolS **head; + symbolS **tail; +{ + unsigned int symbol_number = 0; + symbolS *symbolP; + + for (symbolP = *head; *head != NULL;) + { + symbolS *tmp = *head; + + /* append */ + symbol_remove (tmp, head, tail); + symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP); + + /* and process */ + if (SF_GET_STRING (tmp)) + { + tmp->sy_name_offset = string_byte_count; + string_byte_count += strlen (S_GET_NAME (tmp)) + 1; + } + else + { + tmp->sy_name_offset = 0; + } /* fix "long" names */ + + tmp->sy_number = symbol_number; + symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp); + } /* append the entire extern chain */ + + return symbol_number; +} + +static unsigned int +tie_tags () +{ + unsigned int symbol_number = 0; + + symbolS *symbolP; + for (symbolP = symbol_rootP; symbolP; symbolP = + symbol_next (symbolP)) + { + symbolP->sy_number = symbol_number; + + + + if (SF_GET_TAGGED (symbolP)) + { + SA_SET_SYM_TAGNDX + (symbolP, + ((symbolS *) SA_GET_SYM_TAGNDX (symbolP))->sy_number); + } + + symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP); + } + return symbol_number; + +} + +static void +crawl_symbols (h, abfd) + object_headers *h; + bfd * abfd; +{ + unsigned int i; + + /* Initialize the stack used to keep track of the matching .bb .be */ + + block_stack = stack_init (512, sizeof (symbolS *)); + + /* The symbol list should be ordered according to the following sequence + * order : + * . .file symbol + * . debug entries for functions + * . fake symbols for the sections, including.text .data and .bss + * . defined symbols + * . undefined symbols + * But this is not mandatory. The only important point is to put the + * undefined symbols at the end of the list. + */ + + if (symbol_rootP == NULL + || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) + { + c_dot_file_symbol ("fake"); + } + /* Is there a .file symbol ? If not insert one at the beginning. */ + + /* + * Build up static symbols for the sections, they are filled in later + */ + + + for (i = SEG_E0; i < SEG_E9; i++) + { + if (segment_info[i].scnhdr.s_name[0]) + { + char name[9]; + + strncpy (name, segment_info[i].scnhdr.s_name, 8); + name[8] = '\0'; + segment_info[i].dot = c_section_symbol (name, i - SEG_E0 + 1); + } + } + + + /* Take all the externals out and put them into another chain */ + H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ()); + /* Take the externals and glue them onto the end.*/ + H_SET_SYMBOL_TABLE_SIZE (h, + (H_GET_SYMBOL_COUNT (h) + + glue_symbols (&symbol_globalP, + &symbol_global_lastP) + + glue_symbols (&symbol_externP, + &symbol_extern_lastP))); + + H_SET_SYMBOL_TABLE_SIZE (h, tie_tags ()); + know (symbol_globalP == NULL); + know (symbol_global_lastP == NULL); + know (symbol_externP == NULL); + know (symbol_extern_lastP == NULL); +} + +/* + * Find strings by crawling along symbol table chain. + */ + +void +w_strings (where) + char *where; +{ + symbolS *symbolP; + struct filename_list *filename_list_scan = filename_list_head; + + /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ + md_number_to_chars (where, (valueT) string_byte_count, 4); + where += 4; + for (symbolP = symbol_rootP; + symbolP; + symbolP = symbol_next (symbolP)) + { + unsigned int size; + + if (SF_GET_STRING (symbolP)) + { + size = strlen (S_GET_NAME (symbolP)) + 1; + memcpy (where, S_GET_NAME (symbolP), size); + where += size; + } + if (S_GET_STORAGE_CLASS (symbolP) == C_FILE + && SA_GET_FILE_FNAME_ZEROS (symbolP) == 0) + { + size = strlen (filename_list_scan->filename) + 1; + memcpy (where, filename_list_scan->filename, size); + filename_list_scan = filename_list_scan ->next; + where += size; + } + } +} + +static void +do_linenos_for (abfd, h, file_cursor) + bfd * abfd; + object_headers * h; + unsigned long *file_cursor; +{ + unsigned int idx; + unsigned long start = *file_cursor; + + for (idx = SEG_E0; idx < SEG_E9; idx++) + { + segment_info_type *s = segment_info + idx; + + + if (s->scnhdr.s_nlnno != 0) + { + struct lineno_list *line_ptr; + + struct external_lineno *buffer = + (struct external_lineno *) xmalloc (s->scnhdr.s_nlnno * LINESZ); + + struct external_lineno *dst = buffer; + + /* Run through the table we've built and turn it into its external + form, take this chance to remove duplicates */ + + for (line_ptr = s->lineno_list_head; + line_ptr != (struct lineno_list *) NULL; + line_ptr = line_ptr->next) + { + + if (line_ptr->line.l_lnno == 0) + { + /* Turn a pointer to a symbol into the symbols' index */ + line_ptr->line.l_addr.l_symndx = + ((symbolS *) line_ptr->line.l_addr.l_symndx)->sy_number; + } + else + { + line_ptr->line.l_addr.l_paddr += ((struct frag *) (line_ptr->frag))->fr_address; + } + + + (void) bfd_coff_swap_lineno_out (abfd, &(line_ptr->line), dst); + dst++; + + } + + s->scnhdr.s_lnnoptr = *file_cursor; + + bfd_write (buffer, 1, s->scnhdr.s_nlnno * LINESZ, abfd); + free (buffer); + + *file_cursor += s->scnhdr.s_nlnno * LINESZ; + } + } + H_SET_LINENO_SIZE (h, *file_cursor - start); +} + + +/* Now we run through the list of frag chains in a segment and + make all the subsegment frags appear at the end of the + list, as if the seg 0 was extra long */ + +static void +remove_subsegs () +{ + unsigned int i; + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + frchainS *head = segment_info[i].frchainP; + fragS dummy; + fragS *prev_frag = &dummy; + + while (head && head->frch_seg == i) + { + prev_frag->fr_next = head->frch_root; + prev_frag = head->frch_last; + head = head->frch_next; + } + prev_frag->fr_next = 0; + } +} + +unsigned long machine; +int coff_flags; +extern void +write_object_file () +{ + int i; + char *name; + struct frchain *frchain_ptr; + + object_headers headers; + unsigned long file_cursor; + bfd *abfd; + unsigned int addr; + abfd = bfd_openw (out_file_name, TARGET_FORMAT); + + + if (abfd == 0) + { + as_perror ("FATAL: Can't create %s", out_file_name); + exit (EXIT_FAILURE); + } + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, BFD_ARCH, machine); + + string_byte_count = 4; + + for (frchain_ptr = frchain_root; + frchain_ptr != (struct frchain *) NULL; + frchain_ptr = frchain_ptr->frch_next) + { + /* Run through all the sub-segments and align them up. Also + close any open frags. We tack a .fill onto the end of the + frag chain so that any .align's size can be worked by looking + at the next frag. */ + + subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); +#ifndef SUB_SEGMENT_ALIGN +#define SUB_SEGMENT_ALIGN(SEG) 1 +#endif +#ifdef md_do_align + { + static char nop = NOP_OPCODE; + md_do_align (SUB_SEGMENT_ALIGN (now_seg), &nop, alignment_done); + } +#endif + frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE); +#ifdef md_do_align + alignment_done: +#endif + frag_wane (frag_now); + frag_now->fr_fix = 0; + know (frag_now->fr_next == NULL); + } + + + remove_subsegs (); + + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + relax_segment (segment_info[i].frchainP->frch_root, i); + } + + H_SET_NUMBER_OF_SECTIONS (&headers, 0); + + /* Find out how big the sections are, and set the addresses. */ + addr = 0; + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + long size; + + segment_info[i].scnhdr.s_paddr = addr; + segment_info[i].scnhdr.s_vaddr = addr; + + if (segment_info[i].scnhdr.s_name[0]) + { + H_SET_NUMBER_OF_SECTIONS (&headers, + H_GET_NUMBER_OF_SECTIONS (&headers) + 1); + } + + size = size_section (abfd, (unsigned int) i); + addr += size; + + /* I think the section alignment is only used on the i960; the + i960 needs it, and it should do no harm on other targets. */ + segment_info[i].scnhdr.s_align = section_alignment[i]; + + if (i == SEG_E0) + H_SET_TEXT_SIZE (&headers, size); + else if (i == SEG_E1) + H_SET_DATA_SIZE (&headers, size); + else if (i == SEG_E2) + H_SET_BSS_SIZE (&headers, size); + } + + /* Turn the gas native symbol table shape into a coff symbol table */ + crawl_symbols (&headers, abfd); + + if (string_byte_count == 4) + string_byte_count = 0; + + H_SET_STRING_SIZE (&headers, string_byte_count); + +#ifdef tc_frob_file + tc_frob_file (); +#endif + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + fixup_mdeps (segment_info[i].frchainP->frch_root, &headers, i); + fixup_segment (&segment_info[i], i); + } + + /* Look for ".stab" segments and fill in their initial symbols + correctly. */ + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + name = segment_info[i].scnhdr.s_name; + + if (name != NULL + && strncmp (".stab", name, 5) == 0 + && strncmp (".stabstr", name, 8) != 0) + adjust_stab_section (abfd, i); + } + + file_cursor = H_GET_TEXT_FILE_OFFSET (&headers); + + bfd_seek (abfd, (file_ptr) file_cursor, 0); + + /* Plant the data */ + + fill_section (abfd, &headers, &file_cursor); + + do_relocs_for (abfd, &headers, &file_cursor); + + do_linenos_for (abfd, &headers, &file_cursor); + + H_SET_FILE_MAGIC_NUMBER (&headers, COFF_MAGIC); +#ifndef OBJ_COFF_OMIT_TIMESTAMP + H_SET_TIME_STAMP (&headers, (long)time((time_t *)0)); +#else + H_SET_TIME_STAMP (&headers, 0); +#endif +#ifdef TC_COFF_SET_MACHINE + TC_COFF_SET_MACHINE (&headers); +#endif + +#ifndef COFF_FLAGS +#define COFF_FLAGS 0 +#endif + +#ifdef KEEP_RELOC_INFO + H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) | + COFF_FLAGS | coff_flags)); +#else + H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) | + (H_GET_RELOCATION_SIZE(&headers) ? 0 : F_RELFLG) | + COFF_FLAGS | coff_flags)); +#endif + + { + unsigned int symtable_size = H_GET_SYMBOL_TABLE_SIZE (&headers); + char *buffer1 = xmalloc (symtable_size + string_byte_count + 1); + + H_SET_SYMBOL_TABLE_POINTER (&headers, bfd_tell (abfd)); + w_symbols (abfd, buffer1, symbol_rootP); + if (string_byte_count > 0) + w_strings (buffer1 + symtable_size); + bfd_write (buffer1, 1, symtable_size + string_byte_count, abfd); + free (buffer1); + } + + coff_header_append (abfd, &headers); +#if 0 + /* Recent changes to write need this, but where it should + go is up to Ken.. */ + if (bfd_close_all_done (abfd) == false) + as_fatal ("Can't close %s: %s", out_file_name, + bfd_errmsg (bfd_get_error ())); +#else + { + extern bfd *stdoutput; + stdoutput = abfd; + } +#endif + +} + +/* Add a new segment. This is called from subseg_new via the + obj_new_segment macro. */ + +segT +obj_coff_add_segment (name) + const char *name; +{ + unsigned int len; + unsigned int i; + + /* Find out if we've already got a section of this name. */ + len = strlen (name); + if (len < sizeof (segment_info[i].scnhdr.s_name)) + ++len; + else + len = sizeof (segment_info[i].scnhdr.s_name); + for (i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0]; i++) + if (strncmp (segment_info[i].scnhdr.s_name, name, len) == 0 + && (len == sizeof (segment_info[i].scnhdr.s_name) + || segment_info[i].scnhdr.s_name[len] == '\0')) + return (segT) i; + + if (i == SEG_E9) + { + as_bad ("Too many new sections; can't add \"%s\"", name); + return now_seg; + } + + /* Add a new section. */ + strncpy (segment_info[i].scnhdr.s_name, name, + sizeof (segment_info[i].scnhdr.s_name)); + segment_info[i].scnhdr.s_flags = STYP_REG; + + return (segT) i; +} + +/* + * implement the .section pseudo op: + * .section name {, "flags"} + * ^ ^ + * | +--- optional flags: 'b' for bss + * | 'i' for info + * +-- section name 'l' for lib + * 'n' for noload + * 'o' for over + * 'w' for data + * 'd' (apparently m88k for data) + * 'x' for text + * But if the argument is not a quoted string, treat it as a + * subsegment number. + */ + +void +obj_coff_section (ignore) + int ignore; +{ + /* Strip out the section name */ + char *section_name; + char *section_name_end; + char c; + int argp; + unsigned int len; + unsigned int exp; + long flags; + + if (flag_mri) + { + char type; + + s_mri_sect (&type); + flags = 0; + if (type == 'C') + flags = STYP_TEXT; + else if (type == 'D') + flags = STYP_DATA; + segment_info[now_seg].scnhdr.s_flags |= flags; + + return; + } + + section_name = input_line_pointer; + c = get_symbol_end (); + section_name_end = input_line_pointer; + + len = section_name_end - section_name; + input_line_pointer++; + SKIP_WHITESPACE (); + + argp = 0; + if (c == ',') + argp = 1; + else if (*input_line_pointer == ',') + { + argp = 1; + ++input_line_pointer; + SKIP_WHITESPACE (); + } + + exp = 0; + flags = 0; + if (argp) + { + if (*input_line_pointer != '"') + exp = get_absolute_expression (); + else + { + ++input_line_pointer; + while (*input_line_pointer != '"' + && ! is_end_of_line[(unsigned char) *input_line_pointer]) + { + switch (*input_line_pointer) + { + case 'b': flags |= STYP_BSS; break; + case 'i': flags |= STYP_INFO; break; + case 'l': flags |= STYP_LIB; break; + case 'n': flags |= STYP_NOLOAD; break; + case 'o': flags |= STYP_OVER; break; + case 'd': + case 'w': flags |= STYP_DATA; break; + case 'x': flags |= STYP_TEXT; break; + default: + as_warn("unknown section attribute '%c'", + *input_line_pointer); + break; + } + ++input_line_pointer; + } + if (*input_line_pointer == '"') + ++input_line_pointer; + } + } + + subseg_new (section_name, (subsegT) exp); + + segment_info[now_seg].scnhdr.s_flags |= flags; + + *section_name_end = c; +} + + +static void +obj_coff_text (ignore) + int ignore; +{ + subseg_new (".text", get_absolute_expression ()); +} + + +static void +obj_coff_data (ignore) + int ignore; +{ + if (flag_readonly_data_in_text) + subseg_new (".text", get_absolute_expression () + 1000); + else + subseg_new (".data", get_absolute_expression ()); +} + +static void +obj_coff_bss (ignore) + int ignore; +{ + if (*input_line_pointer == '\n') /* .bss */ + subseg_new(".bss", get_absolute_expression()); + else /* .bss id,expr */ + obj_coff_lcomm(0); +} + +static void +obj_coff_ident (ignore) + int ignore; +{ + segT current_seg = now_seg; /* save current seg */ + subsegT current_subseg = now_subseg; + subseg_new (".comment", 0); /* .comment seg */ + stringer (1); /* read string */ + subseg_set (current_seg, current_subseg); /* restore current seg */ +} + +void +c_symbol_merge (debug, normal) + symbolS *debug; + symbolS *normal; +{ + S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug)); + S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug)); + + if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal)) + { + S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug)); + } /* take the most we have */ + + if (S_GET_NUMBER_AUXILIARY (debug) > 0) + { + memcpy ((char *) &normal->sy_symbol.ost_auxent[0], + (char *) &debug->sy_symbol.ost_auxent[0], + (unsigned int) (S_GET_NUMBER_AUXILIARY (debug) * AUXESZ)); + } /* Move all the auxiliary information */ + + /* Move the debug flags. */ + SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug)); +} /* c_symbol_merge() */ + +static int +c_line_new (symbol, paddr, line_number, frag) + symbolS * symbol; + long paddr; + int line_number; + fragS * frag; +{ + struct lineno_list *new_line = + (struct lineno_list *) xmalloc (sizeof (struct lineno_list)); + + segment_info_type *s = segment_info + now_seg; + new_line->line.l_lnno = line_number; + + if (line_number == 0) + { + last_line_symbol = symbol; + new_line->line.l_addr.l_symndx = (long) symbol; + } + else + { + new_line->line.l_addr.l_paddr = paddr; + } + + new_line->frag = (char *) frag; + new_line->next = (struct lineno_list *) NULL; + + + if (s->lineno_list_head == (struct lineno_list *) NULL) + { + s->lineno_list_head = new_line; + } + else + { + s->lineno_list_tail->next = new_line; + } + s->lineno_list_tail = new_line; + return LINESZ * s->scnhdr.s_nlnno++; +} + +void +c_dot_file_symbol (filename) + char *filename; +{ + symbolS *symbolP; + + symbolP = symbol_new (".file", + SEG_DEBUG, + 0, + &zero_address_frag); + + S_SET_STORAGE_CLASS (symbolP, C_FILE); + S_SET_NUMBER_AUXILIARY (symbolP, 1); + + if (strlen (filename) > FILNMLEN) + { + /* Filename is too long to fit into an auxent, + we stick it into the string table instead. We keep + a linked list of the filenames we find so we can emit + them later.*/ + struct filename_list *f = ((struct filename_list *) + xmalloc (sizeof (struct filename_list))); + + f->filename = filename; + f->next = 0; + + SA_SET_FILE_FNAME_ZEROS (symbolP, 0); + SA_SET_FILE_FNAME_OFFSET (symbolP, 0); + + if (filename_list_tail) + filename_list_tail->next = f; + else + filename_list_head = f; + filename_list_tail = f; + } + else + { + SA_SET_FILE_FNAME (symbolP, filename); + } +#ifndef NO_LISTING + { + extern int listing; + if (listing) + { + listing_source_file (filename); + } + + } + +#endif + SF_SET_DEBUG (symbolP); + S_SET_VALUE (symbolP, (valueT) previous_file_symbol); + + previous_file_symbol = symbolP; + + /* Make sure that the symbol is first on the symbol chain */ + if (symbol_rootP != symbolP) + { + if (symbolP == symbol_lastP) + { + symbol_lastP = symbol_lastP->sy_previous; + } /* if it was the last thing on the list */ + + symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); + symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP); + symbol_rootP = symbolP; + } /* if not first on the list */ + +} /* c_dot_file_symbol() */ + +/* + * Build a 'section static' symbol. + */ + +symbolS * +c_section_symbol (name, idx) + char *name; + int idx; +{ + symbolS *symbolP; + + symbolP = symbol_new (name, idx, + 0, + &zero_address_frag); + + S_SET_STORAGE_CLASS (symbolP, C_STAT); + S_SET_NUMBER_AUXILIARY (symbolP, 1); + + SF_SET_STATICS (symbolP); + + return symbolP; +} /* c_section_symbol() */ + +static void +w_symbols (abfd, where, symbol_rootP) + bfd * abfd; + char *where; + symbolS * symbol_rootP; +{ + symbolS *symbolP; + unsigned int i; + + /* First fill in those values we have only just worked out */ + for (i = SEG_E0; i < SEG_E9; i++) + { + symbolP = segment_info[i].dot; + if (symbolP) + { + SA_SET_SCN_SCNLEN (symbolP, segment_info[i].scnhdr.s_size); + SA_SET_SCN_NRELOC (symbolP, segment_info[i].scnhdr.s_nreloc); + SA_SET_SCN_NLINNO (symbolP, segment_info[i].scnhdr.s_nlnno); + } + } + + /* + * Emit all symbols left in the symbol chain. + */ + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + { + /* Used to save the offset of the name. It is used to point + to the string in memory but must be a file offset. */ + register char *temp; + + tc_coff_symbol_emit_hook (symbolP); + + temp = S_GET_NAME (symbolP); + if (SF_GET_STRING (symbolP)) + { + S_SET_OFFSET (symbolP, symbolP->sy_name_offset); + S_SET_ZEROES (symbolP, 0); + } + else + { + memset (symbolP->sy_symbol.ost_entry.n_name, 0, SYMNMLEN); + strncpy (symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN); + } + where = symbol_to_chars (abfd, where, symbolP); + S_SET_NAME (symbolP, temp); + } + +} /* w_symbols() */ + +static void +obj_coff_lcomm (ignore) + int ignore; +{ + s_lcomm(0); + return; +#if 0 + char *name; + char c; + int temp; + char *p; + + symbolS *symbolP; + + name = input_line_pointer; + + c = get_symbol_end (); + p = input_line_pointer; + *p = c; + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + as_bad ("Expected comma after name"); + ignore_rest_of_line (); + return; + } + if (*input_line_pointer == '\n') + { + as_bad ("Missing size expression"); + return; + } + input_line_pointer++; + if ((temp = get_absolute_expression ()) < 0) + { + as_warn ("lcomm length (%d.) <0! Ignored.", temp); + ignore_rest_of_line (); + return; + } + *p = 0; + + symbolP = symbol_find_or_make(name); + + if (S_GET_SEGMENT(symbolP) == SEG_UNKNOWN && + S_GET_VALUE(symbolP) == 0) + { + if (! need_pass_2) + { + char *p; + segT current_seg = now_seg; /* save current seg */ + subsegT current_subseg = now_subseg; + + subseg_set (SEG_E2, 1); + symbolP->sy_frag = frag_now; + p = frag_var(rs_org, 1, 1, (relax_substateT)0, symbolP, + temp, (char *)0); + *p = 0; + subseg_set (current_seg, current_subseg); /* restore current seg */ + S_SET_SEGMENT(symbolP, SEG_E2); + S_SET_STORAGE_CLASS(symbolP, C_STAT); + } + } + else + as_bad("Symbol %s already defined", name); + + demand_empty_rest_of_line(); +#endif +} + +static void +fixup_mdeps (frags, h, this_segment) + fragS * frags; + object_headers * h; + segT this_segment; +{ + subseg_change (this_segment, 0); + while (frags) + { + switch (frags->fr_type) + { + case rs_align: + case rs_org: +#ifdef HANDLE_ALIGN + HANDLE_ALIGN (frags); +#endif + frags->fr_type = rs_fill; + frags->fr_offset = + (frags->fr_next->fr_address - frags->fr_address - frags->fr_fix); + break; + case rs_machine_dependent: + md_convert_frag (h, this_segment, frags); + frag_wane (frags); + break; + default: + ; + } + frags = frags->fr_next; + } +} + +#if 1 + +#ifndef TC_FORCE_RELOCATION +#define TC_FORCE_RELOCATION(fix) 0 +#endif + +static void +fixup_segment (segP, this_segment_type) + segment_info_type * segP; + segT this_segment_type; +{ + register fixS * fixP; + register symbolS *add_symbolP; + register symbolS *sub_symbolP; + long add_number; + register int size; + register char *place; + register long where; + register char pcrel; + register fragS *fragP; + register segT add_symbol_segment = absolute_section; + + if (linkrelax) + return; + + for (fixP = segP->fix_root; fixP; fixP = fixP->fx_next) + { + fragP = fixP->fx_frag; + know (fragP); + where = fixP->fx_where; + place = fragP->fr_literal + where; + size = fixP->fx_size; + add_symbolP = fixP->fx_addsy; +#ifdef TC_I960 + if (fixP->fx_tcbit && SF_GET_CALLNAME (add_symbolP)) + { + /* Relocation should be done via the associated 'bal' entry + point symbol. */ + + if (!SF_GET_BALNAME (tc_get_bal_of_call (add_symbolP))) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + "No 'bal' entry point for leafproc %s", + S_GET_NAME (add_symbolP)); + continue; + } + fixP->fx_addsy = add_symbolP = tc_get_bal_of_call (add_symbolP); + } +#endif + sub_symbolP = fixP->fx_subsy; + add_number = fixP->fx_offset; + pcrel = fixP->fx_pcrel; + + if (add_symbolP != NULL + && add_symbolP->sy_mri_common) + { + know (add_symbolP->sy_value.X_op == O_symbol); + add_number += S_GET_VALUE (add_symbolP); + fixP->fx_offset = add_number; + add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol; + } + + if (add_symbolP) + { + add_symbol_segment = S_GET_SEGMENT (add_symbolP); + } /* if there is an addend */ + + if (sub_symbolP) + { + if (add_symbolP == NULL || add_symbol_segment == absolute_section) + { + if (add_symbolP != NULL) + { + add_number += S_GET_VALUE (add_symbolP); + add_symbolP = NULL; + fixP->fx_addsy = NULL; + } + + /* It's just -sym. */ + if (S_GET_SEGMENT (sub_symbolP) == absolute_section) + { + add_number -= S_GET_VALUE (sub_symbolP); + fixP->fx_subsy = 0; + fixP->fx_done = 1; + } + else + { +#ifndef TC_M68K + as_bad_where (fixP->fx_file, fixP->fx_line, + "Negative of non-absolute symbol %s", + S_GET_NAME (sub_symbolP)); +#endif + add_number -= S_GET_VALUE (sub_symbolP); + } /* not absolute */ + + /* if sub_symbol is in the same segment that add_symbol + and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */ + } + else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment + && SEG_NORMAL (add_symbol_segment)) + { + /* Difference of 2 symbols from same segment. Can't + make difference of 2 undefineds: 'value' means + something different for N_UNDF. */ +#ifdef TC_I960 + /* Makes no sense to use the difference of 2 arbitrary symbols + as the target of a call instruction. */ + if (fixP->fx_tcbit) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + "callj to difference of 2 symbols"); + } +#endif /* TC_I960 */ + add_number += S_GET_VALUE (add_symbolP) - + S_GET_VALUE (sub_symbolP); + add_symbolP = NULL; + + if (!TC_FORCE_RELOCATION (fixP)) + { + fixP->fx_addsy = NULL; + fixP->fx_subsy = NULL; + fixP->fx_done = 1; +#ifdef TC_M68K /* is this right? */ + pcrel = 0; + fixP->fx_pcrel = 0; +#endif + } + } + else + { + /* Different segments in subtraction. */ + know (!(S_IS_EXTERNAL (sub_symbolP) && (S_GET_SEGMENT (sub_symbolP) == absolute_section))); + + if ((S_GET_SEGMENT (sub_symbolP) == absolute_section)) + { + add_number -= S_GET_VALUE (sub_symbolP); + } +#ifdef DIFF_EXPR_OK + else if (S_GET_SEGMENT (sub_symbolP) == this_segment_type +#if 0 /* Okay for 68k, at least... */ + && !pcrel +#endif + ) + { + /* Make it pc-relative. */ + add_number += (md_pcrel_from (fixP) + - S_GET_VALUE (sub_symbolP)); + pcrel = 1; + fixP->fx_pcrel = 1; + sub_symbolP = 0; + fixP->fx_subsy = 0; + } +#endif + else + { + as_bad_where (fixP->fx_file, fixP->fx_line, + "Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %ld.", + segment_name (S_GET_SEGMENT (sub_symbolP)), + S_GET_NAME (sub_symbolP), + (long) (fragP->fr_address + where)); + } /* if absolute */ + } + } /* if sub_symbolP */ + + if (add_symbolP) + { + if (add_symbol_segment == this_segment_type && pcrel) + { + /* + * This fixup was made when the symbol's segment was + * SEG_UNKNOWN, but it is now in the local segment. + * So we know how to do the address without relocation. + */ +#ifdef TC_I960 + /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal', + * in which cases it modifies *fixP as appropriate. In the case + * of a 'calls', no further work is required, and *fixP has been + * set up to make the rest of the code below a no-op. + */ + reloc_callj (fixP); +#endif /* TC_I960 */ + + add_number += S_GET_VALUE (add_symbolP); + add_number -= md_pcrel_from (fixP); +#if defined (TC_I386) || defined (TE_LYNX) + /* On the 386 we must adjust by the segment + vaddr as well. Ian Taylor. */ + add_number -= segP->scnhdr.s_vaddr; +#endif + pcrel = 0; /* Lie. Don't want further pcrel processing. */ + if (!TC_FORCE_RELOCATION (fixP)) + { + fixP->fx_addsy = NULL; + fixP->fx_done = 1; + } + } + else + { + switch (add_symbol_segment) + { + case absolute_section: +#ifdef TC_I960 + reloc_callj (fixP); /* See comment about reloc_callj() above*/ +#endif /* TC_I960 */ + add_number += S_GET_VALUE (add_symbolP); + add_symbolP = NULL; + + if (!TC_FORCE_RELOCATION (fixP)) + { + fixP->fx_addsy = NULL; + fixP->fx_done = 1; + } + break; + default: + + +#if defined(TC_A29K) || (defined(TE_PE) && defined(TC_I386)) + /* This really should be handled in the linker, but + backward compatibility forbids. */ + add_number += S_GET_VALUE (add_symbolP); +#else + add_number += S_GET_VALUE (add_symbolP) + + segment_info[S_GET_SEGMENT (add_symbolP)].scnhdr.s_paddr; +#endif + break; + + case SEG_UNKNOWN: +#ifdef TC_I960 + if ((int) fixP->fx_bit_fixP == 13) + { + /* This is a COBR instruction. They have only a + * 13-bit displacement and are only to be used + * for local branches: flag as error, don't generate + * relocation. + */ + as_bad_where (fixP->fx_file, fixP->fx_line, + "can't use COBR format with external label"); + fixP->fx_addsy = NULL; + fixP->fx_done = 1; + continue; + } /* COBR */ +#endif /* TC_I960 */ +#if (defined (TC_I386) || defined (TE_LYNX)) && !defined(TE_PE) + /* 386 COFF uses a peculiar format in which the + value of a common symbol is stored in the .text + segment (I've checked this on SVR3.2 and SCO + 3.2.2) Ian Taylor . */ + if (S_IS_COMMON (add_symbolP)) + add_number += S_GET_VALUE (add_symbolP); +#endif + break; + + + } /* switch on symbol seg */ + } /* if not in local seg */ + } /* if there was a + symbol */ + + if (pcrel) + { +#if !defined(TC_M88K) && !(defined(TE_PE) && defined(TC_I386)) && !defined(TC_A29K) + /* This adjustment is not correct on the m88k, for which the + linker does all the computation. */ + add_number -= md_pcrel_from (fixP); +#endif + if (add_symbolP == 0) + { + fixP->fx_addsy = &abs_symbol; + } /* if there's an add_symbol */ +#if defined (TC_I386) || defined (TE_LYNX) + /* On the 386 we must adjust by the segment vaddr + as well. Ian Taylor. */ + add_number -= segP->scnhdr.s_vaddr; +#endif + } /* if pcrel */ + + if (!fixP->fx_bit_fixP) + { +#ifndef TC_M88K + /* The m88k uses the offset field of the reloc to get around + this problem. */ + if ((size == 1 + && (add_number & ~0xFF) + && ((add_number & ~0xFF) != (-1 & ~0xFF))) + || (size == 2 + && (add_number & ~0xFFFF) + && ((add_number & ~0xFFFF) != (-1 & ~0xFFFF)))) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + "Value of %ld too large for field of %d bytes at 0x%lx", + (long) add_number, size, + (unsigned long) (fragP->fr_address + where)); + } +#endif +#ifdef WARN_SIGNED_OVERFLOW_WORD + /* Warn if a .word value is too large when treated as a + signed number. We already know it is not too negative. + This is to catch over-large switches generated by gcc on + the 68k. */ + if (!flag_signed_overflow_ok + && size == 2 + && add_number > 0x7fff) + as_bad_where (fixP->fx_file, fixP->fx_line, + "Signed .word overflow; switch may be too large; %ld at 0x%lx", + (long) add_number, + (unsigned long) (fragP->fr_address + where)); +#endif + } /* not a bit fix */ + /* Once this fix has been applied, we don't have to output + anything nothing more need be done. */ +#ifdef MD_APPLY_FIX3 + md_apply_fix3 (fixP, &add_number, this_segment_type); +#else + md_apply_fix (fixP, add_number); +#endif + } /* For each fixS in this segment. */ +} /* fixup_segment() */ + +#endif + +/* The first entry in a .stab section is special. */ + +void +obj_coff_init_stab_section (seg) + segT seg; +{ + char *file; + char *p; + char *stabstr_name; + unsigned int stroff; + + /* Make space for this first symbol. */ + p = frag_more (12); + /* Zero it out. */ + memset (p, 0, 12); + as_where (&file, (unsigned int *) NULL); + stabstr_name = (char *) alloca (strlen (segment_info[seg].scnhdr.s_name) + 4); + strcpy (stabstr_name, segment_info[seg].scnhdr.s_name); + strcat (stabstr_name, "str"); + stroff = get_stab_string_offset (file, stabstr_name); + know (stroff == 1); + md_number_to_chars (p, stroff, 4); +} + +/* Fill in the counts in the first entry in a .stab section. */ + +static void +adjust_stab_section(abfd, seg) + bfd *abfd; + segT seg; +{ + segT stabstrseg = SEG_UNKNOWN; + char *secname, *name, *name2; + char *p = NULL; + int i, strsz = 0, nsyms; + fragS *frag = segment_info[seg].frchainP->frch_root; + + /* Look for the associated string table section. */ + + secname = segment_info[seg].scnhdr.s_name; + name = (char *) alloca (strlen (secname) + 4); + strcpy (name, secname); + strcat (name, "str"); + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + name2 = segment_info[i].scnhdr.s_name; + if (name2 != NULL && strncmp(name2, name, 8) == 0) + { + stabstrseg = i; + break; + } + } + + /* If we found the section, get its size. */ + if (stabstrseg != SEG_UNKNOWN) + strsz = size_section (abfd, stabstrseg); + + nsyms = size_section (abfd, seg) / 12 - 1; + + /* Look for the first frag of sufficient size for the initial stab + symbol, and collect a pointer to it. */ + while (frag && frag->fr_fix < 12) + frag = frag->fr_next; + assert (frag != 0); + p = frag->fr_literal; + assert (p != 0); + + /* Write in the number of stab symbols and the size of the string + table. */ + bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6); + bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8); +} + +#endif /* not BFD_ASSEMBLER */ + +const pseudo_typeS obj_pseudo_table[] = +{ + {"def", obj_coff_def, 0}, + {"dim", obj_coff_dim, 0}, + {"endef", obj_coff_endef, 0}, + {"line", obj_coff_line, 0}, + {"ln", obj_coff_ln, 0}, + {"appline", obj_coff_ln, 1}, + {"scl", obj_coff_scl, 0}, + {"size", obj_coff_size, 0}, + {"tag", obj_coff_tag, 0}, + {"type", obj_coff_type, 0}, + {"val", obj_coff_val, 0}, + {"section", obj_coff_section, 0}, + {"sect", obj_coff_section, 0}, + /* FIXME: We ignore the MRI short attribute. */ + {"section.s", obj_coff_section, 0}, + {"sect.s", obj_coff_section, 0}, +#ifndef BFD_ASSEMBLER + {"use", obj_coff_section, 0}, + {"text", obj_coff_text, 0}, + {"data", obj_coff_data, 0}, + {"bss", obj_coff_bss, 0}, + {"lcomm", obj_coff_lcomm, 0}, + {"ident", obj_coff_ident, 0}, +#else + {"optim", s_ignore, 0}, /* For sun386i cc (?) */ + {"ident", s_ignore, 0}, /* we don't yet handle this. */ +#endif + {"ABORT", s_abort, 0}, +#ifdef TC_M88K + /* The m88k uses sdef instead of def. */ + {"sdef", obj_coff_def, 0}, +#endif + {NULL} /* end sentinel */ +}; /* obj_pseudo_table */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-coff.h b/gnu/usr.bin/binutils/gas/config/obj-coff.h new file mode 100644 index 00000000000..b40bd3edba9 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-coff.h @@ -0,0 +1,782 @@ +/* coff object file format + Copyright (C) 1989, 90, 91, 92, 94, 1995 Free Software Foundation, Inc. + + This file is part of GAS. + + 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 2, 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. */ + +#ifndef OBJ_FORMAT_H +#define OBJ_FORMAT_H + +#define OBJ_COFF 1 + +#ifndef BFD_ASSEMBLER + +#define WORKING_DOT_WORD +#define WARN_SIGNED_OVERFLOW_WORD +#define OBJ_COFF_OMIT_OPTIONAL_HEADER +#define BFD_HEADERS +#define BFD + +#endif + +#include "targ-cpu.h" + +#include "bfd.h" + +/* This internal_lineno crap is to stop namespace pollution from the + bfd internal coff headerfile. */ +#define internal_lineno bfd_internal_lineno +#include "coff/internal.h" +#undef internal_lineno + +/* CPU-specific setup: */ + +#ifdef TC_ARM +#include "coff/arm.h" +#ifndef TARGET_FORMAT +#define TARGET_FORMAT "coff-arm" +#endif +#endif + +#ifdef TC_PPC +#ifdef TE_PE +#include "coff/powerpc.h" +#else +#include "coff/rs6000.h" +#endif +#endif + +#ifdef TC_SPARC +#include "coff/sparc.h" +#ifdef TE_LYNX +#define TARGET_FORMAT "coff-sparc-lynx" +#else +#define TARGET_FORMAT "coff-sparc" +#endif +#endif + +#ifdef TC_I386 +#include "coff/i386.h" + +#ifdef TE_PE +#define TARGET_FORMAT "pe-i386" +#endif + +#ifndef TARGET_FORMAT +#define TARGET_FORMAT "coff-i386" +#endif +#endif + +#ifdef TC_M68K +#include "coff/m68k.h" +#ifndef TARGET_FORMAT +#define TARGET_FORMAT "coff-m68k" +#endif +#endif + +#ifdef TC_A29K +#include "coff/a29k.h" +#define TARGET_FORMAT "coff-a29k-big" +#endif + +#ifdef TC_I960 +#include "coff/i960.h" +#define TARGET_FORMAT "coff-Intel-little" +#endif + +#ifdef TC_Z8K +#include "coff/z8k.h" +#define TARGET_FORMAT "coff-z8k" +#endif + +#ifdef TC_H8300 +#include "coff/h8300.h" +#define TARGET_FORMAT "coff-h8300" +#endif + +#ifdef TC_H8500 +#include "coff/h8500.h" +#define TARGET_FORMAT "coff-h8500" +#endif + +#ifdef TC_SH +#include "coff/sh.h" +#define TARGET_FORMAT (shl ? "coff-shl" : "coff-sh") +#endif + +#ifdef TC_M88K +#include "coff/m88k.h" +#define TARGET_FORMAT "coff-m88kbcs" +#endif + +#ifdef TC_W65 +#include "coff/w65.h" +#define TARGET_FORMAT "coff-w65" +#endif + +/* Targets may also set this. Also, if BFD_ASSEMBLER is defined, this + will already have been defined. */ +#undef SYMBOLS_NEED_BACKPOINTERS +#define SYMBOLS_NEED_BACKPOINTERS 1 + +#ifndef OBJ_COFF_MAX_AUXENTRIES +#define OBJ_COFF_MAX_AUXENTRIES 1 +#endif /* OBJ_COFF_MAX_AUXENTRIES */ + +/* *********************************************************************** + + This file really contains two implementations of the COFF back end. + They are in the process of being merged, but this is only a + preliminary, mechanical merging. Many definitions that are + identical between the two are still found in both versions. + + The first version, with BFD_ASSEMBLER defined, uses high-level BFD + interfaces and data structures. The second version, with + BFD_ASSEMBLER not defined, also uses BFD, but mostly for swapping + data structures and for doing the actual I/O. The latter defines + the preprocessor symbols BFD and BFD_HEADERS. Try not to let this + confuse you. + + These two are in the process of being merged, and eventually the + BFD_ASSEMBLER version should take over completely. Release timing + issues and namespace problems convinced me to merge the two + together in this fashion, a little sooner than I would have liked. + The real merge should be much better done by the time the next + release comes out. + + For now, the structure of this file is: + + #ifdef BFD_ASSEMBLER + + #else + + #endif + + Unfortunately, the common portions are very small at the moment, + and many declarations or definitions are duplicated. The structure + of obj-coff.c is similar. + + See doc/internals.texi for a brief discussion of the history, if + you care. + + Ken Raeburn, 5 May 1994 + + *********************************************************************** */ + +#ifdef BFD_ASSEMBLER + +#include "bfd/libcoff.h" + +#define OUTPUT_FLAVOR bfd_target_coff_flavour + +/* SYMBOL TABLE */ + +/* Alter the field names, for now, until we've fixed up the other + references to use the new name. */ +#ifdef TC_I960 +#define TC_SYMFIELD_TYPE struct symbol * +#define sy_tc bal +#endif + +#define OBJ_SYMFIELD_TYPE unsigned long +#define sy_obj sy_flags + +#define SYM_AUXENT(S) (&coffsymbol ((S)->bsym)->native[1].u.auxent) + +#define DO_NOT_STRIP 0 +#define DO_STRIP 1 + +extern void obj_coff_section PARAMS ((int)); + +/* The number of auxiliary entries */ +#define S_GET_NUMBER_AUXILIARY(s) (coffsymbol((s)->bsym)->native->u.syment.n_numaux) +/* The number of auxiliary entries */ +#define S_SET_NUMBER_AUXILIARY(s,v) (S_GET_NUMBER_AUXILIARY (s) = (v)) + +/* True if a symbol name is in the string table, i.e. its length is > 8. */ +#define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0) + +extern int S_SET_DATA_TYPE PARAMS ((struct symbol *, int)); +extern int S_SET_STORAGE_CLASS PARAMS ((struct symbol *, int)); +extern int S_GET_STORAGE_CLASS PARAMS ((struct symbol *)); +extern void SA_SET_SYM_ENDNDX PARAMS ((struct symbol *, struct symbol *)); + +/* Auxiliary entry macros. SA_ stands for symbol auxiliary */ +/* Omit the tv related fields */ +/* Accessors */ + +#define SA_GET_SYM_TAGNDX(s) (SYM_AUXENT (s)->x_sym.x_tagndx.l) +#define SA_GET_SYM_LNNO(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno) +#define SA_GET_SYM_SIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size) +#define SA_GET_SYM_FSIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize) +#define SA_GET_SYM_LNNOPTR(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr) +#define SA_GET_SYM_ENDNDX(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx) +#define SA_GET_SYM_DIMEN(s,i) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]) +#define SA_GET_FILE_FNAME(s) (SYM_AUXENT (s)->x_file.x_fname) +#define SA_GET_SCN_SCNLEN(s) (SYM_AUXENT (s)->x_scn.x_scnlen) +#define SA_GET_SCN_NRELOC(s) (SYM_AUXENT (s)->x_scn.x_nreloc) +#define SA_GET_SCN_NLINNO(s) (SYM_AUXENT (s)->x_scn.x_nlinno) + +#define SA_SET_SYM_LNNO(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno=(v)) +#define SA_SET_SYM_SIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size=(v)) +#define SA_SET_SYM_FSIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize=(v)) +#define SA_SET_SYM_LNNOPTR(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr=(v)) +#define SA_SET_SYM_DIMEN(s,i,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v)) +#define SA_SET_FILE_FNAME(s,v) strncpy(SYM_AUXENT (s)->x_file.x_fname,(v),FILNMLEN) +#define SA_SET_SCN_SCNLEN(s,v) (SYM_AUXENT (s)->x_scn.x_scnlen=(v)) +#define SA_SET_SCN_NRELOC(s,v) (SYM_AUXENT (s)->x_scn.x_nreloc=(v)) +#define SA_SET_SCN_NLINNO(s,v) (SYM_AUXENT (s)->x_scn.x_nlinno=(v)) + +/* + * Internal use only definitions. SF_ stands for symbol flags. + * + * These values can be assigned to sy_symbol.ost_flags field of a symbolS. + * + * You'll break i960 if you shift the SYSPROC bits anywhere else. for + * more on the balname/callname hack, see tc-i960.h. b.out is done + * differently. + */ + +#define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */ +#define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */ +#define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */ +#define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */ +#define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */ + +#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */ + +#define SF_STATICS (0x00001000) /* Mark the .text & all symbols */ +#define SF_DEFINED (0x00002000) /* Symbol is defined in this file */ +#define SF_STRING (0x00004000) /* Symbol name length > 8 */ +#define SF_LOCAL (0x00008000) /* Symbol must not be emitted */ + +#define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */ + +#define SF_FUNCTION (0x00010000) /* The symbol is a function */ +#define SF_PROCESS (0x00020000) /* Process symbol before write */ +#define SF_TAGGED (0x00040000) /* Is associated with a tag */ +#define SF_TAG (0x00080000) /* Is a tag */ +#define SF_DEBUG (0x00100000) /* Is in debug or abs section */ +#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */ +/* All other bits are unused. */ + +/* Accessors */ +#define SF_GET(s) ((s)->sy_flags) +#define SF_GET_DEBUG(s) ((s)->bsym->flags & BSF_DEBUGGING) +#define SF_SET_DEBUG(s) ((s)->bsym->flags |= BSF_DEBUGGING) +#define SF_GET_NORMAL_FIELD(s) (SF_GET (s) & SF_NORMAL_MASK) +#define SF_GET_DEBUG_FIELD(s) (SF_GET (s) & SF_DEBUG_MASK) +#define SF_GET_FILE(s) (SF_GET (s) & SF_FILE) +#define SF_GET_STATICS(s) (SF_GET (s) & SF_STATICS) +#define SF_GET_DEFINED(s) (SF_GET (s) & SF_DEFINED) +#define SF_GET_STRING(s) (SF_GET (s) & SF_STRING) +#define SF_GET_LOCAL(s) (SF_GET (s) & SF_LOCAL) +#define SF_GET_FUNCTION(s) (SF_GET (s) & SF_FUNCTION) +#define SF_GET_PROCESS(s) (SF_GET (s) & SF_PROCESS) +#define SF_GET_TAGGED(s) (SF_GET (s) & SF_TAGGED) +#define SF_GET_TAG(s) (SF_GET (s) & SF_TAG) +#define SF_GET_GET_SEGMENT(s) (SF_GET (s) & SF_GET_SEGMENT) +#define SF_GET_I960(s) (SF_GET (s) & SF_I960_MASK) /* used by i960 */ +#define SF_GET_BALNAME(s) (SF_GET (s) & SF_BALNAME) /* used by i960 */ +#define SF_GET_CALLNAME(s) (SF_GET (s) & SF_CALLNAME) /* used by i960 */ +#define SF_GET_IS_SYSPROC(s) (SF_GET (s) & SF_IS_SYSPROC) /* used by i960 */ +#define SF_GET_SYSPROC(s) (SF_GET (s) & SF_SYSPROC) /* used by i960 */ + +/* Modifiers */ +#define SF_SET(s,v) (SF_GET (s) = (v)) +#define SF_SET_NORMAL_FIELD(s,v)(SF_GET (s) |= ((v) & SF_NORMAL_MASK)) +#define SF_SET_DEBUG_FIELD(s,v) (SF_GET (s) |= ((v) & SF_DEBUG_MASK)) +#define SF_SET_FILE(s) (SF_GET (s) |= SF_FILE) +#define SF_SET_STATICS(s) (SF_GET (s) |= SF_STATICS) +#define SF_SET_DEFINED(s) (SF_GET (s) |= SF_DEFINED) +#define SF_SET_STRING(s) (SF_GET (s) |= SF_STRING) +#define SF_SET_LOCAL(s) (SF_GET (s) |= SF_LOCAL) +#define SF_CLEAR_LOCAL(s) (SF_GET (s) &= ~SF_LOCAL) +#define SF_SET_FUNCTION(s) (SF_GET (s) |= SF_FUNCTION) +#define SF_SET_PROCESS(s) (SF_GET (s) |= SF_PROCESS) +#define SF_SET_TAGGED(s) (SF_GET (s) |= SF_TAGGED) +#define SF_SET_TAG(s) (SF_GET (s) |= SF_TAG) +#define SF_SET_GET_SEGMENT(s) (SF_GET (s) |= SF_GET_SEGMENT) +#define SF_SET_I960(s,v) (SF_GET (s) |= ((v) & SF_I960_MASK)) /* used by i960 */ +#define SF_SET_BALNAME(s) (SF_GET (s) |= SF_BALNAME) /* used by i960 */ +#define SF_SET_CALLNAME(s) (SF_GET (s) |= SF_CALLNAME) /* used by i960 */ +#define SF_SET_IS_SYSPROC(s) (SF_GET (s) |= SF_IS_SYSPROC) /* used by i960 */ +#define SF_SET_SYSPROC(s,v) (SF_GET (s) |= ((v) & SF_SYSPROC)) /* used by i960 */ + +/* -------------- Line number handling ------- */ +extern int text_lineno_number; +extern int coff_line_base; +extern int coff_n_line_nos; + +#define obj_emit_lineno(WHERE,LINE,FILE_START) abort () +extern void coff_add_linesym PARAMS ((struct symbol *)); + + +void c_dot_file_symbol PARAMS ((char *filename)); +#define obj_app_file c_dot_file_symbol + +extern void coff_frob_symbol PARAMS ((struct symbol *, int *)); +extern void coff_adjust_symtab PARAMS ((void)); +extern void coff_frob_section PARAMS ((segT)); +extern void coff_adjust_section_syms PARAMS ((bfd *, asection *, PTR)); +extern void coff_frob_file PARAMS ((void)); +#define obj_frob_symbol(S,P) coff_frob_symbol(S,&P) +#define obj_adjust_symtab() coff_adjust_symtab() +#define obj_frob_section(S) coff_frob_section (S) +#define obj_frob_file() coff_frob_file () + +extern struct symbol *coff_last_function; + +/* Forward the segment of a forwarded symbol, handle assignments that + just copy symbol values, etc. */ +#ifndef TE_I386AIX +#define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src) \ + (SF_GET_GET_SEGMENT (dest) \ + ? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \ + : 0) +#else +#define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src) \ + (SF_GET_GET_SEGMENT (dest) && S_GET_SEGMENT (dest) == SEG_UNKNOWN \ + ? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \ + : 0) +#endif + +/* sanity check */ + +#ifdef TC_I960 +#ifndef C_LEAFSTAT +hey ! Where is the C_LEAFSTAT definition ? i960 - coff support is depending on it. +#endif /* no C_LEAFSTAT */ +#endif /* TC_I960 */ + +#else /* not BFD_ASSEMBLER */ + +#ifdef TC_A29K +/* Allow translate from aout relocs to coff relocs */ +#define NO_RELOC 20 +#define RELOC_32 1 +#define RELOC_8 2 +#define RELOC_CONST 3 +#define RELOC_CONSTH 4 +#define RELOC_JUMPTARG 5 +#define RELOC_BASE22 6 +#define RELOC_HI22 7 +#define RELOC_LO10 8 +#define RELOC_BASE13 9 +#define RELOC_WDISP22 10 +#define RELOC_WDISP30 11 +#endif + +extern const segT N_TYPE_seg[]; + +/* Magic number of paged executable. */ +#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 0x8300 + + +/* SYMBOL TABLE */ + +/* Symbol table entry data type */ + +typedef struct +{ + /* Basic symbol */ + struct internal_syment ost_entry; + /* Auxiliary entry. */ + union internal_auxent ost_auxent[OBJ_COFF_MAX_AUXENTRIES]; + /* obj_coff internal use only flags */ + unsigned int ost_flags; +} obj_symbol_type; + +#ifndef DO_NOT_STRIP +#define DO_NOT_STRIP 0 +#define DO_STRIP 1 +#endif +/* Symbol table macros and constants */ + +/* Possible and usefull section number in symbol table + * The values of TEXT, DATA and BSS may not be portable. + */ + +#define C_ABS_SECTION N_ABS +#define C_UNDEF_SECTION N_UNDEF +#define C_DEBUG_SECTION N_DEBUG +#define C_NTV_SECTION N_TV +#define C_PTV_SECTION P_TV +#define C_REGISTER_SECTION 20 + +/* + * Macros to extract information from a symbol table entry. + * This syntaxic indirection allows independence regarding a.out or coff. + * The argument (s) of all these macros is a pointer to a symbol table entry. + */ + +/* Predicates */ +/* True if the symbol is external */ +#define S_IS_EXTERNAL(s) ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION) +/* True if symbol has been defined, ie : + section > 0 (DATA, TEXT or BSS) + section == 0 and value > 0 (external bss symbol) */ +#define S_IS_DEFINED(s) \ + ((s)->sy_symbol.ost_entry.n_scnum > C_UNDEF_SECTION \ + || ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION \ + && S_GET_VALUE (s) > 0) \ + || ((s)->sy_symbol.ost_entry.n_scnum == C_ABS_SECTION)) +/* True if a debug special symbol entry */ +#define S_IS_DEBUG(s) ((s)->sy_symbol.ost_entry.n_scnum == C_DEBUG_SECTION) +/* True if a symbol is local symbol name */ +/* A symbol name whose name includes ^A is a gas internal pseudo symbol */ +#define S_IS_LOCAL(s) \ + ((s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION \ + || (S_LOCAL_NAME(s) && !flag_keep_locals) \ + || (strchr (S_GET_NAME (s), '\001') != NULL)) +/* True if a symbol is not defined in this file */ +#define S_IS_EXTERN(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 \ + && S_GET_VALUE (s) == 0) +/* + * True if a symbol can be multiply defined (bss symbols have this def + * though it is bad practice) + */ +#define S_IS_COMMON(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 \ + && S_GET_VALUE (s) != 0) +/* True if a symbol name is in the string table, i.e. its length is > 8. */ +#define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0) + +/* Accessors */ +/* The name of the symbol */ +#define S_GET_NAME(s) ((char*)(s)->sy_symbol.ost_entry.n_offset) +/* The pointer to the string table */ +#define S_GET_OFFSET(s) ((s)->sy_symbol.ost_entry.n_offset) +/* The numeric value of the segment */ +#define S_GET_SEGMENT(s) s_get_segment(s) +/* The data type */ +#define S_GET_DATA_TYPE(s) ((s)->sy_symbol.ost_entry.n_type) +/* The storage class */ +#define S_GET_STORAGE_CLASS(s) ((s)->sy_symbol.ost_entry.n_sclass) +/* The number of auxiliary entries */ +#define S_GET_NUMBER_AUXILIARY(s) ((s)->sy_symbol.ost_entry.n_numaux) + +/* Modifiers */ +/* Set the name of the symbol */ +#define S_SET_NAME(s,v) ((s)->sy_symbol.ost_entry.n_offset = (unsigned long)(v)) +/* Set the offset of the symbol */ +#define S_SET_OFFSET(s,v) ((s)->sy_symbol.ost_entry.n_offset = (v)) +/* The numeric value of the segment */ +#define S_SET_SEGMENT(s,v) ((s)->sy_symbol.ost_entry.n_scnum = SEGMENT_TO_SYMBOL_TYPE(v)) +/* The data type */ +#define S_SET_DATA_TYPE(s,v) ((s)->sy_symbol.ost_entry.n_type = (v)) +/* The storage class */ +#define S_SET_STORAGE_CLASS(s,v) ((s)->sy_symbol.ost_entry.n_sclass = (v)) +/* The number of auxiliary entries */ +#define S_SET_NUMBER_AUXILIARY(s,v) ((s)->sy_symbol.ost_entry.n_numaux = (v)) + +/* Additional modifiers */ +/* The symbol is external (does not mean undefined) */ +#define S_SET_EXTERNAL(s) { S_SET_STORAGE_CLASS(s, C_EXT) ; SF_CLEAR_LOCAL(s); } + +/* Auxiliary entry macros. SA_ stands for symbol auxiliary */ +/* Omit the tv related fields */ +/* Accessors */ +#define SYM_AUXENT(S) (&(S)->sy_symbol.ost_auxent[0]) + +#define SA_GET_SYM_TAGNDX(s) (SYM_AUXENT (s)->x_sym.x_tagndx.l) +#define SA_GET_SYM_LNNO(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno) +#define SA_GET_SYM_SIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size) +#define SA_GET_SYM_FSIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize) +#define SA_GET_SYM_LNNOPTR(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr) +#define SA_GET_SYM_ENDNDX(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx.l) +#define SA_GET_SYM_DIMEN(s,i) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]) +#define SA_GET_FILE_FNAME(s) (SYM_AUXENT (s)->x_file.x_fname) +#define SA_GET_FILE_FNAME_OFFSET(s) (SYM_AUXENT (s)->x_file.x_n.x_offset) +#define SA_GET_FILE_FNAME_ZEROS(s) (SYM_AUXENT (s)->x_file.x_n.x_zeroes) +#define SA_GET_SCN_SCNLEN(s) (SYM_AUXENT (s)->x_scn.x_scnlen) +#define SA_GET_SCN_NRELOC(s) (SYM_AUXENT (s)->x_scn.x_nreloc) +#define SA_GET_SCN_NLINNO(s) (SYM_AUXENT (s)->x_scn.x_nlinno) + +/* Modifiers */ +#define SA_SET_SYM_TAGNDX(s,v) (SYM_AUXENT (s)->x_sym.x_tagndx.l=(v)) +#define SA_SET_SYM_LNNO(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno=(v)) +#define SA_SET_SYM_SIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size=(v)) +#define SA_SET_SYM_FSIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize=(v)) +#define SA_SET_SYM_LNNOPTR(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr=(v)) +#define SA_SET_SYM_ENDNDX(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx.l=(v)) +#define SA_SET_SYM_DIMEN(s,i,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v)) +#define SA_SET_FILE_FNAME(s,v) strncpy(SYM_AUXENT (s)->x_file.x_fname,(v),FILNMLEN) +#define SA_SET_FILE_FNAME_OFFSET(s,v) (SYM_AUXENT (s)->x_file.x_n.x_offset=(v)) +#define SA_SET_FILE_FNAME_ZEROS(s,v) (SYM_AUXENT (s)->x_file.x_n.x_zeroes=(v)) +#define SA_SET_SCN_SCNLEN(s,v) (SYM_AUXENT (s)->x_scn.x_scnlen=(v)) +#define SA_SET_SCN_NRELOC(s,v) (SYM_AUXENT (s)->x_scn.x_nreloc=(v)) +#define SA_SET_SCN_NLINNO(s,v) (SYM_AUXENT (s)->x_scn.x_nlinno=(v)) + +/* + * Internal use only definitions. SF_ stands for symbol flags. + * + * These values can be assigned to sy_symbol.ost_flags field of a symbolS. + * + * You'll break i960 if you shift the SYSPROC bits anywhere else. for + * more on the balname/callname hack, see tc-i960.h. b.out is done + * differently. + */ + +#define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */ +#define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */ +#define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */ +#define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */ +#define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */ + +#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */ + +#define SF_STATICS (0x00001000) /* Mark the .text & all symbols */ +#define SF_DEFINED (0x00002000) /* Symbol is defined in this file */ +#define SF_STRING (0x00004000) /* Symbol name length > 8 */ +#define SF_LOCAL (0x00008000) /* Symbol must not be emitted */ + +#define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */ + +#define SF_FUNCTION (0x00010000) /* The symbol is a function */ +#define SF_PROCESS (0x00020000) /* Process symbol before write */ +#define SF_TAGGED (0x00040000) /* Is associated with a tag */ +#define SF_TAG (0x00080000) /* Is a tag */ +#define SF_DEBUG (0x00100000) /* Is in debug or abs section */ +#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */ +/* All other bits are unused. */ + +/* Accessors */ +#define SF_GET(s) ((s)->sy_symbol.ost_flags) +#define SF_GET_NORMAL_FIELD(s) (SF_GET (s) & SF_NORMAL_MASK) +#define SF_GET_DEBUG_FIELD(s) (SF_GET (s) & SF_DEBUG_MASK) +#define SF_GET_FILE(s) (SF_GET (s) & SF_FILE) +#define SF_GET_STATICS(s) (SF_GET (s) & SF_STATICS) +#define SF_GET_DEFINED(s) (SF_GET (s) & SF_DEFINED) +#define SF_GET_STRING(s) (SF_GET (s) & SF_STRING) +#define SF_GET_LOCAL(s) (SF_GET (s) & SF_LOCAL) +#define SF_GET_FUNCTION(s) (SF_GET (s) & SF_FUNCTION) +#define SF_GET_PROCESS(s) (SF_GET (s) & SF_PROCESS) +#define SF_GET_DEBUG(s) (SF_GET (s) & SF_DEBUG) +#define SF_GET_TAGGED(s) (SF_GET (s) & SF_TAGGED) +#define SF_GET_TAG(s) (SF_GET (s) & SF_TAG) +#define SF_GET_GET_SEGMENT(s) (SF_GET (s) & SF_GET_SEGMENT) +#define SF_GET_I960(s) (SF_GET (s) & SF_I960_MASK) /* used by i960 */ +#define SF_GET_BALNAME(s) (SF_GET (s) & SF_BALNAME) /* used by i960 */ +#define SF_GET_CALLNAME(s) (SF_GET (s) & SF_CALLNAME) /* used by i960 */ +#define SF_GET_IS_SYSPROC(s) (SF_GET (s) & SF_IS_SYSPROC) /* used by i960 */ +#define SF_GET_SYSPROC(s) (SF_GET (s) & SF_SYSPROC) /* used by i960 */ + +/* Modifiers */ +#define SF_SET(s,v) (SF_GET (s) = (v)) +#define SF_SET_NORMAL_FIELD(s,v)(SF_GET (s) |= ((v) & SF_NORMAL_MASK)) +#define SF_SET_DEBUG_FIELD(s,v) (SF_GET (s) |= ((v) & SF_DEBUG_MASK)) +#define SF_SET_FILE(s) (SF_GET (s) |= SF_FILE) +#define SF_SET_STATICS(s) (SF_GET (s) |= SF_STATICS) +#define SF_SET_DEFINED(s) (SF_GET (s) |= SF_DEFINED) +#define SF_SET_STRING(s) (SF_GET (s) |= SF_STRING) +#define SF_SET_LOCAL(s) (SF_GET (s) |= SF_LOCAL) +#define SF_CLEAR_LOCAL(s) (SF_GET (s) &= ~SF_LOCAL) +#define SF_SET_FUNCTION(s) (SF_GET (s) |= SF_FUNCTION) +#define SF_SET_PROCESS(s) (SF_GET (s) |= SF_PROCESS) +#define SF_SET_DEBUG(s) (SF_GET (s) |= SF_DEBUG) +#define SF_SET_TAGGED(s) (SF_GET (s) |= SF_TAGGED) +#define SF_SET_TAG(s) (SF_GET (s) |= SF_TAG) +#define SF_SET_GET_SEGMENT(s) (SF_GET (s) |= SF_GET_SEGMENT) +#define SF_SET_I960(s,v) (SF_GET (s) |= ((v) & SF_I960_MASK)) /* used by i960 */ +#define SF_SET_BALNAME(s) (SF_GET (s) |= SF_BALNAME) /* used by i960 */ +#define SF_SET_CALLNAME(s) (SF_GET (s) |= SF_CALLNAME) /* used by i960 */ +#define SF_SET_IS_SYSPROC(s) (SF_GET (s) |= SF_IS_SYSPROC) /* used by i960 */ +#define SF_SET_SYSPROC(s,v) (SF_GET (s) |= ((v) & SF_SYSPROC)) /* used by i960 */ + +/* File header macro and type definition */ + +/* + * File position calculators. Beware to use them when all the + * appropriate fields are set in the header. + */ + +#ifdef OBJ_COFF_OMIT_OPTIONAL_HEADER +#define OBJ_COFF_AOUTHDRSZ (0) +#else +#define OBJ_COFF_AOUTHDRSZ (AOUTHDRSZ) +#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ + +#define H_GET_FILE_SIZE(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ + H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h) + \ + H_GET_SYMBOL_TABLE_SIZE(h) + \ + (h)->string_table_size) +#define H_GET_TEXT_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ) +#define H_GET_DATA_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h)) +#define H_GET_BSS_FILE_OFFSET(h) 0 +#define H_GET_RELOCATION_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h)) +#define H_GET_LINENO_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ + H_GET_RELOCATION_SIZE(h)) +#define H_GET_SYMBOL_TABLE_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ + H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h)) + +/* Accessors */ +/* aouthdr */ +#define H_GET_MAGIC_NUMBER(h) ((h)->aouthdr.magic) +#define H_GET_VERSION_STAMP(h) ((h)->aouthdr.vstamp) +#define H_GET_TEXT_SIZE(h) ((h)->aouthdr.tsize) +#define H_GET_DATA_SIZE(h) ((h)->aouthdr.dsize) +#define H_GET_BSS_SIZE(h) ((h)->aouthdr.bsize) +#define H_GET_ENTRY_POINT(h) ((h)->aouthdr.entry) +#define H_GET_TEXT_START(h) ((h)->aouthdr.text_start) +#define H_GET_DATA_START(h) ((h)->aouthdr.data_start) +/* filehdr */ +#define H_GET_FILE_MAGIC_NUMBER(h) ((h)->filehdr.f_magic) +#define H_GET_NUMBER_OF_SECTIONS(h) ((h)->filehdr.f_nscns) +#define H_GET_TIME_STAMP(h) ((h)->filehdr.f_timdat) +#define H_GET_SYMBOL_TABLE_POINTER(h) ((h)->filehdr.f_symptr) +#define H_GET_SYMBOL_COUNT(h) ((h)->filehdr.f_nsyms) +#define H_GET_SYMBOL_TABLE_SIZE(h) (H_GET_SYMBOL_COUNT(h) * SYMESZ) +#define H_GET_SIZEOF_OPTIONAL_HEADER(h) ((h)->filehdr.f_opthdr) +#define H_GET_FLAGS(h) ((h)->filehdr.f_flags) +/* Extra fields to achieve bsd a.out compatibility and for convenience */ +#define H_GET_RELOCATION_SIZE(h) ((h)->relocation_size) +#define H_GET_STRING_SIZE(h) ((h)->string_table_size) +#define H_GET_LINENO_SIZE(h) ((h)->lineno_size) + +#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER +#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \ + + sizeof(AOUTHDR)\ + + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)) +#else /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ +#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \ + + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)) +#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ + +#define H_GET_TEXT_RELOCATION_SIZE(h) (text_section_header.s_nreloc * RELSZ) +#define H_GET_DATA_RELOCATION_SIZE(h) (data_section_header.s_nreloc * RELSZ) + +/* Modifiers */ +/* aouthdr */ +#define H_SET_MAGIC_NUMBER(h,v) ((h)->aouthdr.magic = (v)) +#define H_SET_VERSION_STAMP(h,v) ((h)->aouthdr.vstamp = (v)) +#define H_SET_TEXT_SIZE(h,v) ((h)->aouthdr.tsize = (v)) +#define H_SET_DATA_SIZE(h,v) ((h)->aouthdr.dsize = (v)) +#define H_SET_BSS_SIZE(h,v) ((h)->aouthdr.bsize = (v)) +#define H_SET_ENTRY_POINT(h,v) ((h)->aouthdr.entry = (v)) +#define H_SET_TEXT_START(h,v) ((h)->aouthdr.text_start = (v)) +#define H_SET_DATA_START(h,v) ((h)->aouthdr.data_start = (v)) +/* filehdr */ +#define H_SET_FILE_MAGIC_NUMBER(h,v) ((h)->filehdr.f_magic = (v)) +#define H_SET_NUMBER_OF_SECTIONS(h,v) ((h)->filehdr.f_nscns = (v)) +#define H_SET_TIME_STAMP(h,v) ((h)->filehdr.f_timdat = (v)) +#define H_SET_SYMBOL_TABLE_POINTER(h,v) ((h)->filehdr.f_symptr = (v)) +#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->filehdr.f_nsyms = (v)) +#define H_SET_SIZEOF_OPTIONAL_HEADER(h,v) ((h)->filehdr.f_opthdr = (v)) +#define H_SET_FLAGS(h,v) ((h)->filehdr.f_flags = (v)) +/* Extra fields to achieve bsd a.out compatibility and for convinience */ +#define H_SET_RELOCATION_SIZE(h,t,d) ((h)->relocation_size = (t)+(d)) +#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) +#define H_SET_LINENO_SIZE(h,v) ((h)->lineno_size = (v)) + +/* Segment flipping */ + +typedef struct +{ + struct internal_aouthdr aouthdr; /* a.out header */ + struct internal_filehdr filehdr; /* File header, not machine dep. */ + long string_table_size; /* names + '\0' + sizeof(int) */ + long relocation_size; /* Cumulated size of relocation + information for all sections in + bytes. */ + long lineno_size; /* Size of the line number information + table in bytes */ +} object_headers; + + + +struct lineno_list +{ + struct bfd_internal_lineno line; + char *frag; /* Frag to which the line number is related */ + struct lineno_list *next; /* Forward chain pointer */ +}; + + + + +#define obj_segment_name(i) (segment_info[(int) (i)].scnhdr.s_name) + +#define obj_add_segment(s) obj_coff_add_segment (s) + +extern segT obj_coff_add_segment PARAMS ((const char *)); + +extern void obj_coff_section PARAMS ((int)); + +extern void c_dot_file_symbol PARAMS ((char *filename)); +#define obj_app_file c_dot_file_symbol +extern void obj_extra_stuff PARAMS ((object_headers * headers)); + +extern segT s_get_segment PARAMS ((struct symbol * ptr)); + +extern void c_section_header PARAMS ((struct internal_scnhdr * header, + char *name, + long core_address, + long size, + long data_ptr, + long reloc_ptr, + long lineno_ptr, + long reloc_number, + long lineno_number, + long alignment)); + +#ifndef tc_coff_symbol_emit_hook +void tc_coff_symbol_emit_hook PARAMS ((struct symbol *)); +#endif + +/* sanity check */ + +#ifdef TC_I960 +#ifndef C_LEAFSTAT +hey ! Where is the C_LEAFSTAT definition ? i960 - coff support is depending on it. +#endif /* no C_LEAFSTAT */ +#endif /* TC_I960 */ +extern struct internal_scnhdr data_section_header; +extern struct internal_scnhdr text_section_header; + +/* Forward the segment of a forwarded symbol. */ +#define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src) \ + (SF_GET_GET_SEGMENT (dest) \ + ? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \ + : 0) + +#endif /* not BFD_ASSEMBLER */ + +/* Stabs in a coff file go into their own section. */ +#define SEPARATE_STAB_SECTIONS 1 + +/* We need 12 bytes at the start of the section to hold some initial + information. */ +extern void obj_coff_init_stab_section PARAMS ((segT)); +#define INIT_STAB_SECTION(seg) obj_coff_init_stab_section (seg) + +#endif /* OBJ_FORMAT_H */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-ecoff.c b/gnu/usr.bin/binutils/gas/config/obj-ecoff.c new file mode 100644 index 00000000000..6bd62a1bf58 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-ecoff.c @@ -0,0 +1,299 @@ +/* ECOFF object file format. + Copyright (C) 1993, 1994 Free Software Foundation, Inc. + Contributed by Cygnus Support. + This file was put together by Ian Lance Taylor . + + This file is part of GAS. + + 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 2, 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. */ + +#define OBJ_HEADER "obj-ecoff.h" +#include "as.h" +#include "coff/internal.h" +#include "bfd/libcoff.h" +#include "bfd/libecoff.h" + +/* Almost all of the ECOFF support is actually in ecoff.c in the main + gas directory. This file mostly just arranges to call that one at + the right times. */ + +/* These are the pseudo-ops we support in this file. Only those + relating to debugging information are supported here. + + The following pseudo-ops from the Kane and Heinrich MIPS book + should be defined here, but are currently unsupported: .aent, + .bgnb, .endb, .verstamp, .vreg. + + The following pseudo-ops from the Kane and Heinrich MIPS book are + MIPS CPU specific, and should be defined by tc-mips.c: .alias, + .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option, + .rdata, .sdata, .set. + + The following pseudo-ops from the Kane and Heinrich MIPS book are + not MIPS CPU specific, but are also not ECOFF specific. I have + only listed the ones which are not already in read.c. It's not + completely clear where these should be defined, but tc-mips.c is + probably the most reasonable place: .asciiz, .asm0, .endr, .err, + .half, .lab, .repeat, .struct, .weakext. */ + +const pseudo_typeS obj_pseudo_table[] = +{ + /* COFF style debugging information. .ln is not used; .loc is used + instead. */ + { "def", ecoff_directive_def, 0 }, + { "dim", ecoff_directive_dim, 0 }, + { "endef", ecoff_directive_endef, 0 }, + { "file", ecoff_directive_file, 0 }, + { "scl", ecoff_directive_scl, 0 }, + { "size", ecoff_directive_size, 0 }, + { "esize", ecoff_directive_size, 0 }, + { "tag", ecoff_directive_tag, 0 }, + { "type", ecoff_directive_type, 0 }, + { "etype", ecoff_directive_type, 0 }, + { "val", ecoff_directive_val, 0 }, + + /* ECOFF specific debugging information. */ + { "begin", ecoff_directive_begin, 0 }, + { "bend", ecoff_directive_bend, 0 }, + { "end", ecoff_directive_end, 0 }, + { "ent", ecoff_directive_ent, 0 }, + { "fmask", ecoff_directive_fmask, 0 }, + { "frame", ecoff_directive_frame, 0 }, + { "loc", ecoff_directive_loc, 0 }, + { "mask", ecoff_directive_mask, 0 }, + + /* Other ECOFF directives. */ + { "extern", ecoff_directive_extern, 0 }, + { "weakext", ecoff_directive_weakext, 0 }, + + /* These are used on Irix. I don't know how to implement them. */ + { "bgnb", s_ignore, 0 }, + { "endb", s_ignore, 0 }, + { "verstamp", s_ignore, 0 }, + + /* Sentinel. */ + { NULL } +}; + +/* Swap out the symbols and debugging information for BFD. */ + +void +ecoff_frob_file () +{ + const struct ecoff_debug_swap * const debug_swap + = &ecoff_backend (stdoutput)->debug_swap; + bfd_vma addr; + asection *sec; + HDRR *hdr; + char *buf; + char *set; + + /* Set the section VMA values. We force the .sdata and .sbss + sections to the end to ensure that their VMA addresses are close + together so that the GP register can address both of them. We + put the .bss section after the .sbss section. + + Also, for the Alpha, we must sort the sections, to make sure they + appear in the output file in the correct order. (Actually, maybe + this is a job for BFD. But the VMAs computed would be out of + whack if we computed them given our initial, random ordering. + It's possible that that wouldn't break things; I could do some + experimenting sometime and find out. + + This output ordering of sections is magic, on the Alpha, at + least. The .lita section must come before .lit8 and .lit4, + otherwise the OSF/1 linker may silently trash the .lit{4,8} + section contents. Also, .text must preceed .rdata. These differ + from the order described in some parts of the DEC OSF/1 Assembly + Language Programmer's Guide, but that order doesn't seem to work + with their linker. + + I don't know if section ordering on the MIPS is important. */ + + static const char *const names[] = { + /* text segment */ + ".text", ".rdata", ".init", ".fini", + /* data segment */ + ".data", ".lita", ".lit8", ".lit4", ".sdata", ".got", + /* bss segment */ + ".sbss", ".bss", + }; +#define n_names (sizeof (names) / sizeof (names[0])) + + addr = 0; + { + /* Sections that match names, order to be straightened out later. */ + asection *secs[n_names]; + /* Linked list of sections with non-matching names. Random ordering. */ + asection *other_sections = 0; + /* Pointer to next section, since we're destroying the original + ordering. */ + asection *next; + + int i; + + for (i = 0; i < n_names; i++) + secs[i] = 0; + for (sec = stdoutput->sections; sec != (asection *) NULL; sec = next) + { + next = sec->next; + for (i = 0; i < n_names; i++) + if (!strcmp (sec->name, names[i])) + { + secs[i] = sec; + break; + } + if (i == n_names) + { + bfd_set_section_vma (stdoutput, sec, addr); + addr += bfd_section_size (stdoutput, sec); + sec->next = other_sections; + other_sections = sec; + } + } + for (i = 0; i < n_names; i++) + if (secs[i]) + { + sec = secs[i]; + bfd_set_section_vma (stdoutput, sec, addr); + addr += bfd_section_size (stdoutput, sec); + } + for (i = n_names - 1; i >= 0; i--) + if (secs[i]) + { + sec = secs[i]; + sec->next = other_sections; + other_sections = sec; + } + stdoutput->sections = other_sections; + } + + /* Build the ECOFF debugging information. */ + assert (ecoff_data (stdoutput) != 0); + hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header; + ecoff_build_debug (hdr, &buf, debug_swap); + + /* Finish up the ecoff_tdata structure. */ + set = buf; +#define SET(ptr, count, type, size) \ + if (hdr->count == 0) \ + ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \ + else \ + { \ + ecoff_data (stdoutput)->debug_info.ptr = (type) set; \ + set += hdr->count * size; \ + } + + SET (line, cbLine, unsigned char *, sizeof (unsigned char)); + SET (external_dnr, idnMax, PTR, debug_swap->external_dnr_size); + SET (external_pdr, ipdMax, PTR, debug_swap->external_pdr_size); + SET (external_sym, isymMax, PTR, debug_swap->external_sym_size); + SET (external_opt, ioptMax, PTR, debug_swap->external_opt_size); + SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext)); + SET (ss, issMax, char *, sizeof (char)); + SET (ssext, issExtMax, char *, sizeof (char)); + SET (external_rfd, crfd, PTR, debug_swap->external_rfd_size); + SET (external_fdr, ifdMax, PTR, debug_swap->external_fdr_size); + SET (external_ext, iextMax, PTR, debug_swap->external_ext_size); + +#undef SET + + /* Fill in the register masks. */ + { + unsigned long gprmask = 0; + unsigned long fprmask = 0; + unsigned long *cprmask = NULL; + +#ifdef TC_MIPS + /* Fill in the MIPS register masks. It's probably not worth + setting up a generic interface for this. */ + gprmask = mips_gprmask; + cprmask = mips_cprmask; +#endif + +#ifdef TC_ALPHA + alpha_frob_ecoff_data (); + + if (! bfd_ecoff_set_gp_value (stdoutput, alpha_gp_value)) + as_fatal ("Can't set GP value"); + + gprmask = alpha_gprmask; + fprmask = alpha_fprmask; +#endif + + if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask)) + as_fatal ("Can't set register masks"); + } +} + +/* This is called by the ECOFF code to set the external information + for a symbol. We just pass it on to BFD, which expects the swapped + information to be stored in the native field of the symbol. */ + +void +obj_ecoff_set_ext (sym, ext) + symbolS *sym; + EXTR *ext; +{ + const struct ecoff_debug_swap * const debug_swap + = &ecoff_backend (stdoutput)->debug_swap; + ecoff_symbol_type *esym; + + know (bfd_asymbol_flavour (sym->bsym) == bfd_target_ecoff_flavour); + esym = ecoffsymbol (sym->bsym); + esym->local = false; + esym->native = xmalloc (debug_swap->external_ext_size); + (*debug_swap->swap_ext_out) (stdoutput, ext, esym->native); +} + +static int +ecoff_sec_sym_ok_for_reloc (sec) + asection *sec; +{ + return 1; +} + +static void +obj_ecoff_frob_symbol (sym, puntp) + symbolS *sym; + int *puntp; +{ + ecoff_frob_symbol (sym); +} + +static void +ecoff_pop_insert () +{ + pop_insert (obj_pseudo_table); +} + +const struct format_ops ecoff_format_ops = +{ + bfd_target_ecoff_flavour, + 0, + 1, + obj_ecoff_frob_symbol, + ecoff_frob_file, + 0, 0, + 0, 0, + 0, + ecoff_generate_asm_lineno, + ecoff_stab, + ecoff_sec_sym_ok_for_reloc, + ecoff_pop_insert, + ecoff_set_ext, + ecoff_read_begin_hook, + ecoff_symbol_new_hook, +}; diff --git a/gnu/usr.bin/binutils/gas/config/obj-ecoff.h b/gnu/usr.bin/binutils/gas/config/obj-ecoff.h new file mode 100644 index 00000000000..ea80f8ace21 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-ecoff.h @@ -0,0 +1,65 @@ +/* ECOFF object file format header file. + Copyright (C) 1993 Free Software Foundation, Inc. + Contributed by Cygnus Support. + Written by Ian Lance Taylor . + + This file is part of GAS. + + 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 2, 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. */ + +#define OBJ_ECOFF 1 + +/* Use the generic ECOFF debugging code. */ +#define ECOFF_DEBUGGING 1 + +#define OUTPUT_FLAVOR bfd_target_ecoff_flavour + +#include "targ-cpu.h" + +#include "ecoff.h" + +/* For each gas symbol we keep track of which file it came from, of + whether we have generated an ECOFF symbol for it, and whether the + symbols is undefined (this last is needed to distinguish a .extern + symbols from a .comm symbol). */ + +#define TARGET_SYMBOL_FIELDS \ + struct efdr *ecoff_file; \ + struct localsym *ecoff_symbol; \ + valueT ecoff_extern_size; + +/* Modify the ECOFF symbol. */ +#define obj_frob_symbol(symp, punt) ecoff_frob_symbol (symp) + +/* This is used to write the symbolic data in the format that BFD + expects it. */ +extern void ecoff_frob_file PARAMS ((void)); +#define obj_frob_file() ecoff_frob_file () + +/* We use the ECOFF functions as our hooks. */ +#define obj_read_begin_hook ecoff_read_begin_hook +#define obj_symbol_new_hook ecoff_symbol_new_hook + +/* At the moment we don't want to do any stabs processing in read.c. */ +#define OBJ_PROCESS_STAB(seg, what, string, type, other, desc) \ + ecoff_stab ((seg), (what), (string), (type), (other), (desc)) + +#define OBJ_GENERATE_ASM_LINENO(filename, lineno) \ + ecoff_generate_asm_lineno ((filename), (lineno)) + +#define EMIT_SECTION_SYMBOLS 0 +#define obj_sec_sym_ok_for_reloc(SEC) 1 + +#define obj_ecoff_set_ext ecoff_set_ext diff --git a/gnu/usr.bin/binutils/gas/config/obj-elf.c b/gnu/usr.bin/binutils/gas/config/obj-elf.c new file mode 100644 index 00000000000..2ab7e256403 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-elf.c @@ -0,0 +1,1232 @@ +/* ELF object file format + Copyright (C) 1992, 1993 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 2, + 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. */ + +#define OBJ_HEADER "obj-elf.h" +#include "as.h" +#include "subsegs.h" +#include "obstack.h" + +#ifndef ECOFF_DEBUGGING +#define ECOFF_DEBUGGING 0 +#else +#define NEED_ECOFF_DEBUG +#endif + +#ifdef NEED_ECOFF_DEBUG +#include "ecoff.h" +#endif + +#ifdef TC_MIPS +#include "elf/mips.h" +#endif + +#ifdef NEED_ECOFF_DEBUG +static boolean elf_get_extr PARAMS ((asymbol *, EXTR *)); +static void elf_set_index PARAMS ((asymbol *, bfd_size_type)); +#endif + +static void obj_elf_line PARAMS ((int)); +void obj_elf_version PARAMS ((int)); +static void obj_elf_size PARAMS ((int)); +static void obj_elf_type PARAMS ((int)); +static void obj_elf_ident PARAMS ((int)); +static void obj_elf_weak PARAMS ((int)); +static void obj_elf_local PARAMS ((int)); +static void obj_elf_common PARAMS ((int)); +static void obj_elf_data PARAMS ((int)); +static void obj_elf_text PARAMS ((int)); + +static const pseudo_typeS elf_pseudo_table[] = +{ + {"comm", obj_elf_common, 0}, + {"ident", obj_elf_ident, 0}, + {"local", obj_elf_local, 0}, + {"previous", obj_elf_previous, 0}, + {"section", obj_elf_section, 0}, + {"section.s", obj_elf_section, 0}, + {"sect", obj_elf_section, 0}, + {"sect.s", obj_elf_section, 0}, + {"size", obj_elf_size, 0}, + {"type", obj_elf_type, 0}, + {"version", obj_elf_version, 0}, + {"weak", obj_elf_weak, 0}, + +/* These are used for stabs-in-elf configurations. */ + {"line", obj_elf_line, 0}, + + /* These are used for dwarf. */ + {"2byte", cons, 2}, + {"4byte", cons, 4}, + {"8byte", cons, 8}, + + /* We need to trap the section changing calls to handle .previous. */ + {"data", obj_elf_data, 0}, + {"text", obj_elf_text, 0}, + + /* End sentinel. */ + {NULL}, +}; + +static const pseudo_typeS ecoff_debug_pseudo_table[] = +{ +#ifdef NEED_ECOFF_DEBUG + /* COFF style debugging information for ECOFF. .ln is not used; .loc + is used instead. */ + { "def", ecoff_directive_def, 0 }, + { "dim", ecoff_directive_dim, 0 }, + { "endef", ecoff_directive_endef, 0 }, + { "file", ecoff_directive_file, 0 }, + { "scl", ecoff_directive_scl, 0 }, + { "tag", ecoff_directive_tag, 0 }, + { "val", ecoff_directive_val, 0 }, + + /* COFF debugging requires pseudo-ops .size and .type, but ELF + already has meanings for those. We use .esize and .etype + instead. These are only generated by gcc anyhow. */ + { "esize", ecoff_directive_size, 0 }, + { "etype", ecoff_directive_type, 0 }, + + /* ECOFF specific debugging information. */ + { "begin", ecoff_directive_begin, 0 }, + { "bend", ecoff_directive_bend, 0 }, + { "end", ecoff_directive_end, 0 }, + { "ent", ecoff_directive_ent, 0 }, + { "fmask", ecoff_directive_fmask, 0 }, + { "frame", ecoff_directive_frame, 0 }, + { "loc", ecoff_directive_loc, 0 }, + { "mask", ecoff_directive_mask, 0 }, + + /* Other ECOFF directives. */ + { "extern", ecoff_directive_extern, 0 }, + + /* These are used on Irix. I don't know how to implement them. */ + { "alias", s_ignore, 0 }, + { "bgnb", s_ignore, 0 }, + { "endb", s_ignore, 0 }, + { "lab", s_ignore, 0 }, + { "noalias", s_ignore, 0 }, + { "verstamp", s_ignore, 0 }, + { "vreg", s_ignore, 0 }, +#endif + + {NULL} /* end sentinel */ +}; + +#undef NO_RELOC +#include "aout/aout64.h" + +void +elf_pop_insert () +{ + pop_insert (elf_pseudo_table); + if (ECOFF_DEBUGGING) + pop_insert (ecoff_debug_pseudo_table); +} + +static bfd_vma +elf_s_get_size (sym) + symbolS *sym; +{ + return S_GET_SIZE (sym); +} + +static void +elf_s_set_size (sym, sz) + symbolS *sym; + bfd_vma sz; +{ + S_SET_SIZE (sym, sz); +} + +static bfd_vma +elf_s_get_align (sym) + symbolS *sym; +{ + return S_GET_ALIGN (sym); +} + +static void +elf_s_set_align (sym, align) + symbolS *sym; + bfd_vma align; +{ + S_SET_ALIGN (sym, align); +} + +static void +elf_copy_symbol_attributes (dest, src) + symbolS *dest, *src; +{ + OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src); +} + +static int +elf_sec_sym_ok_for_reloc (sec) + asection *sec; +{ + return obj_sec_sym_ok_for_reloc (sec); +} + +void +elf_file_symbol (s) + char *s; +{ + symbolS *sym; + + sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0); + sym->sy_frag = &zero_address_frag; + sym->bsym->flags |= BSF_FILE; + + if (symbol_rootP != sym) + { + symbol_remove (sym, &symbol_rootP, &symbol_lastP); + symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP); +#ifdef DEBUG + verify_symbol_chain (symbol_rootP, symbol_lastP); +#endif + } +} + +static void +obj_elf_common (ignore) + int ignore; +{ + char *name; + char c; + char *p; + int temp, size; + symbolS *symbolP; + int have_align; + + name = input_line_pointer; + c = get_symbol_end (); + /* just after name is now '\0' */ + p = input_line_pointer; + *p = c; + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + as_bad ("Expected comma after symbol-name"); + ignore_rest_of_line (); + return; + } + input_line_pointer++; /* skip ',' */ + if ((temp = get_absolute_expression ()) < 0) + { + as_bad (".COMMon length (%d.) <0! Ignored.", temp); + ignore_rest_of_line (); + return; + } + size = temp; + *p = 0; + symbolP = symbol_find_or_make (name); + *p = c; + if (S_IS_DEFINED (symbolP)) + { + as_bad ("Ignoring attempt to re-define symbol"); + ignore_rest_of_line (); + return; + } + if (S_GET_VALUE (symbolP) != 0) + { + if (S_GET_VALUE (symbolP) != size) + { + as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.", + S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); + } + } + know (symbolP->sy_frag == &zero_address_frag); + if (*input_line_pointer != ',') + have_align = 0; + else + { + have_align = 1; + input_line_pointer++; + SKIP_WHITESPACE (); + } + if (! have_align || *input_line_pointer != '"') + { + if (! have_align) + temp = 0; + else + { + temp = get_absolute_expression (); + if (temp < 0) + { + temp = 0; + as_warn ("Common alignment negative; 0 assumed"); + } + } + if (symbolP->local) + { + segT old_sec; + int old_subsec; + char *pfrag; + int align; + + /* allocate_bss: */ + old_sec = now_seg; + old_subsec = now_subseg; + if (temp) + { + /* convert to a power of 2 alignment */ + for (align = 0; (temp & 1) == 0; temp >>= 1, ++align); + if (temp != 1) + { + as_bad ("Common alignment not a power of 2"); + ignore_rest_of_line (); + return; + } + } + else + align = 0; + record_alignment (bss_section, align); + subseg_set (bss_section, 0); + if (align) + frag_align (align, 0); + if (S_GET_SEGMENT (symbolP) == bss_section) + symbolP->sy_frag->fr_symbol = 0; + symbolP->sy_frag = frag_now; + pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size, + (char *) 0); + *pfrag = 0; + S_SET_SIZE (symbolP, size); + S_SET_SEGMENT (symbolP, bss_section); + S_CLEAR_EXTERNAL (symbolP); + subseg_set (old_sec, old_subsec); + } + else + { + allocate_common: + S_SET_VALUE (symbolP, (valueT) size); + S_SET_ALIGN (symbolP, temp); + S_SET_EXTERNAL (symbolP); + /* should be common, but this is how gas does it for now */ + S_SET_SEGMENT (symbolP, bfd_und_section_ptr); + } + } + else + { + input_line_pointer++; + /* @@ Some use the dot, some don't. Can we get some consistency?? */ + if (*input_line_pointer == '.') + input_line_pointer++; + /* @@ Some say data, some say bss. */ + if (strncmp (input_line_pointer, "bss\"", 4) + && strncmp (input_line_pointer, "data\"", 5)) + { + while (*--input_line_pointer != '"') + ; + input_line_pointer--; + goto bad_common_segment; + } + while (*input_line_pointer++ != '"') + ; + goto allocate_common; + } + demand_empty_rest_of_line (); + return; + + { + bad_common_segment: + p = input_line_pointer; + while (*p && *p != '\n') + p++; + c = *p; + *p = '\0'; + as_bad ("bad .common segment %s", input_line_pointer + 1); + *p = c; + input_line_pointer = p; + ignore_rest_of_line (); + return; + } +} + +static void +obj_elf_local (ignore) + int ignore; +{ + char *name; + int c; + symbolS *symbolP; + + do + { + name = input_line_pointer; + c = get_symbol_end (); + symbolP = symbol_find_or_make (name); + *input_line_pointer = c; + SKIP_WHITESPACE (); + S_CLEAR_EXTERNAL (symbolP); + symbolP->local = 1; + if (c == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + if (*input_line_pointer == '\n') + c = '\n'; + } + } + while (c == ','); + demand_empty_rest_of_line (); +} + +static void +obj_elf_weak (ignore) + int ignore; +{ + char *name; + int c; + symbolS *symbolP; + + do + { + name = input_line_pointer; + c = get_symbol_end (); + symbolP = symbol_find_or_make (name); + *input_line_pointer = c; + SKIP_WHITESPACE (); + S_SET_WEAK (symbolP); + symbolP->local = 1; + if (c == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + if (*input_line_pointer == '\n') + c = '\n'; + } + } + while (c == ','); + demand_empty_rest_of_line (); +} + +static segT previous_section; +static int previous_subsection; + +/* Handle the .section pseudo-op. This code supports two different + syntaxes. + + The first is found on Solaris, and looks like + .section ".sec1",#alloc,#execinstr,#write + Here the names after '#' are the SHF_* flags to turn on for the + section. I'm not sure how it determines the SHT_* type (BFD + doesn't really give us control over the type, anyhow). + + The second format is found on UnixWare, and probably most SVR4 + machines, and looks like + .section .sec1,"a",@progbits + The quoted string may contain any combination of a, w, x, and + represents the SHF_* flags to turn on for the section. The string + beginning with '@' can be progbits or nobits. There should be + other possibilities, but I don't know what they are. In any case, + BFD doesn't really let us set the section type. */ + +/* Certain named sections have particular defined types, listed on p. + 4-19 of the ABI. */ +struct special_section +{ + const char *name; + int type; + int attributes; +}; + +static struct special_section special_sections[] = +{ + { ".bss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, + { ".comment", SHT_PROGBITS, 0 }, + { ".data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, + { ".data1", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, + { ".debug", SHT_PROGBITS, 0 }, + { ".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, + { ".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, + { ".line", SHT_PROGBITS, 0 }, + { ".note", SHT_NOTE, 0 }, + { ".rodata", SHT_PROGBITS, SHF_ALLOC }, + { ".rodata1", SHT_PROGBITS, SHF_ALLOC }, + { ".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, + +#ifdef ELF_TC_SPECIAL_SECTIONS + ELF_TC_SPECIAL_SECTIONS +#endif + +#if 0 + /* The following section names are special, but they can not + reasonably appear in assembler code. Some of the attributes are + processor dependent. */ + { ".dynamic", SHT_DYNAMIC, SHF_ALLOC /* + SHF_WRITE */ }, + { ".dynstr", SHT_STRTAB, SHF_ALLOC }, + { ".dynsym", SHT_DYNSYM, SHF_ALLOC }, + { ".got", SHT_PROGBITS, 0 }, + { ".hash", SHT_HASH, SHF_ALLOC }, + { ".interp", SHT_PROGBITS, /* SHF_ALLOC */ }, + { ".plt", SHT_PROGBITS, 0 }, + { ".shstrtab",SHT_STRTAB, 0 }, + { ".strtab", SHT_STRTAB, /* SHF_ALLOC */ }, + { ".symtab", SHT_SYMTAB, /* SHF_ALLOC */ }, +#endif + + { NULL, 0, 0 } +}; + +void +obj_elf_section (xxx) + int xxx; +{ + char *string; + int new_sec; + segT sec; + int type, attr; + int i; + flagword flags; + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + if (flag_mri) + { + char type; + + previous_section = now_seg; + previous_subsection = now_subseg; + + s_mri_sect (&type); + +#ifdef md_elf_section_change_hook + md_elf_section_change_hook (); +#endif + + return; + } + + /* Get name of section. */ + SKIP_WHITESPACE (); + if (*input_line_pointer == '"') + { + string = demand_copy_C_string (&xxx); + if (string == NULL) + { + ignore_rest_of_line (); + return; + } + } + else + { + char *p = input_line_pointer; + char c; + while (0 == strchr ("\n\t,; ", *p)) + p++; + if (p == input_line_pointer) + { + as_warn ("Missing section name"); + ignore_rest_of_line (); + return; + } + c = *p; + *p = 0; + string = xmalloc ((unsigned long) (p - input_line_pointer + 1)); + strcpy (string, input_line_pointer); + *p = c; + input_line_pointer = p; + } + + /* Switch to the section, creating it if necessary. */ + previous_section = now_seg; + previous_subsection = now_subseg; + + new_sec = bfd_get_section_by_name (stdoutput, string) == NULL; + sec = subseg_new (string, 0); + + /* If this section already existed, we don't bother to change the + flag values. */ + if (! new_sec) + { + while (! is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + ++input_line_pointer; + +#ifdef md_elf_section_change_hook + md_elf_section_change_hook (); +#endif + + return; + } + + SKIP_WHITESPACE (); + + type = SHT_NULL; + attr = 0; + + if (*input_line_pointer == ',') + { + /* Skip the comma. */ + ++input_line_pointer; + + SKIP_WHITESPACE (); + if (*input_line_pointer == '"') + { + /* Pick up a string with a combination of a, w, x. */ + ++input_line_pointer; + while (*input_line_pointer != '"') + { + switch (*input_line_pointer) + { + case 'a': + attr |= SHF_ALLOC; + break; + case 'w': + attr |= SHF_WRITE; + break; + case 'x': + attr |= SHF_EXECINSTR; + break; + default: + as_warn ("Bad .section directive: want a,w,x in string"); + ignore_rest_of_line (); + return; + } + ++input_line_pointer; + } + + /* Skip the closing quote. */ + ++input_line_pointer; + + SKIP_WHITESPACE (); + if (*input_line_pointer == ',') + { + ++input_line_pointer; + SKIP_WHITESPACE (); + if (*input_line_pointer == '@') + { + ++input_line_pointer; + if (strncmp (input_line_pointer, "progbits", + sizeof "progbits" - 1) == 0) + { + type = SHT_PROGBITS; + input_line_pointer += sizeof "progbits" - 1; + } + else if (strncmp (input_line_pointer, "nobits", + sizeof "nobits" - 1) == 0) + { + type = SHT_NOBITS; + input_line_pointer += sizeof "nobits" - 1; + } + else + { + as_warn ("Unrecognized section type"); + ignore_rest_of_line (); + } + } + } + } + else + { + do + { + SKIP_WHITESPACE (); + if (*input_line_pointer != '#') + { + as_warn ("Bad .section directive"); + ignore_rest_of_line (); + return; + } + ++input_line_pointer; + if (strncmp (input_line_pointer, "write", + sizeof "write" - 1) == 0) + { + attr |= SHF_WRITE; + input_line_pointer += sizeof "write" - 1; + } + else if (strncmp (input_line_pointer, "alloc", + sizeof "alloc" - 1) == 0) + { + attr |= SHF_ALLOC; + input_line_pointer += sizeof "alloc" - 1; + } + else if (strncmp (input_line_pointer, "execinstr", + sizeof "execinstr" - 1) == 0) + { + attr |= SHF_EXECINSTR; + input_line_pointer += sizeof "execinstr" - 1; + } + else + { + as_warn ("Unrecognized section attribute"); + ignore_rest_of_line (); + return; + } + SKIP_WHITESPACE (); + } + while (*input_line_pointer++ == ','); + --input_line_pointer; + } + } + + /* See if this is one of the special sections. */ + for (i = 0; special_sections[i].name != NULL; i++) + { + if (string[1] == special_sections[i].name[1] + && strcmp (string, special_sections[i].name) == 0) + { + if (type == SHT_NULL) + type = special_sections[i].type; + else if (type != special_sections[i].type) + as_warn ("Setting incorrect section type for %s", string); + + if ((attr &~ special_sections[i].attributes) != 0) + as_warn ("Setting incorrect section attributes for %s", string); + attr |= special_sections[i].attributes; + + break; + } + } + + flags = (SEC_RELOC + | ((attr & SHF_WRITE) ? 0 : SEC_READONLY) + | ((attr & SHF_ALLOC) ? SEC_ALLOC | SEC_LOAD : 0) + | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)); + if (special_sections[i].name == NULL) + { + if (type == SHT_PROGBITS) + flags |= SEC_ALLOC | SEC_LOAD; + else if (type == SHT_NOBITS) + { + flags |= SEC_ALLOC; + flags &=~ SEC_LOAD; + } + } + + bfd_set_section_flags (stdoutput, sec, flags); + +#ifdef md_elf_section_change_hook + md_elf_section_change_hook (); +#endif + + demand_empty_rest_of_line (); +} + +/* Change to the .data section. */ + +static void +obj_elf_data (i) + int i; +{ + previous_section = now_seg; + previous_subsection = now_subseg; + s_data (i); +} + +/* Change to the .text section. */ + +static void +obj_elf_text (i) + int i; +{ + previous_section = now_seg; + previous_subsection = now_subseg; + s_text (i); +} + +void +obj_elf_previous (ignore) + int ignore; +{ + if (previous_section == 0) + { + as_bad (".previous without corresponding .section; ignored"); + return; + } + subseg_set (previous_section, previous_subsection); + previous_section = 0; +} + +static void +obj_elf_line (ignore) + int ignore; +{ + /* Assume delimiter is part of expression. BSD4.2 as fails with + delightful bug, so we are not being incompatible here. */ + new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); + demand_empty_rest_of_line (); +} + +void +obj_read_begin_hook () +{ +#ifdef NEED_ECOFF_DEBUG + if (ECOFF_DEBUGGING) + ecoff_read_begin_hook (); +#endif +} + +void +obj_symbol_new_hook (symbolP) + symbolS *symbolP; +{ + symbolP->sy_obj = 0; + +#ifdef NEED_ECOFF_DEBUG + if (ECOFF_DEBUGGING) + ecoff_symbol_new_hook (symbolP); +#endif +} + +void +obj_elf_version (ignore) + int ignore; +{ + char *name; + unsigned int c; + char ch; + char *p; + asection *seg = now_seg; + subsegT subseg = now_subseg; + Elf_Internal_Note i_note; + Elf_External_Note e_note; + asection *note_secp = (asection *) NULL; + int i, len; + + SKIP_WHITESPACE (); + if (*input_line_pointer == '\"') + { + ++input_line_pointer; /* -> 1st char of string. */ + name = input_line_pointer; + + while (is_a_char (c = next_char_of_string ())) + ; + c = *input_line_pointer; + *input_line_pointer = '\0'; + *(input_line_pointer - 1) = '\0'; + *input_line_pointer = c; + + /* create the .note section */ + + note_secp = subseg_new (".note", 0); + bfd_set_section_flags (stdoutput, + note_secp, + SEC_HAS_CONTENTS | SEC_READONLY); + + /* process the version string */ + + len = strlen (name); + + i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */ + i_note.descsz = 0; /* no description */ + i_note.type = NT_VERSION; + p = frag_more (sizeof (e_note.namesz)); + md_number_to_chars (p, (valueT) i_note.namesz, 4); + p = frag_more (sizeof (e_note.descsz)); + md_number_to_chars (p, (valueT) i_note.descsz, 4); + p = frag_more (sizeof (e_note.type)); + md_number_to_chars (p, (valueT) i_note.type, 4); + + for (i = 0; i < len; i++) + { + ch = *(name + i); + { + FRAG_APPEND_1_CHAR (ch); + } + } + frag_align (2, 0); + + subseg_set (seg, subseg); + } + else + { + as_bad ("Expected quoted string"); + } + demand_empty_rest_of_line (); +} + +static void +obj_elf_size (ignore) + int ignore; +{ + char *name = input_line_pointer; + char c = get_symbol_end (); + char *p; + expressionS exp; + symbolS *sym; + + p = input_line_pointer; + *p = c; + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + *p = 0; + as_bad ("expected comma after name `%s' in .size directive", name); + *p = c; + ignore_rest_of_line (); + return; + } + input_line_pointer++; + expression (&exp); + if (exp.X_op == O_absent) + { + as_bad ("missing expression in .size directive"); + exp.X_op = O_constant; + exp.X_add_number = 0; + } + *p = 0; + sym = symbol_find_or_make (name); + *p = c; + if (exp.X_op == O_constant) + S_SET_SIZE (sym, exp.X_add_number); + else + { + sym->sy_obj = (expressionS *) xmalloc (sizeof (expressionS)); + *sym->sy_obj = exp; + } + demand_empty_rest_of_line (); +} + +/* Handle the ELF .type pseudo-op. This sets the type of a symbol. + There are three syntaxes. The first (used on Solaris) is + .type SYM,#function + The second (used on UnixWare) is + .type SYM,@function + The third (reportedly to be used on Irix 6.0) is + .type SYM STT_FUNC + + FIXME: We do not fully support this pseudo-op. In fact, the only + case we do support is setting the type to STT_FUNC, which we do by + setting the BSF_FUNCTION flag. */ + +static void +obj_elf_type (ignore) + int ignore; +{ + char *name; + char c; + int type; + const char *typename; + symbolS *sym; + + name = input_line_pointer; + c = get_symbol_end (); + sym = symbol_find_or_make (name); + *input_line_pointer = c; + + SKIP_WHITESPACE (); + if (*input_line_pointer == ',') + ++input_line_pointer; + + SKIP_WHITESPACE (); + if (*input_line_pointer == '#' || *input_line_pointer == '@') + ++input_line_pointer; + + typename = input_line_pointer; + c = get_symbol_end (); + + type = 0; + if (strcmp (typename, "function") == 0 + || strcmp (typename, "STT_FUNC") == 0) + type = BSF_FUNCTION; + else if (strcmp (typename, "object") == 0 + || strcmp (typename, "STT_OBJECT") == 0) + ; + else + as_bad ("ignoring unrecognized symbol type \"%s\"", typename); + + *input_line_pointer = c; + + sym->bsym->flags |= type; + + demand_empty_rest_of_line (); +} + +static void +obj_elf_ident (ignore) + int ignore; +{ + static segT comment_section; + segT old_section = now_seg; + int old_subsection = now_subseg; + + if (!comment_section) + { + char *p; + comment_section = subseg_new (".comment", 0); + bfd_set_section_flags (stdoutput, comment_section, + SEC_READONLY | SEC_HAS_CONTENTS); + p = frag_more (1); + *p = 0; + } + else + subseg_set (comment_section, 0); + stringer (1); + subseg_set (old_section, old_subsection); +} + +#ifdef INIT_STAB_SECTION + +/* The first entry in a .stabs section is special. */ + +void +obj_elf_init_stab_section (seg) + segT seg; +{ + char *file; + char *p; + char *stabstr_name; + unsigned int stroff; + + /* Force the section to align to a longword boundary. Without this, + UnixWare ar crashes. */ + bfd_set_section_alignment (stdoutput, seg, 2); + + /* Make space for this first symbol. */ + p = frag_more (12); + /* Zero it out. */ + memset (p, 0, 12); + as_where (&file, (unsigned int *) NULL); + stabstr_name = (char *) alloca (strlen (segment_name (seg)) + 4); + strcpy (stabstr_name, segment_name (seg)); + strcat (stabstr_name, "str"); + stroff = get_stab_string_offset (file, stabstr_name); + know (stroff == 1); + md_number_to_chars (p, stroff, 4); + seg_info (seg)->stabu.p = p; +} + +#endif + +/* Fill in the counts in the first entry in a .stabs section. */ + +static void +adjust_stab_sections (abfd, sec, xxx) + bfd *abfd; + asection *sec; + PTR xxx; +{ + char *name; + asection *strsec; + char *p; + int strsz, nsyms; + + if (strncmp (".stab", sec->name, 5)) + return; + if (!strcmp ("str", sec->name + strlen (sec->name) - 3)) + return; + + name = (char *) alloca (strlen (sec->name) + 4); + strcpy (name, sec->name); + strcat (name, "str"); + strsec = bfd_get_section_by_name (abfd, name); + if (strsec) + strsz = bfd_section_size (abfd, strsec); + else + strsz = 0; + nsyms = bfd_section_size (abfd, sec) / 12 - 1; + + p = seg_info (sec)->stabu.p; + assert (p != 0); + + bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6); + bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8); +} + +#ifdef NEED_ECOFF_DEBUG + +/* This function is called by the ECOFF code. It is supposed to + record the external symbol information so that the backend can + write it out correctly. The ELF backend doesn't actually handle + this at the moment, so we do it ourselves. We save the information + in the symbol. */ + +void +elf_ecoff_set_ext (sym, ext) + symbolS *sym; + struct ecoff_extr *ext; +{ + sym->bsym->udata.p = (PTR) ext; +} + +/* This function is called by bfd_ecoff_debug_externals. It is + supposed to *EXT to the external symbol information, and return + whether the symbol should be used at all. */ + +static boolean +elf_get_extr (sym, ext) + asymbol *sym; + EXTR *ext; +{ + if (sym->udata.p == NULL) + return false; + *ext = *(EXTR *) sym->udata.p; + return true; +} + +/* This function is called by bfd_ecoff_debug_externals. It has + nothing to do for ELF. */ + +/*ARGSUSED*/ +static void +elf_set_index (sym, indx) + asymbol *sym; + bfd_size_type indx; +{ +} + +#endif /* NEED_ECOFF_DEBUG */ + +void +elf_frob_symbol (symp, puntp) + symbolS *symp; + int *puntp; +{ +#ifdef NEED_ECOFF_DEBUG + if (ECOFF_DEBUGGING) + ecoff_frob_symbol (symp); +#endif + + if (symp->sy_obj) + { + switch (symp->sy_obj->X_op) + { + case O_subtract: + S_SET_SIZE (symp, + (S_GET_VALUE (symp->sy_obj->X_add_symbol) + + symp->sy_obj->X_add_number + - S_GET_VALUE (symp->sy_obj->X_op_symbol))); + break; + case O_constant: + S_SET_SIZE (symp, + (S_GET_VALUE (symp->sy_obj->X_add_symbol) + + symp->sy_obj->X_add_number)); + break; + default: + as_bad (".size expression too complicated to fix up"); + break; + } + } + free (symp->sy_obj); + symp->sy_obj = 0; + + /* Double check weak symbols. */ + if (symp->bsym->flags & BSF_WEAK) + { + if (S_IS_COMMON (symp)) + as_bad ("Symbol `%s' can not be both weak and common", + S_GET_NAME (symp)); + } +} + +void +elf_frob_file () +{ + bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0); + +#ifdef elf_tc_final_processing + elf_tc_final_processing (); +#endif + +#ifdef NEED_ECOFF_DEBUG + if (ECOFF_DEBUGGING) + /* Generate the ECOFF debugging information. */ + { + const struct ecoff_debug_swap *debug_swap; + struct ecoff_debug_info debug; + char *buf; + asection *sec; + + debug_swap + = get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap; + know (debug_swap != (const struct ecoff_debug_swap *) NULL); + ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap); + + /* Set up the pointers in debug. */ +#define SET(ptr, offset, type) \ + debug.ptr = (type) (buf + debug.symbolic_header.offset) + + SET (line, cbLineOffset, unsigned char *); + SET (external_dnr, cbDnOffset, PTR); + SET (external_pdr, cbPdOffset, PTR); + SET (external_sym, cbSymOffset, PTR); + SET (external_opt, cbOptOffset, PTR); + SET (external_aux, cbAuxOffset, union aux_ext *); + SET (ss, cbSsOffset, char *); + SET (external_fdr, cbFdOffset, PTR); + SET (external_rfd, cbRfdOffset, PTR); + /* ssext and external_ext are set up just below. */ + +#undef SET + + /* Set up the external symbols. */ + debug.ssext = debug.ssext_end = NULL; + debug.external_ext = debug.external_ext_end = NULL; + if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true, + elf_get_extr, elf_set_index)) + as_fatal ("Failed to set up debugging information: %s", + bfd_errmsg (bfd_get_error ())); + + sec = bfd_get_section_by_name (stdoutput, ".mdebug"); + assert (sec != NULL); + + know (stdoutput->output_has_begun == false); + + /* We set the size of the section, call bfd_set_section_contents + to force the ELF backend to allocate a file position, and then + write out the data. FIXME: Is this really the best way to do + this? */ + sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap); + + if (! bfd_set_section_contents (stdoutput, sec, (PTR) NULL, + (file_ptr) 0, (bfd_size_type) 0)) + as_fatal ("Can't start writing .mdebug section: %s", + bfd_errmsg (bfd_get_error ())); + + know (stdoutput->output_has_begun == true); + know (sec->filepos != 0); + + if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap, + sec->filepos)) + as_fatal ("Could not write .mdebug section: %s", + bfd_errmsg (bfd_get_error ())); + } +#endif /* NEED_ECOFF_DEBUG */ +} + +const struct format_ops elf_format_ops = +{ + bfd_target_elf_flavour, + 0, + 1, + elf_frob_symbol, + elf_frob_file, + elf_s_get_size, elf_s_set_size, + elf_s_get_align, elf_s_set_align, + elf_copy_symbol_attributes, +#ifdef NEED_ECOFF_DEBUG + ecoff_generate_asm_lineno, + ecoff_stab, +#else + 0, + 0, /* process_stab */ +#endif + elf_sec_sym_ok_for_reloc, + elf_pop_insert, +#ifdef NEED_ECOFF_DEBUG + elf_ecoff_set_ext, +#else + 0, +#endif + obj_read_begin_hook, + obj_symbol_new_hook, +}; diff --git a/gnu/usr.bin/binutils/gas/config/obj-elf.h b/gnu/usr.bin/binutils/gas/config/obj-elf.h new file mode 100644 index 00000000000..eee6b2720fe --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-elf.h @@ -0,0 +1,132 @@ +/* ELF object file format. + Copyright (C) 1992, 1993 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. */ + + +/* HP PA-RISC support was contributed by the Center for Software Science + at the University of Utah. */ + +#ifndef _OBJ_ELF_H +#define _OBJ_ELF_H + +#define OBJ_ELF 1 + +#define OUTPUT_FLAVOR bfd_target_elf_flavour + +#include + +#define BYTES_IN_WORD 4 /* for now */ +#include "bfd/elf-bfd.h" + +/* Use this to keep track of .size expressions that involve differences + that we can't compute yet. */ +#define OBJ_SYMFIELD_TYPE expressionS * + +/* Symbol fields used by the ELF back end. */ +#define ELF_TARGET_SYMBOL_FIELDS int local:1; unsigned long sy_name_offset; + +/* Don't change this; change ELF_TARGET_SYMBOL_FIELDS instead. */ +#define TARGET_SYMBOL_FIELDS ELF_TARGET_SYMBOL_FIELDS + +#include "targ-cpu.h" + +#ifndef FALSE +#define FALSE 0 +#define TRUE !FALSE +#endif + +/* should be conditional on address size! */ +#define elf_symbol(asymbol) ((elf_symbol_type *)(&(asymbol)->the_bfd)) + +#define S_GET_SIZE(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_size) +#define S_SET_SIZE(S,V) \ + (elf_symbol((S)->bsym)->internal_elf_sym.st_size = (V)) + +#define S_GET_ALIGN(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_value) +#define S_SET_ALIGN(S,V) \ + (elf_symbol ((S)->bsym)->internal_elf_sym.st_value = (V)) + +extern asection *gdb_section; + +#define obj_frob_file() elf_frob_file() + +extern void elf_frob_file PARAMS ((void)); +extern void elf_file_symbol PARAMS ((char *)); +#define obj_app_file elf_file_symbol + +extern void obj_elf_section PARAMS ((int)); +extern void obj_elf_previous PARAMS ((int)); +extern void obj_elf_version PARAMS ((int)); + +/* BFD wants to write the udata field, which is a no-no for the + globally defined sections. */ +#define obj_sec_sym_ok_for_reloc(SEC) ((SEC)->owner != 0) + +/* When setting one symbol equal to another, by default we probably + want them to have the same "size", whatever it means in the current + context. */ +#define OBJ_COPY_SYMBOL_ATTRIBUTES(DEST,SRC) \ + S_SET_SIZE ((DEST), S_GET_SIZE (SRC)) + +/* Stabs go in a separate section. */ +#define SEPARATE_STAB_SECTIONS 1 + +/* We need 12 bytes at the start of the section to hold some initial + information. */ +extern void obj_elf_init_stab_section PARAMS ((segT)); +#define INIT_STAB_SECTION(seg) obj_elf_init_stab_section (seg) + +/* For now, always set ECOFF_DEBUGGING for a MIPS target. */ +#ifdef TC_MIPS +#define ECOFF_DEBUGGING 1 +#endif + +#if ECOFF_DEBUGGING + +/* If we are generating ECOFF debugging information, we need some + additional fields for each symbol. */ +#undef TARGET_SYMBOL_FIELDS +#define TARGET_SYMBOL_FIELDS \ + ELF_TARGET_SYMBOL_FIELDS \ + struct efdr *ecoff_file; \ + struct localsym *ecoff_symbol; \ + valueT ecoff_extern_size; + +/* We smuggle stabs in ECOFF rather than using a separate section. + The Irix linker can not handle a separate stabs section. */ +#undef SEPARATE_STAB_SECTIONS +#undef INIT_STAB_SECTION +#define OBJ_PROCESS_STAB(seg, what, string, type, other, desc) \ + ecoff_stab ((seg), (what), (string), (type), (other), (desc)) + +#define OBJ_GENERATE_ASM_LINENO(filename, lineno) \ + ecoff_generate_asm_lineno ((filename), (lineno)) + +#endif /* ECOFF_DEBUGGING */ + +extern void elf_frob_symbol PARAMS ((struct symbol *, int *)); +#define obj_frob_symbol(symp, punt) elf_frob_symbol (symp, &punt) + +extern void elf_pop_insert PARAMS ((void)); +#define obj_pop_insert() elf_pop_insert() + +#ifndef OBJ_MAYBE_ELF +#define obj_ecoff_set_ext elf_ecoff_set_ext +#endif + +#endif /* _OBJ_ELF_H */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-generic.c b/gnu/usr.bin/binutils/gas/config/obj-generic.c new file mode 100644 index 00000000000..69fc3d1dbf9 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-generic.c @@ -0,0 +1,41 @@ +/* This file is obj-generic.c and is intended to be a template for + object format specific source files. + + Copyright (C) 1987-1992 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 2, 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. */ + +/* Chars that can be used to separate mant from exp in floating point nums */ +char EXP_CHARS[] = "eE"; + +/* Chars that mean this number is a floating point constant */ +/* As in 0f12.456 */ +/* or 0d1.2345e12 */ +char FLT_CHARS[] = "rRsSfFdDxXpP"; + +/* These chars start a comment anywhere in a source file (except inside + another comment */ +const char comment_chars[] = "#"; + +/* + * Local Variables: + * comment-column: 0 + * fill-column: 131 + * End: + */ + +/* end of obj-generic.c */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-generic.h b/gnu/usr.bin/binutils/gas/config/obj-generic.h new file mode 100644 index 00000000000..dc18e439703 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-generic.h @@ -0,0 +1,80 @@ +/* This file is obj-generic.h + Copyright (C) 1987-1992 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 2, 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. */ + +/* + * This file is obj-generic.h and is intended to be a template for + * object format specific header files. + */ + +/* define an obj specific macro off which target cpu back ends may key. */ +#define OBJ_GENERIC 1 + +/* include whatever target cpu is appropriate. */ +#include "targ-cpu.h" + +/* + * SYMBOLS + */ + +/* + * If your object format needs to reorder symbols, define this. When + * defined, symbols are kept on a doubly linked list and functions are + * made available for push, insert, append, and delete. If not defined, + * symbols are kept on a singly linked list, only the append and clear + * facilities are available, and they are macros. + */ + +/* #define SYMBOLS_NEED_PACKPOINTERS */ + +/* */ +typedef struct + { + void *nothing; + } + +obj_symbol_type; /* should be the format's symbol structure */ + +typedef void *object_headers; + +/* symbols have names */ +#define S_GET_NAME(s) ("foo") /* get the name of a symbolP */ +#define S_SET_NAME(s,v) ; +/* symbols have segments */ +#define S_GET_SEGMENT(s) (SEG_UNKNOWN) +#define S_SET_SEGMENT(s,v) ; +/* symbols may be external */ +#define S_IS_EXTERNAL(s) (0) +#define S_SET_EXTERNAL(s) ; + +/* symbols may or may not be defined */ +#define S_IS_DEFINED(s) (0) + + +#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (0) /* your magic number */ + +#define OBJ_EMIT_LINENO(a,b,c) /* must be *something*. This no-op's it out. */ + +/* + * Local Variables: + * comment-column: 0 + * fill-column: 131 + * End: + */ + +/* end of obj-generic.h */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-hp300.c b/gnu/usr.bin/binutils/gas/config/obj-hp300.c new file mode 100644 index 00000000000..6e9cc53927a --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-hp300.c @@ -0,0 +1,52 @@ +/* This file is obj-hp300.h + Copyright (C) 1993 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 2, 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. */ + +#include "config/obj-aout.c" + +/* Aout file generation & utilities */ +void +hp300_header_append (where, headers) + char **where; + object_headers *headers; +{ + tc_headers_hook (headers); + +#define DO(FIELD) \ + { \ + md_number_to_chars (*where, headers->header.FIELD, sizeof (headers->header.FIELD)); \ + *where += sizeof (headers->header.FIELD); \ + } + + DO (a_info); + DO (a_spare1); + DO (a_spare2); + DO (a_text); + DO (a_data); + DO (a_bss); + DO (a_trsize); + DO (a_drsize); + DO (a_spare3); + DO (a_spare4); + DO (a_spare5); + DO (a_entry); + DO (a_spare6); + DO (a_spare7); + DO (a_syms); + DO (a_spare8); +} diff --git a/gnu/usr.bin/binutils/gas/config/obj-hp300.h b/gnu/usr.bin/binutils/gas/config/obj-hp300.h new file mode 100644 index 00000000000..ff4006b6040 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-hp300.h @@ -0,0 +1,71 @@ +/* This file is obj-hp300.h + Copyright (C) 1993 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 2, 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. */ + +#define __STRUCT_EXEC_OVERRIDE__ + +struct exec_bytes +{ + unsigned char a_info[4]; /* a_machtype/a_magic */ + unsigned char a_spare1[4]; + unsigned char a_spare2[4]; + unsigned char a_text[4]; /* length of text, in bytes */ + unsigned char a_data[4]; /* length of data, in bytes */ + unsigned char a_bss[4]; /* length of uninitialized data area for file, in bytes */ + unsigned char a_trsize[4]; /* length of relocation info for text, in bytes */ + unsigned char a_drsize[4]; /* length of relocation info for data, in bytes */ + unsigned char a_spare3[4]; /* HP = pascal interface size */ + unsigned char a_spare4[4]; /* HP = symbol table size */ + unsigned char a_spare5[4]; /* HP = debug name table size */ + unsigned char a_entry[4]; /* start address */ + unsigned char a_spare6[4]; /* HP = source line table size */ + unsigned char a_spare7[4]; /* HP = value table size */ + unsigned char a_syms[4]; /* length of symbol table data in file, in bytes */ + unsigned char a_spare8[4]; +}; + +/* How big the "struct exec" is on disk */ +#define EXEC_BYTES_SIZE (16 * 4) + +struct exec +{ + unsigned long a_info; + unsigned long a_spare1; + unsigned long a_spare2; + unsigned long a_text; + unsigned long a_data; + unsigned long a_bss; + unsigned long a_trsize; + unsigned long a_drsize; + unsigned long a_spare3; + unsigned long a_spare4; + unsigned long a_spare5; + unsigned long a_entry; + unsigned long a_spare6; + unsigned long a_spare7; + unsigned long a_syms; + unsigned long a_spare8; +}; + +#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC) +#define AOUT_VERSION 0x02 +#define AOUT_MACHTYPE 0x0c +#define OMAGIC 0x106 + +#define obj_header_append hp300_header_append +#include "config/obj-aout.h" diff --git a/gnu/usr.bin/binutils/gas/config/obj-ieee.c b/gnu/usr.bin/binutils/gas/config/obj-ieee.c new file mode 100644 index 00000000000..c4217d1d911 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-ieee.c @@ -0,0 +1,616 @@ +/* obj-format for ieee-695 records. + Copyright (C) 1991, 1992 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 2, 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. */ + + +/* + created by + + steve chamberlain steve@cygnus.com + */ + +/* + this will hopefully become the port through which bfd and gas talk, + for the moment, only ieee is known to work well. + */ + +#include "bfd.h" +#include "as.h" +#include "subsegs.h" +#include "output-file.h" +#include "frags.h" + +bfd *abfd; + +/* How many addresses does the .align take? */ +static relax_addressT +relax_align (address, alignment) + register relax_addressT address; /* Address now. */ + register long alignment; /* Alignment (binary). */ +{ + relax_addressT mask; + relax_addressT new_address; + + mask = ~((~0) << alignment); + new_address = (address + mask) & (~mask); + return (new_address - address); +} /* relax_align() */ + +/* calculate the size of the frag chain and create a bfd section + to contain all of it */ +static void +DEFUN (size_section, (abfd, idx), + bfd * abfd AND + unsigned int idx) +{ + asection *sec; + unsigned int size = 0; + fragS *frag = segment_info[idx].frag_root; + while (frag) + { + if (frag->fr_address != size) + { + printf ("Out of step\n"); + size = frag->fr_address; + } + size += frag->fr_fix; + switch (frag->fr_type) + { + case rs_fill: + case rs_org: + size += frag->fr_offset * frag->fr_var; + break; + case rs_align: + size += relax_align (size, frag->fr_offset); + } + frag = frag->fr_next; + } + if (size) + { + char *name = segment_info[idx].name; + if (name == (char *) NULL) + { + name = ".data"; + } + segment_info[idx].user_stuff = (char *) (sec = bfd_make_section (abfd, name)); + /* Make it output through itself */ + sec->output_section = sec; + sec->flags |= SEC_HAS_CONTENTS; + bfd_set_section_size (abfd, sec, size); + } +} + +/* run through a frag chain and write out the data to go with it */ +static void +DEFUN (fill_section, (abfd, idx), + bfd * abfd AND + unsigned int idx) +{ + asection *sec = segment_info[idx].user_stuff; + if (sec) + { + fragS *frag = segment_info[idx].frag_root; + unsigned int offset = 0; + while (frag) + { + unsigned int fill_size; + unsigned int count; + switch (frag->fr_type) + { + case rs_fill: + case rs_align: + case rs_org: + if (frag->fr_fix) + { + bfd_set_section_contents (abfd, + sec, + frag->fr_literal, + frag->fr_address, + frag->fr_fix); + } + offset += frag->fr_fix; + fill_size = frag->fr_var; + if (fill_size) + { + unsigned int off = frag->fr_fix; + for (count = frag->fr_offset; count; count--) + { + bfd_set_section_contents (abfd, sec, + frag->fr_literal + + frag->fr_fix, + frag->fr_address + off, + fill_size); + off += fill_size; + } + } + break; + default: + abort (); + } + frag = frag->fr_next; + } + } +} + +/* Count the relocations in a chain */ + +static unsigned int +DEFUN (count_entries_in_chain, (idx), + unsigned int idx) +{ + unsigned int nrelocs; + fixS *fixup_ptr; + + /* Count the relocations */ + fixup_ptr = segment_info[idx].fix_root; + nrelocs = 0; + while (fixup_ptr != (fixS *) NULL) + { + fixup_ptr = fixup_ptr->fx_next; + nrelocs++; + } + return nrelocs; +} + +/* output all the relocations for a section */ +void +DEFUN (do_relocs_for, (idx), + unsigned int idx) +{ + unsigned int nrelocs; + arelent **reloc_ptr_vector; + arelent *reloc_vector; + asymbol **ptrs; + asection *section = (asection *) (segment_info[idx].user_stuff); + unsigned int i; + fixS *from; + if (section) + { + nrelocs = count_entries_in_chain (idx); + + reloc_ptr_vector = (arelent **) malloc ((nrelocs + 1) * sizeof (arelent *)); + reloc_vector = (arelent *) malloc (nrelocs * sizeof (arelent)); + ptrs = (asymbol **) malloc (nrelocs * sizeof (asymbol *)); + from = segment_info[idx].fix_root; + for (i = 0; i < nrelocs; i++) + { + arelent *to = reloc_vector + i; + asymbol *s; + reloc_ptr_vector[i] = to; + to->howto = (reloc_howto_type *) (from->fx_r_type); + +#if 0 /* We can't represent complicated things in a reloc yet */ + if (from->fx_addsy == 0 || from->fx_subsy != 0) abort(); +#endif + + s = &(from->fx_addsy->sy_symbol.sy); + to->address = ((char *) (from->fx_frag->fr_address + + from->fx_where)) + - ((char *) (&(from->fx_frag->fr_literal))); + to->addend = from->fx_offset; + /* If we know the symbol which we want to relocate to, turn + this reloaction into a section relative. + + If this relocation is pcrelative, and we know the + destination, we still want to keep the relocation - since + the linker might relax some of the bytes, but it stops + being pc relative and turns into an absolute relocation. */ + if (s) + { + if ((s->flags & BSF_UNDEFINED) == 0) + { + to->section = s->section; + + /* We can refer directly to the value field here, + rather than using S_GET_VALUE, because this is + only called after do_symbols, which sets up the + value field. */ + to->addend += s->value; + + to->sym_ptr_ptr = 0; + if (to->howto->pcrel_offset) + { + /* This is a pcrel relocation, the addend should be adjusted */ + to->addend -= to->address + 1; + } + } + else + { + to->section = 0; + *ptrs = &(from->fx_addsy->sy_symbol.sy); + to->sym_ptr_ptr = ptrs; + + if (to->howto->pcrel_offset) + { + /* This is a pcrel relocation, the addend should be adjusted */ + to->addend -= to->address - 1; + } + } + + } + else + { + to->section = 0; + } + + ptrs++; + from = from->fx_next; + } + + /* attatch to the section */ + section->orelocation = reloc_ptr_vector; + section->reloc_count = nrelocs; + section->flags |= SEC_LOAD; + } +} + +/* do the symbols.. */ +static void +DEFUN (do_symbols, (abfd), + bfd * abfd) +{ + extern symbolS *symbol_rootP; + symbolS *ptr; + asymbol **symbol_ptr_vec; + asymbol *symbol_vec; + unsigned int count = 0; + unsigned int index; + + + for (ptr = symbol_rootP; + ptr != (symbolS *) NULL; + ptr = ptr->sy_next) + { + if (SEG_NORMAL (ptr->sy_symbol.seg)) + { + ptr->sy_symbol.sy.section = + (asection *) (segment_info[ptr->sy_symbol.seg].user_stuff); + S_SET_VALUE (ptr, S_GET_VALUE (ptr) + ptr->sy_frag->fr_address); + if (ptr->sy_symbol.sy.flags == 0) + { + ptr->sy_symbol.sy.flags = BSF_LOCAL; + } + } + else + { + switch (ptr->sy_symbol.seg) + { + case SEG_ABSOLUTE: + ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE; + ptr->sy_symbol.sy.section = 0; + break; + case SEG_UNKNOWN: + ptr->sy_symbol.sy.flags = BSF_UNDEFINED; + ptr->sy_symbol.sy.section = 0; + break; + default: + abort (); + } + } + ptr->sy_symbol.sy.value = S_GET_VALUE (ptr); + count++; + } + symbol_ptr_vec = (asymbol **) malloc ((count + 1) * sizeof (asymbol *)); + + index = 0; + for (ptr = symbol_rootP; + ptr != (symbolS *) NULL; + ptr = ptr->sy_next) + { + symbol_ptr_vec[index] = &(ptr->sy_symbol.sy); + index++; + } + symbol_ptr_vec[index] = 0; + abfd->outsymbols = symbol_ptr_vec; + abfd->symcount = count; +} + +/* The generic as->bfd converter. Other backends may have special case + code */ + +void +DEFUN_VOID (bfd_as_write_hook) +{ + int i; + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + size_section (abfd, i); + } + + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + fill_section (abfd, i); + + do_symbols (abfd); + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + do_relocs_for (i); + +} + +S_SET_SEGMENT (x, y) + symbolS *x; + int y; +{ + x->sy_symbol.seg = y; +} + +S_IS_DEFINED (x) + symbolS *x; +{ + if (SEG_NORMAL (x->sy_symbol.seg)) + { + return 1; + } + switch (x->sy_symbol.seg) + { + case SEG_UNKNOWN: + return 0; + default: + abort (); + } +} + +S_IS_EXTERNAL (x) +{ + abort (); +} + +S_GET_DESC (x) +{ + abort (); +} + +S_GET_SEGMENT (x) + symbolS *x; +{ + return x->sy_symbol.seg; +} + +S_SET_EXTERNAL (x) + symbolS *x; +{ + x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT; +} + +S_SET_NAME (x, y) + symbolS *x; + char *y; +{ + x->sy_symbol.sy.name = y; +} + +S_GET_OTHER (x) +{ + abort (); +} + +S_IS_DEBUG (x) +{ + abort (); +} + +char * +segment_name () +{ + abort (); +} + +void +obj_read_begin_hook () +{ +} + +static void +obj_ieee_section (ignore) + int ignore; +{ + extern char *input_line_pointer; + extern char is_end_of_line[]; + char *p = input_line_pointer; + char *s = p; + int i; + /* Look up the name, if it doesn't exist, make it */ + while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p]) + { + p++; + } + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + if (segment_info[i].hadone) + { + if (strncmp (segment_info[i].name, s, p - s) == 0) + { + goto ok; + + } + } + else + break; + } + if (i == SEG_UNKNOWN) + { + as_bad ("too many sections"); + return; + } + + segment_info[i].hadone = 1; + segment_info[i].name = malloc (p - s + 1); + memcpy (segment_info[i].name, s, p - s); + segment_info[i].name[p - s] = 0; +ok: + subseg_set (i, 0); + while (!is_end_of_line[*p]) + p++; + input_line_pointer = p; + +} + + +void cons (); +void s_ignore (); + + +void s_globl (); +const pseudo_typeS obj_pseudo_table[] = +{ + {"section", obj_ieee_section, 0}, + {"data.b", cons, 1}, + {"data.w", cons, 2}, + {"data.l", cons, 4}, + {"export", s_globl, 0}, + {"option", s_ignore, 0}, + {"end", s_ignore, 0}, + {"import", s_ignore, 0}, + {"sdata", stringer, 0}, + 0, + +}; + + + +void +obj_symbol_new_hook (symbolP) + symbolS *symbolP; +{ + symbolP->sy_symbol.sy.the_bfd = abfd; +} + + + + + +#if 1 +extern void +DEFUN_VOID (write_object_file) +{ + int i; + struct frchain *frchain_ptr; + struct frag *frag_ptr; + + abfd = bfd_openw (out_file_name, "ieee"); + + if (abfd == 0) + { + as_perror ("FATAL: Can't create %s", out_file_name); + exit (EXIT_FAILURE); + } + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, bfd_arch_h8300, 0); + subseg_set (1, 0); + subseg_set (2, 0); + subseg_set (3, 0); + for (frchain_ptr = frchain_root; + frchain_ptr != (struct frchain *) NULL; + frchain_ptr = frchain_ptr->frch_next) + { + /* Run through all the sub-segments and align them up. Also close any + open frags. We tack a .fill onto the end of the frag chain so + that any .align's size can be worked by looking at the next + frag. */ + + subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); +#ifndef SUB_SEGMENT_ALIGN +#define SUB_SEGMENT_ALIGN(SEG) 2 +#endif + frag_align (SUB_SEGMENT_ALIGN (now_seg), 0); + frag_wane (frag_now); + frag_now->fr_fix = 0; + know (frag_now->fr_next == NULL); + } + + /* Now build one big frag chain for each segment, linked through + fr_next. */ + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + + fragS **prev_frag_ptr_ptr; + struct frchain *next_frchain_ptr; + + /* struct frag **head_ptr = segment_info[i].frag_root;*/ + + segment_info[i].frag_root = segment_info[i].frchainP->frch_root; +#if 0 + /* Im not sure what this is for */ + for (frchain_ptr = segment_info[i].frchainP->frch_root; + frchain_ptr != (struct frchain *) NULL; + frchain_ptr = frchain_ptr->frch_next) + { + *head_ptr = frchain_ptr; + head_ptr = &frchain_ptr->next; + } + + +#endif + } + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + relax_segment (segment_info[i].frag_root, i); + } + + /* Now the addresses of the frags are correct within the segment */ + + bfd_as_write_hook (); + bfd_close (abfd); +} + +#endif + +H_SET_TEXT_SIZE (a, b) +{ + abort (); +} + +H_GET_TEXT_SIZE () +{ + abort (); +} + +H_SET_BSS_SIZE () +{ + abort (); +} + +H_SET_STRING_SIZE () +{ + abort (); +} + +H_SET_RELOCATION_SIZE () +{ + abort (); +} + +H_SET_MAGIC_NUMBER () +{ + abort (); +} + +H_GET_FILE_SIZE () +{ + abort (); +} + +H_GET_TEXT_RELOCATION_SIZE () +{ + abort (); +} + +/* end of obj-ieee.c */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-ieee.h b/gnu/usr.bin/binutils/gas/config/obj-ieee.h new file mode 100644 index 00000000000..4a0f126ebe4 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-ieee.h @@ -0,0 +1,50 @@ +/* This file is obj-ieee.h + + Copyright (C) 1987-1992 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 2, 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. */ + +#define BFD 1 + +#include + +typedef struct +{ + asymbol sy; + int seg; +} + +obj_symbol_type; + +#define S_GET_NAME(s) (((s)->sy_symbol.sy.name)) + +typedef struct + { + int x; + } + +object_headers; + +#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 1 + + +int lineno_rootP; + + +#define IEEE_STYLE + +/* end of obj-ieee.h */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-multi.c b/gnu/usr.bin/binutils/gas/config/obj-multi.c new file mode 100644 index 00000000000..d115093aff3 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-multi.c @@ -0,0 +1,4 @@ +/* foo */ + +#include "as.h" + diff --git a/gnu/usr.bin/binutils/gas/config/obj-multi.h b/gnu/usr.bin/binutils/gas/config/obj-multi.h new file mode 100644 index 00000000000..78c299afbb0 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-multi.h @@ -0,0 +1,41 @@ +/* hi */ + +#include "emul.h" +#include "targ-cpu.h" + +#define OUTPUT_FLAVOR (this_format->flavor) +#define obj_frob_symbol(S,P) (this_format->frob_symbol)(S,&(P)) +#define obj_frob_file (this_format->frob_file) +#define obj_ecoff_set_ext (this_format->ecoff_set_ext) +#define obj_pop_insert (this_format->pop_insert) +#define obj_read_begin_hook() (this_format->read_begin_hook?this_format->read_begin_hook():(void)0) +#define obj_symbol_new_hook (this_format->symbol_new_hook) +#define obj_sec_sym_ok_for_reloc (this_format->sec_sym_ok_for_reloc) +#define S_GET_SIZE (this_format->s_get_size) +#define S_SET_SIZE (this_format->s_set_size) +#define S_GET_ALIGN (this_format->s_get_align) +#define S_SET_ALIGN (this_format->s_set_align) +#define obj_copy_symbol_attributes (this_format->copy_symbol_attributes) +#define OBJ_PROCESS_STAB (this_format->process_stab) + +#if defined (OBJ_MAYBE_ECOFF) || (defined (OBJ_MAYBE_ELF) && defined (TC_MIPS)) +#define ECOFF_DEBUGGING 1 +#endif + +#ifdef OBJ_MAYBE_ELF +#define ELF_TARGET_SYMBOL_FIELDS int local:1; unsigned long sy_name_offset; +#else +#define ELF_TARGET_SYMBOL_FIELDS +#endif + +#ifdef ECOFF_DEBUGGING +struct efdr; +struct localsym; +#define ECOFF_DEBUG_TARGET_SYMBOL_FIELDS struct efdr *ecoff_file; struct localsym *ecoff_symbol; valueT ecoff_extern_size; +#else +#define ECOFF_DEBUG_TARGET_SYMBOL_FIELDS +#endif + +#define TARGET_SYMBOL_FIELDS \ + ELF_TARGET_SYMBOL_FIELDS \ + ECOFF_DEBUG_TARGET_SYMBOL_FIELDS diff --git a/gnu/usr.bin/binutils/gas/config/obj-som.c b/gnu/usr.bin/binutils/gas/config/obj-som.c new file mode 100644 index 00000000000..d745d20bf2f --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-som.c @@ -0,0 +1,227 @@ +/* SOM object file format. + Copyright (C) 1993 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 2, + 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. + + Written by the Center for Software Science at the University of Utah + and by Cygnus Support. */ + +#include "as.h" +#include "subsegs.h" +#include "aout/stab_gnu.h" +#include "obstack.h" + +/* SOM does not need any pseudo-ops. */ + +const pseudo_typeS obj_pseudo_table[] = +{ + {NULL} +}; + +static int version_seen = 0; +static int copyright_seen = 0; + +/* Unused by SOM. */ +void obj_read_begin_hook () {} + +/* Handle a .version directive. */ + +void +obj_som_version (unused) + int unused; +{ + char *version, c; + + if (version_seen) + { + as_bad ("Only one .version pseudo-op per file!"); + ignore_rest_of_line (); + return; + } + + SKIP_WHITESPACE (); + if (*input_line_pointer == '\"') + { + version = input_line_pointer; + ++input_line_pointer; + while (is_a_char (next_char_of_string ())) + ; + c = *input_line_pointer; + *input_line_pointer = '\000'; + } + else + { + as_bad ("Expected quoted string"); + ignore_rest_of_line (); + return; + } + + version_seen = 1; + if (bfd_som_attach_aux_hdr (stdoutput, VERSION_AUX_ID, version) == false) + { + bfd_perror (stdoutput->filename); + as_perror ("FATAL: Attaching version header %s", stdoutput->filename); + exit (EXIT_FAILURE); + } + *input_line_pointer = c; + demand_empty_rest_of_line (); +} + +/* Handle a .copyright directive. This probably isn't complete, but + it's of dubious value anyway and (IMHO) not worth the time to finish. + If you care about copyright strings that much, you fix it. */ + +void +obj_som_copyright (unused) + int unused; +{ + char *copyright, c; + + if (copyright_seen) + { + as_bad ("Only one .copyright pseudo-op per file!"); + ignore_rest_of_line (); + return; + } + + SKIP_WHITESPACE (); + if (*input_line_pointer == '\"') + { + copyright = input_line_pointer; + ++input_line_pointer; + while (is_a_char (next_char_of_string ())) + ; + c = *input_line_pointer; + *input_line_pointer = '\000'; + } + else + { + as_bad ("Expected quoted string"); + ignore_rest_of_line (); + return; + } + + copyright_seen = 1; + if (bfd_som_attach_aux_hdr (stdoutput, COPYRIGHT_AUX_ID, copyright) == false) + { + bfd_perror (stdoutput->filename); + as_perror ("FATAL: Attaching copyright header %s", stdoutput->filename); + exit (EXIT_FAILURE); + } + *input_line_pointer = c; + demand_empty_rest_of_line (); +} + +/* Perform any initialization necessary for stabs support. + + For SOM we need to create the space which will contain the + two stabs subspaces. Additionally we need to set up the + space/subspace relationships and set space/subspace attributes + which BFD does not understand. */ + +void +obj_som_init_stab_section (seg) + segT seg; +{ + segT saved_seg = now_seg; + segT space; + subsegT saved_subseg = now_subseg; + char *p, *file; + unsigned int stroff; + + /* Make the space which will contain the debug subspaces. */ + space = bfd_make_section_old_way (stdoutput, "$GDB_DEBUG$"); + + /* Set SOM specific attributes for the space. In particular we set + the space "defined", "private", "sort_key", and "spnum" values. + + Due to a bug in pxdb (called by hpux linker), the sort keys + of the various stabs spaces/subspaces need to be "small". We + reserve range 72/73 which appear to work well. */ + obj_set_section_attributes (space, 1, 1, 72, 2); + bfd_set_section_alignment (stdoutput, space, 2); + + /* Set the containing space for both stab sections to be $GDB_DEBUG$ + (just created above). Also set some attributes which BFD does + not understand. In particular, access bits, sort keys, and load + quadrant. */ + obj_set_subsection_attributes (seg, space, 0x1f, 73, 0); + bfd_set_section_alignment (stdoutput, seg, 2); + + /* Make some space for the first special stab entry and zero the memory. + It contains information about the length of this file's + stab string and the like. Using it avoids the need to + relocate the stab strings. + + The $GDB_STRINGS$ space will be created as a side effect of + the call to get_stab_string_offset. */ + p = frag_more (12); + memset (p, 0, 12); + as_where (&file, (unsigned int *) NULL); + stroff = get_stab_string_offset (file, "$GDB_STRINGS$"); + know (stroff == 1); + md_number_to_chars (p, stroff, 4); + seg_info (seg)->stabu.p = p; + + /* Set the containing space for both stab sections to be $GDB_DEBUG$ + (just created above). Also set some attributes which BFD does + not understand. In particular, access bits, sort keys, and load + quadrant. */ + seg = bfd_get_section_by_name (stdoutput, "$GDB_STRINGS$"); + obj_set_subsection_attributes (seg, space, 0x1f, 72, 0); + bfd_set_section_alignment (stdoutput, seg, 2); + + subseg_set (saved_seg, saved_subseg); +} + +/* Fill in the counts in the first entry in a .stabs section. */ + +static void +adjust_stab_sections (abfd, sec, xxx) + bfd *abfd; + asection *sec; + PTR xxx; +{ + asection *strsec; + char *p; + int strsz, nsyms; + + if (strcmp ("$GDB_SYMBOLS$", sec->name)) + return; + + strsec = bfd_get_section_by_name (abfd, "$GDB_STRINGS$"); + if (strsec) + strsz = bfd_section_size (abfd, strsec); + else + strsz = 0; + nsyms = bfd_section_size (abfd, sec) / 12 - 1; + + p = seg_info (sec)->stabu.p; + assert (p != 0); + + bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6); + bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8); +} + +/* Called late in the asssembly phase to adjust the special + stab entry and to set the starting address for each code subspace. */ + +void +som_frob_file () +{ + bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0); +} diff --git a/gnu/usr.bin/binutils/gas/config/obj-som.h b/gnu/usr.bin/binutils/gas/config/obj-som.h new file mode 100644 index 00000000000..fa5cb1fe099 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-som.h @@ -0,0 +1,70 @@ +/* SOM object file format. + Copyright (C) 1993 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. + + Written by the Center for Software Science at the University of Utah + and by Cygnus Support. */ + +#ifndef _OBJ_SOM_H +#define _OBJ_SOM_H + +#define OBJ_SOM 1 + +#include +#include "bfd/som.h" +#include "targ-cpu.h" + +#ifndef FALSE +#define FALSE 0 +#define TRUE !FALSE +#endif + +/* should be conditional on address size! */ +#define som_symbol(asymbol) ((som_symbol_type *)(&(asymbol)->the_bfd)) + +extern void som_file_symbol PARAMS ((char *)); +extern void obj_som_version PARAMS ((int)); +extern void obj_som_init_stab_section PARAMS ((segT)); + +#define obj_symbol_new_hook(s) {;} + +/* SOM has several attributes for spaces/subspaces which can not + be easily expressed in BFD. We use these macros to trigger calls + into the SOM BFD backend to set these attributes. */ +#define obj_set_section_attributes bfd_som_set_section_attributes +#define obj_set_subsection_attributes bfd_som_set_subsection_attributes + +/* Likewise for symbol types. */ +#define obj_set_symbol_type bfd_som_set_symbol_type + +/* Stabs go in a separate sections. GDB expects to find them in sections + with the names $GDB_SYMBOLS$ and $GDB_STRINGS$ rather than .stab and + .stabstr. */ +#define SEPARATE_STAB_SECTIONS 1 +#define STAB_SECTION_NAME "$GDB_SYMBOLS$" +#define STAB_STRING_SECTION_NAME "$GDB_STRINGS$" + +/* We use INIT_STAB_SECTION to record the space/subspace relationships + for the various debugging sections. */ +#define INIT_STAB_SECTION(seg) obj_som_init_stab_section (seg) + +/* We'll be updating the magic 1st stab entry once the entire assembly + fail has been processed. */ +#define obj_frob_file() som_frob_file() + +#endif /* _OBJ_SOM_H */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-vms.c b/gnu/usr.bin/binutils/gas/config/obj-vms.c new file mode 100644 index 00000000000..55ca06c4bea --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-vms.c @@ -0,0 +1,5421 @@ +/* vms.c -- Write out a VAX/VMS object file + Copyright (C) 1987, 1988, 1992, 1994, 1995 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 2, 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. */ + +/* Written by David L. Kashtan */ +/* Modified by Eric Youngdale to write VMS debug records for program + variables */ + +/* Want all of obj-vms.h (as obj-format.h, via targ-env.h, via as.h). */ +#define WANT_VMS_OBJ_DEFS + +#include "as.h" +#include "config.h" +#include "subsegs.h" +#include "obstack.h" + +/* What we do if there is a goof. */ +#define error as_fatal + +#ifdef VMS /* These are of no use if we are cross assembling. */ +#include /* Define File Access Block */ +#include /* Define NAM Block */ +#include /* Define XAB - all different types*/ +extern int sys$open(), sys$close(), sys$asctim(); +#endif + +/* + * Version string of the compiler that produced the code we are + * assembling. (And this assembler, if we do not have compiler info.) + */ +char *compiler_version_string; + +extern int flag_hash_long_names; /* -+ */ +extern int flag_one; /* -1; compatibility with gcc 1.x */ +extern int flag_show_after_trunc; /* -H */ +extern int flag_no_hash_mixed_case; /* -h NUM */ + +/* Flag that determines how we map names. This takes several values, and + * is set with the -h switch. A value of zero implies names should be + * upper case, and the presence of the -h switch inhibits the case hack. + * No -h switch at all sets vms_name_mapping to 0, and allows case hacking. + * A value of 2 (set with -h2) implies names should be + * all lower case, with no case hack. A value of 3 (set with -h3) implies + * that case should be preserved. */ + +/* If the -+ switch is given, then the hash is appended to any name that is + * longer than 31 characters, regardless of the setting of the -h switch. + */ + +char vms_name_mapping = 0; + +static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */ + +/* + * We augment the "gas" symbol structure with this + */ +struct VMS_Symbol +{ + struct VMS_Symbol *Next; + symbolS *Symbol; + int Size; + int Psect_Index; + int Psect_Offset; +}; + +struct VMS_Symbol *VMS_Symbols = 0; + +/* We need this to keep track of the various input files, so that we can + * give the debugger the correct source line. + */ + +struct input_file +{ + struct input_file *next; + struct input_file *same_file_fpnt; + int file_number; + int max_line; + int min_line; + int offset; + char flag; + char *name; + symbolS *spnt; +}; + +static struct input_file *file_root = (struct input_file *) NULL; + + +/* + * Styles of PSECTS (program sections) that we generate; just shorthand + * to avoid lists of section attributes. Used by VMS_Psect_Spec(). + */ +enum ps_type +{ + ps_TEXT, ps_DATA, ps_COMMON, ps_CONST +}; + +/* + * This enum is used to keep track of the various types of variables that + * may be present. + */ + +enum advanced_type +{ + BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, ALIAS, UNKNOWN +}; + +/* + * This structure contains the information from the stabs directives, and the + * information is filled in by VMS_typedef_parse. Everything that is needed + * to generate the debugging record for a given symbol is present here. + * This could be done more efficiently, using nested struct/unions, but for now + * I am happy that it works. + */ +struct VMS_DBG_Symbol +{ + struct VMS_DBG_Symbol *next; + /* description of what this is */ + enum advanced_type advanced; + /* this record is for this type */ + int dbx_type; + /* For advanced types this is the type referred to. I.e., the type + a pointer points to, or the type of object that makes up an + array. */ + int type2; + /* Use this type when generating a variable def */ + int VMS_type; + /* used for arrays - this will be present for all */ + int index_min; + /* entries, but will be meaningless for non-arrays */ + int index_max; + /* Size in bytes of the data type. For an array, this is the size + of one element in the array */ + int data_size; + /* Number of the structure/union/enum - used for ref */ + int struc_numb; +}; + +#define SYMTYPLST_SIZE (1<<4) /* 16; must be power of two */ +#define SYMTYP_HASH(x) ((unsigned)(x) & (SYMTYPLST_SIZE-1)) +struct VMS_DBG_Symbol *VMS_Symbol_type_list[SYMTYPLST_SIZE]; + +/* + * We need this structure to keep track of forward references to + * struct/union/enum that have not been defined yet. When they are ultimately + * defined, then we can go back and generate the TIR commands to make a back + * reference. + */ + +struct forward_ref +{ + struct forward_ref *next; + int dbx_type; + int struc_numb; + char resolved; +}; + +struct forward_ref *f_ref_root = (struct forward_ref *) NULL; + +/* + * This routine is used to compare the names of certain types to various + * fixed types that are known by the debugger. + */ +#define type_check(X) !strcmp (symbol_name, X) + +/* + * This variable is used to keep track of the name of the symbol we are + * working on while we are parsing the stabs directives. + */ +static const char *symbol_name; + +/* We use this counter to assign numbers to all of the structures, unions + * and enums that we define. When we actually declare a variable to the + * debugger, we can simply do it by number, rather than describing the + * whole thing each time. + */ + +static structure_count = 0; + +/* This variable is used to indicate that we are making the last attempt to + parse the stabs, and that we should define as much as we can, and ignore + the rest */ + +static int final_pass; + +/* This variable is used to keep track of the current structure number + * for a given variable. If this is < 0, that means that the structure + * has not yet been defined to the debugger. This is still cool, since + * the VMS object language has ways of fixing things up after the fact, + * so we just make a note of this, and generate fixups at the end. + */ +static int struct_number; + +/* This is used to distinguish between D_float and G_float for telling + the debugger about doubles. gcc outputs the same .stabs regardless + of whether -mg is used to select alternate doubles. */ + +static int vax_g_doubles = 0; + +/* Local symbol references (used to handle N_ABS symbols; gcc does not + generate those, but they're possible with hand-coded assembler input) + are always made relative to some particular environment. If the current + input has any such symbols, then we expect this to get incremented + exactly once and end up having all of them be in environment #0. */ + +static int Current_Environment = -1; + +/* Every object file must specify an module name, which is also used by + traceback records. Set in Write_VMS_MHD_Records(). */ + +static char Module_Name[255+1]; + +/* + * Variable descriptors are used tell the debugger the data types of certain + * more complicated variables (basically anything involving a structure, + * union, enum, array or pointer). Some non-pointer variables of the + * basic types that the debugger knows about do not require a variable + * descriptor. + * + * Since it is impossible to have a variable descriptor longer than 128 + * bytes by virtue of the way that the VMS object language is set up, + * it makes not sense to make the arrays any longer than this, or worrying + * about dynamic sizing of the array. + * + * These are the arrays and counters that we use to build a variable + * descriptor. + */ + +#define MAX_DEBUG_RECORD 128 +static char Local[MAX_DEBUG_RECORD]; /* buffer for variable descriptor */ +static char Asuffix[MAX_DEBUG_RECORD]; /* buffer for array descriptor */ +static int Lpnt; /* index into Local */ +static int Apoint; /* index into Asuffix */ +static char overflow; /* flag to indicate we have written too much*/ +static int total_len; /* used to calculate the total length of variable + descriptor plus array descriptor - used for len byte*/ + +/* Flag if we have told user about finding global constants in the text + section. */ +static int gave_compiler_message = 0; + + +/* + * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime) + */ +static int VMS_Object_File_FD; /* File Descriptor for object file */ +static char Object_Record_Buffer[512]; /* Buffer for object file records */ +static int Object_Record_Offset;/* Offset to end of data */ +static int Current_Object_Record_Type; /* Type of record in above */ + +/* + * Macros for moving data around. Must work on big-endian systems. + */ +#ifdef VMS /* These are more efficient for VMS->VMS systems */ +#define COPY_LONG(dest,val) ( *(long *)(dest) = (val) ) +#define COPY_SHORT(dest,val) ( *(short *)(dest) = (val) ) +#else +#define COPY_LONG(dest,val) md_number_to_chars ((dest), (val), 4) +#define COPY_SHORT(dest,val) md_number_to_chars ((dest), (val), 2) +#endif +/* + * Macros for placing data into the object record buffer. + */ +#define PUT_LONG(val) \ + ( COPY_LONG (&Object_Record_Buffer[Object_Record_Offset], (val)), \ + Object_Record_Offset += 4 ) + +#define PUT_SHORT(val) \ + ( COPY_SHORT (&Object_Record_Buffer[Object_Record_Offset], (val)), \ + Object_Record_Offset += 2 ) + +#define PUT_CHAR(val) ( Object_Record_Buffer[Object_Record_Offset++] = (val) ) + +#define PUT_COUNTED_STRING(cp) do { \ + register const char *p = (cp); \ + PUT_CHAR ((char) strlen (p)); \ + while (*p) PUT_CHAR (*p++); } while (0) + +/* + * Macro for determining if a Name has psect attributes attached + * to it. + */ +#define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_" +#define PSECT_ATTRIBUTES_STRING_LENGTH 18 + +#define HAS_PSECT_ATTRIBUTES(Name) \ + (strncmp ((*Name == '_' ? Name + 1 : Name), \ + PSECT_ATTRIBUTES_STRING, \ + PSECT_ATTRIBUTES_STRING_LENGTH) == 0) + + + /* in: segT out: N_TYPE bits */ +const short seg_N_TYPE[] = +{ + N_ABS, + N_TEXT, + N_DATA, + N_BSS, + N_UNDF, /* unknown */ + N_UNDF, /* error */ + N_UNDF, /* expression */ + N_UNDF, /* debug */ + N_UNDF, /* ntv */ + N_UNDF, /* ptv */ + N_REGISTER, /* register */ +}; + +const segT N_TYPE_seg[N_TYPE + 2] = +{ /* N_TYPE == 0x1E = 32-2 */ + SEG_UNKNOWN, /* N_UNDF == 0 */ + SEG_GOOF, + SEG_ABSOLUTE, /* N_ABS == 2 */ + SEG_GOOF, + SEG_TEXT, /* N_TEXT == 4 */ + SEG_GOOF, + SEG_DATA, /* N_DATA == 6 */ + SEG_GOOF, + SEG_BSS, /* N_BSS == 8 */ + SEG_GOOF, + SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, + SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, + SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, + SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */ + SEG_GOOF, +}; + + +/* Local support routines which return a value. */ + +static struct input_file *find_file PARAMS ((symbolS *)); +static struct VMS_DBG_Symbol *find_symbol PARAMS ((int)); +static symbolS *Define_Routine PARAMS ((symbolS *,int,symbolS *,int)); + +static char *cvt_integer PARAMS ((char *,int *)); +static char *fix_name PARAMS ((char *)); +static char *get_struct_name PARAMS ((char *)); + +static offsetT VMS_Initialized_Data_Size PARAMS ((symbolS *,unsigned)); + +static int VMS_TBT_Source_File PARAMS ((char *,int)); +static int gen1 PARAMS ((struct VMS_DBG_Symbol *,int)); +static int forward_reference PARAMS ((char *)); +static int final_forward_reference PARAMS ((struct VMS_DBG_Symbol *)); +static int VMS_typedef_parse PARAMS ((char *)); +static int hash_string PARAMS ((const char *)); +static int VMS_Psect_Spec PARAMS ((const char *,int,enum ps_type, + struct VMS_Symbol *)); + +/* Local support routines which don't directly return any value. */ + +static void s_const PARAMS ((int)); +static void Create_VMS_Object_File PARAMS ((void)); +static void Flush_VMS_Object_Record_Buffer PARAMS ((void)); +static void Set_VMS_Object_File_Record PARAMS ((int)); +static void Close_VMS_Object_File PARAMS ((void)); +static void vms_tir_stack_psect PARAMS ((int,int,int)); +static void VMS_Store_Immediate_Data PARAMS ((const char *,int,int)); +static void VMS_Set_Data PARAMS ((int,int,int,int)); +static void VMS_Store_Struct PARAMS ((int)); +static void VMS_Def_Struct PARAMS ((int)); +static void VMS_Set_Struct PARAMS ((int)); +static void VMS_TBT_Module_Begin PARAMS ((void)); +static void VMS_TBT_Module_End PARAMS ((void)); +static void VMS_TBT_Routine_Begin PARAMS ((symbolS *,int)); +static void VMS_TBT_Routine_End PARAMS ((int,symbolS *)); +static void VMS_TBT_Block_Begin PARAMS ((symbolS *,int,char *)); +static void VMS_TBT_Block_End PARAMS ((valueT)); +static void VMS_TBT_Line_PC_Correlation PARAMS ((int,int,int,int)); +static void VMS_TBT_Source_Lines PARAMS ((int,int,int)); +static void fpush PARAMS ((int,int)); +static void rpush PARAMS ((int,int)); +static void array_suffix PARAMS ((struct VMS_DBG_Symbol *)); +static void new_forward_ref PARAMS ((int)); +static void generate_suffix PARAMS ((struct VMS_DBG_Symbol *,int)); +static void bitfield_suffix PARAMS ((struct VMS_DBG_Symbol *,int)); +static void setup_basic_type PARAMS ((struct VMS_DBG_Symbol *)); +static void VMS_DBG_record PARAMS ((struct VMS_DBG_Symbol *,int,int,char *)); +static void VMS_local_stab_Parse PARAMS ((symbolS *)); +static void VMS_stab_parse PARAMS ((symbolS *,int,int,int,int)); +static void VMS_GSYM_Parse PARAMS ((symbolS *,int)); +static void VMS_LCSYM_Parse PARAMS ((symbolS *,int)); +static void VMS_STSYM_Parse PARAMS ((symbolS *,int)); +static void VMS_RSYM_Parse PARAMS ((symbolS *,symbolS *,int)); +static void VMS_LSYM_Parse PARAMS ((void)); +static void Define_Local_Symbols PARAMS ((symbolS *,symbolS *,symbolS *,int)); +static void Write_VMS_MHD_Records PARAMS ((void)); +static void Write_VMS_EOM_Record PARAMS ((int,valueT)); +static void VMS_Case_Hack_Symbol PARAMS ((const char *,char *)); +static void VMS_Modify_Psect_Attributes PARAMS ((const char *,int *)); +static void VMS_Global_Symbol_Spec PARAMS ((const char *,int,int,int)); +static void VMS_Local_Environment_Setup PARAMS ((const char *)); +static void VMS_Emit_Globalvalues PARAMS ((unsigned,unsigned,char *)); +static void VMS_Procedure_Entry_Pt PARAMS ((char *,int,int,int)); +static void VMS_Set_Psect PARAMS ((int,int,int)); +static void VMS_Store_Repeated_Data PARAMS ((int,char *,int,int)); +static void VMS_Store_PIC_Symbol_Reference PARAMS ((symbolS *,int, + int,int,int,int)); +static void VMS_Fix_Indirect_Reference PARAMS ((int,int,fragS *,fragS *)); + +/* Support code which used to be inline within vms_write_object_file. */ +static void vms_fixup_text_section PARAMS ((unsigned,struct frag *,struct frag *)); +static void synthesize_data_segment PARAMS ((unsigned,unsigned,struct frag *)); +static void vms_fixup_data_section PARAMS ((unsigned,unsigned)); +static void global_symbol_directory PARAMS ((unsigned,unsigned)); +static void local_symbols_DST PARAMS ((symbolS *,symbolS *)); +static void vms_build_DST PARAMS ((unsigned)); + + +/* The following code defines the special types of pseudo-ops that we + use with VMS. */ + +unsigned char const_flag = IN_DEFAULT_SECTION; + +static void +s_const (arg) + int arg; /* 3rd field from obj_pseudo_table[]; not needed here */ +{ + /* Since we don't need `arg', use it as our scratch variable so that + we won't get any "not used" warnings about it. */ + arg = get_absolute_expression (); + subseg_set (SEG_DATA, (subsegT) arg); + const_flag = 1; + demand_empty_rest_of_line (); +} + +const pseudo_typeS obj_pseudo_table[] = +{ + {"const", s_const, 0}, + {0, 0, 0}, +}; /* obj_pseudo_table */ + + +/* Routine to perform RESOLVE_SYMBOL_REDEFINITION(). */ + +int +vms_resolve_symbol_redef (sym) + symbolS *sym; +{ + /* + * If the new symbol is .comm AND it has a size of zero, + * we ignore it (i.e. the old symbol overrides it) + */ + if (SEGMENT_TO_SYMBOL_TYPE ((int) now_seg) == (N_UNDF | N_EXT) + && frag_now_fix () == 0) + { + as_warn ("compiler emitted zero-size common symbol `%s' already defined", + S_GET_NAME (sym)); + return 1; + } + /* + * If the old symbol is .comm and it has a size of zero, + * we override it with the new symbol value. + */ + if (S_IS_EXTERNAL (sym) && S_IS_DEFINED (sym) && S_GET_VALUE (sym) == 0) + { + as_warn ("compiler redefined zero-size common symbol `%s'", + S_GET_NAME (sym)); + sym->sy_frag = frag_now; + S_SET_OTHER (sym, const_flag); + S_SET_VALUE (sym, frag_now_fix ()); + /* Keep N_EXT bit. */ + sym->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE ((int) now_seg); + return 1; + } + + return 0; +} + + +/* `tc_frob_label' handler for colon(symbols.c), used to examine the + dummy label(s) gcc inserts at the beginning of each file it generates. + gcc 1.x put "gcc_compiled."; gcc 2.x (as of 2.7) puts "gcc2_compiled." + and "__gnu_language_" and possibly "__vax__doubles". */ + +void +vms_check_for_special_label (symbolP) +symbolS *symbolP; +{ + /* Special labels only occur prior to explicit section directives. */ + if ((const_flag & IN_DEFAULT_SECTION) != 0) + { + char *sym_name = S_GET_NAME (symbolP); + + if (*sym_name == '_') + ++sym_name; + + if (!strcmp (sym_name, "__vax_g_doubles")) + vax_g_doubles = 1; +#if 0 /* not necessary */ + else if (!strcmp (sym_name, "__vax_d_doubles")) + vax_g_doubles = 0; +#endif +#if 0 /* these are potential alternatives to tc-vax.c's md_parse_options() */ + else if (!strcmp (sym_name, "gcc_compiled.")) + flag_one = 1; + else if (!strcmp (sym_name, "__gnu_language_cplusplus")) + flag_hash_long_names = 1; +#endif + } + return; +} + + +void +obj_read_begin_hook () +{ + return; +} + + +void +obj_crawl_symbol_chain (headers) + object_headers *headers; +{ + symbolS *symbolP; + symbolS **symbolPP; + int symbol_number = 0; + + symbolPP = &symbol_rootP; /* -> last symbol chain link. */ + while ((symbolP = *symbolPP) != NULL) + { + resolve_symbol_value (symbolP); + + /* OK, here is how we decide which symbols go out into the + brave new symtab. Symbols that do are: + + * symbols with no name (stabd's?) + * symbols with debug info in their N_TYPE + * symbols with \1 as their 3rd character (numeric labels) + * "local labels" needed for PIC fixups + + Symbols that don't are: + * symbols that are registers + + All other symbols are output. We complain if a deleted + symbol was marked external. */ + + if (!S_IS_REGISTER (symbolP)) + { + symbolP->sy_number = symbol_number++; + symbolP->sy_name_offset = 0; + symbolPP = &(symbol_next (symbolP)); + } + else + { + if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP)) + { + as_bad ("Local symbol %s never defined", S_GET_NAME (symbolP)); + } /* oops. */ + + /* Unhook it from the chain. */ + *symbolPP = symbol_next (symbolP); + } /* if this symbol should be in the output */ + + } /* for each symbol */ + + H_SET_STRING_SIZE (headers, string_byte_count); + H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number); +} /* obj_crawl_symbol_chain() */ + + + /****** VMS OBJECT FILE HACKING ROUTINES *******/ + + +/* Create the VMS object file. */ + +static void +Create_VMS_Object_File () +{ +#if defined(eunice) || !defined(VMS) + VMS_Object_File_FD = creat (out_file_name, 0777, "var"); +#else /* eunice */ + VMS_Object_File_FD = creat (out_file_name, 0, "rfm=var", + "mbc=16", "deq=64", "fop=tef", "shr=nil"); +#endif /* eunice */ + /* Deal with errors. */ + if (VMS_Object_File_FD < 0) + as_fatal ("Couldn't create VMS object file \"%s\"", out_file_name); + /* Initialize object file hacking variables. */ + Object_Record_Offset = 0; + Current_Object_Record_Type = -1; +} + + +/* Flush the object record buffer to the object file. */ + +static void +Flush_VMS_Object_Record_Buffer () +{ + /* If the buffer is empty, there's nothing to do. */ + if (Object_Record_Offset == 0) + return; + +#ifndef VMS /* For cross-assembly purposes. */ + { + char RecLen[2]; + + /* "Variable-length record" files have a two byte length field + prepended to each record. It's normally out-of-band, and native + VMS output will insert it automatically for this type of file. + When cross-assembling, we must write it explicitly. */ + md_number_to_chars (RecLen, Object_Record_Offset, 2); + if (write (VMS_Object_File_FD, RecLen, 2) != 2) + error ("I/O error writing VMS object file (length prefix)"); + /* We also need to force the actual record to be an even number of + bytes. For native output, that's automatic; when cross-assembling, + pad with a NUL byte if length is odd. Do so _after_ writing the + pre-padded length. Since our buffer is defined with even size, + an odd offset implies that it has some room left. */ + if ((Object_Record_Offset & 1) != 0) + Object_Record_Buffer[Object_Record_Offset++] = '\0'; + } +#endif /* not VMS */ + + /* Write the data to the file. */ + if (write (VMS_Object_File_FD, Object_Record_Buffer, Object_Record_Offset) + != Object_Record_Offset) + error ("I/O error writing VMS object file"); + + /* The buffer is now empty. */ + Object_Record_Offset = 0; +} + + +/* Declare a particular type of object file record. */ + +static void +Set_VMS_Object_File_Record (Type) + int Type; +{ + /* If the type matches, we are done. */ + if (Type == Current_Object_Record_Type) + return; + /* Otherwise: flush the buffer. */ + Flush_VMS_Object_Record_Buffer (); + /* Remember the new type. */ + Current_Object_Record_Type = Type; +} + + +/* Close the VMS Object file. */ + +static void +Close_VMS_Object_File () +{ + /* Flush (should never be necessary) and reset saved record-type context. */ + Set_VMS_Object_File_Record (-1); + +#ifndef VMS /* For cross-assembly purposes. */ + { + char RecLen[2]; + int minus_one = -1; + + /* Write a 2 byte record-length field of -1 into the file, which + means end-of-block when read, hence end-of-file when occurring + in the file's last block. It is only needed for variable-length + record files transferred to VMS as fixed-length record files + (typical for binary FTP; NFS shouldn't need it, but it won't hurt). */ + md_number_to_chars (RecLen, minus_one, 2); + write (VMS_Object_File_FD, RecLen, 2); + } +#else + /* When written on a VMS system, the file header (cf inode) will record + the actual end-of-file position and no inline marker is needed. */ +#endif + + close (VMS_Object_File_FD); +} + + + /****** Text Information and Relocation routines ******/ + + +/* Stack Psect base followed by signed, varying-sized offset. + Common to several object records. */ + +static void +vms_tir_stack_psect (Psect_Index, Offset, Force) + int Psect_Index; + int Offset; + int Force; +{ + int psect_width, offset_width; + + psect_width = ((unsigned) Psect_Index > 255) ? 2 : 1; + offset_width = (Force || Offset > 32767 || Offset < -32768) ? 4 + : (Offset > 127 || Offset < -128) ? 2 : 1; +#define Sta_P(p,o) (((o)<<1) | ((p)-1)) + /* byte or word psect; byte, word, or longword offset */ + switch (Sta_P(psect_width,offset_width)) + { + case Sta_P(1,1): PUT_CHAR (TIR_S_C_STA_PB); + PUT_CHAR ((char)(unsigned char) Psect_Index); + PUT_CHAR ((char) Offset); + break; + case Sta_P(1,2): PUT_CHAR (TIR_S_C_STA_PW); + PUT_CHAR ((char)(unsigned char) Psect_Index); + PUT_SHORT (Offset); + break; + case Sta_P(1,4): PUT_CHAR (TIR_S_C_STA_PL); + PUT_CHAR ((char)(unsigned char) Psect_Index); + PUT_LONG (Offset); + break; + case Sta_P(2,1): PUT_CHAR (TIR_S_C_STA_WPB); + PUT_SHORT (Psect_Index); + PUT_CHAR ((char) Offset); + break; + case Sta_P(2,2): PUT_CHAR (TIR_S_C_STA_WPW); + PUT_SHORT (Psect_Index); + PUT_SHORT (Offset); + break; + case Sta_P(2,4): PUT_CHAR (TIR_S_C_STA_WPL); + PUT_SHORT (Psect_Index); + PUT_LONG (Offset); + break; + } +#undef Sta_P +} + + +/* Store immediate data in current Psect. */ + +static void +VMS_Store_Immediate_Data (Pointer, Size, Record_Type) + const char *Pointer; + int Size; + int Record_Type; +{ + register int i; + + Set_VMS_Object_File_Record (Record_Type); + /* We can only store as most 128 bytes at a time due to the way that + TIR commands are encoded. */ + while (Size > 0) + { + i = (Size > 128) ? 128 : Size; + Size -= i; + /* If we cannot accommodate this record, flush the buffer. */ + if ((Object_Record_Offset + i + 1) >= sizeof Object_Record_Buffer) + Flush_VMS_Object_Record_Buffer (); + /* If the buffer is empty we must insert record type. */ + if (Object_Record_Offset == 0) + PUT_CHAR (Record_Type); + /* Store the count. The Store Immediate TIR command is implied by + a negative command byte, and the length of the immediate data + is abs(command_byte). So, we write the negated length value. */ + PUT_CHAR ((char) (-i & 0xff)); + /* Now store the data. */ + while (--i >= 0) + PUT_CHAR (*Pointer++); + } + /* Flush the buffer if it is more than 75% full. */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + + +/* Make a data reference. */ + +static void +VMS_Set_Data (Psect_Index, Offset, Record_Type, Force) + int Psect_Index; + int Offset; + int Record_Type; + int Force; +{ + Set_VMS_Object_File_Record (Record_Type); + /* If the buffer is empty we must insert the record type. */ + if (Object_Record_Offset == 0) + PUT_CHAR (Record_Type); + /* Stack the Psect base with its offset. */ + vms_tir_stack_psect (Psect_Index, Offset, Force); + /* Set relocation base. */ + PUT_CHAR (TIR_S_C_STO_PIDR); + /* Flush the buffer if it is more than 75% full. */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + + +/* Make a debugger reference to a struct, union or enum. */ + +static void +VMS_Store_Struct (Struct_Index) + int Struct_Index; +{ + /* We are writing a debug record. */ + Set_VMS_Object_File_Record (OBJ_S_C_DBG); + /* If the buffer is empty we must insert the record type. */ + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_DBG); + PUT_CHAR (TIR_S_C_STA_UW); + PUT_SHORT (Struct_Index); + PUT_CHAR (TIR_S_C_CTL_STKDL); + PUT_CHAR (TIR_S_C_STO_L); + /* Flush the buffer if it is more than 75% full. */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + + +/* Make a debugger reference to partially define a struct, union or enum. */ + +static void +VMS_Def_Struct (Struct_Index) + int Struct_Index; +{ + /* We are writing a debug record. */ + Set_VMS_Object_File_Record (OBJ_S_C_DBG); + /* If the buffer is empty we must insert the record type. */ + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_DBG); + PUT_CHAR (TIR_S_C_STA_UW); + PUT_SHORT (Struct_Index); + PUT_CHAR (TIR_S_C_CTL_DFLOC); + /* Flush the buffer if it is more than 75% full. */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + +static void +VMS_Set_Struct (Struct_Index) + int Struct_Index; +{ /* see previous functions for comments */ + Set_VMS_Object_File_Record (OBJ_S_C_DBG); + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_DBG); + PUT_CHAR (TIR_S_C_STA_UW); + PUT_SHORT (Struct_Index); + PUT_CHAR (TIR_S_C_CTL_STLOC); + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + + + /****** Traceback Information routines ******/ + + +/* Write the Traceback Module Begin record. */ + +static void +VMS_TBT_Module_Begin () +{ + register char *cp, *cp1; + int Size; + char Local[256]; + + /* Arrange to store the data locally (leave room for size byte). */ + cp = &Local[1]; + /* Begin module. */ + *cp++ = DST_S_C_MODBEG; + *cp++ = 0; /* flags; not used */ + /* + * Language type == "C" + * + * (FIXME: this should be based on the input...) + */ + COPY_LONG (cp, DST_S_C_C); + cp += 4; + /* Store the module name. */ + *cp++ = (char) strlen (Module_Name); + cp1 = Module_Name; + while (*cp1) + *cp++ = *cp1++; + /* Now we can store the record size. */ + Size = (cp - Local); + Local[0] = Size - 1; + /* Put it into the object record. */ + VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT); +} + + +/* Write the Traceback Module End record. */ + +static void +VMS_TBT_Module_End () +{ + char Local[2]; + + /* End module. */ + Local[0] = 1; + Local[1] = DST_S_C_MODEND; + /* Put it into the object record. */ + VMS_Store_Immediate_Data (Local, 2, OBJ_S_C_TBT); +} + + +/* Write a Traceback Routine Begin record. */ + +static void +VMS_TBT_Routine_Begin (symbolP, Psect) + symbolS *symbolP; + int Psect; +{ + register char *cp, *cp1; + char *Name; + int Offset; + int Size; + char Local[512]; + + /* Strip the leading "_" from the name. */ + Name = S_GET_NAME (symbolP); + if (*Name == '_') + Name++; + /* Get the text psect offset. */ + Offset = S_GET_VALUE (symbolP); + /* Set the record size. */ + Size = 1 + 1 + 4 + 1 + strlen (Name); + Local[0] = Size; + /* DST type "routine begin". */ + Local[1] = DST_S_C_RTNBEG; + /* Uses CallS/CallG. */ + Local[2] = 0; + /* Store the data so far. */ + VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT); + /* Make sure we are still generating a OBJ_S_C_TBT record. */ + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_TBT); + /* Stack the address. */ + vms_tir_stack_psect (Psect, Offset, 0); + /* Store the data reference. */ + PUT_CHAR (TIR_S_C_STO_PIDR); + /* Store the counted string as data. */ + cp = Local; + cp1 = Name; + Size = strlen (cp1) + 1; + *cp++ = Size - 1; + while (*cp1) + *cp++ = *cp1++; + VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT); +} + + +/* Write a Traceback Routine End record. + + We *must* search the symbol table to find the next routine, since the + assember has a way of reassembling the symbol table OUT OF ORDER Thus + the next routine in the symbol list is not necessarily the next one in + memory. For debugging to work correctly we must know the size of the + routine. */ + +static void +VMS_TBT_Routine_End (Max_Size, sp) + int Max_Size; + symbolS *sp; +{ + symbolS *symbolP; + int Size = 0x7fffffff; + char Local[16]; + valueT sym_value, sp_value = S_GET_VALUE (sp); + + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + { + if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT) + { + if (*S_GET_NAME (symbolP) == 'L') + continue; + sym_value = S_GET_VALUE (symbolP); + if (sym_value > sp_value && sym_value < Size) + Size = sym_value; + + /* + * Dummy labels like "gcc_compiled." should no longer reach here. + */ +#if 0 + else + /* check if gcc_compiled. has size of zero */ + if (sym_value == sp_value && + sp != symbolP && + (!strcmp (S_GET_NAME (sp), "gcc_compiled.") || + !strcmp (S_GET_NAME (sp), "gcc2_compiled."))) + Size = sym_value; +#endif + } + } + if (Size == 0x7fffffff) + Size = Max_Size; + Size -= sp_value; /* and get the size of the routine */ + /* Record Size. */ + Local[0] = 6; + /* DST type is "routine end". */ + Local[1] = DST_S_C_RTNEND; + Local[2] = 0; /* unused */ + /* Size of routine. */ + COPY_LONG (&Local[3], Size); + /* Store the record. */ + VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT); +} + + +/* Write a Traceback Block Begin record. */ + +static void +VMS_TBT_Block_Begin (symbolP, Psect, Name) + symbolS *symbolP; + int Psect; + char *Name; +{ + register char *cp, *cp1; + int Offset; + int Size; + char Local[512]; + + /* Set the record size. */ + Size = 1 + 1 + 4 + 1 + strlen (Name); + Local[0] = Size; + /* DST type is "begin block"; we simulate with a phony routine. */ + Local[1] = DST_S_C_BLKBEG; + /* Uses CallS/CallG. */ + Local[2] = 0; + /* Store the data so far. */ + VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_DBG); + /* Make sure we are still generating a debug record. */ + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_DBG); + /* Now get the symbol address. */ + PUT_CHAR (TIR_S_C_STA_WPL); + PUT_SHORT (Psect); + /* Get the text psect offset. */ + Offset = S_GET_VALUE (symbolP); + PUT_LONG (Offset); + /* Store the data reference. */ + PUT_CHAR (TIR_S_C_STO_PIDR); + /* Store the counted string as data. */ + cp = Local; + cp1 = Name; + Size = strlen (cp1) + 1; + *cp++ = Size - 1; + while (*cp1) + *cp++ = *cp1++; + VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_DBG); +} + + +/* Write a Traceback Block End record. */ + +static void +VMS_TBT_Block_End (Size) + valueT Size; +{ + char Local[16]; + + Local[0] = 6; /* record length */ + /* DST type is "block end"; simulate with a phony end routine. */ + Local[1] = DST_S_C_BLKEND; + Local[2] = 0; /* unused, must be zero */ + COPY_LONG (&Local[3], Size); + VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_DBG); +} + + +/* Write a Line number <-> Program Counter correlation record. */ + +static void +VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta) + int Line_Number; + int Offset; + int Psect; + int Do_Delta; +{ + register char *cp; + char Local[64]; + + if (Do_Delta == 0) + { + /* + * If not delta, set our PC/Line number correlation. + */ + cp = &Local[1]; /* Put size in Local[0] later. */ + /* DST type is "Line Number/PC correlation". */ + *cp++ = DST_S_C_LINE_NUM; + /* Set Line number. */ + if (Line_Number - 1 <= 255) + { + *cp++ = DST_S_C_SET_LINUM_B; + *cp++ = (char) (Line_Number - 1); + } + else if (Line_Number - 1 <= 65535) + { + *cp++ = DST_S_C_SET_LINE_NUM; + COPY_SHORT (cp, Line_Number - 1), cp += 2; + } + else + { + *cp++ = DST_S_C_SET_LINUM_L; + COPY_LONG (cp, Line_Number - 1), cp += 4; + } + /* Set PC. */ + *cp++ = DST_S_C_SET_ABS_PC; + /* Store size now that we know it, then output the data. */ + Local[0] = cp - &Local[1]; + /* Account for the space that TIR_S_C_STO_PIDR will use for the PC. */ + Local[0] += 4; /* size includes length of another longword */ + VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT); + /* Make sure we are still generating a OBJ_S_C_TBT record. */ + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_TBT); + vms_tir_stack_psect (Psect, Offset, 0); + PUT_CHAR (TIR_S_C_STO_PIDR); + /* Do a PC offset of 0 to register the line number. */ + Local[0] = 2; + Local[1] = DST_S_C_LINE_NUM; + Local[2] = 0; /* Increment PC by 0 and register line # */ + VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT); + } + else + { + if (Do_Delta < 0) + { + /* + * When delta is negative, terminate the line numbers. + */ + Local[0] = 1 + 1 + 4; + Local[1] = DST_S_C_LINE_NUM; + Local[2] = DST_S_C_TERM_L; + COPY_LONG (&Local[3], Offset); + VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT); + return; + } + /* + * Do a PC/Line delta. + */ + cp = &Local[1]; + *cp++ = DST_S_C_LINE_NUM; + if (Line_Number > 1) + { + /* We need to increment the line number. */ + if (Line_Number - 1 <= 255) + { + *cp++ = DST_S_C_INCR_LINUM; + *cp++ = Line_Number - 1; + } + else if (Line_Number - 1 <= 65535) + { + *cp++ = DST_S_C_INCR_LINUM_W; + COPY_SHORT (cp, Line_Number - 1), cp += 2; + } + else + { + *cp++ = DST_S_C_INCR_LINUM_L; + COPY_LONG (cp, Line_Number - 1), cp += 4; + } + } + /* + * Increment the PC + */ + if (Offset <= 128) + { + /* Small offsets are encoded as negative numbers, rather than the + usual non-negative type code followed by another data field. */ + *cp++ = (char) -Offset; + } + else if (Offset <= 65535) + { + *cp++ = DST_S_C_DELTA_PC_W; + COPY_SHORT (cp, Offset), cp += 2; + } + else + { + *cp++ = DST_S_C_DELTA_PC_L; + COPY_LONG (cp, Offset), cp += 4; + } + /* Set size now that be know it, then output the data. */ + Local[0] = cp - &Local[1]; + VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT); + } +} + + +/* Describe a source file to the debugger. */ + +static int +VMS_TBT_Source_File (Filename, ID_Number) + char *Filename; + int ID_Number; +{ + register char *cp; + int len, rfo, ffb, ebk; + char cdt[8]; + char Local[512]; +#ifdef VMS /* Used for native assembly */ + unsigned Status; + struct FAB fab; /* RMS file access block */ + struct NAM nam; /* file name information */ + struct XABDAT xabdat; /* date+time fields */ + struct XABFHC xabfhc; /* file header characteristics */ + char resultant_string_buffer[255 + 1]; + + /* + * Set up RMS structures: + */ + /* FAB -- file access block */ + memset ((char *) &fab, 0, sizeof fab); + fab.fab$b_bid = FAB$C_BID; + fab.fab$b_bln = (unsigned char) sizeof fab; + fab.fab$l_fna = Filename; + fab.fab$b_fns = (unsigned char) strlen (Filename); + fab.fab$l_nam = (char *) &nam; + fab.fab$l_xab = (char *) &xabdat; + /* NAM -- file name block */ + memset ((char *) &nam, 0, sizeof nam); + nam.nam$b_bid = NAM$C_BID; + nam.nam$b_bln = (unsigned char) sizeof nam; + nam.nam$l_rsa = resultant_string_buffer; + nam.nam$b_rss = (unsigned char) (sizeof resultant_string_buffer - 1); + /* XABs -- extended attributes blocks */ + memset ((char *) &xabdat, 0, sizeof xabdat); + xabdat.xab$b_cod = XAB$C_DAT; + xabdat.xab$b_bln = (unsigned char) sizeof xabdat; + xabdat.xab$l_nxt = (char *) &xabfhc; + memset ((char *) &xabfhc, 0, sizeof xabfhc); + xabfhc.xab$b_cod = XAB$C_FHC; + xabfhc.xab$b_bln = (unsigned char) sizeof xabfhc; + xabfhc.xab$l_nxt = 0; + /* + * Get the file information + */ + Status = sys$open (&fab); + if (!(Status & 1)) + { + as_tsktsk ("Couldn't find source file \"%s\", status=%%X%x", + Filename, Status); + return 0; + } + sys$close (&fab); + /* Now extract fields of interest. */ + memcpy (cdt, (char *) &xabdat.xab$q_cdt, 8); /* creation date */ + ebk = xabfhc.xab$l_ebk; /* end-of-file block */ + ffb = xabfhc.xab$w_ffb; /* first free byte of last block */ + rfo = xabfhc.xab$b_rfo; /* record format */ + len = nam.nam$b_rsl; /* length of Filename */ + resultant_string_buffer[len] = '\0'; + Filename = resultant_string_buffer; /* full filename */ +#else /* Cross-assembly */ + /* [Perhaps we ought to use actual values derived from stat() here?] */ + memset (cdt, 0, 8); /* null VMS quadword binary time */ + ebk = ffb = rfo = 0; + len = strlen (Filename); + if (len > 255) /* a single byte is used as count prefix */ + { + Filename += (len - 255); /* tail end is more significant */ + len = 255; + } +#endif /* VMS */ + + cp = &Local[1]; /* fill in record length later */ + *cp++ = DST_S_C_SOURCE; /* DST type is "source file" */ + *cp++ = DST_S_C_SRC_FORMFEED; /* formfeeds count as source records */ + *cp++ = DST_S_C_SRC_DECLFILE; /* declare source file */ + know (cp == &Local[4]); + *cp++ = 0; /* fill in this length below */ + *cp++ = 0; /* flags; must be zero */ + COPY_SHORT (cp, ID_Number), cp += 2; /* file ID number */ + memcpy (cp, cdt, 8), cp += 8; /* creation date+time */ + COPY_LONG (cp, ebk), cp += 4; /* end-of-file block */ + COPY_SHORT (cp, ffb), cp += 2; /* first free byte of last block */ + *cp++ = (char) rfo; /* RMS record format */ + /* Filename. */ + *cp++ = (char) len; + while (--len >= 0) + *cp++ = *Filename++; + /* Library module name (none). */ + *cp++ = 0; + /* Now that size is known, fill it in and write out the record. */ + Local[4] = cp - &Local[5]; /* source file declaration size */ + Local[0] = cp - &Local[1]; /* TBT record size */ + VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT); + return 1; +} + + +/* Traceback information is described in terms of lines from compiler + listing files, not lines from source files. We need to set up the + correlation between listing line numbers and source line numbers. + Since gcc's .stabn directives refer to the source lines, we just + need to describe a one-to-one correspondence. */ + +static void +VMS_TBT_Source_Lines (ID_Number, Starting_Line_Number, Number_Of_Lines) + int ID_Number; + int Starting_Line_Number; + int Number_Of_Lines; +{ + char *cp; + int chunk_limit; + char Local[128]; /* room enough to describe 1310700 lines... */ + + cp = &Local[1]; /* Put size in Local[0] later. */ + *cp++ = DST_S_C_SOURCE; /* DST type is "source file". */ + *cp++ = DST_S_C_SRC_SETFILE; /* Set Source File. */ + COPY_SHORT (cp, ID_Number), cp += 2; /* File ID Number. */ + /* Set record number and define lines. Since no longword form of + SRC_DEFLINES is available, we need to be able to cope with any huge + files a chunk at a time. It doesn't matter for tracebacks, since + unspecified lines are mapped one-to-one and work out right, but it + does matter within the debugger. Without this explicit mapping, + it will complain about lines not existing in the module. */ + chunk_limit = (sizeof Local - 5) / 6; + if (Number_Of_Lines > 65535 * chunk_limit) /* avoid buffer overflow */ + Number_Of_Lines = 65535 * chunk_limit; + while (Number_Of_Lines > 65535) + { + *cp++ = DST_S_C_SRC_SETREC_L; + COPY_LONG (cp, Starting_Line_Number), cp += 4; + *cp++ = DST_S_C_SRC_DEFLINES_W; + COPY_SHORT (cp, 65535), cp += 2; + Starting_Line_Number += 65535; + Number_Of_Lines -= 65535; + } + /* Set record number and define lines, normal case. */ + if (Starting_Line_Number <= 65535) + { + *cp++ = DST_S_C_SRC_SETREC_W; + COPY_SHORT (cp, Starting_Line_Number), cp += 2; + } + else + { + *cp++ = DST_S_C_SRC_SETREC_L; + COPY_LONG (cp, Starting_Line_Number), cp += 4; + } + *cp++ = DST_S_C_SRC_DEFLINES_W; + COPY_SHORT (cp, Number_Of_Lines), cp += 2; + /* Set size now that be know it, then output the data. */ + Local[0] = cp - &Local[1]; + VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT); +} + + + /****** Debugger Information support routines ******/ + + +/* This routine locates a file in the list of files. If an entry does + not exist, one is created. For include files, a new entry is always + created such that inline functions can be properly debugged. */ + +static struct input_file * +find_file (sp) + symbolS *sp; +{ + struct input_file *same_file = 0; + struct input_file *fpnt, *last = 0; + char *sp_name; + + for (fpnt = file_root; fpnt; fpnt = fpnt->next) + { + if (fpnt->spnt == sp) + return fpnt; + last = fpnt; + } + sp_name = S_GET_NAME (sp); + for (fpnt = file_root; fpnt; fpnt = fpnt->next) + { + if (strcmp (sp_name, fpnt->name) == 0) + { + if (fpnt->flag == 1) + return fpnt; + same_file = fpnt; + break; + } + } + fpnt = (struct input_file *) xmalloc (sizeof (struct input_file)); + if (!file_root) + file_root = fpnt; + else + last->next = fpnt; + fpnt->next = 0; + fpnt->name = sp_name; + fpnt->min_line = 0x7fffffff; + fpnt->max_line = 0; + fpnt->offset = 0; + fpnt->flag = 0; + fpnt->file_number = 0; + fpnt->spnt = sp; + fpnt->same_file_fpnt = same_file; + return fpnt; +} + + +/* This routine converts a number string into an integer, and stops when + it sees an invalid character. The return value is the address of the + character just past the last character read. No error is generated. */ + +static char * +cvt_integer (str, rtn) + char *str; + int *rtn; +{ + int ival = 0, sgn = 1; + + if (*str == '-') + sgn = -1, ++str; + while (*str >= '0' && *str <= '9') + ival = 10 * ival + *str++ - '0'; + *rtn = sgn * ival; + return str; +} + + +/* + * The following functions and definitions are used to generate object + * records that will describe program variables to the VMS debugger. + * + * This file contains many of the routines needed to output debugging info + * into the object file that the VMS debugger needs to understand symbols. + * These routines are called very late in the assembly process, and thus + * we can be fairly lax about changing things, since the GSD and the TIR + * sections have already been output. + */ + + +/* This routine fixes the names that are generated by C++, ".this" is a good + example. The period does not work for the debugger, since it looks like + the syntax for a structure element, and thus it gets mightily confused. + + We also use this to strip the PsectAttribute hack from the name before we + write a debugger record. */ + +static char * +fix_name (pnt) + char *pnt; +{ + char *pnt1; + + /* Kill any leading "_". */ + if (*pnt == '_') + pnt++; + + /* Is there a Psect Attribute to skip?? */ + if (HAS_PSECT_ATTRIBUTES (pnt)) + { + /* Yes: Skip it. */ + pnt += PSECT_ATTRIBUTES_STRING_LENGTH; + while (*pnt) + { + if ((pnt[0] == '$') && (pnt[1] == '$')) + { + pnt += 2; + break; + } + pnt++; + } + } + + /* Here we fix the .this -> $this conversion. */ + for (pnt1 = pnt; *pnt1 != 0; pnt1++) + if (*pnt1 == '.') + *pnt1 = '$'; + + return pnt; +} + + +/* When defining a structure, this routine is called to find the name of + the actual structure. It is assumed that str points to the equal sign + in the definition, and it moves backward until it finds the start of the + name. If it finds a 0, then it knows that this structure def is in the + outermost level, and thus symbol_name points to the symbol name. */ + +static char * +get_struct_name (str) + char *str; +{ + char *pnt; + pnt = str; + while ((*pnt != ':') && (*pnt != '\0')) + pnt--; + if (*pnt == '\0') + return (char *) symbol_name; + *pnt-- = '\0'; + while ((*pnt != ';') && (*pnt != '=')) + pnt--; + if (*pnt == ';') + return pnt + 1; + while ((*pnt < '0') || (*pnt > '9')) + pnt++; + while ((*pnt >= '0') && (*pnt <= '9')) + pnt++; + return pnt; +} + + +/* Search symbol list for type number dbx_type. + Return a pointer to struct. */ + +static struct VMS_DBG_Symbol * +find_symbol (dbx_type) + int dbx_type; +{ + struct VMS_DBG_Symbol *spnt; + + spnt = VMS_Symbol_type_list[SYMTYP_HASH (dbx_type)]; + while (spnt) + { + if (spnt->dbx_type == dbx_type) + break; + spnt = spnt->next; + } + if (!spnt || spnt->advanced != ALIAS) + return spnt; + return find_symbol (spnt->type2); +} + + +#if 0 /* obsolete */ +/* this routine puts info into either Local or Asuffix, depending on the sign + * of size. The reason is that it is easier to build the variable descriptor + * backwards, while the array descriptor is best built forwards. In the end + * they get put together, if there is not a struct/union/enum along the way + */ +static void +push (value, size1) + int value, size1; +{ + if (size1 < 0) + { + size1 = -size1; + if (Lpnt < size1) + { + overflow = 1; + Lpnt = 1; + return; + } + Lpnt -= size1; + md_number_to_chars (&Local[Lpnt + 1], value, size1); + } + else + { + if (Apoint + size1 >= MAX_DEBUG_RECORD) + { + overflow = 1; + Apoint = MAX_DEBUG_RECORD - 1; + return; + } + md_number_to_chars (&Asuffix[Apoint], value, size1); + Apoint += size1; + } +} +#endif + + +static void +fpush (value, size) + int value, size; +{ + if (Apoint + size >= MAX_DEBUG_RECORD) + { + overflow = 1; + Apoint = MAX_DEBUG_RECORD - 1; + return; + } + if (size == 1) + Asuffix[Apoint++] = (char) value; + else + { + md_number_to_chars (&Asuffix[Apoint], value, size); + Apoint += size; + } +} + +static void +rpush (value, size) + int value, size; +{ + if (Lpnt < size) + { + overflow = 1; + Lpnt = 1; + return; + } + if (size == 1) + Local[Lpnt--] = (char) value; + else + { + Lpnt -= size; + md_number_to_chars (&Local[Lpnt + 1], value, size); + } +} + + +/* This routine generates the array descriptor for a given array. */ + +static void +array_suffix (spnt2) + struct VMS_DBG_Symbol *spnt2; +{ + struct VMS_DBG_Symbol *spnt; + struct VMS_DBG_Symbol *spnt1; + int rank; + int total_size; + + rank = 0; + spnt = spnt2; + while (spnt->advanced != ARRAY) + { + spnt = find_symbol (spnt->type2); + if (!spnt) + return; + } + spnt1 = spnt; + total_size = 1; + while (spnt1->advanced == ARRAY) + { + rank++; + total_size *= (spnt1->index_max - spnt1->index_min + 1); + spnt1 = find_symbol (spnt1->type2); + } + total_size = total_size * spnt1->data_size; + fpush (spnt1->data_size, 2); /* element size */ + if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE) + fpush (0, 1); + else + fpush (spnt1->VMS_type, 1); /* element type */ + fpush (DSC_K_CLASS_A, 1); /* descriptor class */ + fpush (0, 4); /* base address */ + fpush (0, 1); /* scale factor -- not applicable */ + fpush (0, 1); /* digit count -- not applicable */ + fpush (0xc0, 1); /* flags: multiplier block & bounds present */ + fpush (rank, 1); /* number of dimensions */ + fpush (total_size, 4); + fpush (0, 4); /* pointer to element [0][0]...[0] */ + spnt1 = spnt; + while (spnt1->advanced == ARRAY) + { + fpush (spnt1->index_max - spnt1->index_min + 1, 4); + spnt1 = find_symbol (spnt1->type2); + } + spnt1 = spnt; + while (spnt1->advanced == ARRAY) + { + fpush (spnt1->index_min, 4); + fpush (spnt1->index_max, 4); + spnt1 = find_symbol (spnt1->type2); + } +} + + +/* This routine generates the start of a variable descriptor based upon + a struct/union/enum that has yet to be defined. We define this spot as + a new location, and save four bytes for the address. When the struct is + finally defined, then we can go back and plug in the correct address. */ + +static void +new_forward_ref (dbx_type) + int dbx_type; +{ + struct forward_ref *fpnt; + fpnt = (struct forward_ref *) xmalloc (sizeof (struct forward_ref)); + fpnt->next = f_ref_root; + f_ref_root = fpnt; + fpnt->dbx_type = dbx_type; + fpnt->struc_numb = ++structure_count; + fpnt->resolved = 'N'; + rpush (DST_K_TS_IND, 1); /* indirect type specification */ + total_len = 5; + rpush (total_len, 2); + struct_number = -fpnt->struc_numb; +} + + +/* This routine generates the variable descriptor used to describe non-basic + variables. It calls itself recursively until it gets to the bottom of it + all, and then builds the descriptor backwards. It is easiest to do it + this way since we must periodically write length bytes, and it is easiest + if we know the value when it is time to write it. */ + +static int +gen1 (spnt, array_suffix_len) + struct VMS_DBG_Symbol *spnt; + int array_suffix_len; +{ + struct VMS_DBG_Symbol *spnt1; + int i; + + switch (spnt->advanced) + { + case VOID: + rpush (DBG_S_C_VOID, 1); + total_len += 1; + rpush (total_len, 2); + return 0; + case BASIC: + case FUNCTION: + if (array_suffix_len == 0) + { + rpush (spnt->VMS_type, 1); + rpush (DBG_S_C_BASIC, 1); + total_len = 2; + rpush (total_len, 2); + return 1; + } + rpush (0, 4); + rpush (DST_K_VFLAGS_DSC, 1); + rpush (DST_K_TS_DSC, 1); /* descriptor type specification */ + total_len = -2; + return 1; + case STRUCT: + case UNION: + case ENUM: + struct_number = spnt->struc_numb; + if (struct_number < 0) + { + new_forward_ref (spnt->dbx_type); + return 1; + } + rpush (DBG_S_C_STRUCT, 1); + total_len = 5; + rpush (total_len, 2); + return 1; + case POINTER: + spnt1 = find_symbol (spnt->type2); + i = 1; + if (!spnt1) + new_forward_ref (spnt->type2); + else + i = gen1 (spnt1, 0); + if (i) + { /* (*void) is a special case, do not put pointer suffix */ + rpush (DBG_S_C_POINTER, 1); + total_len += 3; + rpush (total_len, 2); + } + return 1; + case ARRAY: + spnt1 = spnt; + while (spnt1->advanced == ARRAY) + { + spnt1 = find_symbol (spnt1->type2); + if (!spnt1) + { + as_tsktsk ("debugger forward reference error, dbx type %d", + spnt->type2); + return 0; + } + } +/* It is too late to generate forward references, so the user gets a message. + * This should only happen on a compiler error */ + (void) gen1 (spnt1, 1); + i = Apoint; + array_suffix (spnt); + array_suffix_len = Apoint - i; + switch (spnt1->advanced) + { + case BASIC: + case FUNCTION: + break; + default: + rpush (0, 2); + total_len += 2; + rpush (total_len, 2); + rpush (DST_K_VFLAGS_DSC, 1); + rpush (1, 1); /* flags: element value spec included */ + rpush (1, 1); /* one dimension */ + rpush (DBG_S_C_COMPLEX_ARRAY, 1); + } + total_len += array_suffix_len + 8; + rpush (total_len, 2); + break; + default: /* lint suppression */ + break; + } + return 0; +} + + +/* This generates a suffix for a variable. If it is not a defined type yet, + then dbx_type contains the type we are expecting so we can generate a + forward reference. This calls gen1 to build most of the descriptor, and + then it puts the icing on at the end. It then dumps whatever is needed + to get a complete descriptor (i.e. struct reference, array suffix). */ + +static void +generate_suffix (spnt, dbx_type) + struct VMS_DBG_Symbol *spnt; + int dbx_type; +{ + static const char pvoid[6] = { + 5, /* record.length == 5 */ + DST_K_TYPSPEC, /* record.type == 1 (type specification) */ + 0, /* name.length == 0, no name follows */ + 1, 0, /* type.length == 1 {2 bytes, little endian} */ + DBG_S_C_VOID /* type.type == 5 (pointer to unspecified) */ + }; + int i; + + Apoint = 0; + Lpnt = MAX_DEBUG_RECORD - 1; + total_len = 0; + struct_number = 0; + overflow = 0; + if (!spnt) + new_forward_ref (dbx_type); + else + { + if (spnt->VMS_type != DBG_S_C_ADVANCED_TYPE) + return; /* no suffix needed */ + gen1 (spnt, 0); + } + rpush (0, 1); /* no name (len==0) */ + rpush (DST_K_TYPSPEC, 1); + total_len += 4; + rpush (total_len, 1); + /* If the variable descriptor overflows the record, output a descriptor + for a pointer to void. */ + if ((total_len >= MAX_DEBUG_RECORD) || overflow) + { + as_warn ("Variable descriptor %d too complicated. Defined as `void *'.", + spnt->dbx_type); + VMS_Store_Immediate_Data (pvoid, 6, OBJ_S_C_DBG); + return; + } + i = 0; + while (Lpnt < MAX_DEBUG_RECORD - 1) + Local[i++] = Local[++Lpnt]; + Lpnt = i; + /* we use this for reference to structure that has already been defined */ + if (struct_number > 0) + { + VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); + Lpnt = 0; + VMS_Store_Struct (struct_number); + } + /* We use this for a forward reference to a structure that has yet to + be defined. We store four bytes of zero to make room for the actual + address once it is known. */ + if (struct_number < 0) + { + struct_number = -struct_number; + VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); + Lpnt = 0; + VMS_Def_Struct (struct_number); + COPY_LONG (&Local[Lpnt], 0L); + Lpnt += 4; + VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); + Lpnt = 0; + } + i = 0; + while (i < Apoint) + Local[Lpnt++] = Asuffix[i++]; + if (Lpnt != 0) + VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); + Lpnt = 0; +} + + + /* "novel length" type doesn't work for simple atomic types */ +#define USE_BITSTRING_DESCRIPTOR(t) ((t)->advanced == BASIC) +#undef SETUP_BASIC_TYPES + +/* This routine generates a type description for a bitfield. */ + +static void +bitfield_suffix (spnt, width) + struct VMS_DBG_Symbol *spnt; + int width; +{ + Local[Lpnt++] = 13; /* rec.len==13 */ + Local[Lpnt++] = DST_K_TYPSPEC; /* a type specification record */ + Local[Lpnt++] = 0; /* not named */ + COPY_SHORT (&Local[Lpnt], 9); /* typ.len==9 */ + Lpnt += 2; + Local[Lpnt++] = DST_K_TS_NOV_LENG; /* This type is a "novel length" + incarnation of some other type. */ + COPY_LONG (&Local[Lpnt], width); /* size in bits == novel length */ + Lpnt += 4; + VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); + Lpnt = 0; + /* assert( spnt->struc_numb > 0 ); */ + VMS_Store_Struct (spnt->struc_numb); /* output 4 more bytes */ +} + + +/* Formally define a builtin type, so that it can serve as the target of + an indirect reference. It makes bitfield_suffix() easier by avoiding + the need to use a forward reference for the first occurrence of each + type used in a bitfield. */ + +static void +setup_basic_type (spnt) + struct VMS_DBG_Symbol *spnt; +{ +#ifdef SETUP_BASIC_TYPES + /* This would be very useful if "novel length" fields actually worked + with basic types like they do with enumerated types. However, + they do not, so this isn't worth doing just so that you can use + EXAMINE/TYPE=(__long_long_int) instead of EXAMINE/QUAD. */ + char *p; +#ifndef SETUP_SYNONYM_TYPES + /* This determines whether compatible things like `int' and `long int' + ought to have distinct type records rather than sharing one. */ + struct VMS_DBG_Symbol *spnt2; + + /* first check whether this type has already been seen by another name */ + for (spnt2 = VMS_Symbol_type_list[SYMTYP_HASH (spnt->VMS_type)]; + spnt2; + spnt2 = spnt2->next) + if (spnt2 != spnt && spnt2->VMS_type == spnt->VMS_type) + { + spnt->struc_numb = spnt2->struc_numb; + return; + } +#endif + + /* `structure number' doesn't really mean `structure'; it means an index + into a linker maintained set of saved locations which can be referenced + again later. */ + spnt->struc_numb = ++structure_count; + VMS_Def_Struct (spnt->struc_numb); /* remember where this type lives */ + /* define the simple scalar type */ + Local[Lpnt++] = 6 + strlen (symbol_name) + 2; /* rec.len */ + Local[Lpnt++] = DST_K_TYPSPEC; /* rec.typ==type specification */ + Local[Lpnt++] = strlen (symbol_name) + 2; + Local[Lpnt++] = '_'; /* prefix name with "__" */ + Local[Lpnt++] = '_'; + for (p = symbol_name; *p; p++) + Local[Lpnt++] = *p == ' ' ? '_' : *p; + COPY_SHORT (&Local[Lpnt], 2); /* typ.len==2 */ + Lpnt += 2; + Local[Lpnt++] = DST_K_TS_ATOM; /* typ.kind is simple type */ + Local[Lpnt++] = spnt->VMS_type; /* typ.type */ + VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); + Lpnt = 0; +#endif /* SETUP_BASIC_TYPES */ + return; +} + + +/* This routine generates a symbol definition for a C symbol for the debugger. + It takes a psect and offset for global symbols; if psect < 0, then this is + a local variable and the offset is relative to FP. In this case it can + be either a variable (Offset < 0) or a parameter (Offset > 0). */ + +static void +VMS_DBG_record (spnt, Psect, Offset, Name) + struct VMS_DBG_Symbol *spnt; + int Psect; + int Offset; + char *Name; +{ + char *Name_pnt; + int len; + int i = 0; + + /* if there are bad characters in name, convert them */ + Name_pnt = fix_name (Name); + + len = strlen (Name_pnt); + if (Psect < 0) + { /* this is a local variable, referenced to SP */ + Local[i++] = 7 + len; + Local[i++] = spnt->VMS_type; + Local[i++] = (Offset > 0) ? DBG_C_FUNCTION_PARAM : DBG_C_LOCAL_SYM; + COPY_LONG (&Local[i], Offset); + i += 4; + } + else + { + Local[i++] = 7 + len; + Local[i++] = spnt->VMS_type; + Local[i++] = DST_K_VALKIND_ADDR; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + VMS_Set_Data (Psect, Offset, OBJ_S_C_DBG, 0); + } + Local[i++] = len; + while (*Name_pnt != '\0') + Local[i++] = *Name_pnt++; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE) + generate_suffix (spnt, 0); +} + + +/* This routine parses the stabs entries in order to make the definition + for the debugger of local symbols and function parameters. */ + +static void +VMS_local_stab_Parse (sp) + symbolS *sp; +{ + struct VMS_DBG_Symbol *spnt; + char *pnt; + char *pnt1; + char *str; + int dbx_type; + + dbx_type = 0; + str = S_GET_NAME (sp); + pnt = (char *) strchr (str, ':'); + if (!pnt) + return; /* no colon present */ + pnt1 = pnt++; /* save this for later, and skip colon */ + if (*pnt == 'c') + return; /* ignore static constants */ + +/* there is one little catch that we must be aware of. Sometimes function + * parameters are optimized into registers, and the compiler, in its infiite + * wisdom outputs stabs records for *both*. In general we want to use the + * register if it is present, so we must search the rest of the symbols for + * this function to see if this parameter is assigned to a register. + */ + { + symbolS *sp1; + char *str1; + char *pnt2; + + if (*pnt == 'p') + { + for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1)) + { + if (!S_IS_DEBUG (sp1)) + continue; + if (S_GET_RAW_TYPE (sp1) == N_FUN) + { + pnt2 = (char *) strchr (S_GET_NAME (sp1), ':') + 1; + if (*pnt2 == 'F' || *pnt2 == 'f') + break; + } + if (S_GET_RAW_TYPE (sp1) != N_RSYM) + continue; + str1 = S_GET_NAME (sp1); /* and get the name */ + pnt2 = str; + while (*pnt2 != ':') + { + if (*pnt2 != *str1) + break; + pnt2++; + str1++; + } + if (*str1 == ':' && *pnt2 == ':') + return; /* they are the same! lets skip this one */ + } /* for */ + pnt++; /* skip p in case no register */ + } /* if */ + } /* p block */ + + pnt = cvt_integer (pnt, &dbx_type); + spnt = find_symbol (dbx_type); + if (!spnt) + return; /*Dunno what this is*/ + *pnt1 = '\0'; + VMS_DBG_record (spnt, -1, S_GET_VALUE (sp), str); + *pnt1 = ':'; /* and restore the string */ + return; +} + + +/* This routine parses a stabs entry to find the information required + to define a variable. It is used for global and static variables. + Basically we need to know the address of the symbol. With older + versions of the compiler, const symbols are treated differently, in + that if they are global they are written into the text psect. The + global symbol entry for such a const is actually written as a program + entry point (Yuk!!), so if we cannot find a symbol in the list of + psects, we must search the entry points as well. static consts are + even harder, since they are never assigned a memory address. The + compiler passes a stab to tell us the value, but I am not sure what + to do with it. */ + +static void +VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect) + symbolS *sp; + int expected_type; /* char */ + int type1, type2, Text_Psect; +{ + char *pnt; + char *pnt1; + char *str; + symbolS *sp1; + struct VMS_DBG_Symbol *spnt; + struct VMS_Symbol *vsp; + int dbx_type; + + dbx_type = 0; + str = S_GET_NAME (sp); + pnt = (char *) strchr (str, ':'); + if (!pnt) + return; /* no colon present */ + pnt1 = pnt; /* save this for later*/ + pnt++; + if (*pnt == expected_type) + { + pnt = cvt_integer (pnt + 1, &dbx_type); + spnt = find_symbol (dbx_type); + if (!spnt) + return; /*Dunno what this is*/ + /* + * Now we need to search the symbol table to find the psect and + * offset for this variable. + */ + *pnt1 = '\0'; + vsp = VMS_Symbols; + while (vsp) + { + pnt = S_GET_NAME (vsp->Symbol); + if (pnt && *pnt++ == '_' + /* make sure name is the same and symbol type matches */ + && strcmp (pnt, str) == 0 + && (S_GET_RAW_TYPE (vsp->Symbol) == type1 + || S_GET_RAW_TYPE (vsp->Symbol) == type2)) + break; + vsp = vsp->Next; + } + if (vsp) + { + VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str); + *pnt1 = ':'; /* and restore the string */ + return; + } + /* The symbol was not in the symbol list, but it may be an + "entry point" if it was a constant. */ + for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1)) + { + /* + * Dispatch on STAB type + */ + if (S_IS_DEBUG (sp1) || (S_GET_TYPE (sp1) != N_TEXT)) + continue; + pnt = S_GET_NAME (sp1); + if (*pnt == '_') + pnt++; + if (strcmp (pnt, str) == 0) + { + if (!gave_compiler_message && expected_type == 'G') + { + static const char long_const_msg[] = "\ +***Warning - the assembly code generated by the compiler has placed \n\ + global constant(s) in the text psect. These will not be available to \n\ + other modules, since this is not the correct way to handle this. You \n\ + have two options: 1) get a patched compiler that does not put global \n\ + constants in the text psect, or 2) remove the 'const' keyword from \n\ + definitions of global variables in your source module(s). Don't say \n\ + I didn't warn you! \n"; + + as_tsktsk (long_const_msg); + gave_compiler_message = 1; + } + VMS_DBG_record (spnt, + Text_Psect, + S_GET_VALUE (sp1), + str); + *pnt1 = ':'; + /* fool assembler to not output this as a routine in the TBT */ + pnt1 = S_GET_NAME (sp1); + *pnt1 = 'L'; + S_SET_NAME (sp1, pnt1); + return; + } + } + } + *pnt1 = ':'; /* and restore the string */ + return; +} + + +/* Simpler interfaces into VMS_stab_parse(). */ + +static void +VMS_GSYM_Parse (sp, Text_Psect) + symbolS *sp; + int Text_Psect; +{ /* Global variables */ + VMS_stab_parse (sp, 'G', (N_UNDF | N_EXT), (N_DATA | N_EXT), Text_Psect); +} + +static void +VMS_LCSYM_Parse (sp, Text_Psect) + symbolS *sp; + int Text_Psect; +{ /* Static symbols - uninitialized */ + VMS_stab_parse (sp, 'S', N_BSS, -1, Text_Psect); +} + +static void +VMS_STSYM_Parse (sp, Text_Psect) + symbolS *sp; + int Text_Psect; +{ /* Static symbols - initialized */ + VMS_stab_parse (sp, 'S', N_DATA, -1, Text_Psect); +} + + +/* For register symbols, we must figure out what range of addresses + within the psect are valid. We will use the brackets in the stab + directives to give us guidance as to the PC range that this variable + is in scope. I am still not completely comfortable with this but + as I learn more, I seem to get a better handle on what is going on. + Caveat Emptor. */ + +static void +VMS_RSYM_Parse (sp, Current_Routine, Text_Psect) + symbolS *sp, *Current_Routine; + int Text_Psect; +{ + symbolS *symbolP; + struct VMS_DBG_Symbol *spnt; + char *pnt; + char *pnt1; + char *str; + int dbx_type; + int len; + int i = 0; + int bcnt = 0; + int Min_Offset = -1; /* min PC of validity */ + int Max_Offset = 0; /* max PC of validity */ + + for (symbolP = sp; symbolP; symbolP = symbol_next (symbolP)) + { + /* + * Dispatch on STAB type + */ + switch (S_GET_RAW_TYPE (symbolP)) + { + case N_LBRAC: + if (bcnt++ == 0) + Min_Offset = S_GET_VALUE (symbolP); + break; + case N_RBRAC: + if (--bcnt == 0) + Max_Offset = S_GET_VALUE (symbolP) - 1; + break; + } + if ((Min_Offset != -1) && (bcnt == 0)) + break; + if (S_GET_RAW_TYPE (symbolP) == N_FUN) + { + pnt = (char *) strchr (S_GET_NAME (symbolP), ':') + 1; + if (*pnt == 'F' || *pnt == 'f') break; + } + } + + /* Check to see that the addresses were defined. If not, then there + were no brackets in the function, and we must try to search for + the next function. Since functions can be in any order, we should + search all of the symbol list to find the correct ending address. */ + if (Min_Offset == -1) + { + int Max_Source_Offset; + int This_Offset; + + Min_Offset = S_GET_VALUE (sp); + Max_Source_Offset = Min_Offset; /* just in case no N_SLINEs found */ + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + switch (S_GET_RAW_TYPE (symbolP)) + { + case N_TEXT | N_EXT: + This_Offset = S_GET_VALUE (symbolP); + if (This_Offset > Min_Offset && This_Offset < Max_Offset) + Max_Offset = This_Offset; + break; + case N_SLINE: + This_Offset = S_GET_VALUE (symbolP); + if (This_Offset > Max_Source_Offset) + Max_Source_Offset = This_Offset; + break; + } + /* If this is the last routine, then we use the PC of the last source + line as a marker of the max PC for which this reg is valid. */ + if (Max_Offset == 0x7fffffff) + Max_Offset = Max_Source_Offset; + } + + dbx_type = 0; + str = S_GET_NAME (sp); + if ((pnt = (char *) strchr (str, ':')) == 0) + return; /* no colon present */ + pnt1 = pnt; /* save this for later*/ + pnt++; + if (*pnt != 'r') + return; + pnt = cvt_integer (pnt + 1, &dbx_type); + spnt = find_symbol (dbx_type); + if (!spnt) + return; /*Dunno what this is yet*/ + *pnt1 = '\0'; + pnt = fix_name (S_GET_NAME (sp)); /* if there are bad characters in name, convert them */ + len = strlen (pnt); + Local[i++] = 25 + len; + Local[i++] = spnt->VMS_type; + Local[i++] = DST_K_VFLAGS_TVS; /* trailing value specified */ + COPY_LONG (&Local[i], 1 + len); /* relative offset, beyond name */ + i += 4; + Local[i++] = len; /* name length (ascic prefix) */ + while (*pnt != '\0') + Local[i++] = *pnt++; + Local[i++] = DST_K_VS_FOLLOWS; /* value specification follows */ + COPY_SHORT (&Local[i], 15); /* length of rest of record */ + i += 2; + Local[i++] = DST_K_VS_ALLOC_SPLIT; /* split lifetime */ + Local[i++] = 1; /* one binding follows */ + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + VMS_Set_Data (Text_Psect, Min_Offset, OBJ_S_C_DBG, 1); + VMS_Set_Data (Text_Psect, Max_Offset, OBJ_S_C_DBG, 1); + Local[i++] = DST_K_VALKIND_REG; /* nested value spec */ + COPY_LONG (&Local[i], S_GET_VALUE (sp)); + i += 4; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + *pnt1 = ':'; + if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE) + generate_suffix (spnt, 0); +} + + +/* This function examines a structure definition, checking all of the elements + to make sure that all of them are fully defined. The only thing that we + kick out are arrays of undefined structs, since we do not know how big + they are. All others we can handle with a normal forward reference. */ + +static int +forward_reference (pnt) + char *pnt; +{ + struct VMS_DBG_Symbol *spnt, *spnt1; + int i; + + pnt = cvt_integer (pnt + 1, &i); + if (*pnt == ';') + return 0; /* no forward references */ + do + { + pnt = (char *) strchr (pnt, ':'); + pnt = cvt_integer (pnt + 1, &i); + spnt = find_symbol (i); + while (spnt && (spnt->advanced == POINTER || spnt->advanced == ARRAY)) + { + spnt1 = find_symbol (spnt->type2); + if (spnt->advanced == ARRAY && !spnt1) + return 1; + spnt = spnt1; + } + pnt = cvt_integer (pnt + 1, &i); + pnt = cvt_integer (pnt + 1, &i); + } while (*++pnt != ';'); + return 0; /* no forward refences found */ +} + + +/* Used to check a single element of a structure on the final pass. */ + +static int +final_forward_reference (spnt) + struct VMS_DBG_Symbol *spnt; +{ + struct VMS_DBG_Symbol *spnt1; + + while (spnt && (spnt->advanced == POINTER || spnt->advanced == ARRAY)) + { + spnt1 = find_symbol (spnt->type2); + if (spnt->advanced == ARRAY && !spnt1) + return 1; + spnt = spnt1; + } + return 0; /* no forward refences found */ +} + + +/* This routine parses the stabs directives to find any definitions of dbx + type numbers. It makes a note of all of them, creating a structure + element of VMS_DBG_Symbol that describes it. This also generates the + info for the debugger that describes the struct/union/enum, so that + further references to these data types will be by number + + We have to process pointers right away, since there can be references + to them later in the same stabs directive. We cannot have forward + references to pointers, (but we can have a forward reference to a + pointer to a structure/enum/union) and this is why we process them + immediately. After we process the pointer, then we search for defs + that are nested even deeper. + + 8/15/92: We have to process arrays right away too, because there can + be multiple references to identical array types in one structure + definition, and only the first one has the definition. */ + +static int +VMS_typedef_parse (str) + char *str; +{ + char *pnt; + char *pnt1; + const char *pnt2; + int i; + int dtype; + struct forward_ref *fpnt; + int i1, i2, i3, len; + struct VMS_DBG_Symbol *spnt; + struct VMS_DBG_Symbol *spnt1; + + /* check for any nested def's */ + pnt = (char *) strchr (str + 1, '='); + if (pnt && str[1] != '*' && (str[1] != 'a' || str[2] != 'r') + && VMS_typedef_parse (pnt) == 1) + return 1; + /* now find dbx_type of entry */ + pnt = str - 1; + if (*pnt == 'c') + { /* check for static constants */ + *str = '\0'; /* for now we ignore them */ + return 0; + } + while ((*pnt <= '9') && (*pnt >= '0')) + pnt--; + pnt++; /* and get back to the number */ + cvt_integer (pnt, &i1); + spnt = find_symbol (i1); + /* first see if this has been defined already, due to forward reference */ + if (!spnt) + { + i2 = SYMTYP_HASH (i1); + spnt = (struct VMS_DBG_Symbol *) xmalloc (sizeof (struct VMS_DBG_Symbol)); + spnt->next = VMS_Symbol_type_list[i2]; + VMS_Symbol_type_list[i2] = spnt; + spnt->dbx_type = i1; /* and save the type */ + spnt->type2 = spnt->VMS_type = spnt->data_size = 0; + spnt->index_min = spnt->index_max = spnt->struc_numb = 0; + } + /* + * For structs and unions, do a partial parse, otherwise we sometimes get + * circular definitions that are impossible to resolve. We read enough + * info so that any reference to this type has enough info to be resolved. + */ + pnt = str + 1; /* point to character past equal sign */ + if (*pnt >= '0' && *pnt <= '9') + { + if (type_check ("void")) + { /* this is the void symbol */ + *str = '\0'; + spnt->advanced = VOID; + return 0; + } + if (type_check ("unknown type")) + { + *str = '\0'; + spnt->advanced = UNKNOWN; + return 0; + } + pnt1 = cvt_integer (pnt, &i1); + if (i1 != spnt->dbx_type) + { + spnt->advanced = ALIAS; + spnt->type2 = i1; + strcpy (str, pnt1); + return 0; + } + as_tsktsk ("debugginer output: %d is an unknown untyped variable.", + spnt->dbx_type); + return 1; /* do not know what this is */ + } + + pnt = str + 1; /* point to character past equal sign */ + switch (*pnt) + { + case 'r': + spnt->advanced = BASIC; + if (type_check ("int")) + { + spnt->VMS_type = DBG_S_C_SLINT; + spnt->data_size = 4; + } + else if (type_check ("long int")) + { + spnt->VMS_type = DBG_S_C_SLINT; + spnt->data_size = 4; + } + else if (type_check ("unsigned int")) + { + spnt->VMS_type = DBG_S_C_ULINT; + spnt->data_size = 4; + } + else if (type_check ("long unsigned int")) + { + spnt->VMS_type = DBG_S_C_ULINT; + spnt->data_size = 4; + } + else if (type_check ("short int")) + { + spnt->VMS_type = DBG_S_C_SSINT; + spnt->data_size = 2; + } + else if (type_check ("short unsigned int")) + { + spnt->VMS_type = DBG_S_C_USINT; + spnt->data_size = 2; + } + else if (type_check ("char")) + { + spnt->VMS_type = DBG_S_C_SCHAR; + spnt->data_size = 1; + } + else if (type_check ("signed char")) + { + spnt->VMS_type = DBG_S_C_SCHAR; + spnt->data_size = 1; + } + else if (type_check ("unsigned char")) + { + spnt->VMS_type = DBG_S_C_UCHAR; + spnt->data_size = 1; + } + else if (type_check ("float")) + { + spnt->VMS_type = DBG_S_C_REAL4; + spnt->data_size = 4; + } + else if (type_check ("double")) + { + spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8; + spnt->data_size = 8; + } + else if (type_check ("long double")) + { + /* same as double, at least for now */ + spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8; + spnt->data_size = 8; + } + else if (type_check ("long long int")) + { + spnt->VMS_type = DBG_S_C_SQUAD; /* signed quadword */ + spnt->data_size = 8; + } + else if (type_check ("long long unsigned int")) + { + spnt->VMS_type = DBG_S_C_UQUAD; /* unsigned quadword */ + spnt->data_size = 8; + } + else if (type_check ("complex float")) + { + spnt->VMS_type = DBG_S_C_COMPLX4; + spnt->data_size = 2 * 4; + } + else if (type_check ("complex double")) + { + spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8; + spnt->data_size = 2 * 8; + } + else if (type_check ("complex long double")) + { + /* same as complex double, at least for now */ + spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8; + spnt->data_size = 2 * 8; + } + else + { + /* [pr] + * Shouldn't get here, but if we do, something + * more substantial ought to be done... + */ + spnt->VMS_type = 0; + spnt->data_size = 0; + } + if (spnt->VMS_type != 0) + setup_basic_type (spnt); + pnt1 = (char *) strchr (str, ';') + 1; + break; + case 's': + case 'u': + spnt->advanced = (*pnt == 's') ? STRUCT : UNION; + spnt->VMS_type = DBG_S_C_ADVANCED_TYPE; + pnt1 = cvt_integer (pnt + 1, &spnt->data_size); + if (!final_pass && forward_reference (pnt)) + { + spnt->struc_numb = -1; + return 1; + } + spnt->struc_numb = ++structure_count; + pnt1--; + pnt = get_struct_name (str); + VMS_Def_Struct (spnt->struc_numb); + i = 0; + for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next) + if (fpnt->dbx_type == spnt->dbx_type) + { + fpnt->resolved = 'Y'; + VMS_Set_Struct (fpnt->struc_numb); + VMS_Store_Struct (spnt->struc_numb); + i++; + } + if (i > 0) + VMS_Set_Struct (spnt->struc_numb); + i = 0; + Local[i++] = 11 + strlen (pnt); + Local[i++] = DBG_S_C_STRUCT_START; + Local[i++] = DST_K_VFLAGS_NOVAL; /* structure definition only */ + COPY_LONG (&Local[i], 0L); /* hence value is unused */ + i += 4; + Local[i++] = strlen (pnt); + pnt2 = pnt; + while (*pnt2 != '\0') + Local[i++] = *pnt2++; + i2 = spnt->data_size * 8; /* number of bits */ + COPY_LONG (&Local[i], i2); + i += 4; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + if (pnt != symbol_name) + { + pnt += strlen (pnt); + *pnt = ':'; + } /* replace colon for later */ + while (*++pnt1 != ';') + { + pnt = (char *) strchr (pnt1, ':'); + *pnt = '\0'; + pnt2 = pnt1; + pnt1 = cvt_integer (pnt + 1, &dtype); + pnt1 = cvt_integer (pnt1 + 1, &i2); + pnt1 = cvt_integer (pnt1 + 1, &i3); + spnt1 = find_symbol (dtype); + len = strlen (pnt2); + if (spnt1 && (spnt1->advanced == BASIC || spnt1->advanced == ENUM) + && ((i3 != spnt1->data_size * 8) || (i2 % 8 != 0))) + { /* bitfield */ + if (USE_BITSTRING_DESCRIPTOR (spnt1)) + { + /* This uses a type descriptor, which doesn't work if + the enclosing structure has been placed in a register. + Also, enum bitfields degenerate to simple integers. */ + int unsigned_type = (spnt1->VMS_type == DBG_S_C_ULINT + || spnt1->VMS_type == DBG_S_C_USINT + || spnt1->VMS_type == DBG_S_C_UCHAR + || spnt1->VMS_type == DBG_S_C_UQUAD + || spnt1->advanced == ENUM); /* (approximate) */ + Apoint = 0; + fpush (19 + len, 1); + fpush (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1); + fpush (DST_K_VFLAGS_DSC, 1); /* specified by descriptor */ + fpush (1 + len, 4); /* relative offset to descriptor */ + fpush (len, 1); /* length byte (ascic prefix) */ + while (*pnt2 != '\0') /* name bytes */ + fpush (*pnt2++, 1); + fpush (i3, 2); /* dsc length == size of bitfield */ + /* dsc type == un?signed bitfield */ + fpush (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1); + fpush (DSC_K_CLASS_UBS, 1); /* dsc class == unaligned bitstring */ + fpush (0x00, 4); /* dsc pointer == zeroes */ + fpush (i2, 4); /* start position */ + VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG); + Apoint = 0; + } + else + { + /* Use a "novel length" type specification, which works + right for register structures and for enum bitfields + but results in larger object modules. */ + Local[i++] = 7 + len; + Local[i++] = DBG_S_C_ADVANCED_TYPE; /* type spec follows */ + Local[i++] = DBG_S_C_STRUCT_ITEM; /* value is a bit offset */ + COPY_LONG (&Local[i], i2); /* bit offset */ + i += 4; + Local[i++] = strlen (pnt2); + while (*pnt2 != '\0') + Local[i++] = *pnt2++; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + bitfield_suffix (spnt1, i3); + } + } + else + { /* not a bitfield */ + /* check if this is a forward reference */ + if (final_pass && final_forward_reference (spnt1)) + { + as_tsktsk ("debugger output: structure element `%s' has undefined type", + pnt2); + continue; + } + Local[i++] = 7 + len; + Local[i++] = spnt1 ? spnt1->VMS_type : DBG_S_C_ADVANCED_TYPE; + Local[i++] = DBG_S_C_STRUCT_ITEM; + COPY_LONG (&Local[i], i2); /* bit offset */ + i += 4; + Local[i++] = strlen (pnt2); + while (*pnt2 != '\0') + Local[i++] = *pnt2++; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + if (!spnt1) + generate_suffix (spnt1, dtype); + else if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE) + generate_suffix (spnt1, 0); + } + } + pnt1++; + Local[i++] = 0x01; /* length byte */ + Local[i++] = DBG_S_C_STRUCT_END; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + break; + case 'e': + spnt->advanced = ENUM; + spnt->VMS_type = DBG_S_C_ADVANCED_TYPE; + spnt->struc_numb = ++structure_count; + spnt->data_size = 4; + VMS_Def_Struct (spnt->struc_numb); + i = 0; + for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next) + if (fpnt->dbx_type == spnt->dbx_type) + { + fpnt->resolved = 'Y'; + VMS_Set_Struct (fpnt->struc_numb); + VMS_Store_Struct (spnt->struc_numb); + i++; + } + if (i > 0) + VMS_Set_Struct (spnt->struc_numb); + i = 0; + len = strlen (symbol_name); + Local[i++] = 3 + len; + Local[i++] = DBG_S_C_ENUM_START; + Local[i++] = 4 * 8; /* enum values are 32 bits */ + Local[i++] = len; + pnt2 = symbol_name; + while (*pnt2 != '\0') + Local[i++] = *pnt2++; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + while (*++pnt != ';') + { + pnt1 = (char *) strchr (pnt, ':'); + *pnt1++ = '\0'; + pnt1 = cvt_integer (pnt1, &i1); + len = strlen (pnt); + Local[i++] = 7 + len; + Local[i++] = DBG_S_C_ENUM_ITEM; + Local[i++] = DST_K_VALKIND_LITERAL; + COPY_LONG (&Local[i], i1); + i += 4; + Local[i++] = len; + pnt2 = pnt; + while (*pnt != '\0') + Local[i++] = *pnt++; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + pnt = pnt1; /* Skip final semicolon */ + } + Local[i++] = 0x01; /* len byte */ + Local[i++] = DBG_S_C_ENUM_END; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + pnt1 = pnt + 1; + break; + case 'a': + spnt->advanced = ARRAY; + spnt->VMS_type = DBG_S_C_ADVANCED_TYPE; + pnt = (char *) strchr (pnt, ';'); + if (!pnt) + return 1; + pnt1 = cvt_integer (pnt + 1, &spnt->index_min); + pnt1 = cvt_integer (pnt1 + 1, &spnt->index_max); + pnt1 = cvt_integer (pnt1 + 1, &spnt->type2); + pnt = (char *) strchr (str + 1, '='); + if (pnt && VMS_typedef_parse (pnt) == 1) + return 1; + break; + case 'f': + spnt->advanced = FUNCTION; + spnt->VMS_type = DBG_S_C_FUNCTION_ADDR; + /* this masquerades as a basic type*/ + spnt->data_size = 4; + pnt1 = cvt_integer (pnt + 1, &spnt->type2); + break; + case '*': + spnt->advanced = POINTER; + spnt->VMS_type = DBG_S_C_ADVANCED_TYPE; + spnt->data_size = 4; + pnt1 = cvt_integer (pnt + 1, &spnt->type2); + pnt = (char *) strchr (str + 1, '='); + if (pnt && VMS_typedef_parse (pnt) == 1) + return 1; + break; + default: + spnt->advanced = UNKNOWN; + spnt->VMS_type = 0; + as_tsktsk ("debugger output: %d is an unknown type of variable.", + spnt->dbx_type); + return 1; /* unable to decipher */ + } + /* This removes the evidence of the definition so that the outer levels + of parsing do not have to worry about it. */ + pnt = str; + while (*pnt1 != '\0') + *pnt++ = *pnt1++; + *pnt = '\0'; + return 0; +} + + +/* This is the root routine that parses the stabs entries for definitions. + it calls VMS_typedef_parse, which can in turn call itself. We need to + be careful, since sometimes there are forward references to other symbol + types, and these cannot be resolved until we have completed the parse. + + Also check and see if we are using continuation stabs, if we are, then + paste together the entire contents of the stab before we pass it to + VMS_typedef_parse. */ + +static void +VMS_LSYM_Parse () +{ + char *pnt; + char *pnt1; + char *pnt2; + char *str; + char *parse_buffer = 0; + char fixit[10]; + int incomplete, pass, incom1; + struct forward_ref *fpnt; + symbolS *sp; + + pass = 0; + final_pass = 0; + incomplete = 0; + do + { + incom1 = incomplete; + incomplete = 0; + for (sp = symbol_rootP; sp; sp = symbol_next (sp)) + { + /* + * Deal with STAB symbols + */ + if (S_IS_DEBUG (sp)) + { + /* + * Dispatch on STAB type + */ + switch (S_GET_RAW_TYPE (sp)) + { + case N_GSYM: + case N_LCSYM: + case N_STSYM: + case N_PSYM: + case N_RSYM: + case N_LSYM: + case N_FUN: /*sometimes these contain typedefs*/ + str = S_GET_NAME (sp); + symbol_name = str; + pnt = str + strlen (str) - 1; + if (*pnt == '?') /* Continuation stab. */ + { + symbolS *spnext; + int tlen = 0; + + spnext = sp; + do { + tlen += strlen (str) - 1; + spnext = symbol_next (spnext); + str = S_GET_NAME (spnext); + pnt = str + strlen (str) - 1; + } while (*pnt == '?'); + tlen += strlen (str); + parse_buffer = (char *) xmalloc (tlen + 1); + strcpy (parse_buffer, S_GET_NAME (sp)); + pnt2 = parse_buffer + strlen (parse_buffer) - 1; + *pnt2 = '\0'; + spnext = sp; + do { + spnext = symbol_next (spnext); + str = S_GET_NAME (spnext); + strcat (pnt2, str); + pnt2 += strlen (str) - 1; + *str = '\0'; /* Erase this string */ + /* S_SET_NAME (spnext, str); */ + if (*pnt2 != '?') break; + *pnt2 = '\0'; + } while (1); + str = parse_buffer; + symbol_name = str; + } + if ((pnt = (char *) strchr (str, ':')) != 0) + { + *pnt = '\0'; + pnt1 = pnt + 1; + if ((pnt2 = (char *) strchr (pnt1, '=')) != 0) + incomplete += VMS_typedef_parse (pnt2); + if (parse_buffer) + { + /* At this point the parse buffer should just + contain name:nn. If it does not, then we + are in real trouble. Anyway, this is always + shorter than the original line. */ + pnt2 = S_GET_NAME (sp); + strcpy (pnt2, parse_buffer); + /* S_SET_NAME (sp, pnt2); */ + free (parse_buffer), parse_buffer = 0; + } + *pnt = ':'; /* put back colon to restore dbx_type */ + } + break; + } /*switch*/ + } /* if */ + } /*for*/ + pass++; + /* + * Make one last pass, if needed, and define whatever we can + * that is left. + */ + if (final_pass == 0 && incomplete == incom1) + { + final_pass = 1; + incom1++; /* Force one last pass through */ + } + } while (incomplete != 0 && incomplete != incom1); + /* repeat until all refs resolved if possible */ +/* if (pass > 1) printf (" Required %d passes\n", pass); */ + if (incomplete != 0) + { + as_tsktsk ("debugger output: Unable to resolve %d circular references.", + incomplete); + } + fpnt = f_ref_root; + symbol_name = "\0"; + while (fpnt) + { + if (fpnt->resolved != 'Y') + { + if (find_symbol (fpnt->dbx_type)) + { + as_tsktsk ("debugger forward reference error, dbx type %d", + fpnt->dbx_type); + break; + } + fixit[0] = 0; + sprintf (&fixit[1], "%d=s4;", fpnt->dbx_type); + pnt2 = (char *) strchr (&fixit[1], '='); + VMS_typedef_parse (pnt2); + } + fpnt = fpnt->next; + } +} + + +static void +Define_Local_Symbols (s0P, s2P, Current_Routine, Text_Psect) + symbolS *s0P, *s2P; + symbolS *Current_Routine; + int Text_Psect; +{ + symbolS *s1P; /* each symbol from s0P .. s2P (exclusive) */ + + for (s1P = symbol_next (s0P); s1P != s2P; s1P = symbol_next (s1P)) + { + if (!s1P) + break; /* and return */ + if (S_GET_RAW_TYPE (s1P) == N_FUN) + { + char *pnt = (char *) strchr (S_GET_NAME (s1P), ':') + 1; + if (*pnt == 'F' || *pnt == 'f') break; + } + if (!S_IS_DEBUG (s1P)) + continue; + /* + * Dispatch on STAB type + */ + switch (S_GET_RAW_TYPE (s1P)) + { + default: + continue; /* not left or right brace */ + + case N_LSYM: + case N_PSYM: + VMS_local_stab_Parse (s1P); + break; + + case N_RSYM: + VMS_RSYM_Parse (s1P, Current_Routine, Text_Psect); + break; + } /*switch*/ + } /* for */ +} + + +/* This function crawls the symbol chain searching for local symbols that + need to be described to the debugger. When we enter a new scope with + a "{", it creates a new "block", which helps the debugger keep track + of which scope we are currently in. */ + +static symbolS * +Define_Routine (s0P, Level, Current_Routine, Text_Psect) + symbolS *s0P; + int Level; + symbolS *Current_Routine; + int Text_Psect; +{ + symbolS *s1P; + valueT Offset; + int rcount = 0; + + for (s1P = symbol_next (s0P); s1P != 0; s1P = symbol_next (s1P)) + { + if (S_GET_RAW_TYPE (s1P) == N_FUN) + { + char *pnt = (char *) strchr (S_GET_NAME (s1P), ':') + 1; + if (*pnt == 'F' || *pnt == 'f') break; + } + if (!S_IS_DEBUG (s1P)) + continue; + /* + * Dispatch on STAB type + */ + switch (S_GET_RAW_TYPE (s1P)) + { + default: + continue; /* not left or right brace */ + + case N_LBRAC: + if (Level != 0) + { + char str[10]; + sprintf (str, "$%d", rcount++); + VMS_TBT_Block_Begin (s1P, Text_Psect, str); + } + Offset = S_GET_VALUE (s1P); /* side-effect: fully resolve symbol */ + Define_Local_Symbols (s0P, s1P, Current_Routine, Text_Psect); + s1P = Define_Routine (s1P, Level + 1, Current_Routine, Text_Psect); + if (Level != 0) + VMS_TBT_Block_End (S_GET_VALUE (s1P) - Offset); + s0P = s1P; + break; + + case N_RBRAC: + return s1P; + } /*switch*/ + } /* for */ + + /* We end up here if there were no brackets in this function. + Define everything. */ + Define_Local_Symbols (s0P, (symbolS *)0, Current_Routine, Text_Psect); + return s1P; +} + + +#ifndef VMS +#include +#include +static void get_VMS_time_on_unix PARAMS ((char *)); + +/* Manufacture a VMS-like time string on a Unix based system. */ +static void +get_VMS_time_on_unix (Now) + char *Now; +{ + char *pnt; + time_t timeb; + + time (&timeb); + pnt = ctime (&timeb); + pnt[3] = 0; + pnt[7] = 0; + pnt[10] = 0; + pnt[16] = 0; + pnt[24] = 0; + sprintf (Now, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11); +} +#endif /* not VMS */ + + +/* Write the MHD (Module Header) records. */ + +static void +Write_VMS_MHD_Records () +{ + register const char *cp; + register char *cp1; + register int i; +#ifdef VMS + struct { unsigned short len, mbz; char *ptr; } Descriptor; +#endif + char Now[17+1]; + + /* We are writing a module header record. */ + Set_VMS_Object_File_Record (OBJ_S_C_HDR); + /* + * *************************** + * *MAIN MODULE HEADER RECORD* + * *************************** + */ + /* Store record type and header type. */ + PUT_CHAR (OBJ_S_C_HDR); + PUT_CHAR (MHD_S_C_MHD); + /* Structure level is 0. */ + PUT_CHAR (OBJ_S_C_STRLVL); + /* Maximum record size is size of the object record buffer. */ + PUT_SHORT (sizeof (Object_Record_Buffer)); + + /* + * FIXME: module name and version should be user + * specifiable via `.ident' and/or `#pragma ident'. + */ + + /* Get module name (the FILENAME part of the object file). */ + cp = out_file_name; + cp1 = Module_Name; + while (*cp) + { + if (*cp == ']' || *cp == '>' || *cp == ':' || *cp == '/') + { + cp1 = Module_Name; + cp++; + continue; + } + *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++; + } + *cp1 = '\0'; + + /* Limit it to 31 characters and store in the object record. */ + while (--cp1 >= Module_Name) + if (*cp1 == '.') + *cp1 = '\0'; + if (strlen (Module_Name) > 31) + { + if (flag_hash_long_names) + as_tsktsk ("Module name truncated: %s\n", Module_Name); + Module_Name[31] = '\0'; + } + PUT_COUNTED_STRING (Module_Name); + /* Module Version is "V1.0". */ + PUT_COUNTED_STRING ("V1.0"); + /* Creation time is "now" (17 chars of time string): "dd-MMM-yyyy hh:mm". */ +#ifndef VMS + get_VMS_time_on_unix (Now); +#else /* VMS */ + Descriptor.len = sizeof Now - 1; + Descriptor.mbz = 0; /* type & class unspecified */ + Descriptor.ptr = Now; + (void) sys$asctim ((unsigned short *)0, &Descriptor, (long *)0, 0); +#endif /* VMS */ + for (i = 0; i < 17; i++) + PUT_CHAR (Now[i]); + /* Patch time is "never" (17 zeros). */ + for (i = 0; i < 17; i++) + PUT_CHAR (0); + /* Force this to be a separate output record. */ + Flush_VMS_Object_Record_Buffer (); + + /* + * ************************* + * *LANGUAGE PROCESSOR NAME* + * ************************* + */ + /* Store record type and header type. */ + PUT_CHAR (OBJ_S_C_HDR); + PUT_CHAR (MHD_S_C_LNM); + /* + * Store language processor name and version (not a counted string!). + * + * This is normally supplied by the gcc driver for the command line + * which invokes gas. If absent, we fall back to gas's version. + */ + cp = compiler_version_string; + if (cp == 0) + { + cp = "GNU AS V"; + while (*cp) + PUT_CHAR (*cp++); + cp = GAS_VERSION; + } + while (*cp >= ' ') + PUT_CHAR (*cp++); + /* Force this to be a separate output record. */ + Flush_VMS_Object_Record_Buffer (); +} + + +/* Write the EOM (End Of Module) record. */ + +static void +Write_VMS_EOM_Record (Psect, Offset) + int Psect; + valueT Offset; +{ + /* + * We are writing an end-of-module record + * (this assumes that the entry point will always be in a psect + * represented by a single byte, which is the case for code in + * Text_Psect==0) + */ + Set_VMS_Object_File_Record (OBJ_S_C_EOM); + PUT_CHAR (OBJ_S_C_EOM); /* Record type. */ + PUT_CHAR (0); /* Error severity level (we ignore it). */ + /* + * Store the entry point, if it exists + */ + if (Psect >= 0) + { + PUT_CHAR (Psect); + PUT_LONG (Offset); + } + /* Flush the record; this will be our final output. */ + Flush_VMS_Object_Record_Buffer (); +} + + +/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/ + +static int +hash_string (ptr) + const char *ptr; +{ + register const unsigned char *p = (unsigned char *) ptr; + register const unsigned char *end = p + strlen (ptr); + register unsigned char c; + register int hash = 0; + + while (p != end) + { + c = *p++; + hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c); + } + return hash; +} + +/* + * Generate a Case-Hacked VMS symbol name (limited to 31 chars) + */ +static void +VMS_Case_Hack_Symbol (In, Out) + register const char *In; + register char *Out; +{ + long int init; + long int result; + char *pnt = 0; + char *new_name; + const char *old_name; + register int i; + int destructor = 0; /*hack to allow for case sens in a destructor*/ + int truncate = 0; + int Case_Hack_Bits = 0; + int Saw_Dollar = 0; + static char Hex_Table[16] = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + /* + * Kill any leading "_" + */ + if ((In[0] == '_') && ((In[1] > '9') || (In[1] < '0'))) + In++; + + new_name = Out; /* save this for later*/ + +#if barfoo /* Dead code */ + if ((In[0] == '_') && (In[1] == '$') && (In[2] == '_')) + destructor = 1; +#endif + + /* We may need to truncate the symbol, save the hash for later*/ + result = (strlen (In) > 23) ? hash_string (In) : 0; + /* + * Is there a Psect Attribute to skip?? + */ + if (HAS_PSECT_ATTRIBUTES (In)) + { + /* + * Yes: Skip it + */ + In += PSECT_ATTRIBUTES_STRING_LENGTH; + while (*In) + { + if ((In[0] == '$') && (In[1] == '$')) + { + In += 2; + break; + } + In++; + } + } + + old_name = In; +/* if (strlen (In) > 31 && flag_hash_long_names) + as_tsktsk ("Symbol name truncated: %s\n", In); */ + /* + * Do the case conversion + */ + i = 23; /* Maximum of 23 chars */ + while (*In && (--i >= 0)) + { + Case_Hack_Bits <<= 1; + if (*In == '$') + Saw_Dollar = 1; + if ((destructor == 1) && (i == 21)) + Saw_Dollar = 0; + switch (vms_name_mapping) + { + case 0: + if (isupper (*In)) { + *Out++ = *In++; + Case_Hack_Bits |= 1; + } else { + *Out++ = islower (*In) ? toupper (*In++) : *In++; + } + break; + case 3: *Out++ = *In++; + break; + case 2: + if (islower (*In)) { + *Out++ = *In++; + } else { + *Out++ = isupper (*In) ? tolower (*In++) : *In++; + } + break; + } + } + /* + * If we saw a dollar sign, we don't do case hacking + */ + if (flag_no_hash_mixed_case || Saw_Dollar) + Case_Hack_Bits = 0; + + /* + * If we have more than 23 characters and everything is lowercase + * we can insert the full 31 characters + */ + if (*In) + { + /* + * We have more than 23 characters + * If we must add the case hack, then we have truncated the str + */ + pnt = Out; + truncate = 1; + if (Case_Hack_Bits == 0) + { + /* + * And so far they are all lower case: + * Check up to 8 more characters + * and ensure that they are lowercase + */ + for (i = 0; (In[i] != 0) && (i < 8); i++) + if (isupper (In[i]) && !Saw_Dollar && !flag_no_hash_mixed_case) + break; + + if (In[i] == 0) + truncate = 0; + + if ((i == 8) || (In[i] == 0)) + { + /* + * They are: Copy up to 31 characters + * to the output string + */ + i = 8; + while ((--i >= 0) && (*In)) + switch (vms_name_mapping){ + case 0: *Out++ = islower (*In) ? toupper (*In++) : *In++; + break; + case 3: *Out++ = *In++; + break; + case 2: *Out++ = isupper (*In) ? tolower (*In++) : *In++; + break; + } + } + } + } + /* + * If there were any uppercase characters in the name we + * take on the case hacking string + */ + + /* Old behavior for regular GNU-C compiler */ + if (!flag_hash_long_names) + truncate = 0; + if ((Case_Hack_Bits != 0) || (truncate == 1)) + { + if (truncate == 0) + { + *Out++ = '_'; + for (i = 0; i < 6; i++) + { + *Out++ = Hex_Table[Case_Hack_Bits & 0xf]; + Case_Hack_Bits >>= 4; + } + *Out++ = 'X'; + } + else + { + Out = pnt; /*Cut back to 23 characters maximum */ + *Out++ = '_'; + for (i = 0; i < 7; i++) + { + init = result & 0x01f; + *Out++ = (init < 10) ? ('0' + init) : ('A' + init - 10); + result = result >> 5; + } + } + } /*Case Hack */ + /* + * Done + */ + *Out = 0; + if (truncate == 1 && flag_hash_long_names && flag_show_after_trunc) + as_tsktsk ("Symbol %s replaced by %s\n", old_name, new_name); +} + + +/* + * Scan a symbol name for a psect attribute specification + */ +#define GLOBALSYMBOL_BIT 0x10000 +#define GLOBALVALUE_BIT 0x20000 + + +static void +VMS_Modify_Psect_Attributes (Name, Attribute_Pointer) + const char *Name; + int *Attribute_Pointer; +{ + register int i; + register const char *cp; + int Negate; + static const struct + { + const char *Name; + int Value; + } Attributes[] = + { + {"PIC", GPS_S_M_PIC}, + {"LIB", GPS_S_M_LIB}, + {"OVR", GPS_S_M_OVR}, + {"REL", GPS_S_M_REL}, + {"GBL", GPS_S_M_GBL}, + {"SHR", GPS_S_M_SHR}, + {"EXE", GPS_S_M_EXE}, + {"RD", GPS_S_M_RD}, + {"WRT", GPS_S_M_WRT}, + {"VEC", GPS_S_M_VEC}, + {"GLOBALSYMBOL", GLOBALSYMBOL_BIT}, + {"GLOBALVALUE", GLOBALVALUE_BIT}, + {0, 0} + }; + + /* + * Kill leading "_" + */ + if (*Name == '_') + Name++; + /* + * Check for a PSECT attribute list + */ + if (!HAS_PSECT_ATTRIBUTES (Name)) + return; /* If not, return */ + /* + * Skip the attribute list indicator + */ + Name += PSECT_ATTRIBUTES_STRING_LENGTH; + /* + * Process the attributes ("_" separated, "$" terminated) + */ + while (*Name != '$') + { + /* + * Assume not negating + */ + Negate = 0; + /* + * Check for "NO" + */ + if ((Name[0] == 'N') && (Name[1] == 'O')) + { + /* + * We are negating (and skip the NO) + */ + Negate = 1; + Name += 2; + } + /* + * Find the token delimiter + */ + cp = Name; + while (*cp && (*cp != '_') && (*cp != '$')) + cp++; + /* + * Look for the token in the attribute list + */ + for (i = 0; Attributes[i].Name; i++) + { + /* + * If the strings match, set/clear the attr. + */ + if (strncmp (Name, Attributes[i].Name, cp - Name) == 0) + { + /* + * Set or clear + */ + if (Negate) + *Attribute_Pointer &= + ~Attributes[i].Value; + else + *Attribute_Pointer |= + Attributes[i].Value; + /* + * Done + */ + break; + } + } + /* + * Now skip the attribute + */ + Name = cp; + if (*Name == '_') + Name++; + } +} + + +#define GBLSYM_REF 0 +#define GBLSYM_DEF 1 +#define GBLSYM_VAL 2 +#define GBLSYM_LCL 4 /* not GBL after all... */ + +/* + * Define a global symbol (or possibly a local one). + */ +static void +VMS_Global_Symbol_Spec (Name, Psect_Number, Psect_Offset, Flags) + const char *Name; + int Psect_Number; + int Psect_Offset; + int Flags; +{ + char Local[32]; + + /* + * We are writing a GSD record + */ + Set_VMS_Object_File_Record (OBJ_S_C_GSD); + /* + * If the buffer is empty we must insert the GSD record type + */ + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_GSD); + /* + * We are writing a Global (or local) symbol definition subrecord. + */ + PUT_CHAR ((Flags & GBLSYM_LCL) != 0 ? GSD_S_C_LSY : + ((unsigned) Psect_Number <= 255) ? GSD_S_C_SYM : GSD_S_C_SYMW); + /* + * Data type is undefined + */ + PUT_CHAR (0); + /* + * Switch on Definition/Reference + */ + if ((Flags & GBLSYM_DEF) == 0) + { + /* + * Reference + */ + PUT_SHORT (((Flags & GBLSYM_VAL) == 0) ? GSY_S_M_REL : 0); + if ((Flags & GBLSYM_LCL) != 0) /* local symbols have extra field */ + PUT_SHORT (Current_Environment); + } + else + { + /* + * Definition + *[ assert (LSY_S_M_DEF == GSY_S_M_DEF && LSY_S_M_REL == GSY_S_M_REL); ] + */ + PUT_SHORT (((Flags & GBLSYM_VAL) == 0) ? + GSY_S_M_DEF | GSY_S_M_REL : GSY_S_M_DEF); + if ((Flags & GBLSYM_LCL) != 0) /* local symbols have extra field */ + PUT_SHORT (Current_Environment); + /* + * Psect Number + */ + if ((Flags & GBLSYM_LCL) == 0 && (unsigned) Psect_Number <= 255) + PUT_CHAR (Psect_Number); + else + PUT_SHORT (Psect_Number); + /* + * Offset + */ + PUT_LONG (Psect_Offset); + } + /* + * Finally, the global symbol name + */ + VMS_Case_Hack_Symbol (Name, Local); + PUT_COUNTED_STRING (Local); + /* + * Flush the buffer if it is more than 75% full + */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + +/* + * Define an environment to support local symbol references. + * This is just to mollify the linker; we don't actually do + * anything useful with it. + */ +static void +VMS_Local_Environment_Setup (Env_Name) + const char *Env_Name; +{ + /* We are writing a GSD record. */ + Set_VMS_Object_File_Record (OBJ_S_C_GSD); + /* If the buffer is empty we must insert the GSD record type. */ + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_GSD); + /* We are writing an ENV subrecord. */ + PUT_CHAR (GSD_S_C_ENV); + + ++Current_Environment; /* index of environment being defined */ + + /* ENV$W_FLAGS: we are defining the next environment. It's not nested. */ + PUT_SHORT (ENV_S_M_DEF); + /* ENV$W_ENVINDX: index is always 0 for non-nested definitions. */ + PUT_SHORT (0); + + /* ENV$B_NAMLNG + ENV$T_NAME: environment name in ASCIC format. */ + if (!Env_Name) Env_Name = ""; + PUT_COUNTED_STRING ((char *)Env_Name); + + /* Flush the buffer if it is more than 75% full. */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + + +/* + * Define a psect + */ +static int +VMS_Psect_Spec (Name, Size, Type, vsp) + const char *Name; + int Size; + enum ps_type Type; + struct VMS_Symbol *vsp; +{ + char Local[32]; + int Psect_Attributes; + + /* + * Generate the appropriate PSECT flags given the PSECT type + */ + switch (Type) + { + case ps_TEXT: + /* Text psects are PIC,noOVR,REL,noGBL,SHR,EXE,RD,noWRT. */ + Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_SHR|GPS_S_M_EXE + |GPS_S_M_RD); + break; + case ps_DATA: + /* Data psects are PIC,noOVR,REL,noGBL,noSHR,noEXE,RD,WRT. */ + Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD|GPS_S_M_WRT); + break; + case ps_COMMON: + /* Common block psects are: PIC,OVR,REL,GBL,SHR,noEXE,RD,WRT. */ + Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL + |GPS_S_M_SHR|GPS_S_M_RD|GPS_S_M_WRT); + break; + case ps_CONST: + /* Const data psects are: PIC,OVR,REL,GBL,SHR,noEXE,RD,noWRT. */ + Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL + |GPS_S_M_SHR|GPS_S_M_RD); + break; + default: + /* impossible */ + error ("Unknown VMS psect type (%ld)", (long) Type); + break; + } + /* + * Modify the psect attributes according to any attribute string + */ + if (vsp && S_GET_TYPE (vsp->Symbol) == N_ABS) + Psect_Attributes |= GLOBALVALUE_BIT; + else if (HAS_PSECT_ATTRIBUTES (Name)) + VMS_Modify_Psect_Attributes (Name, &Psect_Attributes); + /* + * Check for globalref/def/val. + */ + if ((Psect_Attributes & GLOBALVALUE_BIT) != 0) + { + /* + * globalvalue symbols were generated before. This code + * prevents unsightly psect buildup, and makes sure that + * fixup references are emitted correctly. + */ + vsp->Psect_Index = -1; /* to catch errors */ + S_SET_TYPE (vsp->Symbol, N_UNDF); /* make refs work */ + return 1; /* decrement psect counter */ + } + + if ((Psect_Attributes & GLOBALSYMBOL_BIT) != 0) + { + switch (S_GET_RAW_TYPE (vsp->Symbol)) + { + case N_UNDF | N_EXT: + VMS_Global_Symbol_Spec (Name, vsp->Psect_Index, + vsp->Psect_Offset, GBLSYM_REF); + vsp->Psect_Index = -1; + S_SET_TYPE (vsp->Symbol, N_UNDF); + return 1; /* return and indicate no psect */ + case N_DATA | N_EXT: + VMS_Global_Symbol_Spec (Name, vsp->Psect_Index, + vsp->Psect_Offset, GBLSYM_DEF); + /* In this case we still generate the psect */ + break; + default: + as_fatal ("Globalsymbol attribute for symbol %s was unexpected.", + Name); + break; + } /* switch */ + } + + Psect_Attributes &= 0xffff; /* clear out the globalref/def stuff */ + /* + * We are writing a GSD record + */ + Set_VMS_Object_File_Record (OBJ_S_C_GSD); + /* + * If the buffer is empty we must insert the GSD record type + */ + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_GSD); + /* + * We are writing a PSECT definition subrecord + */ + PUT_CHAR (GSD_S_C_PSC); + /* + * Psects are always LONGWORD aligned + */ + PUT_CHAR (2); + /* + * Specify the psect attributes + */ + PUT_SHORT (Psect_Attributes); + /* + * Specify the allocation + */ + PUT_LONG (Size); + /* + * Finally, the psect name + */ + VMS_Case_Hack_Symbol (Name, Local); + PUT_COUNTED_STRING (Local); + /* + * Flush the buffer if it is more than 75% full + */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); + return 0; +} + + +/* Given the pointer to a symbol we calculate how big the data at the + symbol is. We do this by looking for the next symbol (local or global) + which will indicate the start of another datum. */ + +static offsetT +VMS_Initialized_Data_Size (s0P, End_Of_Data) + register symbolS *s0P; + unsigned End_Of_Data; +{ + symbolS *s1P; + valueT s0P_val = S_GET_VALUE (s0P), s1P_val, + nearest_val = (valueT) End_Of_Data; + + /* Find the nearest symbol what follows this one. */ + for (s1P = symbol_rootP; s1P; s1P = symbol_next (s1P)) + { + /* The data type must match. */ + if (S_GET_TYPE (s1P) != N_DATA) + continue; + s1P_val = S_GET_VALUE (s1P); + if (s1P_val > s0P_val && s1P_val < nearest_val) + nearest_val = s1P_val; + } + /* Calculate its size. */ + return (offsetT) (nearest_val - s0P_val); +} + + +/* Check symbol names for the Psect hack with a globalvalue, and then + generate globalvalues for those that have it. */ + +static void +VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment) + unsigned text_siz; + unsigned data_siz; + char *Data_Segment; +{ + register symbolS *sp; + char *stripped_name, *Name; + int Size; + int Psect_Attributes; + int globalvalue; + int typ, abstyp; + + /* + * Scan the symbol table for globalvalues, and emit def/ref when + * required. These will be caught again later and converted to + * N_UNDF + */ + for (sp = symbol_rootP; sp; sp = sp->sy_next) + { + typ = S_GET_RAW_TYPE (sp); + abstyp = ((typ & ~N_EXT) == N_ABS); + /* + * See if this is something we want to look at. + */ + if (!abstyp && + typ != (N_DATA | N_EXT) && + typ != (N_UNDF | N_EXT)) + continue; + /* + * See if this has globalvalue specification. + */ + Name = S_GET_NAME (sp); + + if (abstyp) + { + stripped_name = 0; + Psect_Attributes = GLOBALVALUE_BIT; + } + else if (HAS_PSECT_ATTRIBUTES (Name)) + { + stripped_name = (char *) xmalloc (strlen (Name) + 1); + strcpy (stripped_name, Name); + Psect_Attributes = 0; + VMS_Modify_Psect_Attributes (stripped_name, &Psect_Attributes); + } + else + continue; + + if ((Psect_Attributes & GLOBALVALUE_BIT) != 0) + { + switch (typ) + { + case N_ABS: + /* Local symbol references will want + to have an environment defined. */ + if (Current_Environment < 0) + VMS_Local_Environment_Setup (".N_ABS"); + VMS_Global_Symbol_Spec (Name, 0, + S_GET_VALUE (sp), + GBLSYM_DEF|GBLSYM_VAL|GBLSYM_LCL); + break; + case N_ABS | N_EXT: + VMS_Global_Symbol_Spec (Name, 0, + S_GET_VALUE (sp), + GBLSYM_DEF|GBLSYM_VAL); + break; + case N_UNDF | N_EXT: + VMS_Global_Symbol_Spec (stripped_name, 0, 0, GBLSYM_VAL); + break; + case N_DATA | N_EXT: + Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz); + if (Size > 4) + error ("Invalid data type for globalvalue"); + globalvalue = md_chars_to_number (Data_Segment + + S_GET_VALUE (sp) - text_siz , Size); + /* Three times for good luck. The linker seems to get confused + if there are fewer than three */ + VMS_Global_Symbol_Spec (stripped_name, 0, 0, GBLSYM_VAL); + VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, + GBLSYM_DEF|GBLSYM_VAL); + VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, + GBLSYM_DEF|GBLSYM_VAL); + break; + default: + as_warn ("Invalid globalvalue of %s", stripped_name); + break; + } /* switch */ + } /* if */ + if (stripped_name) free (stripped_name); /* clean up */ + } /* for */ + +} + + +/* + * Define a procedure entry pt/mask + */ +static void +VMS_Procedure_Entry_Pt (Name, Psect_Number, Psect_Offset, Entry_Mask) + char *Name; + int Psect_Number; + int Psect_Offset; + int Entry_Mask; +{ + char Local[32]; + + /* + * We are writing a GSD record + */ + Set_VMS_Object_File_Record (OBJ_S_C_GSD); + /* + * If the buffer is empty we must insert the GSD record type + */ + if (Object_Record_Offset == 0) + PUT_CHAR (OBJ_S_C_GSD); + /* + * We are writing a Procedure Entry Pt/Mask subrecord + */ + PUT_CHAR (((unsigned) Psect_Number <= 255) ? GSD_S_C_EPM : GSD_S_C_EPMW); + /* + * Data type is undefined + */ + PUT_CHAR (0); + /* + * Flags = "RELOCATABLE" and "DEFINED" + */ + PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL); + /* + * Psect Number + */ + if ((unsigned) Psect_Number <= 255) + PUT_CHAR (Psect_Number); + else + PUT_SHORT (Psect_Number); + /* + * Offset + */ + PUT_LONG (Psect_Offset); + /* + * Entry mask + */ + PUT_SHORT (Entry_Mask); + /* + * Finally, the global symbol name + */ + VMS_Case_Hack_Symbol (Name, Local); + PUT_COUNTED_STRING (Local); + /* + * Flush the buffer if it is more than 75% full + */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + + +/* + * Set the current location counter to a particular Psect and Offset + */ +static void +VMS_Set_Psect (Psect_Index, Offset, Record_Type) + int Psect_Index; + int Offset; + int Record_Type; +{ + /* + * We are writing a "Record_Type" record + */ + Set_VMS_Object_File_Record (Record_Type); + /* + * If the buffer is empty we must insert the record type + */ + if (Object_Record_Offset == 0) + PUT_CHAR (Record_Type); + /* + * Stack the Psect base + Offset + */ + vms_tir_stack_psect (Psect_Index, Offset, 0); + /* + * Set relocation base + */ + PUT_CHAR (TIR_S_C_CTL_SETRB); + /* + * Flush the buffer if it is more than 75% full + */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + + +/* + * Store repeated immediate data in current Psect + */ +static void +VMS_Store_Repeated_Data (Repeat_Count, Pointer, Size, Record_Type) + int Repeat_Count; + register char *Pointer; + int Size; + int Record_Type; +{ + + /* + * Ignore zero bytes/words/longwords + */ + switch (Size) + { + case 4: + if (Pointer[3] != 0 || Pointer[2] != 0) break; + /* else FALLTHRU */ + case 2: + if (Pointer[1] != 0) break; + /* else FALLTHRU */ + case 1: + if (Pointer[0] != 0) break; + /* zero value */ + return; + default: + break; + } + /* + * If the data is too big for a TIR_S_C_STO_RIVB sub-record + * then we do it manually + */ + if (Size > 255) + { + while (--Repeat_Count >= 0) + VMS_Store_Immediate_Data (Pointer, Size, Record_Type); + return; + } + /* + * We are writing a "Record_Type" record + */ + Set_VMS_Object_File_Record (Record_Type); + /* + * If the buffer is empty we must insert record type + */ + if (Object_Record_Offset == 0) + PUT_CHAR (Record_Type); + /* + * Stack the repeat count + */ + PUT_CHAR (TIR_S_C_STA_LW); + PUT_LONG (Repeat_Count); + /* + * And now the command and its data + */ + PUT_CHAR (TIR_S_C_STO_RIVB); + PUT_CHAR (Size); + while (--Size >= 0) + PUT_CHAR (*Pointer++); + /* + * Flush the buffer if it is more than 75% full + */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + + +/* + * Store a Position Independent Reference + */ +static void +VMS_Store_PIC_Symbol_Reference (Symbol, Offset, PC_Relative, + Psect, Psect_Offset, Record_Type) + symbolS *Symbol; + int Offset; + int PC_Relative; + int Psect; + int Psect_Offset; + int Record_Type; +{ + register struct VMS_Symbol *vsp = Symbol->sy_obj; + char Local[32]; + int local_sym = 0; + + /* + * We are writing a "Record_Type" record + */ + Set_VMS_Object_File_Record (Record_Type); + /* + * If the buffer is empty we must insert record type + */ + if (Object_Record_Offset == 0) + PUT_CHAR (Record_Type); + /* + * Set to the appropriate offset in the Psect. + * For a Code reference we need to fix the operand + * specifier as well, so back up 1 byte; + * for a Data reference we just store HERE. + */ + VMS_Set_Psect (Psect, + PC_Relative ? Psect_Offset - 1 : Psect_Offset, + Record_Type); + /* + * Make sure we are still generating a "Record Type" record + */ + if (Object_Record_Offset == 0) + PUT_CHAR (Record_Type); + /* + * Dispatch on symbol type (so we can stack its value) + */ + switch (S_GET_RAW_TYPE (Symbol)) + { + /* + * Global symbol + */ + case N_ABS: + local_sym = 1; + /*FALLTHRU*/ + case N_ABS | N_EXT: +#ifdef NOT_VAX_11_C_COMPATIBLE + case N_UNDF | N_EXT: + case N_DATA | N_EXT: +#endif /* NOT_VAX_11_C_COMPATIBLE */ + case N_UNDF: + case N_TEXT | N_EXT: + /* + * Get the symbol name (case hacked) + */ + VMS_Case_Hack_Symbol (S_GET_NAME (Symbol), Local); + /* + * Stack the global symbol value + */ + if (!local_sym) + { + PUT_CHAR (TIR_S_C_STA_GBL); + } + else + { + /* Local symbols have an extra field. */ + PUT_CHAR (TIR_S_C_STA_LSY); + PUT_SHORT (Current_Environment); + } + PUT_COUNTED_STRING (Local); + if (Offset) + { + /* + * Stack the longword offset + */ + PUT_CHAR (TIR_S_C_STA_LW); + PUT_LONG (Offset); + /* + * Add the two, leaving the result on the stack + */ + PUT_CHAR (TIR_S_C_OPR_ADD); + } + break; + /* + * Uninitialized local data + */ + case N_BSS: + /* + * Stack the Psect (+offset) + */ + vms_tir_stack_psect (vsp->Psect_Index, + vsp->Psect_Offset + Offset, + 0); + break; + /* + * Local text + */ + case N_TEXT: + /* + * Stack the Psect (+offset) + */ + vms_tir_stack_psect (vsp->Psect_Index, + S_GET_VALUE (Symbol) + Offset, + 0); + break; + /* + * Initialized local or global data + */ + case N_DATA: +#ifndef NOT_VAX_11_C_COMPATIBLE + case N_UNDF | N_EXT: + case N_DATA | N_EXT: +#endif /* NOT_VAX_11_C_COMPATIBLE */ + /* + * Stack the Psect (+offset) + */ + vms_tir_stack_psect (vsp->Psect_Index, + vsp->Psect_Offset + Offset, + 0); + break; + } + /* + * Store either a code or data reference + */ + PUT_CHAR (PC_Relative ? TIR_S_C_STO_PICR : TIR_S_C_STO_PIDR); + /* + * Flush the buffer if it is more than 75% full + */ + if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) + Flush_VMS_Object_Record_Buffer (); +} + + +/* + * Check in the text area for an indirect pc-relative reference + * and fix it up with addressing mode 0xff [PC indirect] + * + * THIS SHOULD BE REPLACED BY THE USE OF TIR_S_C_STO_PIRR IN THE + * PIC CODE GENERATING FIXUP ROUTINE. + */ +static void +VMS_Fix_Indirect_Reference (Text_Psect, Offset, fragP, text_frag_root) + int Text_Psect; + int Offset; + register fragS *fragP; + fragS *text_frag_root; +{ + /* + * The addressing mode byte is 1 byte before the address + */ + Offset--; + /* + * Is it in THIS frag?? + */ + if ((Offset < fragP->fr_address) || + (Offset >= (fragP->fr_address + fragP->fr_fix))) + { + /* + * We need to search for the fragment containing this + * Offset + */ + for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) + { + if ((Offset >= fragP->fr_address) && + (Offset < (fragP->fr_address + fragP->fr_fix))) + break; + } + /* + * If we couldn't find the frag, things are BAD!! + */ + if (fragP == 0) + error ("Couldn't find fixup fragment when checking for indirect reference"); + } + /* + * Check for indirect PC relative addressing mode + */ + if (fragP->fr_literal[Offset - fragP->fr_address] == (char) 0xff) + { + static char Address_Mode = (char) 0xff; + + /* + * Yes: Store the indirect mode back into the image + * to fix up the damage done by STO_PICR + */ + VMS_Set_Psect (Text_Psect, Offset, OBJ_S_C_TIR); + VMS_Store_Immediate_Data (&Address_Mode, 1, OBJ_S_C_TIR); + } +} + + +/* + * If the procedure "main()" exists we have to add the instruction + * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C". + * + * FIXME: the macro name `HACK_DEC_C_STARTUP' should be renamed + * to `HACK_VAXCRTL_STARTUP' because Digital's compiler + * named "DEC C" uses run-time library "DECC$SHR", but this + * startup code is for "VAXCRTL", the library for Digital's + * older "VAX C". Also, this extra code isn't needed for + * supporting gcc because it already generates the VAXCRTL + * startup call when compiling main(). The reference to + * `flag_hash_long_names' looks very suspicious too; + * probably an old-style command line option was inadvertently + * overloaded here, then blindly converted into the new one. + */ +void +vms_check_for_main () +{ + register symbolS *symbolP; +#ifdef HACK_DEC_C_STARTUP /* JF */ + register struct frchain *frchainP; + register fragS *fragP; + register fragS **prev_fragPP; + register struct fix *fixP; + register fragS *New_Frag; + int i; +#endif /* HACK_DEC_C_STARTUP */ + + symbolP = (symbolS *) symbol_find ("_main"); + if (symbolP && !S_IS_DEBUG (symbolP) && + S_IS_EXTERNAL (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT)) + { +#ifdef HACK_DEC_C_STARTUP + if (!flag_hash_long_names) + { +#endif + /* + * Remember the entry point symbol + */ + Entry_Point_Symbol = symbolP; +#ifdef HACK_DEC_C_STARTUP + } + else + { + /* + * Scan all the fragment chains for the one with "_main" + * (Actually we know the fragment from the symbol, but we need + * the previous fragment so we can change its pointer) + */ + frchainP = frchain_root; + while (frchainP) + { + /* + * Scan all the fragments in this chain, remembering + * the "previous fragment" + */ + prev_fragPP = &frchainP->frch_root; + fragP = frchainP->frch_root; + while (fragP && (fragP != frchainP->frch_last)) + { + /* + * Is this the fragment? + */ + if (fragP == symbolP->sy_frag) + { + /* + * Yes: Modify the fragment by replacing + * it with a new fragment. + */ + New_Frag = (fragS *) + xmalloc (sizeof (*New_Frag) + + fragP->fr_fix + + fragP->fr_var + + 5); + /* + * The fragments are the same except + * that the "fixed" area is larger + */ + *New_Frag = *fragP; + New_Frag->fr_fix += 6; + /* + * Copy the literal data opening a hole + * 2 bytes after "_main" (i.e. just after + * the entry mask). Into which we place + * the JSB instruction. + */ + New_Frag->fr_literal[0] = fragP->fr_literal[0]; + New_Frag->fr_literal[1] = fragP->fr_literal[1]; + New_Frag->fr_literal[2] = 0x16; /* Jsb */ + New_Frag->fr_literal[3] = 0xef; + New_Frag->fr_literal[4] = 0; + New_Frag->fr_literal[5] = 0; + New_Frag->fr_literal[6] = 0; + New_Frag->fr_literal[7] = 0; + for (i = 2; i < fragP->fr_fix + fragP->fr_var; i++) + New_Frag->fr_literal[i + 6] = + fragP->fr_literal[i]; + /* + * Now replace the old fragment with the + * newly generated one. + */ + *prev_fragPP = New_Frag; + /* + * Remember the entry point symbol + */ + Entry_Point_Symbol = symbolP; + /* + * Scan the text area fixup structures + * as offsets in the fragment may have + * changed + */ + for (fixP = text_fix_root; fixP; fixP = fixP->fx_next) + { + /* + * Look for references to this + * fragment. + */ + if (fixP->fx_frag == fragP) + { + /* + * Change the fragment + * pointer + */ + fixP->fx_frag = New_Frag; + /* + * If the offset is after + * the entry mask we need + * to account for the JSB + * instruction we just + * inserted. + */ + if (fixP->fx_where >= 2) + fixP->fx_where += 6; + } + } + /* + * Scan the symbols as offsets in the + * fragment may have changed + */ + for (symbolP = symbol_rootP; + symbolP; + symbolP = symbol_next (symbolP)) + { + /* + * Look for references to this + * fragment. + */ + if (symbolP->sy_frag == fragP) + { + /* + * Change the fragment + * pointer + */ + symbolP->sy_frag = New_Frag; + /* + * If the offset is after + * the entry mask we need + * to account for the JSB + * instruction we just + * inserted. + */ + if (S_GET_VALUE (symbolP) >= 2) + S_SET_VALUE (symbolP, + S_GET_VALUE (symbolP) + 6); + } + } + /* + * Make a symbol reference to + * "_c$main_args" so we can get + * its address inserted into the + * JSB instruction. + */ + symbolP = (symbolS *) xmalloc (sizeof (*symbolP)); + S_SET_NAME (symbolP, "_C$MAIN_ARGS"); + S_SET_TYPE (symbolP, N_UNDF); + S_SET_OTHER (symbolP, 0); + S_SET_DESC (symbolP, 0); + S_SET_VALUE (symbolP, 0); + symbolP->sy_name_offset = 0; + symbolP->sy_number = 0; + symbolP->sy_obj = 0; + symbolP->sy_frag = New_Frag; + symbolP->sy_resolved = 0; + symbolP->sy_resolving = 0; + /* this actually inserts at the beginning of the list */ + symbol_append (symbol_rootP, symbolP, + &symbol_rootP, &symbol_lastP); + + symbol_rootP = symbolP; + /* + * Generate a text fixup structure + * to get "_c$main_args" stored into the + * JSB instruction. + */ + fixP = (struct fix *) xmalloc (sizeof (*fixP)); + fixP->fx_frag = New_Frag; + fixP->fx_where = 4; + fixP->fx_addsy = symbolP; + fixP->fx_subsy = 0; + fixP->fx_offset = 0; + fixP->fx_size = 4; + fixP->fx_pcrel = 1; + fixP->fx_next = text_fix_root; + text_fix_root = fixP; + /* + * Now make sure we exit from the loop + */ + frchainP = 0; + break; + } + /* + * Try the next fragment + */ + prev_fragPP = &fragP->fr_next; + fragP = fragP->fr_next; + } + /* + * Try the next fragment chain + */ + if (frchainP) + frchainP = frchainP->frch_next; + } + } +#endif /* HACK_DEC_C_STARTUP */ + } +} + + +/* + * Beginning of vms_write_object_file(). + */ + +static +struct vms_obj_state { + + /* Next program section index to use. */ + int psect_number; + + /* Psect index for code. Always ends up #0. */ + int text_psect; + + /* Psect index for initialized static variables. */ + int data_psect; + + /* Psect index for uninitialized static variables. */ + int bss_psect; + + /* Number of bytes used for local symbol data. */ + int local_initd_data_size; + + /* Dynamic buffer for initialized data. */ + char *data_segment; + +} vms_obj_state; + +#define Psect_Number vms_obj_state.psect_number +#define Text_Psect vms_obj_state.text_psect +#define Data_Psect vms_obj_state.data_psect +#define Bss_Psect vms_obj_state.bss_psect +#define Local_Initd_Data_Size vms_obj_state.local_initd_data_size +#define Data_Segment vms_obj_state.data_segment + + +#define IS_GXX_VTABLE(symP) (strncmp (S_GET_NAME (symP), "__vt.", 5) == 0) + + +/* Perform text segment fixups. */ + +static void +vms_fixup_text_section (text_siz, text_frag_root, data_frag_root) + unsigned text_siz; + struct frag *text_frag_root; + struct frag *data_frag_root; +{ + register fragS *fragP; + register struct fix *fixP; + offsetT dif; + + /* Scan the text fragments. */ + for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) + { + /* Stop if we get to the data fragments. */ + if (fragP == data_frag_root) + break; + /* Ignore fragments with no data. */ + if ((fragP->fr_fix == 0) && (fragP->fr_var == 0)) + continue; + /* Go the the appropriate offset in the Text Psect. */ + VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR); + /* Store the "fixed" part. */ + if (fragP->fr_fix) + VMS_Store_Immediate_Data (fragP->fr_literal, + fragP->fr_fix, + OBJ_S_C_TIR); + /* Store the "variable" part. */ + if (fragP->fr_var && fragP->fr_offset) + VMS_Store_Repeated_Data (fragP->fr_offset, + fragP->fr_literal + fragP->fr_fix, + fragP->fr_var, + OBJ_S_C_TIR); + } /* text frag loop */ + + /* + * Now we go through the text segment fixups and generate + * TIR records to fix up addresses within the Text Psect. + */ + for (fixP = text_fix_root; fixP; fixP = fixP->fx_next) + { + /* We DO handle the case of "Symbol - Symbol" as + long as it is in the same segment. */ + if (fixP->fx_subsy && fixP->fx_addsy) + { + /* They need to be in the same segment. */ + if (S_GET_RAW_TYPE (fixP->fx_subsy) != + S_GET_RAW_TYPE (fixP->fx_addsy)) + error ("Fixup data addsy and subsy don't have the same type"); + /* And they need to be in one that we can check the psect on. */ + if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) && + (S_GET_TYPE (fixP->fx_addsy) != N_TEXT)) + error ("Fixup data addsy and subsy don't have an appropriate type"); + /* This had better not be PC relative! */ + if (fixP->fx_pcrel) + error ("Fixup data is erroneously \"pcrel\""); + /* Subtract their values to get the difference. */ + dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy); + md_number_to_chars (Local, (valueT)dif, fixP->fx_size); + /* Now generate the fixup object records; + set the psect and store the data. */ + VMS_Set_Psect (Text_Psect, + fixP->fx_where + fixP->fx_frag->fr_address, + OBJ_S_C_TIR); + VMS_Store_Immediate_Data (Local, + fixP->fx_size, + OBJ_S_C_TIR); + continue; /* done with this fixup */ + } /* if fx_subsy && fx_addsy */ + /* Size will HAVE to be "long". */ + if (fixP->fx_size != 4) + error ("Fixup datum is not a longword"); + /* Symbol must be "added" (if it is ever + subtracted we can fix this assumption). */ + if (fixP->fx_addsy == 0) + error ("Fixup datum is not \"fixP->fx_addsy\""); + /* Store the symbol value in a PIC fashion. */ + VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy, + fixP->fx_offset, + fixP->fx_pcrel, + Text_Psect, + fixP->fx_where + fixP->fx_frag->fr_address, + OBJ_S_C_TIR); + /* + * Check for indirect address reference, which has to be fixed up + * (as the linker will screw it up with TIR_S_C_STO_PICR)... + */ + if (fixP->fx_pcrel) + VMS_Fix_Indirect_Reference (Text_Psect, + fixP->fx_where + fixP->fx_frag->fr_address, + fixP->fx_frag, + text_frag_root); + } /* text fix loop */ +} + + +/* Create a buffer holding the data segment. */ + +static void +synthesize_data_segment (data_siz, text_siz, data_frag_root) + unsigned data_siz, text_siz; + struct frag *data_frag_root; +{ + register fragS *fragP; + char *fill_literal; + long fill_size, count, i; + + /* Allocate the data segment. */ + Data_Segment = (char *) xmalloc (data_siz); + /* Run through the data fragments, filling in the segment. */ + for (fragP = data_frag_root; fragP; fragP = fragP->fr_next) + { + i = fragP->fr_address - text_siz; + if (fragP->fr_fix) + memcpy (Data_Segment + i, fragP->fr_literal, fragP->fr_fix); + i += fragP->fr_fix; + + if ((fill_size = fragP->fr_var) != 0) + { + fill_literal = fragP->fr_literal + fragP->fr_fix; + for (count = fragP->fr_offset; count; count--) + { + memcpy (Data_Segment + i, fill_literal, fill_size); + i += fill_size; + } + } + } /* data frag loop */ + + return; +} + + +/* Perform data segment fixups. */ + +static void +vms_fixup_data_section (data_siz, text_siz) + unsigned data_siz, text_siz; +{ + register struct VMS_Symbol *vsp; + register struct fix *fixP; + register symbolS *sp; + addressT fr_address; + offsetT dif; + valueT val; + + /* Run through all the data symbols and store the data. */ + for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) + { + /* Ignore anything other than data symbols. */ + if (S_GET_TYPE (vsp->Symbol) != N_DATA) + continue; + /* Set the Psect + Offset. */ + VMS_Set_Psect (vsp->Psect_Index, + vsp->Psect_Offset, + OBJ_S_C_TIR); + /* Store the data. */ + val = S_GET_VALUE (vsp->Symbol); + VMS_Store_Immediate_Data (Data_Segment + val - text_siz, + vsp->Size, + OBJ_S_C_TIR); + } /* N_DATA symbol loop */ + + /* + * Now we go through the data segment fixups and generate + * TIR records to fix up addresses within the Data Psects. + */ + for (fixP = data_fix_root; fixP; fixP = fixP->fx_next) + { + /* Find the symbol for the containing datum. */ + for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) + { + /* Only bother with Data symbols. */ + sp = vsp->Symbol; + if (S_GET_TYPE (sp) != N_DATA) + continue; + /* Ignore symbol if After fixup. */ + val = S_GET_VALUE (sp); + fr_address = fixP->fx_frag->fr_address; + if (val > fixP->fx_where + fr_address) + continue; + /* See if the datum is here. */ + if (val + vsp->Size <= fixP->fx_where + fr_address) + continue; + /* We DO handle the case of "Symbol - Symbol" as + long as it is in the same segment. */ + if (fixP->fx_subsy && fixP->fx_addsy) + { + /* They need to be in the same segment. */ + if (S_GET_RAW_TYPE (fixP->fx_subsy) != + S_GET_RAW_TYPE (fixP->fx_addsy)) + error ("Fixup data addsy and subsy don't have the same type"); + /* And they need to be in one that we can check the psect on. */ + if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) && + (S_GET_TYPE (fixP->fx_addsy) != N_TEXT)) + error ("Fixup data addsy and subsy don't have an appropriate type"); + /* This had better not be PC relative! */ + if (fixP->fx_pcrel) + error ("Fixup data is erroneously \"pcrel\""); + /* Subtract their values to get the difference. */ + dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy); + md_number_to_chars (Local, (valueT)dif, fixP->fx_size); + /* + * Now generate the fixup object records; + * set the psect and store the data. + */ + VMS_Set_Psect (vsp->Psect_Index, + fr_address + fixP->fx_where + - val + vsp->Psect_Offset, + OBJ_S_C_TIR); + VMS_Store_Immediate_Data (Local, + fixP->fx_size, + OBJ_S_C_TIR); + break; /* done with this fixup */ + } + /* Size will HAVE to be "long". */ + if (fixP->fx_size != 4) + error ("Fixup datum is not a longword"); + /* Symbol must be "added" (if it is ever + subtracted we can fix this assumption). */ + if (fixP->fx_addsy == 0) + error ("Fixup datum is not \"fixP->fx_addsy\""); + /* Store the symbol value in a PIC fashion. */ + VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy, + fixP->fx_offset, + fixP->fx_pcrel, + vsp->Psect_Index, + fr_address + fixP->fx_where + - val + vsp->Psect_Offset, + OBJ_S_C_TIR); + /* Done with this fixup. */ + break; + } /* vms_symbol loop */ + + } /* data fix loop */ +} + + +/* Define symbols for the linker. */ + +static void +global_symbol_directory (text_siz, data_siz) + unsigned text_siz, data_siz; +{ + register fragS *fragP; + register symbolS *sp; + register struct VMS_Symbol *vsp; + int Globalref, define_as_global_symbol; + +#ifndef gxx_bug_fixed + /* + * The g++ compiler does not write out external references to vtables + * correctly. Check for this and holler if we see it happening. + * If that compiler bug is ever fixed we can remove this. + * (Jun'95: gcc 2.7.0's cc1plus still exhibits this behavior.) + */ + for (sp = symbol_rootP; sp; sp = symbol_next (sp)) + if (S_GET_RAW_TYPE (sp) == N_UNDF && IS_GXX_VTABLE (sp)) + { + S_SET_TYPE (sp, N_UNDF | N_EXT); + S_SET_OTHER (sp, 1); + as_warn ("g++ wrote an extern reference to `%s' as a routine.\n%s", + S_GET_NAME (sp), + "I will fix it, but I hope that it was not really a routine."); + } +#endif /* gxx_bug_fixed */ + + /* + * Now scan the symbols and emit the appropriate GSD records + */ + for (sp = symbol_rootP; sp; sp = symbol_next (sp)) + { + define_as_global_symbol = 0; + vsp = 0; + /* Dispatch on symbol type. */ + switch (S_GET_RAW_TYPE (sp)) + { + + /* Global uninitialized data. */ + case N_UNDF | N_EXT: + /* Make a VMS data symbol entry. */ + vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp); + vsp->Symbol = sp; + vsp->Size = S_GET_VALUE (sp); + vsp->Psect_Index = Psect_Number++; + vsp->Psect_Offset = 0; + vsp->Next = VMS_Symbols; + VMS_Symbols = vsp; + sp->sy_obj = vsp; + /* Make the psect for this data. */ + Globalref = VMS_Psect_Spec (S_GET_NAME (sp), + vsp->Size, + S_GET_OTHER (sp) ? ps_CONST : ps_COMMON, + vsp); + if (Globalref) + Psect_Number--; +#ifdef NOT_VAX_11_C_COMPATIBLE + define_as_global_symbol = 1; +#else + /* See if this is an external vtable. We want to help the + linker find these things in libraries, so we make a symbol + reference. This is not compatible with VAX-C usage for + variables, but since vtables are only used internally by + g++, we can get away with this hack. */ + define_as_global_symbol = IS_GXX_VTABLE (sp); +#endif + break; + + /* Local uninitialized data. */ + case N_BSS: + /* Make a VMS data symbol entry. */ + vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp); + vsp->Symbol = sp; + vsp->Size = 0; + vsp->Psect_Index = Bss_Psect; + vsp->Psect_Offset = S_GET_VALUE (sp) - bss_address_frag.fr_address; + vsp->Next = VMS_Symbols; + VMS_Symbols = vsp; + sp->sy_obj = vsp; + break; + + /* Global initialized data. */ + case N_DATA | N_EXT: + /* Make a VMS data symbol entry. */ + vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp); + vsp->Symbol = sp; + vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz); + vsp->Psect_Index = Psect_Number++; + vsp->Psect_Offset = 0; + vsp->Next = VMS_Symbols; + VMS_Symbols = vsp; + sp->sy_obj = vsp; + /* Make its psect. */ + Globalref = VMS_Psect_Spec (S_GET_NAME (sp), + vsp->Size, + S_GET_OTHER (sp) ? ps_CONST : ps_COMMON, + vsp); + if (Globalref) + Psect_Number--; +#ifdef NOT_VAX_11_C_COMPATIBLE + define_as_global_symbol = 1; +#else + /* See N_UNDF|N_EXT above for explanation. */ + define_as_global_symbol = IS_GXX_VTABLE (sp); +#endif + break; + + /* Local initialized data. */ + case N_DATA: + { + char *sym_name = S_GET_NAME (sp); + + /* Always suppress local numeric labels. */ + if (sym_name && strcmp (sym_name, FAKE_LABEL_NAME) == 0) + break; + + /* Make a VMS data symbol entry. */ + vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp); + vsp->Symbol = sp; + vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz); + vsp->Psect_Index = Data_Psect; + vsp->Psect_Offset = Local_Initd_Data_Size; + Local_Initd_Data_Size += vsp->Size; + vsp->Next = VMS_Symbols; + VMS_Symbols = vsp; + sp->sy_obj = vsp; + } + break; + + /* Global Text definition. */ + case N_TEXT | N_EXT: + { + unsigned short Entry_Mask; + + /* Get the entry mask. */ + fragP = sp->sy_frag; + /* First frag might be empty if we're generating listings. + So skip empty rs_fill frags. */ + while (fragP && fragP->fr_type == rs_fill && fragP->fr_fix == 0) + fragP = fragP->fr_next; + + /* If first frag doesn't contain the data, what do we do? + If it's possibly smaller than two bytes, that would + imply that the entry mask is not stored where we're + expecting it. + + If you can find a test case that triggers this, report + it (and tell me what the entry mask field ought to be), + and I'll try to fix it. KR */ + if (fragP->fr_fix < 2) + abort (); + + Entry_Mask = (fragP->fr_literal[0] & 0x00ff) | + ((fragP->fr_literal[1] & 0x00ff) << 8); + /* Define the procedure entry point. */ + VMS_Procedure_Entry_Pt (S_GET_NAME (sp), + Text_Psect, + S_GET_VALUE (sp), + Entry_Mask); + break; + } + + /* Local Text definition. */ + case N_TEXT: + /* Make a VMS data symbol entry. */ + if (Text_Psect != -1) + { + vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp); + vsp->Symbol = sp; + vsp->Size = 0; + vsp->Psect_Index = Text_Psect; + vsp->Psect_Offset = S_GET_VALUE (sp); + vsp->Next = VMS_Symbols; + VMS_Symbols = vsp; + sp->sy_obj = vsp; + } + break; + + /* Global Reference. */ + case N_UNDF: + /* Make a GSD global symbol reference record. */ + VMS_Global_Symbol_Spec (S_GET_NAME (sp), + 0, + 0, + GBLSYM_REF); + break; + + /* Absolute symbol. */ + case N_ABS: + case N_ABS | N_EXT: + /* gcc doesn't generate these; + VMS_Emit_Globalvalue handles them though. */ + vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp); + vsp->Symbol = sp; + vsp->Size = 4; /* always assume 32 bits */ + vsp->Psect_Index = 0; + vsp->Psect_Offset = S_GET_VALUE (sp); + vsp->Next = VMS_Symbols; + VMS_Symbols = vsp; + sp->sy_obj = vsp; + break; + + /* Anything else. */ + default: + /* Ignore STAB symbols, including .stabs emitted by g++. */ + if (S_IS_DEBUG (sp) || (S_GET_TYPE (sp) == 22)) + break; + /* + * Error otherwise. + */ + as_tsktsk ("unhandled stab type %d", S_GET_TYPE (sp)); + break; + } + + /* Global symbols have different linkage than external variables. */ + if (define_as_global_symbol) + VMS_Global_Symbol_Spec (S_GET_NAME (sp), + vsp->Psect_Index, + 0, + GBLSYM_DEF); + } + + return; +} + + +/* Output debugger symbol table information for symbols which + are local to a specific routine. */ + +static void +local_symbols_DST (s0P, Current_Routine) + symbolS *s0P, *Current_Routine; +{ + symbolS *s1P; + char *s0P_name, *pnt0, *pnt1; + + s0P_name = S_GET_NAME (s0P); + if (*s0P_name++ != '_') + return; + + for (s1P = Current_Routine; s1P; s1P = symbol_next (s1P)) + { +#if 0 /* redundant; RAW_TYPE != N_FUN suffices */ + if (!S_IS_DEBUG (s1P)) + continue; +#endif + if (S_GET_RAW_TYPE (s1P) != N_FUN) + continue; + pnt0 = s0P_name; + pnt1 = S_GET_NAME (s1P); + /* We assume the two strings are never exactly equal... */ + while (*pnt0++ == *pnt1++) + { + } + /* Found it if s0P name is exhausted and s1P name has ":F" or ":f" next. + Note: both pointers have advanced one past the non-matching char. */ + if ((*pnt1 == 'F' || *pnt1 == 'f') && *--pnt1 == ':' && *--pnt0 == '\0') + { + Define_Routine (s1P, 0, Current_Routine, Text_Psect); + return; + } + } +} + + +/* Construct and output the debug symbol table. */ + +static void +vms_build_DST (text_siz) + unsigned text_siz; +{ + register symbolS *symbolP; + symbolS *Current_Routine = 0; + struct input_file *Cur_File = 0; + offsetT Cur_Offset = -1; + int Cur_Line_Number = 0; + int File_Number = 0; + int Debugger_Offset = 0; + int file_available; + int dsc; + offsetT val; + + /* Write the Traceback Begin Module record. */ + VMS_TBT_Module_Begin (); + + /* + * Output debugging info for global variables and static variables + * that are not specific to one routine. We also need to examine + * all stabs directives, to find the definitions to all of the + * advanced data types, and this is done by VMS_LSYM_Parse. This + * needs to be done before any definitions are output to the object + * file, since there can be forward references in the stabs + * directives. When through with parsing, the text of the stabs + * directive is altered, with the definitions removed, so that later + * passes will see directives as they would be written if the type + * were already defined. + * + * We also look for files and include files, and make a list of + * them. We examine the source file numbers to establish the actual + * lines that code was generated from, and then generate offsets. + */ + VMS_LSYM_Parse (); + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + { + /* Only deal with STAB symbols here. */ + if (!S_IS_DEBUG (symbolP)) + continue; + /* + * Dispatch on STAB type. + */ + switch (S_GET_RAW_TYPE (symbolP)) + { + case N_SLINE: + dsc = S_GET_DESC (symbolP); + if (dsc > Cur_File->max_line) + Cur_File->max_line = dsc; + if (dsc < Cur_File->min_line) + Cur_File->min_line = dsc; + break; + case N_SO: + Cur_File = find_file (symbolP); + Cur_File->flag = 1; + Cur_File->min_line = 1; + break; + case N_SOL: + Cur_File = find_file (symbolP); + break; + case N_GSYM: + VMS_GSYM_Parse (symbolP, Text_Psect); + break; + case N_LCSYM: + VMS_LCSYM_Parse (symbolP, Text_Psect); + break; + case N_FUN: /* For static constant symbols */ + case N_STSYM: + VMS_STSYM_Parse (symbolP, Text_Psect); + break; + default: + break; + } /* switch */ + } /* for */ + + /* + * Now we take a quick sweep through the files and assign offsets + * to each one. This will essentially be the starting line number to + * the debugger for each file. Output the info for the debugger to + * specify the files, and then tell it how many lines to use. + */ + for (Cur_File = file_root; Cur_File; Cur_File = Cur_File->next) + { + if (Cur_File->max_line == 0) + continue; + if ((strncmp (Cur_File->name, "GNU_GXX_INCLUDE:", 16) == 0) && + !flag_debug) + continue; + if ((strncmp (Cur_File->name, "GNU_CC_INCLUDE:", 15) == 0) && + !flag_debug) + continue; + /* show a few extra lines at the start of the region selected */ + if (Cur_File->min_line > 2) + Cur_File->min_line -= 2; + Cur_File->offset = Debugger_Offset - Cur_File->min_line + 1; + Debugger_Offset += Cur_File->max_line - Cur_File->min_line + 1; + if (Cur_File->same_file_fpnt) + { + Cur_File->file_number = Cur_File->same_file_fpnt->file_number; + } + else + { + Cur_File->file_number = ++File_Number; + file_available = VMS_TBT_Source_File (Cur_File->name, + Cur_File->file_number); + if (!file_available) + { + Cur_File->file_number = 0; + File_Number--; + continue; + } + } + VMS_TBT_Source_Lines (Cur_File->file_number, + Cur_File->min_line, + Cur_File->max_line - Cur_File->min_line + 1); + } /* for */ + Cur_File = (struct input_file *) NULL; + + /* + * Scan the symbols and write out the routines + * (this makes the assumption that symbols are in + * order of ascending text segment offset) + */ + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) + { + /* + * Deal with text symbols. + */ + if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT) + { + /* + * Ignore symbols starting with "L", as they are local symbols. + */ + if (*S_GET_NAME (symbolP) == 'L') + continue; + /* + * If there is a routine start defined, terminate it. + */ + if (Current_Routine) + VMS_TBT_Routine_End (text_siz, Current_Routine); + + /* + * Check for & skip dummy labels like "gcc_compiled.". + * They're identified by the IN_DEFAULT_SECTION flag. + */ + if ((S_GET_OTHER (symbolP) & IN_DEFAULT_SECTION) != 0 && + S_GET_VALUE (symbolP) == 0) + continue; + /* + * Store the routine begin traceback info. + */ + VMS_TBT_Routine_Begin (symbolP, Text_Psect); + Current_Routine = symbolP; + /* + * Define symbols local to this routine. + */ + local_symbols_DST (symbolP, Current_Routine); + /* + * Done + */ + continue; + + } + /* + * Deal with STAB symbols. + */ + else if (S_IS_DEBUG (symbolP)) + { + /* + * Dispatch on STAB type. + */ + switch (S_GET_RAW_TYPE (symbolP)) + { + /* + * Line number + */ + case N_SLINE: + /* Offset the line into the correct portion of the file. */ + if (Cur_File->file_number == 0) + break; + val = S_GET_VALUE (symbolP); + /* Sometimes the same offset gets several source lines + assigned to it. We should be selective about which + lines we allow, we should prefer lines that are in + the main source file when debugging inline functions. */ + if (val == Cur_Offset && Cur_File->file_number != 1) + break; + + /* calculate actual debugger source line */ + dsc = S_GET_DESC (symbolP) + Cur_File->offset; + S_SET_DESC (symbolP, dsc); + /* + * Define PC/Line correlation. + */ + if (Cur_Offset == -1) + { + /* + * First N_SLINE; set up initial correlation. + */ + VMS_TBT_Line_PC_Correlation (dsc, + val, + Text_Psect, + 0); + } + else if ((dsc - Cur_Line_Number) <= 0) + { + /* + * Line delta is not +ve, we need to close the line and + * start a new PC/Line correlation. + */ + VMS_TBT_Line_PC_Correlation (0, + val - Cur_Offset, + 0, + -1); + VMS_TBT_Line_PC_Correlation (dsc, + val, + Text_Psect, + 0); + } + else + { + /* + * Line delta is +ve, all is well. + */ + VMS_TBT_Line_PC_Correlation (dsc - Cur_Line_Number, + val - Cur_Offset, + 0, + 1); + } + /* Update the current line/PC info. */ + Cur_Line_Number = dsc; + Cur_Offset = val; + break; + + /* + * Source file + */ + case N_SO: + /* Remember that we had a source file and emit + the source file debugger record. */ + Cur_File = find_file (symbolP); + break; + + case N_SOL: + /* We need to make sure that we are really in the actual + source file when we compute the maximum line number. + Otherwise the debugger gets really confused. */ + Cur_File = find_file (symbolP); + break; + + default: + break; + } /* switch */ + } /* if (IS_DEBUG) */ + } /* for */ + + /* + * If there is a routine start defined, terminate it + * (and the line numbers). + */ + if (Current_Routine) + { + /* Terminate the line numbers. */ + VMS_TBT_Line_PC_Correlation (0, + text_siz - S_GET_VALUE (Current_Routine), + 0, + -1); + /* Terminate the routine. */ + VMS_TBT_Routine_End (text_siz, Current_Routine); + } + + /* Write the Traceback End Module TBT record. */ + VMS_TBT_Module_End (); +} + + +/* Write a VAX/VMS object file (everything else has been done!). */ + +void +vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root, + data_frag_root) + unsigned text_siz; + unsigned data_siz; + unsigned bss_siz; + fragS *text_frag_root; + fragS *data_frag_root; +{ + register struct VMS_Symbol *vsp; + + /* + * Initialize program section indices; values get updated later. + */ + Psect_Number = 0; /* next Psect Index to use */ + Text_Psect = -1; /* Text Psect Index */ + Data_Psect = -2; /* Data Psect Index JF: Was -1 */ + Bss_Psect = -3; /* Bss Psect Index JF: Was -1 */ + /* Initialize other state variables. */ + Data_Segment = 0; + Local_Initd_Data_Size = 0; + + /* + * Create the actual output file and populate it with required + * "module header" information. + */ + Create_VMS_Object_File (); + Write_VMS_MHD_Records (); + + /* + * Create the Data segment: + * + * Since this is REALLY hard to do any other way, + * we actually manufacture the data segment and + * then store the appropriate values out of it. + * We need to generate this early, so that globalvalues + * can be properly emitted. + */ + if (data_siz > 0) + synthesize_data_segment (data_siz, text_siz, data_frag_root); + + + /******* Global Symbol Directory *******/ + + /* + * Emit globalvalues now. We must do this before the text psect is + * defined, or we will get linker warnings about multiply defined + * symbols. All of the globalvalues "reference" psect 0, although + * it really does not have anything to do with it. + */ + VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment); + /* + * Define the Text Psect + */ + Text_Psect = Psect_Number++; + VMS_Psect_Spec ("$code", text_siz, ps_TEXT, 0); + /* + * Define the BSS Psect + */ + if (bss_siz > 0) + { + Bss_Psect = Psect_Number++; + VMS_Psect_Spec ("$uninitialized_data", bss_siz, ps_DATA, 0); + } + /* + * Define symbols to the linker. + */ + global_symbol_directory (text_siz, data_siz); + /* + * Define the Data Psect + */ + if (data_siz > 0 && Local_Initd_Data_Size > 0) + { + Data_Psect = Psect_Number++; + VMS_Psect_Spec ("$data", Local_Initd_Data_Size, ps_DATA, 0); + /* + * Local initialized data (N_DATA) symbols need to be updated to the + * proper value of Data_Psect now that it's actually been defined. + * (A dummy value was used in global_symbol_directory() above.) + */ + for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) + if (vsp->Psect_Index < 0 && S_GET_RAW_TYPE (vsp->Symbol) == N_DATA) + vsp->Psect_Index = Data_Psect; + } + + + /******* Text Information and Relocation Records *******/ + + /* + * Write the text segment data + */ + if (text_siz > 0) + vms_fixup_text_section (text_siz, text_frag_root, data_frag_root); + /* + * Write the data segment data, then discard it. + */ + if (data_siz > 0) + { + vms_fixup_data_section (data_siz, text_siz); + free (Data_Segment), Data_Segment = 0; + } + + + /******* Debugger Symbol Table Records *******/ + + vms_build_DST (text_siz); + + + /******* Wrap things up *******/ + + /* + * Write the End Of Module record + */ + if (Entry_Point_Symbol) + Write_VMS_EOM_Record (Text_Psect, S_GET_VALUE (Entry_Point_Symbol)); + else + Write_VMS_EOM_Record (-1, (valueT) 0); + + /* + * All done, close the object file + */ + Close_VMS_Object_File (); +} + +/* end of obj-vms.c */ diff --git a/gnu/usr.bin/binutils/gas/config/obj-vms.h b/gnu/usr.bin/binutils/gas/config/obj-vms.h new file mode 100644 index 00000000000..1105bb2f860 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/obj-vms.h @@ -0,0 +1,544 @@ +/* VMS object file format + Copyright (C) 1989, 1990, 1991, 1994, 1995 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 2, +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. */ + +/* Tag to validate a.out object file format processing */ +#define OBJ_VMS 1 + +#include "targ-cpu.h" + +/* This macro controls subsection alignment within a section. + * + * Under VAX/VMS, the linker (and PSECT specifications) + * take care of correctly aligning the segments. + * Doing the alignment here (on initialized data) can + * mess up the calculation of global data PSECT sizes. + */ +#define SUB_SEGMENT_ALIGN(SEG) (((SEG) == data_section) ? 0 : 2) + +/* This flag is used to remember whether we are in the const or the + data section. By and large they are identical, but we set a no-write + bit for psects in the const section. */ + +extern unsigned char const_flag; + +/* This is overloaded onto const_flag, for convenience. It's used to flag + dummy labels like "gcc2_compiled." which occur before the first .text + or .data section directive. */ + +#define IN_DEFAULT_SECTION 0x80 + +/* These are defined in obj-vms.c. */ +extern const short seg_N_TYPE[]; +extern const segT N_TYPE_seg[]; + +#undef NO_RELOC +enum reloc_type + { + NO_RELOC, RELOC_32 + }; + +#define N_BADMAG(x) (0) +#define N_TXTOFF(x) ( sizeof(struct exec) ) +#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) +#define N_TROFF(x) ( N_DATOFF(x) + (x).a_data ) +#define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize ) +#define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize ) +#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) + +/* We use this copy of the exec header for VMS. We do not actually use it, but + what we actually do is let gas fill in the relevant slots, and when we get + around to writing an obj file, we just pick out what we need. */ + +struct exec +{ + 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_entry; /* start address */ + unsigned long a_syms; /* length of symbol table data in file, in bytes */ +}; + +typedef struct + { + struct exec header; /* a.out header */ + long string_table_size; /* names + '\0' + sizeof(int) */ + } +object_headers; + +/* A single entry in the symbol table + * (this started as a clone of bout.h's nlist, but much was unneeded). + */ +struct nlist + { + char *n_name; + unsigned char n_type; /* See below */ + unsigned char n_other; /* used for const_flag and "default section" */ + unsigned : 16; /* padding for alignment */ + int n_desc; /* source line number for N_SLINE stabs */ + }; + +/* Legal values of n_type (see aout/stab.def for the majority of the codes). + */ +#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 */ + +#include "aout/stab_gnu.h" + +/* SYMBOL TABLE */ +/* Symbol table entry data type */ + +typedef struct nlist obj_symbol_type; /* Symbol table entry */ + +/* Symbol table macros and constants */ + +#define OBJ_SYMFIELD_TYPE struct VMS_Symbol * + +/* + * Macros to extract information from a symbol table entry. + * This syntaxic indirection allows independence regarding a.out or coff. + * The argument (s) of all these macros is a pointer to a symbol table entry. + */ + +/* True if the symbol is external */ +#define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT) + +/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */ +#define S_IS_DEFINED(s) (S_GET_TYPE(s) != N_UNDF) + +#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER) + +/* True if a debug special symbol entry */ +#define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB) +/* True if a symbol is local symbol name */ +/* A symbol name whose name begin with ^A is a gas internal pseudo symbol + nameless symbols come from .stab directives. */ +#define S_IS_LOCAL(s) (S_GET_NAME(s) && \ + !S_IS_DEBUG(s) && \ + (S_GET_NAME(s)[0] == '\001' || \ + (S_LOCAL_NAME(s) && !flag_keep_locals))) +/* True if a symbol is not defined in this file */ +#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT) +/* True if the symbol has been generated because of a .stabd directive */ +#define S_IS_STABD(s) (S_GET_NAME(s) == (char *)0) + +/* Accessors */ +/* The name of the symbol */ +#define S_GET_NAME(s) ((s)->sy_symbol.n_name) +/* The pointer to the string table */ +#define S_GET_OFFSET(s) ((s)->sy_name_offset) +/* The raw type of the symbol */ +#define S_GET_RAW_TYPE(s) ((s)->sy_symbol.n_type) +/* The type of the symbol */ +#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE) +/* The numeric value of the segment */ +#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)]) +/* The n_other expression value */ +#define S_GET_OTHER(s) ((s)->sy_symbol.n_other) +/* The n_desc expression value */ +#define S_GET_DESC(s) ((s)->sy_symbol.n_desc) + +/* Modifiers */ +/* Assume that a symbol cannot be simultaneously in more than on segment */ +/* set segment */ +#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg)) +/* The symbol is external */ +#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT) +/* The symbol is not external */ +#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT) +/* Set the name of the symbol */ +#define S_SET_NAME(s,v) ((s)->sy_symbol.n_name = (v)) +/* Set the offset in the string table */ +#define S_SET_OFFSET(s,v) ((s)->sy_name_offset = (v)) +/* Set the n_other expression value */ +#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v)) +/* Set the n_desc expression value */ +#define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v)) +/* Set the n_type expression value */ +#define S_SET_TYPE(s,v) ((s)->sy_symbol.n_type = (v)) + + +/* File header macro and type definition */ + +#define H_GET_TEXT_SIZE(h) ((h)->header.a_text) +#define H_GET_DATA_SIZE(h) ((h)->header.a_data) +#define H_GET_BSS_SIZE(h) ((h)->header.a_bss) + +#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v))) +#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v))) +#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v))) + +#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) +#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * \ + sizeof(struct nlist)) + +/* line numbering stuff. */ +#define OBJ_EMIT_LINENO(a, b, c) {;} + +#define obj_symbol_new_hook(s) {;} + +/* Force structure tags into scope so that their use in prototypes + will never be their first occurance. */ +struct fix; +struct symbol; +struct frag; + +/* obj-vms routines visible to the rest of gas. */ + +extern void tc_aout_fix_to_chars PARAMS ((char *,struct fix *,relax_addressT)); + +extern int vms_resolve_symbol_redef PARAMS ((struct symbol *)); +#define RESOLVE_SYMBOL_REDEFINITION(X) vms_resolve_symbol_redef(X) + +/* Compiler-generated label "__vax_g_doubles" is used to augment .stabs. */ +extern void vms_check_for_special_label PARAMS ((struct symbol *)); +#define tc_frob_label(X) vms_check_for_special_label(X) + +extern void vms_check_for_main PARAMS ((void)); + +extern void vms_write_object_file PARAMS ((unsigned,unsigned,unsigned, + struct frag *,struct frag *)); + +/* VMS executables are nothing like a.out, but the VMS port of gcc uses + a.out format stabs which obj-vms.c then translates. */ + +#define AOUT_STABS + + +#ifdef WANT_VMS_OBJ_DEFS + +/* The rest of this file contains definitions for constants used within + the actual VMS object file. We do not use a $ in the symbols (as per + usual VMS convention) since System V gags on it. */ + +#define OBJ_S_C_HDR 0 +#define OBJ_S_C_HDR_MHD 0 +#define OBJ_S_C_HDR_LNM 1 +#define OBJ_S_C_HDR_SRC 2 +#define OBJ_S_C_HDR_TTL 3 +#define OBJ_S_C_HDR_CPR 4 +#define OBJ_S_C_HDR_MTC 5 +#define OBJ_S_C_HDR_GTX 6 +#define OBJ_S_C_GSD 1 +#define OBJ_S_C_GSD_PSC 0 +#define OBJ_S_C_GSD_SYM 1 +#define OBJ_S_C_GSD_EPM 2 +#define OBJ_S_C_GSD_PRO 3 +#define OBJ_S_C_GSD_SYMW 4 +#define OBJ_S_C_GSD_EPMW 5 +#define OBJ_S_C_GSD_PROW 6 +#define OBJ_S_C_GSD_IDC 7 +#define OBJ_S_C_GSD_ENV 8 +#define OBJ_S_C_GSD_LSY 9 +#define OBJ_S_C_GSD_LEPM 10 +#define OBJ_S_C_GSD_LPRO 11 +#define OBJ_S_C_GSD_SPSC 12 +#define OBJ_S_C_TIR 2 +#define OBJ_S_C_EOM 3 +#define OBJ_S_C_DBG 4 +#define OBJ_S_C_TBT 5 +#define OBJ_S_C_LNK 6 +#define OBJ_S_C_EOMW 7 +#define OBJ_S_C_MAXRECTYP 7 +#define OBJ_S_K_SUBTYP 1 +#define OBJ_S_C_SUBTYP 1 +#define OBJ_S_C_MAXRECSIZ 2048 +#define OBJ_S_C_STRLVL 0 +#define OBJ_S_C_SYMSIZ 31 +#define OBJ_S_C_STOREPLIM -1 +#define OBJ_S_C_PSCALILIM 9 + +#define MHD_S_C_MHD 0 +#define MHD_S_C_LNM 1 +#define MHD_S_C_SRC 2 +#define MHD_S_C_TTL 3 +#define MHD_S_C_CPR 4 +#define MHD_S_C_MTC 5 +#define MHD_S_C_GTX 6 +#define MHD_S_C_MAXHDRTYP 6 + +#define GSD_S_K_ENTRIES 1 +#define GSD_S_C_ENTRIES 1 +#define GSD_S_C_PSC 0 +#define GSD_S_C_SYM 1 +#define GSD_S_C_EPM 2 +#define GSD_S_C_PRO 3 +#define GSD_S_C_SYMW 4 +#define GSD_S_C_EPMW 5 +#define GSD_S_C_PROW 6 +#define GSD_S_C_IDC 7 +#define GSD_S_C_ENV 8 +#define GSD_S_C_LSY 9 +#define GSD_S_C_LEPM 10 +#define GSD_S_C_LPRO 11 +#define GSD_S_C_SPSC 12 +#define GSD_S_C_SYMV 13 +#define GSD_S_C_EPMV 14 +#define GSD_S_C_PROV 15 +#define GSD_S_C_MAXRECTYP 15 + +#define GSY_S_M_WEAK 1 +#define GSY_S_M_DEF 2 +#define GSY_S_M_UNI 4 +#define GSY_S_M_REL 8 + +#define LSY_S_M_DEF 2 +#define LSY_S_M_REL 8 + +#define ENV_S_M_DEF 1 +#define ENV_S_M_NESTED 2 + +#define GPS_S_M_PIC 1 +#define GPS_S_M_LIB 2 +#define GPS_S_M_OVR 4 +#define GPS_S_M_REL 8 +#define GPS_S_M_GBL 16 +#define GPS_S_M_SHR 32 +#define GPS_S_M_EXE 64 +#define GPS_S_M_RD 128 +#define GPS_S_M_WRT 256 +#define GPS_S_M_VEC 512 +#define GPS_S_K_NAME 9 +#define GPS_S_C_NAME 9 + +#define TIR_S_C_STA_GBL 0 +#define TIR_S_C_STA_SB 1 +#define TIR_S_C_STA_SW 2 +#define TIR_S_C_STA_LW 3 +#define TIR_S_C_STA_PB 4 +#define TIR_S_C_STA_PW 5 +#define TIR_S_C_STA_PL 6 +#define TIR_S_C_STA_UB 7 +#define TIR_S_C_STA_UW 8 +#define TIR_S_C_STA_BFI 9 +#define TIR_S_C_STA_WFI 10 +#define TIR_S_C_STA_LFI 11 +#define TIR_S_C_STA_EPM 12 +#define TIR_S_C_STA_CKARG 13 +#define TIR_S_C_STA_WPB 14 +#define TIR_S_C_STA_WPW 15 +#define TIR_S_C_STA_WPL 16 +#define TIR_S_C_STA_LSY 17 +#define TIR_S_C_STA_LIT 18 +#define TIR_S_C_STA_LEPM 19 +#define TIR_S_C_MAXSTACOD 19 +#define TIR_S_C_MINSTOCOD 20 +#define TIR_S_C_STO_SB 20 +#define TIR_S_C_STO_SW 21 +#define TIR_S_C_STO_L 22 +#define TIR_S_C_STO_BD 23 +#define TIR_S_C_STO_WD 24 +#define TIR_S_C_STO_LD 25 +#define TIR_S_C_STO_LI 26 +#define TIR_S_C_STO_PIDR 27 +#define TIR_S_C_STO_PICR 28 +#define TIR_S_C_STO_RSB 29 +#define TIR_S_C_STO_RSW 30 +#define TIR_S_C_STO_RL 31 +#define TIR_S_C_STO_VPS 32 +#define TIR_S_C_STO_USB 33 +#define TIR_S_C_STO_USW 34 +#define TIR_S_C_STO_RUB 35 +#define TIR_S_C_STO_RUW 36 +#define TIR_S_C_STO_B 37 +#define TIR_S_C_STO_W 38 +#define TIR_S_C_STO_RB 39 +#define TIR_S_C_STO_RW 40 +#define TIR_S_C_STO_RIVB 41 +#define TIR_S_C_STO_PIRR 42 +#define TIR_S_C_MAXSTOCOD 42 +#define TIR_S_C_MINOPRCOD 50 +#define TIR_S_C_OPR_NOP 50 +#define TIR_S_C_OPR_ADD 51 +#define TIR_S_C_OPR_SUB 52 +#define TIR_S_C_OPR_MUL 53 +#define TIR_S_C_OPR_DIV 54 +#define TIR_S_C_OPR_AND 55 +#define TIR_S_C_OPR_IOR 56 +#define TIR_S_C_OPR_EOR 57 +#define TIR_S_C_OPR_NEG 58 +#define TIR_S_C_OPR_COM 59 +#define TIR_S_C_OPR_INSV 60 +#define TIR_S_C_OPR_ASH 61 +#define TIR_S_C_OPR_USH 62 +#define TIR_S_C_OPR_ROT 63 +#define TIR_S_C_OPR_SEL 64 +#define TIR_S_C_OPR_REDEF 65 +#define TIR_S_C_OPR_DFLIT 66 +#define TIR_S_C_MAXOPRCOD 66 +#define TIR_S_C_MINCTLCOD 80 +#define TIR_S_C_CTL_SETRB 80 +#define TIR_S_C_CTL_AUGRB 81 +#define TIR_S_C_CTL_DFLOC 82 +#define TIR_S_C_CTL_STLOC 83 +#define TIR_S_C_CTL_STKDL 84 +#define TIR_S_C_MAXCTLCOD 84 + +/* + * Debugger symbol definitions: These are done by hand, as no + * machine-readable version seems + * to be available. + */ +#define DST_S_C_C 7 /* Language == "C" */ +#define DST_S_C_CXX 15 /* Language == "C++" */ +#define DST_S_C_VERSION 153 +#define DST_S_C_SOURCE 155 /* Source file */ +#define DST_S_C_PROLOG 162 +#define DST_S_C_BLKBEG 176 /* Beginning of block */ +#define DST_S_C_BLKEND 177 /* End of block */ +#define DST_S_C_ENTRY 181 +#define DST_S_C_PSECT 184 +#define DST_S_C_LINE_NUM 185 /* Line Number */ +#define DST_S_C_LBLORLIT 186 +#define DST_S_C_LABEL 187 +#define DST_S_C_MODBEG 188 /* Beginning of module */ +#define DST_S_C_MODEND 189 /* End of module */ +#define DST_S_C_RTNBEG 190 /* Beginning of routine */ +#define DST_S_C_RTNEND 191 /* End of routine */ +#define DST_S_C_DELTA_PC_W 1 /* Incr PC */ +#define DST_S_C_INCR_LINUM 2 /* Incr Line # */ +#define DST_S_C_INCR_LINUM_W 3 /* Incr Line # */ +#define DST_S_C_SET_LINUM_INCR 4 +#define DST_S_C_SET_LINUM_INCR_W 5 +#define DST_S_C_RESET_LINUM_INCR 6 +#define DST_S_C_BEG_STMT_MODE 7 +#define DST_S_C_END_STMT_MODE 8 +#define DST_S_C_SET_LINE_NUM 9 /* Set Line # */ +#define DST_S_C_SET_PC 10 +#define DST_S_C_SET_PC_W 11 +#define DST_S_C_SET_PC_L 12 +#define DST_S_C_SET_STMTNUM 13 +#define DST_S_C_TERM 14 /* End of lines */ +#define DST_S_C_TERM_W 15 /* End of lines */ +#define DST_S_C_SET_ABS_PC 16 /* Set PC */ +#define DST_S_C_DELTA_PC_L 17 /* Incr PC */ +#define DST_S_C_INCR_LINUM_L 18 /* Incr Line # */ +#define DST_S_C_SET_LINUM_B 19 /* Set Line # */ +#define DST_S_C_SET_LINUM_L 20 /* Set Line # */ +#define DST_S_C_TERM_L 21 /* End of lines */ +/* these are used with DST_S_C_SOURCE */ +#define DST_S_C_SRC_DECLFILE 1 /* Declare source file */ +#define DST_S_C_SRC_SETFILE 2 /* Set source file */ +#define DST_S_C_SRC_SETREC_L 3 /* Set record, longword value */ +#define DST_S_C_SRC_SETREC_W 4 /* Set record, word value */ +#define DST_S_C_SRC_DEFLINES_W 10 /* # of line, word counter */ +#define DST_S_C_SRC_DEFLINES_B 11 /* # of line, byte counter */ +#define DST_S_C_SRC_FORMFEED 16 /* ^L counts as a record */ +/* the following are the codes for the various data types. Anything not on + * the list is included under 'advanced_type' + */ +#define DBG_S_C_UCHAR 0x02 +#define DBG_S_C_USINT 0x03 +#define DBG_S_C_ULINT 0x04 +#define DBG_S_C_UQUAD 0x05 +#define DBG_S_C_SCHAR 0x06 +#define DBG_S_C_SSINT 0x07 +#define DBG_S_C_SLINT 0x08 +#define DBG_S_C_SQUAD 0x09 +#define DBG_S_C_REAL4 0x0a +#define DBG_S_C_REAL8 0x0b /* D_float double */ +#define DBG_S_C_COMPLX4 0x0c /* 2xF_float complex float */ +#define DBG_S_C_COMPLX8 0x0d /* 2xD_float complex double */ +#define DBG_S_C_REAL8_G 0x1b /* G_float double */ +#define DBG_S_C_COMPLX8_G 0x1d /* 2xG_float complex double */ +#define DBG_S_C_FUNCTION_ADDR 0x17 +#define DBG_S_C_ADVANCED_TYPE 0xa3 +/* Some of these are just for future reference. [pr] + */ +#define DBG_S_C_UBITA 0x01 /* unsigned, aligned bit field */ +#define DBG_S_C_UBITU 0x22 /* unsigned, unaligned bit field */ +#define DBG_S_C_SBITA 0x29 /* signed, aligned bit field */ +#define DBG_S_C_SBITU 0x2a /* signed, unaligned bit field */ +#define DBG_S_C_CSTRING 0x2e /* asciz ('\0' terminated) string */ +#define DBG_S_C_WCHAR 0x38 /* wchar_t */ +/* These are descriptor class codes. + */ +#define DSC_K_CLASS_S 0x01 /* static (fixed length) */ +#define DSC_K_CLASS_D 0x02 /* dynamic string (not via malloc!) */ +#define DSC_K_CLASS_A 0x04 /* array */ +#define DSC_K_CLASS_UBS 0x0d /* unaligned bit string */ +/* These are the codes that are used to generate the definitions of struct + * union and enum records + */ +#define DBG_S_C_ENUM_ITEM 0xa4 +#define DBG_S_C_ENUM_START 0xa5 +#define DBG_S_C_ENUM_END 0xa6 +#define DBG_S_C_STRUCT_ITEM DST_K_VFLAGS_BITOFFS /* 0xff */ +#define DBG_S_C_STRUCT_START 0xab +#define DBG_S_C_STRUCT_END 0xac +#define DST_K_TYPSPEC 0xaf /* type specification */ +/* These codes are used in the generation of the symbol definition records + */ +#define DST_K_VFLAGS_NOVAL 0x80 /* struct definition only */ +#define DST_K_VFLAGS_DSC 0xfa /* descriptor used */ +#define DST_K_VFLAGS_TVS 0xfb /* trailing value specified */ +#define DST_K_VS_FOLLOWS 0xfd /* value spec follows */ +#define DST_K_VFLAGS_BITOFFS 0xff /* value contains bit offset */ +#define DST_K_VALKIND_LITERAL 0 +#define DST_K_VALKIND_ADDR 1 +#define DST_K_VALKIND_DESC 2 +#define DST_K_VALKIND_REG 3 +#define DST_K_REG_VAX_AP 0x0c /* R12 */ +#define DST_K_REG_VAX_FP 0x0d /* R13 */ +#define DST_K_REG_VAX_SP 0x0e /* R14 */ +#define DST_V_VALKIND 0 /* offset of valkind field */ +#define DST_V_INDIRECT 2 /* offset to indirect bit */ +#define DST_V_DISP 3 /* offset to displacement bit */ +#define DST_V_REGNUM 4 /* offset to register number */ +#define DST_M_INDIRECT (1< +#include "as.h" + +#include "opcode/a29k.h" + +/* Make it easier to clone this machine desc into another one. */ +#define machine_opcode a29k_opcode +#define machine_opcodes a29k_opcodes +#define machine_ip a29k_ip +#define machine_it a29k_it + +#define IMMEDIATE_BIT 0x01000000 /* Turns RB into Immediate */ +#define ABSOLUTE_BIT 0x01000000 /* Turns PC-relative to Absolute */ +#define CE_BIT 0x00800000 /* Coprocessor enable in LOAD */ +#define UI_BIT 0x00000080 /* Unsigned integer in CONVERT */ + +/* handle of the OPCODE hash table */ +static struct hash_control *op_hash = NULL; + +struct machine_it + { + char *error; + unsigned long opcode; + struct nlist *nlistp; + expressionS exp; + int pcrel; + int reloc_offset; /* Offset of reloc within insn */ + + int reloc; + } +the_insn; + +static void machine_ip PARAMS ((char *str)); +/* static void print_insn PARAMS ((struct machine_it *insn)); */ +#ifndef OBJ_COFF +static void s_data1 PARAMS ((void)); +static void s_use PARAMS ((int)); +#endif + +const pseudo_typeS +md_pseudo_table[] = +{ + {"align", s_align_bytes, 4}, + {"block", s_space, 0}, + {"cputype", s_ignore, 0}, /* CPU as 29000 or 29050 */ + {"reg", s_lsym, 0}, /* Register equate, same as equ */ + {"space", s_ignore, 0}, /* Listing control */ + {"sect", s_ignore, 0}, /* Creation of coff sections */ +#ifndef OBJ_COFF + /* We can do this right with coff. */ + {"use", s_use, 0}, +#endif + {"word", cons, 4}, + {NULL, 0, 0}, +}; + +int md_short_jump_size = 4; +int md_long_jump_size = 4; +#if defined(BFD_HEADERS) +#ifdef RELSZ +const int md_reloc_size = RELSZ; /* Coff headers */ +#else +const int md_reloc_size = 12; /* something else headers */ +#endif +#else +const int md_reloc_size = 12; /* Not bfdized*/ +#endif + +/* This array holds the chars that always start a comment. If the + pre-processor is disabled, these aren't very useful */ +const char comment_chars[] = ";"; + +/* This array holds the chars that only start a comment at the beginning of + a line. If the line seems to have the form '# 123 filename' + .line and .file directives will appear in the pre-processed output */ +/* Note that input_file.c hand checks for '#' at the beginning of the + first line of the input file. This is because the compiler outputs + #NO_APP at the beginning of its output. */ +/* Also note that comments like this one will always work */ +const char line_comment_chars[] = "#"; + +/* We needed an unused char for line separation to work around the + lack of macros, using sed and such. */ +const char line_separator_chars[] = "@"; + +/* Chars that can be used to separate mant from exp in floating point nums */ +const char EXP_CHARS[] = "eE"; + +/* Chars that mean this number is a floating point constant */ +/* As in 0f12.456 */ +/* or 0d1.2345e12 */ +const char FLT_CHARS[] = "rRsSfFdDxXpP"; + +/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be + changed in read.c. Ideally it shouldn't have to know about it at + all, but nothing is ideal around here. */ + +/* + * anull bit - causes the branch delay slot instructions to not be executed + */ +#define ANNUL (1 << 29) + +#ifndef OBJ_COFF + +static void +s_use (ignore) + int ignore; +{ + if (strncmp (input_line_pointer, ".text", 5) == 0) + { + input_line_pointer += 5; + s_text (0); + return; + } + if (strncmp (input_line_pointer, ".data", 5) == 0) + { + input_line_pointer += 5; + s_data (0); + return; + } + if (strncmp (input_line_pointer, ".data1", 6) == 0) + { + input_line_pointer += 6; + s_data1 (); + return; + } + /* Literals can't go in the text segment because you can't read from + instruction memory on some 29k's. So, into initialized data. */ + if (strncmp (input_line_pointer, ".lit", 4) == 0) + { + input_line_pointer += 4; + subseg_set (SEG_DATA, 200); + demand_empty_rest_of_line (); + return; + } + + as_bad ("Unknown segment type"); + demand_empty_rest_of_line (); +} + +static void +s_data1 () +{ + subseg_set (SEG_DATA, 1); + demand_empty_rest_of_line (); +} + +#endif /* OBJ_COFF */ + +/* Install symbol definition that maps REGNAME to REGNO. + FIXME-SOON: These are not recognized in mixed case. */ + +static void +insert_sreg (regname, regnum) + char *regname; + int regnum; +{ + /* FIXME-SOON, put something in these syms so they won't be output + to the symbol table of the resulting object file. */ + + /* Must be large enough to hold the names of the special registers. */ + char buf[80]; + int i; + + symbol_table_insert (symbol_new (regname, SEG_REGISTER, (valueT) regnum, + &zero_address_frag)); + for (i = 0; regname[i]; i++) + buf[i] = islower (regname[i]) ? toupper (regname[i]) : regname[i]; + buf[i] = '\0'; + + symbol_table_insert (symbol_new (buf, SEG_REGISTER, (valueT) regnum, + &zero_address_frag)); +} + +/* Install symbol definitions for assorted special registers. + See ASM29K Ref page 2-9. */ + +void +define_some_regs () +{ +#define SREG 256 + + /* Protected special-purpose register names */ + insert_sreg ("vab", SREG + 0); + insert_sreg ("ops", SREG + 1); + insert_sreg ("cps", SREG + 2); + insert_sreg ("cfg", SREG + 3); + insert_sreg ("cha", SREG + 4); + insert_sreg ("chd", SREG + 5); + insert_sreg ("chc", SREG + 6); + insert_sreg ("rbp", SREG + 7); + insert_sreg ("tmc", SREG + 8); + insert_sreg ("tmr", SREG + 9); + insert_sreg ("pc0", SREG + 10); + insert_sreg ("pc1", SREG + 11); + insert_sreg ("pc2", SREG + 12); + insert_sreg ("mmu", SREG + 13); + insert_sreg ("lru", SREG + 14); + + /* Additional protected special-purpose registers for the 29050 */ + insert_sreg ("rsn", SREG + 15); + insert_sreg ("rma0", SREG + 16); + insert_sreg ("rmc0", SREG + 17); + insert_sreg ("rma1", SREG + 18); + insert_sreg ("rmc1", SREG + 19); + insert_sreg ("spc0", SREG + 20); + insert_sreg ("spc1", SREG + 21); + insert_sreg ("spc2", SREG + 22); + insert_sreg ("iba0", SREG + 23); + insert_sreg ("ibc0", SREG + 24); + insert_sreg ("iba1", SREG + 25); + insert_sreg ("ibc1", SREG + 26); + + /* Additional registers for the 29040. */ + insert_sreg ("dba", SREG + 27); + insert_sreg ("dbc", SREG + 28); + insert_sreg ("cir", SREG + 29); + insert_sreg ("cdr", SREG + 30); + + /* Unprotected special-purpose register names */ + insert_sreg ("ipc", SREG + 128); + insert_sreg ("ipa", SREG + 129); + insert_sreg ("ipb", SREG + 130); + insert_sreg ("q", SREG + 131); + insert_sreg ("alu", SREG + 132); + insert_sreg ("bp", SREG + 133); + insert_sreg ("fc", SREG + 134); + insert_sreg ("cr", SREG + 135); + insert_sreg ("fpe", SREG + 160); + insert_sreg ("inte", SREG + 161); + insert_sreg ("fps", SREG + 162); + /* "", SREG+163); Reserved */ + insert_sreg ("exop", SREG + 164); +} + +/* This function is called once, at assembler startup time. It should + set up all the tables, etc., that the MD part of the assembler will + need. */ +void +md_begin () +{ + register const char *retval = NULL; + int lose = 0; + register int skipnext = 0; + register unsigned int i; + register char *strend, *strend2; + + /* Hash up all the opcodes for fast use later. */ + + op_hash = hash_new (); + + for (i = 0; i < num_opcodes; i++) + { + const char *name = machine_opcodes[i].name; + + if (skipnext) + { + skipnext = 0; + continue; + } + + /* Hack to avoid multiple opcode entries. We pre-locate all the + variations (b/i field and P/A field) and handle them. */ + + if (!strcmp (name, machine_opcodes[i + 1].name)) + { + if ((machine_opcodes[i].opcode & 0x01000000) != 0 + || (machine_opcodes[i + 1].opcode & 0x01000000) == 0 + || ((machine_opcodes[i].opcode | 0x01000000) + != machine_opcodes[i + 1].opcode)) + goto bad_table; + strend = machine_opcodes[i].args + strlen (machine_opcodes[i].args) - 1; + strend2 = machine_opcodes[i + 1].args + strlen (machine_opcodes[i + 1].args) - 1; + switch (*strend) + { + case 'b': + if (*strend2 != 'i') + goto bad_table; + break; + case 'P': + if (*strend2 != 'A') + goto bad_table; + break; + default: + bad_table: + fprintf (stderr, "internal error: can't handle opcode %s\n", + name); + lose = 1; + } + + /* OK, this is an i/b or A/P pair. We skip the + higher-valued one, and let the code for operand checking + handle OR-ing in the bit. */ + skipnext = 1; + } + + retval = hash_insert (op_hash, name, (PTR) &machine_opcodes[i]); + if (retval != NULL) + { + fprintf (stderr, "internal error: can't hash `%s': %s\n", + machine_opcodes[i].name, retval); + lose = 1; + } + } + + if (lose) + as_fatal ("Broken assembler. No assembly attempted."); + + define_some_regs (); +} + +/* Assemble a single instruction. Its label has already been handled + by the generic front end. We just parse opcode and operands, and + produce the bytes of data and relocation. */ + +void +md_assemble (str) + char *str; +{ + char *toP; + + know (str); + machine_ip (str); + toP = frag_more (4); + /* put out the opcode */ + md_number_to_chars (toP, the_insn.opcode, 4); + + /* put out the symbol-dependent stuff */ + if (the_insn.reloc != NO_RELOC) + { + fix_new_exp (frag_now, + (toP - frag_now->fr_literal + the_insn.reloc_offset), + 4, /* size */ + &the_insn.exp, + the_insn.pcrel, + the_insn.reloc); + } +} + +char * +parse_operand (s, operandp, opt) + char *s; + expressionS *operandp; + int opt; +{ + char *save = input_line_pointer; + char *new; + + input_line_pointer = s; + expression (operandp); + if (operandp->X_op == O_absent && ! opt) + as_bad ("missing operand"); + new = input_line_pointer; + input_line_pointer = save; + return new; +} + +/* Instruction parsing. Takes a string containing the opcode. + Operands are at input_line_pointer. Output is in the_insn. + Warnings or errors are generated. */ + +static void +machine_ip (str) + char *str; +{ + char *s; + const char *args; + struct machine_opcode *insn; + char *argsStart; + unsigned long opcode; + expressionS the_operand; + expressionS *operand = &the_operand; + unsigned int reg; + + /* Must handle `div0' opcode. */ + s = str; + if (isalpha (*s)) + for (; isalnum (*s); ++s) + if (isupper (*s)) + *s = tolower (*s); + + switch (*s) + { + case '\0': + break; + + case ' ': /* FIXME-SOMEDAY more whitespace */ + *s++ = '\0'; + break; + + default: + as_bad ("Unknown opcode: `%s'", str); + return; + } + if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL) + { + as_bad ("Unknown opcode `%s'.", str); + return; + } + argsStart = s; + opcode = insn->opcode; + memset (&the_insn, '\0', sizeof (the_insn)); + the_insn.reloc = NO_RELOC; + + /* Build the opcode, checking as we go to make sure that the + operands match. + + If an operand matches, we modify the_insn or opcode appropriately, + and do a "continue". If an operand fails to match, we "break". */ + + if (insn->args[0] != '\0') + { + /* Prime the pump. */ + s = parse_operand (s, operand, insn->args[0] == 'I'); + } + + for (args = insn->args;; ++args) + { + switch (*args) + { + + case '\0': /* end of args */ + if (*s == '\0') + { + /* We are truly done. */ + the_insn.opcode = opcode; + return; + } + as_bad ("Too many operands: %s", s); + break; + + case ',': /* Must match a comma */ + if (*s++ == ',') + { + /* Parse next operand. */ + s = parse_operand (s, operand, args[1] == 'I'); + continue; + } + break; + + case 'v': /* Trap numbers (immediate field) */ + if (operand->X_op == O_constant) + { + if (operand->X_add_number < 256) + { + opcode |= (operand->X_add_number << 16); + continue; + } + else + { + as_bad ("Immediate value of %ld is too large", + (long) operand->X_add_number); + continue; + } + } + the_insn.reloc = RELOC_8; + the_insn.reloc_offset = 1; /* BIG-ENDIAN Byte 1 of insn */ + the_insn.exp = *operand; + continue; + + case 'b': /* A general register or 8-bit immediate */ + case 'i': + /* We treat the two cases identically since we mashed + them together in the opcode table. */ + if (operand->X_op == O_register) + goto general_reg; + + /* Make sure the 'i' case really exists. */ + if ((insn->opcode | IMMEDIATE_BIT) != (insn + 1)->opcode) + break; + + opcode |= IMMEDIATE_BIT; + if (operand->X_op == O_constant) + { + if (operand->X_add_number < 256) + { + opcode |= operand->X_add_number; + continue; + } + else + { + as_bad ("Immediate value of %ld is too large", + (long) operand->X_add_number); + continue; + } + } + the_insn.reloc = RELOC_8; + the_insn.reloc_offset = 3; /* BIG-ENDIAN Byte 3 of insn */ + the_insn.exp = *operand; + continue; + + case 'a': /* next operand must be a register */ + case 'c': + general_reg: + /* lrNNN or grNNN or %%expr or a user-def register name */ + if (operand->X_op != O_register) + break; /* Only registers */ + know (operand->X_add_symbol == 0); + know (operand->X_op_symbol == 0); + reg = operand->X_add_number; + if (reg >= SREG) + break; /* No special registers */ + + /* Got the register, now figure out where it goes in the + opcode. */ + switch (*args) + { + case 'a': + opcode |= reg << 8; + continue; + + case 'b': + case 'i': + opcode |= reg; + continue; + + case 'c': + opcode |= reg << 16; + continue; + } + as_fatal ("failed sanity check."); + break; + + case 'x': /* 16 bit constant, zero-extended */ + case 'X': /* 16 bit constant, one-extended */ + if (operand->X_op == O_constant) + { + opcode |= (operand->X_add_number & 0xFF) << 0 | + ((operand->X_add_number & 0xFF00) << 8); + continue; + } + the_insn.reloc = RELOC_CONST; + the_insn.exp = *operand; + continue; + + case 'h': + if (operand->X_op == O_constant) + { + opcode |= (operand->X_add_number & 0x00FF0000) >> 16 | + (((unsigned long) operand->X_add_number + /* avoid sign ext */ & 0xFF000000) >> 8); + continue; + } + the_insn.reloc = RELOC_CONSTH; + the_insn.exp = *operand; + continue; + + case 'P': /* PC-relative jump address */ + case 'A': /* Absolute jump address */ + /* These two are treated together since we folded the + opcode table entries together. */ + if (operand->X_op == O_constant) + { + /* Make sure the 'A' case really exists. */ + if ((insn->opcode | ABSOLUTE_BIT) != (insn + 1)->opcode) + break; + { + bfd_vma v, mask; + mask = 0x1ffff; + v = operand->X_add_number & ~ mask; + if (v) + as_bad ("call/jmp target out of range"); + } + opcode |= ABSOLUTE_BIT | + (operand->X_add_number & 0x0003FC00) << 6 | + ((operand->X_add_number & 0x000003FC) >> 2); + continue; + } + the_insn.reloc = RELOC_JUMPTARG; + the_insn.exp = *operand; + the_insn.pcrel = 1; /* Assume PC-relative jump */ + /* FIXME-SOON, Do we figure out whether abs later, after + know sym val? */ + continue; + + case 'e': /* Coprocessor enable bit for LOAD/STORE insn */ + if (operand->X_op == O_constant) + { + if (operand->X_add_number == 0) + continue; + if (operand->X_add_number == 1) + { + opcode |= CE_BIT; + continue; + } + } + break; + + case 'n': /* Control bits for LOAD/STORE instructions */ + if (operand->X_op == O_constant && + operand->X_add_number < 128) + { + opcode |= (operand->X_add_number << 16); + continue; + } + break; + + case 's': /* Special register number */ + if (operand->X_op != O_register) + break; /* Only registers */ + if (operand->X_add_number < SREG) + break; /* Not a special register */ + opcode |= (operand->X_add_number & 0xFF) << 8; + continue; + + case 'u': /* UI bit of CONVERT */ + if (operand->X_op == O_constant) + { + if (operand->X_add_number == 0) + continue; + if (operand->X_add_number == 1) + { + opcode |= UI_BIT; + continue; + } + } + break; + + case 'r': /* RND bits of CONVERT */ + if (operand->X_op == O_constant && + operand->X_add_number < 8) + { + opcode |= operand->X_add_number << 4; + continue; + } + break; + + case 'I': /* ID bits of INV and IRETINV. */ + /* This operand is optional. */ + if (operand->X_op == O_absent) + continue; + else if (operand->X_op == O_constant + && operand->X_add_number < 4) + { + opcode |= operand->X_add_number << 16; + continue; + } + break; + + case 'd': /* FD bits of CONVERT */ + if (operand->X_op == O_constant && + operand->X_add_number < 4) + { + opcode |= operand->X_add_number << 2; + continue; + } + break; + + + case 'f': /* FS bits of CONVERT */ + if (operand->X_op == O_constant && + operand->X_add_number < 4) + { + opcode |= operand->X_add_number << 0; + continue; + } + break; + + case 'C': + if (operand->X_op == O_constant && + operand->X_add_number < 4) + { + opcode |= operand->X_add_number << 16; + continue; + } + break; + + case 'F': + if (operand->X_op == O_constant && + operand->X_add_number < 16) + { + opcode |= operand->X_add_number << 18; + continue; + } + break; + + default: + BAD_CASE (*args); + } + /* Types or values of args don't match. */ + as_bad ("Invalid operands"); + return; + } +} + +/* This is identical to the md_atof in m68k.c. I think this is right, + but I'm not sure. + + Turn a string in input_line_pointer into a floating point constant + of type type, and store the appropriate bytes in *litP. The number + of LITTLENUMS emitted is stored in *sizeP . An error message is + returned, or NULL on OK. */ + +/* Equal to MAX_PRECISION in atof-ieee.c */ +#define MAX_LITTLENUMS 6 + +char * +md_atof (type, litP, sizeP) + char type; + char *litP; + int *sizeP; +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + + switch (type) + { + + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return "Bad call to MD_ATOF()"; + } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + *sizeP = prec * sizeof (LITTLENUM_TYPE); + for (wordP = words; prec--;) + { + md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + return 0; +} + +/* + * Write out big-endian. + */ +void +md_number_to_chars (buf, val, n) + char *buf; + valueT val; + int n; +{ + number_to_chars_bigendian (buf, val, n); +} + +void +md_apply_fix (fixP, val) + fixS *fixP; + long val; +{ + char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; + + fixP->fx_addnumber = val; /* Remember value for emit_reloc */ + + + know (fixP->fx_size == 4); + know (fixP->fx_r_type < NO_RELOC); + + /* This is a hack. There should be a better way to handle this. */ + if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) + { + val += fixP->fx_where + fixP->fx_frag->fr_address; + } + + switch (fixP->fx_r_type) + { + + case RELOC_32: + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val; + break; + + case RELOC_8: + buf[0] = val; + break; + + case RELOC_WDISP30: + val = (val >>= 2) + 1; + buf[0] |= (val >> 24) & 0x3f; + buf[1] = (val >> 16); + buf[2] = val >> 8; + buf[3] = val; + break; + + case RELOC_HI22: + buf[1] |= (val >> 26) & 0x3f; + buf[2] = val >> 18; + buf[3] = val >> 10; + break; + + case RELOC_LO10: + buf[2] |= (val >> 8) & 0x03; + buf[3] = val; + break; + + case RELOC_BASE13: + buf[2] |= (val >> 8) & 0x1f; + buf[3] = val; + break; + + case RELOC_WDISP22: + val = (val >>= 2) + 1; + /* FALLTHROUGH */ + case RELOC_BASE22: + buf[1] |= (val >> 16) & 0x3f; + buf[2] = val >> 8; + buf[3] = val; + break; + + case RELOC_JUMPTARG: /* 00XX00XX pattern in a word */ + if (!fixP->fx_done) + { + /* The linker tries to support both AMD and old GNU style + R_IREL relocs. That means that if the addend is exactly + the negative of the address within the section, the + linker will not handle it correctly. */ + if (fixP->fx_pcrel + && val != 0 + && val == - (fixP->fx_frag->fr_address + fixP->fx_where)) + as_bad_where + (fixP->fx_file, fixP->fx_line, + "the linker will not handle this relocation correctly"); + } + else if (fixP->fx_pcrel) + { + long v = val >> 17; + if (v != 0 && v != -1) + as_bad_where (fixP->fx_file, fixP->fx_line, + "call/jmp target out of range"); + } + else + /* this case was supposed to be handled in machine_ip */ + abort (); + buf[1] = val >> 10; /* Holds bits 0003FFFC of address */ + buf[3] = val >> 2; + break; + + case RELOC_CONST: /* 00XX00XX pattern in a word */ + buf[1] = val >> 8; /* Holds bits 0000XXXX */ + buf[3] = val; + break; + + case RELOC_CONSTH: /* 00XX00XX pattern in a word */ + buf[1] = val >> 24; /* Holds bits XXXX0000 */ + buf[3] = val >> 16; + break; + + case NO_RELOC: + default: + as_bad ("bad relocation type: 0x%02x", fixP->fx_r_type); + break; + } +} + +#ifdef OBJ_COFF +short +tc_coff_fix2rtype (fixP) + fixS *fixP; +{ + + switch (fixP->fx_r_type) + { + case RELOC_32: + return (R_WORD); + case RELOC_8: + return (R_BYTE); + case RELOC_CONST: + return (R_ILOHALF); + case RELOC_CONSTH: + return (R_IHIHALF); + case RELOC_JUMPTARG: + return (R_IREL); + default: + printf ("need %o3\n", fixP->fx_r_type); + abort (); + } /* switch on type */ + + return (0); +} + +#endif /* OBJ_COFF */ + +/* should never be called for 29k */ +void +md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + as_fatal ("a29k_create_short_jmp\n"); +} + +/* should never be called for 29k */ +void +md_convert_frag (headers, seg, fragP) + object_headers *headers; + segT seg; + register fragS *fragP; +{ + as_fatal ("a29k_convert_frag\n"); +} + +/* should never be called for 29k */ +void +md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr; + addressT to_addr; + fragS *frag; + symbolS *to_symbol; +{ + as_fatal ("a29k_create_long_jump\n"); +} + +/* should never be called for a29k */ +int +md_estimate_size_before_relax (fragP, segtype) + register fragS *fragP; + segT segtype; +{ + as_fatal ("a29k_estimate_size_before_relax\n"); + return 0; +} + +#if 0 +/* for debugging only */ +static void +print_insn (insn) + struct machine_it *insn; +{ + char *Reloc[] = + { + "RELOC_8", + "RELOC_16", + "RELOC_32", + "RELOC_DISP8", + "RELOC_DISP16", + "RELOC_DISP32", + "RELOC_WDISP30", + "RELOC_WDISP22", + "RELOC_HI22", + "RELOC_22", + "RELOC_13", + "RELOC_LO10", + "RELOC_SFA_BASE", + "RELOC_SFA_OFF13", + "RELOC_BASE10", + "RELOC_BASE13", + "RELOC_BASE22", + "RELOC_PC10", + "RELOC_PC22", + "RELOC_JMP_TBL", + "RELOC_SEGOFF16", + "RELOC_GLOB_DAT", + "RELOC_JMP_SLOT", + "RELOC_RELATIVE", + "NO_RELOC" + }; + + if (insn->error) + { + fprintf (stderr, "ERROR: %s\n"); + } + fprintf (stderr, "opcode=0x%08x\n", insn->opcode); + fprintf (stderr, "reloc = %s\n", Reloc[insn->reloc]); + fprintf (stderr, "exp = {\n"); + fprintf (stderr, "\t\tX_add_symbol = %s\n", + insn->exp.X_add_symbol ? + (S_GET_NAME (insn->exp.X_add_symbol) ? + S_GET_NAME (insn->exp.X_add_symbol) : "???") : "0"); + fprintf (stderr, "\t\tX_op_symbol = %s\n", + insn->exp.X_op_symbol ? + (S_GET_NAME (insn->exp.X_op_symbol) ? + S_GET_NAME (insn->exp.X_op_symbol) : "???") : "0"); + fprintf (stderr, "\t\tX_add_number = %d\n", + insn->exp.X_add_number); + fprintf (stderr, "}\n"); +} + +#endif + +/* Translate internal representation of relocation info to target format. + + On sparc/29k: first 4 bytes are normal unsigned long address, next three + bytes are index, most sig. byte first. Byte 7 is broken up with + bit 7 as external, bits 6 & 5 unused, and the lower + five bits as relocation type. Next 4 bytes are long addend. */ +/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ + +#ifdef OBJ_AOUT + +void +tc_aout_fix_to_chars (where, fixP, segment_address_in_file) + char *where; + fixS *fixP; + relax_addressT segment_address_in_file; +{ + long r_symbolnum; + + know (fixP->fx_r_type < NO_RELOC); + know (fixP->fx_addsy != NULL); + + md_number_to_chars (where, + fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, + 4); + + r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) + ? S_GET_TYPE (fixP->fx_addsy) + : fixP->fx_addsy->sy_number); + + where[4] = (r_symbolnum >> 16) & 0x0ff; + where[5] = (r_symbolnum >> 8) & 0x0ff; + where[6] = r_symbolnum & 0x0ff; + where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F); + /* Also easy */ + md_number_to_chars (&where[8], fixP->fx_addnumber, 4); +} + +#endif /* OBJ_AOUT */ + +CONST char *md_shortopts = ""; +struct option md_longopts[] = { + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof(md_longopts); + +int +md_parse_option (c, arg) + int c; + char *arg; +{ + return 0; +} + +void +md_show_usage (stream) + FILE *stream; +{ +} + +/* Default the values of symbols known that should be "predefined". We + don't bother to predefine them unless you actually use one, since there + are a lot of them. */ + +symbolS * +md_undefined_symbol (name) + char *name; +{ + long regnum; + char testbuf[5 + /*SLOP*/ 5]; + + if (name[0] == 'g' || name[0] == 'G' + || name[0] == 'l' || name[0] == 'L' + || name[0] == 's' || name[0] == 'S') + { + /* Perhaps a global or local register name */ + if (name[1] == 'r' || name[1] == 'R') + { + long maxreg; + + /* Parse the number, make sure it has no extra zeroes or + trailing chars. */ + regnum = atol (&name[2]); + + if (name[0] == 's' || name[0] == 'S') + maxreg = 255; + else + maxreg = 127; + if (regnum > maxreg) + return NULL; + + sprintf (testbuf, "%ld", regnum); + if (strcmp (testbuf, &name[2]) != 0) + return NULL; /* gr007 or lr7foo or whatever */ + + /* We have a wiener! Define and return a new symbol for it. */ + if (name[0] == 'l' || name[0] == 'L') + regnum += 128; + else if (name[0] == 's' || name[0] == 'S') + regnum += SREG; + return (symbol_new (name, SEG_REGISTER, (valueT) regnum, + &zero_address_frag)); + } + } + + return NULL; +} + +/* Parse an operand that is machine-specific. */ + +void +md_operand (expressionP) + expressionS *expressionP; +{ + + if (input_line_pointer[0] == '%' && input_line_pointer[1] == '%') + { + /* We have a numeric register expression. No biggy. */ + input_line_pointer += 2; /* Skip %% */ + (void) expression (expressionP); + if (expressionP->X_op != O_constant + || expressionP->X_add_number > 255) + as_bad ("Invalid expression after %%%%\n"); + expressionP->X_op = O_register; + } + else if (input_line_pointer[0] == '&') + { + /* We are taking the 'address' of a register...this one is not + in the manual, but it *is* in traps/fpsymbol.h! What they + seem to want is the register number, as an absolute number. */ + input_line_pointer++; /* Skip & */ + (void) expression (expressionP); + if (expressionP->X_op != O_register) + as_bad ("Invalid register in & expression"); + else + expressionP->X_op = O_constant; + } + else if (input_line_pointer[0] == '$') + { + char *s; + char type; + int fieldnum, fieldlimit; + LITTLENUM_TYPE floatbuf[8]; + + /* $float(), $doubleN(), or $extendN() convert floating values + to integers. */ + + s = input_line_pointer; + + ++s; + + fieldnum = 0; + if (strncmp (s, "double", sizeof "double" - 1) == 0) + { + s += sizeof "double" - 1; + type = 'd'; + fieldlimit = 2; + } + else if (strncmp (s, "float", sizeof "float" - 1) == 0) + { + s += sizeof "float" - 1; + type = 'f'; + fieldlimit = 1; + } + else if (strncmp (s, "extend", sizeof "extend" - 1) == 0) + { + s += sizeof "extend" - 1; + type = 'x'; + fieldlimit = 4; + } + else + { + /* FIXME: We should handle a29k local labels here. */ + return; + } + + if (isdigit (*s)) + { + fieldnum = *s - '0'; + ++s; + } + if (fieldnum >= fieldlimit) + return; + + SKIP_WHITESPACE (); + if (*s != '(') + return; + ++s; + SKIP_WHITESPACE (); + + s = atof_ieee (s, type, floatbuf); + if (s == NULL) + return; + s = s; + + SKIP_WHITESPACE (); + if (*s != ')') + return; + ++s; + SKIP_WHITESPACE (); + + input_line_pointer = s; + expressionP->X_op = O_constant; + expressionP->X_unsigned = 1; + expressionP->X_add_number = ((floatbuf[fieldnum * 2] + << LITTLENUM_NUMBER_OF_BITS) + + floatbuf[fieldnum * 2 + 1]); + } +} + +/* Round up a section size to the appropriate boundary. */ +valueT +md_section_align (segment, size) + segT segment; + valueT size; +{ + return size; /* Byte alignment is fine */ +} + +/* Exactly what point is a PC-relative offset relative TO? + On the 29000, they're relative to the address of the instruction, + which we have set up as the address of the fixup too. */ +long +md_pcrel_from (fixP) + fixS *fixP; +{ + return fixP->fx_where + fixP->fx_frag->fr_address; +} + +/* end of tc-a29k.c */ diff --git a/gnu/usr.bin/binutils/gas/config/tc-a29k.h b/gnu/usr.bin/binutils/gas/config/tc-a29k.h new file mode 100644 index 00000000000..1c36f07fc99 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-a29k.h @@ -0,0 +1,48 @@ +/* tc-a29k.h -- Assemble for the AMD 29000. + Copyright (C) 1989, 1990, 1991 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 2, 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. */ + +#define TC_A29K + +#define TARGET_BYTES_BIG_ENDIAN 1 + +#define LEX_DOLLAR 1 + +#define tc_headers_hook(a) ; /* not used */ +#define tc_headers_hook(a) ; /* not used */ +#define tc_crawl_symbol_chain(a) ; /* not used */ +#define tc_coff_symbol_emit_hook(a) ; /* not used */ + +#define AOUT_MACHTYPE 101 +#define TC_COFF_FIX2RTYPE(fix_ptr) tc_coff_fix2rtype(fix_ptr) +#define BFD_ARCH bfd_arch_a29k +#define COFF_MAGIC SIPFBOMAGIC +/* Should the reloc be output ? + on the 29k, this is true only if there is a symbol attatched. + on the h8, this is allways true, since no fixup is done +*/ +#define TC_COUNT_RELOC(x) (x->fx_addsy) +#define TC_CONS_RELOC RELOC_32 + +#define COFF_FLAGS F_AR32W +#define reloc_type int +#define NEED_FX_R_TYPE + +#define ZERO_BASED_SEGMENTS + +/* end of tc-a29k.h */ diff --git a/gnu/usr.bin/binutils/gas/config/tc-alpha.c b/gnu/usr.bin/binutils/gas/config/tc-alpha.c new file mode 100644 index 00000000000..728fed5b562 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-alpha.c @@ -0,0 +1,2741 @@ +/* tc-alpha.c - Processor-specific code for the DEC Alpha CPU. + Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc. + Contributed by Carnegie Mellon University, 1993. + Written by Alessandro Forin, based on earlier gas-1.38 target CPU files. + Modified by Ken Raeburn for gas-2.x and ECOFF support. + + 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 2, 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. */ + +/* + * Mach Operating System + * Copyright (c) 1993 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 + * 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 the + * rights to redistribute these changes. + */ +/* + * HISTORY + * 5-Oct-93 Alessandro Forin (af) at Carnegie-Mellon University + * First Checkin + * + * Author: Alessandro Forin, Carnegie Mellon University + * Date: Jan 1993 + */ + +#include + +#include "as.h" +#include "alpha-opcode.h" +#include "subsegs.h" + +/* The OSF/1 V2.0 Alpha compiler can't compile this file with inline + functions. */ +#ifndef __GNUC__ +#undef inline +#define inline +#endif + +/* @@ Will a simple 0x8000 work here? If not, why not? */ +#define GP_ADJUSTMENT (0x8000 - 0x10) + +/* These are exported to relaxing code, even though we don't do any + relaxing on this processor currently. */ +int md_short_jump_size = 4; +int md_long_jump_size = 4; + +/* handle of the OPCODE hash table */ +static struct hash_control *op_hash; + +/* Sections and symbols we'll want to keep track of. */ +static segT lita_sec, rdata, sdata, lit8_sec, lit4_sec; +static symbolS *lit8_sym, *lit4_sym; + +/* Setting for ".set [no]{at,macro}". */ +static int at_ok = 1, macro_ok = 1; + +/* Keep track of global pointer. */ +valueT alpha_gp_value; +static symbolS *gp; + +/* We'll probably be using this relocation frequently, and we + will want to compare for it. */ +static reloc_howto_type *gpdisp_hi16_howto; + +/* These are exported to ECOFF code. */ +unsigned long alpha_gprmask, alpha_fprmask; + +/* Used for LITUSE relocations. */ +static expressionS lituse_basereg, lituse_byteoff, lituse_jsr; + +/* Address size: In OSF/1 1.3, an undocumented "-32addr" option will + cause all addresses to be treated as 32-bit values in memory. (The + in-register versions are all sign-extended to 64 bits, of course.) + Some other systems may want this option too. */ +static int addr32; + +/* Symbol labelling the current insn. When the Alpha gas sees + foo: + .quad 0 + and the section happens to not be on an eight byte boundary, it + will align both the symbol and the .quad to an eight byte boundary. */ +static symbolS *insn_label; + +/* Whether we should automatically align data generation pseudo-ops. + .align 0 will turn this off. */ +static int auto_align = 1; + +/* Imported functions -- they should be defined in header files somewhere. */ +extern segT subseg_get (); +extern PTR bfd_alloc_by_size_t (); +extern void s_globl (), s_long (), s_short (), s_space (), cons (), s_text (), + s_data (), float_cons (); + +/* Static functions, needing forward declarations. */ +static void s_base (), s_proc (), s_alpha_set (); +static void s_gprel32 (), s_rdata (), s_sdata (), s_alpha_comm (); +static void s_alpha_text PARAMS ((int)); +static void s_alpha_data PARAMS ((int)); +static void s_alpha_align PARAMS ((int)); +static void s_alpha_cons PARAMS ((int)); +static void s_alpha_float_cons PARAMS ((int)); +static int alpha_ip (); + +static void emit_unaligned_io PARAMS ((char *, int, valueT, int)); +static void emit_load_unal PARAMS ((int, valueT, int)); +static void emit_store_unal PARAMS ((int, valueT, int)); +static void emit_byte_manip_r PARAMS ((char *, int, int, int, int, int)); +static void emit_extract_r PARAMS ((int, int, int, int, int)); +static void emit_insert_r PARAMS ((int, int, int, int, int)); +static void emit_mask_r PARAMS ((int, int, int, int, int)); +static void emit_sign_extend PARAMS ((int, int)); +static void emit_bis_r PARAMS ((int, int, int)); +static int build_mem PARAMS ((int, int, int, bfd_signed_vma)); +static int build_operate_n PARAMS ((int, int, int, int, int)); +static void emit_sll_n PARAMS ((int, int, int)); +static void emit_ldah_num PARAMS ((int, bfd_vma, int)); +static void emit_addq_r PARAMS ((int, int, int)); +static void emit_lda_n PARAMS ((int, bfd_vma, int)); +static void emit_add64 PARAMS ((int, int, bfd_vma)); +static int in_range_signed PARAMS ((bfd_vma, int)); +static void alpha_align PARAMS ((int, int, symbolS *)); + +const pseudo_typeS md_pseudo_table[] = +{ + {"common", s_comm, 0}, /* is this used? */ + {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */ + {"text", s_alpha_text, 0}, + {"data", s_alpha_data, 0}, + {"rdata", s_rdata, 0}, + {"sdata", s_sdata, 0}, + {"gprel32", s_gprel32, 0}, + {"t_floating", s_alpha_float_cons, 'd'}, + {"s_floating", s_alpha_float_cons, 'f'}, + {"f_floating", s_alpha_float_cons, 'F'}, + {"g_floating", s_alpha_float_cons, 'G'}, + {"d_floating", s_alpha_float_cons, 'D'}, + + {"proc", s_proc, 0}, + {"aproc", s_proc, 1}, + {"set", s_alpha_set, 0}, + {"reguse", s_ignore, 0}, + {"livereg", s_ignore, 0}, + {"base", s_base, 0}, /*??*/ + {"option", s_ignore, 0}, + {"prologue", s_ignore, 0}, + {"aent", s_ignore, 0}, + {"ugen", s_ignore, 0}, + + {"align", s_alpha_align, 0}, + {"byte", s_alpha_cons, 0}, + {"hword", s_alpha_cons, 1}, + {"int", s_alpha_cons, 2}, + {"long", s_alpha_cons, 2}, + {"octa", s_alpha_cons, 4}, + {"quad", s_alpha_cons, 3}, + {"short", s_alpha_cons, 1}, + {"word", s_alpha_cons, 1}, + {"double", s_alpha_float_cons, 'd'}, + {"float", s_alpha_float_cons, 'f'}, + {"single", s_alpha_float_cons, 'f'}, + +/* We don't do any optimizing, so we can safely ignore these. */ + {"noalias", s_ignore, 0}, + {"alias", s_ignore, 0}, + + {NULL, 0, 0}, +}; + +#define SA 21 /* shift for register Ra */ +#define SB 16 /* shift for register Rb */ +#define SC 0 /* shift for register Rc */ +#define SN 13 /* shift for 8 bit immediate # */ + +#define T9 23 +#define T10 24 +#define T11 25 +#define T12 26 +#define RA 26 /* note: same as T12 */ +#define PV 27 +#define AT 28 +#define GP 29 +#define SP 30 +#define ZERO 31 + +#define OPCODE(X) (((X) >> 26) & 0x3f) +#define OP_FCN(X) (((X) >> 5) & 0x7f) + +#ifndef FIRST_32BIT_QUADRANT +#define FIRST_32BIT_QUADRANT 0 +#endif + +int first_32bit_quadrant = FIRST_32BIT_QUADRANT; +int base_register = FIRST_32BIT_QUADRANT ? ZERO : GP; + +int no_mixed_code = 0; +int nofloats = 0; + +/* This array holds the chars that always start a comment. If the + pre-processor is disabled, these aren't very useful */ +const char comment_chars[] = "#"; + +/* This array holds the chars that only start a comment at the beginning of + a line. If the line seems to have the form '# 123 filename' + .line and .file directives will appear in the pre-processed output */ +/* Note that input_file.c hand checks for '#' at the beginning of the + first line of the input file. This is because the compiler outputs + #NO_APP at the beginning of its output. */ +/* Also note that C style comments are always recognized. */ +const char line_comment_chars[] = "#!"; + +/* Chars that can be used to separate mant from exp in floating point nums */ +const char EXP_CHARS[] = "eE"; + +const char line_separator_chars[1]; + +/* Chars that mean this number is a floating point constant, as in + "0f12.456" or "0d1.2345e12". */ +/* @@ Do all of these really get used on the alpha?? */ +char FLT_CHARS[] = "rRsSfFdDxXpP"; + +/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be + changed in read.c. Ideally it shouldn't have to know about it at all, + but nothing is ideal around here. */ + +struct reloc_data { + expressionS exp; + int pcrel; + bfd_reloc_code_real_type code; +}; + +/* Occasionally, two relocations will be desired for one address. + Mainly only in cases like "jsr $r,foo" where we want both a LITUSE + and a HINT reloc. */ +#define MAX_RELOCS 2 + +struct alpha_it { + unsigned long opcode; /* need at least 32 bits */ + struct reloc_data reloc[MAX_RELOCS]; +}; + +static void getExpression (char *str, struct alpha_it *insn); +static char *expr_end; + +#define note_gpreg(R) (alpha_gprmask |= (1 << (R))) +#define note_fpreg(R) (alpha_fprmask |= (1 << (R))) + +int +tc_get_register (frame) + int frame; +{ + int framereg = SP; + + SKIP_WHITESPACE (); + if (*input_line_pointer == '$') + { + input_line_pointer++; + if (input_line_pointer[0] == 's' + && input_line_pointer[1] == 'p') + { + input_line_pointer += 2; + framereg = SP; + } + else + framereg = get_absolute_expression (); + framereg &= 31; /* ? */ + } + else + as_warn ("frame reg expected, using $%d.", framereg); + + note_gpreg (framereg); + return framereg; +} + +/* Handle the .text pseudo-op. This is like the usual one, but it + clears insn_label and restores auto alignment. */ + +static void +s_alpha_text (i) + int i; +{ + s_text (i); + insn_label = NULL; + auto_align = 1; +} + +/* Handle the .data pseudo-op. This is like the usual one, but it + clears insn_label and restores auto alignment. */ + +static void +s_alpha_data (i) + int i; +{ + s_data (i); + insn_label = NULL; + auto_align = 1; +} + +static void +s_rdata (ignore) + int ignore; +{ + int temp; + + temp = get_absolute_expression (); +#if 0 + if (!rdata) + rdata = subseg_get (".rdata", 0); + subseg_set (rdata, (subsegT) temp); +#else + rdata = subseg_new (".rdata", 0); +#endif + demand_empty_rest_of_line (); + insn_label = NULL; + auto_align = 1; +} + +static void +s_sdata (ignore) + int ignore; +{ + int temp; + + temp = get_absolute_expression (); +#if 0 + if (!sdata) + sdata = subseg_get (".sdata", 0); + subseg_set (sdata, (subsegT) temp); +#else + sdata = subseg_new (".sdata", 0); +#endif + demand_empty_rest_of_line (); + insn_label = NULL; + auto_align = 1; +} + +static void +s_alpha_comm (ignore) + int ignore; +{ + register char *name; + register char c; + register char *p; + offsetT temp; + register symbolS *symbolP; + + name = input_line_pointer; + c = get_symbol_end (); + /* just after name is now '\0' */ + p = input_line_pointer; + *p = c; + SKIP_WHITESPACE (); + /* Alpha OSF/1 compiler doesn't provide the comma, gcc does. */ + if (*input_line_pointer == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + } + if ((temp = get_absolute_expression ()) < 0) + { + as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp); + ignore_rest_of_line (); + return; + } + *p = 0; + symbolP = symbol_find_or_make (name); + *p = c; + if (S_IS_DEFINED (symbolP)) + { + as_bad ("Ignoring attempt to re-define symbol"); + ignore_rest_of_line (); + return; + } + if (S_GET_VALUE (symbolP)) + { + if (S_GET_VALUE (symbolP) != (valueT) temp) + as_bad ("Length of .comm \"%s\" is already %ld. Not changed to %ld.", + S_GET_NAME (symbolP), + (long) S_GET_VALUE (symbolP), + (long) temp); + } + else + { + S_SET_VALUE (symbolP, (valueT) temp); + S_SET_EXTERNAL (symbolP); + } + + know (symbolP->sy_frag == &zero_address_frag); + demand_empty_rest_of_line (); +} + +arelent * +tc_gen_reloc (sec, fixp) + asection *sec; + fixS *fixp; +{ + arelent *reloc; + + reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent)); + reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + + if (fixp->fx_r_type > BFD_RELOC_UNUSED) + abort (); + + if (fixp->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16) + { + if (!gpdisp_hi16_howto) + gpdisp_hi16_howto = bfd_reloc_type_lookup (stdoutput, + fixp->fx_r_type); + reloc->howto = gpdisp_hi16_howto; + } + else + reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); + assert (reloc->howto != 0); + if (!fixp->fx_pcrel != !reloc->howto->pc_relative) + { + as_fatal ("internal error? cannot generate `%s' relocation", + bfd_get_reloc_code_name (fixp->fx_r_type)); + } + assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); + + if (fixp->fx_r_type == BFD_RELOC_ALPHA_LITERAL) + { + /* fake out bfd_perform_relocation. sigh */ + reloc->addend = -alpha_gp_value; + } + else if (reloc->howto->pc_relative && reloc->howto->pcrel_offset) + { + reloc->addend = fixp->fx_offset - reloc->address; + } + else + reloc->addend = fixp->fx_offset; + return reloc; +} + +static void +s_base () +{ + if (first_32bit_quadrant) + { + /* not fatal, but it might not work in the end */ + as_warn ("File overrides no-base-register option."); + first_32bit_quadrant = 0; + } + + SKIP_WHITESPACE (); + if (*input_line_pointer == '$') + { /* $rNN form */ + input_line_pointer++; + if (*input_line_pointer == 'r') + input_line_pointer++; + } + + base_register = get_absolute_expression (); + if (base_register < 0 || base_register > 31) + { + base_register = GP; + as_warn ("Bad base register, using $%d.", base_register); + } + demand_empty_rest_of_line (); +} + +static int in_range_signed (val, nbits) + bfd_vma val; + int nbits; +{ + /* Look at top bit of value that would be stored, figure out how it + would be extended by the hardware, and see if that matches the + original supplied value. */ + bfd_vma mask; + bfd_vma one = 1; + bfd_vma top_bit, stored_value, missing_bits; + + mask = (one << nbits) - 1; + stored_value = val & mask; + top_bit = stored_value & (one << (nbits - 1)); + missing_bits = val & ~mask; + /* will sign-extend */ + if (top_bit) + { + /* all remaining bits beyond mask should be one */ + missing_bits |= mask; + return missing_bits + 1 == 0; + } + else + { + /* all other bits should be zero */ + return missing_bits == 0; + } +} + +#if 0 +static int in_range_unsigned (val, nbits) + bfd_vma val; + int nbits; +{ + /* Look at top bit of value that would be stored, figure out how it + would be extended by the hardware, and see if that matches the + original supplied value. */ + bfd_vma mask; + bfd_vma one = 1; + bfd_vma top_bit, stored_value, missing_bits; + + mask = (one << nbits) - 1; + stored_value = val & mask; + top_bit = stored_value & (one << nbits - 1); + missing_bits = val & ~mask; + return missing_bits == 0; +} +#endif + +static void +s_gprel32 () +{ + expressionS e; + char *p; + + SKIP_WHITESPACE (); + expression (&e); + switch (e.X_op) + { + case O_constant: + e.X_add_symbol = section_symbol (absolute_section); + /* fall through */ + case O_symbol: + e.X_op = O_subtract; + e.X_op_symbol = gp; + break; + default: + abort (); + } + if (auto_align) + alpha_align (2, 0, insn_label); + p = frag_more (4); + memset (p, 0, 4); + fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &e, 0, + BFD_RELOC_GPREL32); + insn_label = NULL; +} + +static void +create_literal_section (secp, name) + segT *secp; + const char *name; +{ + segT current_section = now_seg; + int current_subsec = now_subseg; + segT new_sec; + + *secp = new_sec = subseg_new (name, 0); + subseg_set (current_section, current_subsec); + bfd_set_section_alignment (stdoutput, new_sec, 3); + bfd_set_section_flags (stdoutput, new_sec, + SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY + | SEC_DATA); +} + +static valueT +get_lit8_offset (val) + bfd_vma val; +{ + valueT retval; + if (lit8_sec == 0) + { + create_literal_section (&lit8_sec, ".lit8"); + lit8_sym = section_symbol (lit8_sec); + } + retval = add_to_literal_pool ((symbolS *) 0, val, lit8_sec, 8); + if (retval >= 0xfff0) + as_fatal ("overflow in fp literal (.lit8) table"); + return retval; +} + +static valueT +get_lit4_offset (val) + bfd_vma val; +{ + valueT retval; + if (lit4_sec == 0) + { + create_literal_section (&lit4_sec, ".lit4"); + lit4_sym = section_symbol (lit4_sec); + } + retval = add_to_literal_pool ((symbolS *) 0, val, lit4_sec, 4); + if (retval >= 0xfff0) + as_fatal ("overflow in fp literal (.lit4) table"); + return retval; +} + +static struct alpha_it clear_insn; + +/* This function is called once, at assembler startup time. It should + set up all the tables, etc. that the MD part of the assembler will + need, that can be determined before arguments are parsed. */ +void +md_begin () +{ + const char *retval, *name; + unsigned int i = 0; + + op_hash = hash_new (); + + for (i = 0; i < NUMOPCODES; ) + { + const char *name = alpha_opcodes[i].name; + retval = hash_insert (op_hash, name, (PTR) &alpha_opcodes[i]); + if (retval) + as_fatal ("internal error: can't hash opcode `%s': %s", + name, retval); + + do + i++; + while (i < NUMOPCODES + && (alpha_opcodes[i].name == name + || !strcmp (alpha_opcodes[i].name, name))); + } + /* Some opcodes include modifiers of various sorts with a "/mod" + syntax, like the architecture documentation suggests. However, + for use with gcc at least, we also need to access those same + opcodes without the "/". */ + for (i = 0; i < NUMOPCODES; ) + { + name = alpha_opcodes[i].name; + + if (strchr (name, '/')) + { + char *p = xmalloc (strlen (name)); + const char *q = name; + char *q2 = p; + + for (; *q; q++) + if (*q != '/') + *q2++ = *q; + + *q2++ = 0; + retval = hash_insert (op_hash, p, (PTR) &alpha_opcodes[i]); + /* Ignore failures -- the opcode table does duplicate some + variants in different forms, like "hw_stq" and "hw_st/q". + Maybe the variants can be eliminated, and this error + checking restored. */ + } + + do + i++; + while (i < NUMOPCODES + && (alpha_opcodes[i].name == name + || !strcmp (alpha_opcodes[i].name, name))); + } + + lituse_basereg.X_op = O_constant; + lituse_basereg.X_add_number = 1; + lituse_byteoff.X_op = O_constant; + lituse_byteoff.X_add_number = 2; + lituse_jsr.X_op = O_constant; + lituse_jsr.X_add_number = 3; + + /* So .sbss will get used for tiny objects. */ + bfd_set_gp_size (stdoutput, 8); + create_literal_section (&lita_sec, ".lita"); + /* For handling the GP, create a symbol that won't be output in the + symbol table. We'll edit it out of relocs later. */ + gp = symbol_create ("", lita_sec, 0x8000, &zero_address_frag); + + memset (&clear_insn, 0, sizeof (clear_insn)); + for (i = 0; i < MAX_RELOCS; i++) + clear_insn.reloc[i].code = BFD_RELOC_NONE; +} + +int optnum = 1; + +static void +emit_insn (insn) + struct alpha_it *insn; +{ + char *toP; + int j; + + toP = frag_more (4); + + /* put out the opcode */ + md_number_to_chars (toP, insn->opcode, 4); + + /* put out the symbol-dependent stuff */ + for (j = 0; j < MAX_RELOCS; j++) + { + struct reloc_data *r = &insn->reloc[j]; + fixS *f; + + if (r->code != BFD_RELOC_NONE) + { + if (r->exp.X_op == O_constant) + { + r->exp.X_add_symbol = section_symbol (absolute_section); + r->exp.X_op = O_symbol; + } + f = fix_new_exp (frag_now, (toP - frag_now->fr_literal), 4, + &r->exp, r->pcrel, r->code); + if (r->code == BFD_RELOC_ALPHA_GPDISP_LO16) + { + static bit_fixS cookie; + /* @@ This'll make the range checking in write.c shut up. */ + f->fx_bit_fixP = &cookie; + } + } + } + + insn_label = NULL; +} + +void +md_assemble (str) + char *str; +{ + int i, count; +#define MAX_INSNS 5 + struct alpha_it insns[MAX_INSNS]; + + count = alpha_ip (str, insns); + if (count <= 0) + return; + + for (i = 0; i < count; i++) + emit_insn (&insns[i]); +} + +static inline void +maybe_set_gp (sec) + asection *sec; +{ + bfd_vma vma; + if (!sec) + return; + vma = bfd_get_section_vma (foo, sec); + if (vma && vma < alpha_gp_value) + alpha_gp_value = vma; +} + +static void +select_gp_value () +{ + if (alpha_gp_value != 0) + abort (); + + /* Get minus-one in whatever width... */ + alpha_gp_value = 0; alpha_gp_value--; + + /* Select the smallest VMA of these existing sections. */ + maybe_set_gp (lita_sec); +/* maybe_set_gp (sdata); Was disabled before -- should we use it? */ +#if 0 + maybe_set_gp (lit8_sec); + maybe_set_gp (lit4_sec); +#endif + + alpha_gp_value += GP_ADJUSTMENT; + + S_SET_VALUE (gp, alpha_gp_value); + +#ifdef DEBUG1 + printf ("Chose GP value of %lx\n", alpha_gp_value); +#endif +} + +int +alpha_force_relocation (f) + fixS *f; +{ + switch (f->fx_r_type) + { + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + case BFD_RELOC_ALPHA_LITERAL: + case BFD_RELOC_ALPHA_LITUSE: + case BFD_RELOC_GPREL32: + return 1; + case BFD_RELOC_ALPHA_HINT: + case BFD_RELOC_64: + case BFD_RELOC_32: + case BFD_RELOC_16: + case BFD_RELOC_8: + case BFD_RELOC_23_PCREL_S2: + case BFD_RELOC_14: + case BFD_RELOC_26: + return 0; + default: + abort (); + return 0; + } +} + +int +alpha_fix_adjustable (f) + fixS *f; +{ + /* Are there any relocation types for which we must generate a reloc + but we can adjust the values contained within it? */ + switch (f->fx_r_type) + { + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + return 0; + case BFD_RELOC_GPREL32: + return 1; + default: + return !alpha_force_relocation (f); + } + /*NOTREACHED*/ +} + +valueT +md_section_align (seg, size) + segT seg; + valueT size; +{ +#ifdef OBJ_ECOFF + /* This should probably be handled within BFD, or by pulling the + number from BFD at least. */ +#define MIN 15 + size += MIN; + size &= ~MIN; +#endif + return size; +} + +/* Add this thing to the .lita section and produce a LITERAL reloc referring + to it. */ + +/* Are we currently eligible to emit a LITUSE reloc for the literal + references just generated? */ +static int lituse_pending; + +static void +load_symbol_address (reg, insn) + int reg; + struct alpha_it *insn; +{ + static symbolS *lita_sym; + + int x; + valueT retval; + + if (!lita_sym) + { + lita_sym = section_symbol (lita_sec); + S_CLEAR_EXTERNAL (lita_sym); + } + + retval = add_to_literal_pool (insn->reloc[0].exp.X_add_symbol, + insn->reloc[0].exp.X_add_number, + lita_sec, 8); + + /* Now emit a LITERAL relocation for the original section. */ + insn->reloc[0].exp.X_op = O_symbol; + insn->reloc[0].exp.X_add_symbol = lita_sym; + insn->reloc[0].exp.X_add_number = retval; + insn->reloc[0].code = BFD_RELOC_ALPHA_LITERAL; + lituse_pending = 1; + + if (retval == 0x8000) + /* Overflow? */ + as_fatal ("overflow in literal (.lita) table"); + x = retval; + if (addr32) + insn->opcode = (0xa0000000 /* ldl */ + | (reg << SA) + | (base_register << SB) + | (x & 0xffff)); + else + insn->opcode = (0xa4000000 /* ldq */ + | (reg << SA) + | (base_register << SB) + | (x & 0xffff)); + note_gpreg (base_register); +} + +/* To load an address with a single instruction, + emit a LITERAL reloc in this section, and a REFQUAD + for the .lita section, so that we'll be able to access + it via $gp: + lda REG, xx -> ldq REG, -32752(gp) + lda REG, xx+4 -> ldq REG, -32752(gp) + lda REG, 4(REG) + + The offsets need to start near -0x8000, and the generated LITERAL + relocations should negate the offset. I don't completely grok the + scheme yet. */ + +static int +load_expression (reg, insn) + int reg; + struct alpha_it *insn; +{ + valueT addend, addendhi, addendlo; + int num_insns = 1; + + if (insn->reloc[0].exp.X_add_symbol->bsym->flags & BSF_SECTION_SYM) + { + addend = 0; + } + else + { + addend = insn->reloc[0].exp.X_add_number; + insn->reloc[0].exp.X_add_number = 0; + } + load_symbol_address (reg, insn); + if (addend) + { + if ((addend & ~0x7fffffff) != 0 + && (addend & ~0x7fffffff) + 0x80000000 != 0) + { + as_bad ("assembler not prepared to handle constants >32 bits yet"); + addend = 0; + } + addendlo = addend & 0xffff; + addend -= addendlo; + addendhi = addend >> 16; + if (addendlo & 0x8000) + addendhi++; + /* It appears that the BASEREG LITUSE reloc should not be used on + an LDAH instruction. */ + if (addendlo) + { + insn[1].opcode = (0x20000000 /* lda */ + | (reg << SA) + | (reg << SB) + | (addendlo & 0xffff)); + insn[1].reloc[0].code = BFD_RELOC_ALPHA_LITUSE; + insn[1].reloc[0].exp = lituse_basereg; + num_insns++; + } + if (addendhi) + { + insn[num_insns].opcode = (0x24000000 + | (reg << SA) + | (reg << SB) + | (addendhi & 0xffff)); + num_insns++; + } + if (num_insns == 1) + abort (); + lituse_pending = 0; + } + return num_insns; +} + +static inline void +getExpression (str, this_insn) + char *str; + struct alpha_it *this_insn; +{ + char *save_in; + segT seg; + +#if 0 /* Not converted to bfd yet, and I don't think we need them + for ECOFF. Re-adding a.out support will probably require + them though. */ + static const struct am { + char *name; + bfd_reloc_code_real_type reloc; + } macro[] = { + { "hi", RELOC_48_63 }, + { "lo", RELOC_0_15 }, + { "ml", RELOC_16_31 }, + { "mh", RELOC_32_47 }, + { "uhi", RELOC_U_48_63 }, + { "uml", RELOC_U_16_31 }, + { "umh", RELOC_U_32_47 }, + { 0, } + }; + + /* Handle macros: "%macroname(expr)" */ + if (*str == '%') + { + struct am *m; + char *p, *q; + + str++; + m = ¯o[0]; + while (q = m->name) + { + p = str; + while (*q && *p == *q) + p++, q++; + if (*q == 0) + break; + m++; + } + if (q) + { + str = p; /* keep the '(' */ + this_insn->reloc = m->reloc; + } + } +#endif + + save_in = input_line_pointer; + input_line_pointer = str; + + seg = expression (&this_insn->reloc[0].exp); + /* XXX validate seg and exp, make sure they're reasonable */ + expr_end = input_line_pointer; + input_line_pointer = save_in; +} + +static void +emit_unaligned_io (dir, addr_reg, addr_offset, reg) + char *dir; + int addr_reg, reg; + valueT addr_offset; +{ + char buf[90]; + sprintf (buf, "%sq_u $%d,%ld($%d)", dir, reg, (long) addr_offset, addr_reg); + md_assemble (buf); +} + +static void +emit_load_unal (addr_reg, addr_offset, reg) + int addr_reg, reg; + valueT addr_offset; +{ + emit_unaligned_io ("ld", addr_reg, addr_offset, reg); +} + +static void +emit_store_unal (addr_reg, addr_offset, reg) + int addr_reg, reg; + valueT addr_offset; +{ + emit_unaligned_io ("st", addr_reg, addr_offset, reg); +} + +static void +emit_byte_manip_r (op, in, mask, out, mode, which) + char *op; + int in, mask, out, mode, which; +{ + char buf[90]; + sprintf (buf, "%s%c%c $%d,$%d,$%d", op, mode, which, in, mask, out); + md_assemble (buf); +} + +static void +emit_extract_r (in, mask, out, mode, which) + int in, mask, out, mode, which; +{ + emit_byte_manip_r ("ext", in, mask, out, mode, which); +} + +static void +emit_insert_r (in, mask, out, mode, which) + int in, mask, out, mode, which; +{ + emit_byte_manip_r ("ins", in, mask, out, mode, which); +} + +static void +emit_mask_r (in, mask, out, mode, which) + int in, mask, out, mode, which; +{ + emit_byte_manip_r ("msk", in, mask, out, mode, which); +} + +static void +emit_sign_extend (reg, size) + int reg, size; +{ + char buf[90]; + sprintf (buf, "sll $%d,0x%x,$%d", reg, 64 - size, reg); + md_assemble (buf); + sprintf (buf, "sra $%d,0x%x,$%d", reg, 64 - size, reg); + md_assemble (buf); +} + +static void +emit_bis_r (in1, in2, out) + int in1, in2, out; +{ + char buf[90]; + sprintf (buf, "bis $%d,$%d,$%d", in1, in2, out); + md_assemble (buf); +} + +static int +build_mem (opc, ra, rb, disp) + int opc, ra, rb; + bfd_signed_vma disp; +{ + if ((disp >> 15) != 0 + && (disp >> 15) + 1 != 0) + abort (); + return ((opc << 26) | (ra << SA) | (rb << SB) | (disp & 0xffff)); +} + +static int +build_operate_n (opc, fn, ra, lit, rc) + int opc, fn, ra, rc; + int lit; +{ + if (lit & ~0xff) + abort (); + return ((opc << 26) | (fn << 5) | (ra << SA) | (lit << SN) | (1 << 12) | (rc << SC)); +} + +static void +emit_sll_n (dest, disp, src) + int dest, disp, src; +{ + struct alpha_it insn = clear_insn; + insn.opcode = build_operate_n (0x12, 0x39, src, disp, dest); + emit_insn (&insn); +} + +static void +emit_ldah_num (dest, addend, src) + int dest, src; + bfd_vma addend; +{ + struct alpha_it insn = clear_insn; + insn.opcode = build_mem (0x09, dest, src, addend); + emit_insn (&insn); +} + +static void +emit_addq_r (in1, in2, out) + int in1, in2, out; +{ + struct alpha_it insn = clear_insn; + insn.opcode = 0x40000400 | (in1 << SA) | (in2 << SB) | (out << SC); + emit_insn (&insn); +} + +static void +emit_lda_n (dest, addend, src) + int dest, src; + bfd_vma addend; +{ + struct alpha_it insn = clear_insn; + insn.opcode = build_mem (0x08, dest, src, addend); + emit_insn (&insn); +} + +static void +emit_add64 (in, out, num) + int in, out; + bfd_vma num; +{ + bfd_signed_vma snum = num; + + if (in_range_signed (num, 16)) + { + emit_lda_n (out, num, in); + return; + } + if ((num & 0xffff) == 0 + && in == ZERO + && in_range_signed (snum >> 16, 16)) + { + emit_ldah_num (out, snum >> 16, in); + return; + } + /* I'm not sure this one is getting invoked when it could. */ + if ((num & 1) == 0 && in == ZERO) + { + if (in_range_signed (snum >> 1, 16)) + { + emit_lda_n (out, snum >> 1, in); + emit_addq_r (out, out, out); + return; + } + else if (num & 0x1fffe == 0 + && in_range_signed (snum >> 17, 16)) + { + emit_ldah_num (out, snum >> 17, in); + emit_addq_r (out, out, out); + return; + } + } + if (in_range_signed (num, 32)) + { + bfd_vma lo = num & 0xffff; + if (lo & 0x8000) + lo -= 0x10000; + num -= lo; + emit_ldah_num (out, snum >> 16, in); + if (lo) + emit_lda_n (out, lo, out); + return; + } + + if (in != ZERO && in != AT && out != AT && at_ok) + { + emit_add64 (ZERO, AT, num); + emit_addq_r (AT, in, out); + return; + } + + if (in != ZERO) + as_bad ("load expression too complex to expand"); + + /* Could check also for loading 16- or 32-bit value and shifting by + arbitrary displacement. */ + + { + bfd_vma lo = snum & 0xffffffff; + if (lo & 0x80000000) + lo -= ((bfd_vma)0x10000000 << 4); + snum -= lo; + emit_add64 (ZERO, out, snum >> 32); + emit_sll_n (out, 32, out); + if (lo != 0) + emit_add64 (out, out, lo); + } +} + +static int +alpha_ip (str, insns) + char *str; + struct alpha_it insns[]; +{ + char *s; + const char *args; + char c; + unsigned long i; + struct alpha_opcode *pattern; + char *argsStart; + unsigned int opcode; + unsigned int mask = 0; + int match = 0, num_gen = 1; + int comma = 0; + int do_add64, add64_in = 0, add64_out = 0; + bfd_vma add64_addend = 0; + + for (s = str; + islower (*s) || *s == '_' || *s == '/' || *s == '4' || *s == '8'; + ++s) + ; + switch (*s) + { + + case '\0': + break; + + case ',': + comma = 1; + + /*FALLTHROUGH*/ + + case ' ': + *s++ = '\0'; + break; + + default: + as_fatal ("Unknown opcode: `%s'", str); + } + if ((pattern = (struct alpha_opcode *) hash_find (op_hash, str)) == NULL) + { + as_bad ("Unknown opcode: `%s'", str); + return -1; + } + if (comma) + *--s = ','; + + argsStart = s; + for (;;) + { + do_add64 = 0; + opcode = pattern->match; + num_gen = 1; + for (i = 0; i < MAX_INSNS; i++) + insns[i] = clear_insn; + + /* Build the opcode, checking as we go to make sure that the + operands match. */ + for (args = pattern->args;; ++args) + { + switch (*args) + { + + case '\0': /* end of args */ + if (*s == '\0') + { + match = 1; + } + break; + + case '+': + if (*s == '+') + { + ++s; + continue; + } + if (*s == '-') + { + continue; + } + break; + + case '(': /* these must match exactly */ + case ')': + case ',': + case ' ': + case '0': + if (*s++ == *args) + continue; + break; + + case '1': /* next operand must be a register */ + case '2': + case '3': + case 'r': + case 'R': + if (*s++ == '$') + { + switch (c = *s++) + { + + case 'a': /* $at: as temporary */ + if (*s++ != 't') + goto error; + mask = AT; + break; + + case 'g': /* $gp: base register */ + if (*s++ != 'p') + goto error; + mask = base_register; + break; + + case 's': /* $sp: stack pointer */ + if (*s++ != 'p') + goto error; + mask = SP; + break; + + + case 'r': /* any register */ + if (!isdigit (c = *s++)) + { + goto error; + } + /* FALLTHROUGH */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (isdigit (*s)) + { + if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) + { + goto error; + } + } + else + { + c -= '0'; + } + if ((c == GP) && first_32bit_quadrant) + c = ZERO; + + mask = c; + break; + + default: + goto error; + } + note_gpreg (mask); + /* Got the register, now figure out where it goes in + the opcode. */ + doregister: + switch (*args) + { + + case '1': + case 'e': + opcode |= mask << SA; + continue; + + case '2': + case 'f': + opcode |= mask << SB; + continue; + + case '3': + case 'g': + opcode |= mask; + continue; + + case 'r': + opcode |= (mask << SA) | mask; + continue; + + case 'R': /* ra and rb are the same */ + opcode |= (mask << SA) | (mask << SB); + continue; + + case 'E': + opcode |= (mask << SA) | (mask << SB) | (mask); + continue; + } + } + break; + + case 'e': /* next operand is a floating point register */ + case 'f': + case 'g': + case 'E': + if (*s++ == '$' && *s++ == 'f' && isdigit (*s)) + { + mask = *s++; + if (isdigit (*s)) + { + mask = 10 * (mask - '0') + (*s++ - '0'); + if (mask >= 32) + { + break; + } + } + else + { + mask -= '0'; + } + note_fpreg (mask); + /* same encoding as gp registers */ + goto doregister; + } + break; + +#if 0 + case 'h': /* bits 16..31 */ + insns[0].reloc = RELOC_16_31; + goto immediate; +#endif + + case 'l': /* bits 0..15 */ + insns[0].reloc[0].code = BFD_RELOC_16; + goto immediate; + + case 'L': /* 21 bit PC relative immediate */ + insns[0].reloc[0].code = BFD_RELOC_23_PCREL_S2; + insns[0].reloc[0].pcrel = 1; + goto immediate; + + case 'i': /* 14 bit immediate */ + if (OPCODE (opcode) != 0x1a) + /* Not a jmp variant?? */ + abort (); + else if (opcode & 0x8000) + /* ret or jsr_coroutine */ + { + insns[0].reloc[0].code = BFD_RELOC_14; + insns[0].reloc[0].pcrel = 0; + } + else + /* jmp or jsr */ + { + insns[0].reloc[0].code = BFD_RELOC_ALPHA_HINT; + insns[0].reloc[0].pcrel = 1; + } + goto immediate; + + case 'b': /* 8 bit immediate */ + insns[0].reloc[0].code = BFD_RELOC_8; + goto immediate; + + case 'I': /* 26 bit immediate, for PALcode */ + insns[0].reloc[0].code = BFD_RELOC_26; + goto immediate; + + case 't': /* 12 bit displacement, for PALcode */ + insns[0].reloc[0].code = BFD_RELOC_12_PCREL; + goto immediate; + + case '8': /* 8 bit 0...7 */ + insns[0].reloc[0].code = BFD_RELOC_8; + goto immediate; + + immediate: + if (*s == ' ') + s++; + getExpression (s, &insns[0]); + s = expr_end; + /* Handle overflow in certain instructions by converting + to other instructions. */ + if (insns[0].reloc[0].code == BFD_RELOC_8 + && insns[0].reloc[0].exp.X_op == O_constant + && (insns[0].reloc[0].exp.X_add_number < 0 + || insns[0].reloc[0].exp.X_add_number > 0xff)) + { + if (OPCODE (opcode) == 0x10 + && (OP_FCN (opcode) == 0x00 /* addl */ + || OP_FCN (opcode) == 0x40 /* addl/v */ + || OP_FCN (opcode) == 0x20 /* addq */ + || OP_FCN (opcode) == 0x60 /* addq/v */ + || OP_FCN (opcode) == 0x09 /* subl */ + || OP_FCN (opcode) == 0x49 /* subl/v */ + || OP_FCN (opcode) == 0x29 /* subq */ + || OP_FCN (opcode) == 0x69 /* subq/v */ + || OP_FCN (opcode) == 0x02 /* s4addl */ + || OP_FCN (opcode) == 0x22 /* s4addq */ + || OP_FCN (opcode) == 0x0b /* s4subl */ + || OP_FCN (opcode) == 0x2b /* s4subq */ + || OP_FCN (opcode) == 0x12 /* s8addl */ + || OP_FCN (opcode) == 0x32 /* s8addq */ + || OP_FCN (opcode) == 0x1b /* s8subl */ + || OP_FCN (opcode) == 0x3b /* s8subq */ + ) + /* Can we make it fit by negating? */ + && -insns[0].reloc[0].exp.X_add_number < 0xff + && -insns[0].reloc[0].exp.X_add_number > 0) + { + opcode ^= 0x120; /* convert add<=>sub */ + insns[0].reloc[0].exp.X_add_number *= -1; + } + else if (at_ok && macro_ok) + { + /* Constant value supplied, but it's too large. */ + do_add64 = 1; + add64_in = ZERO; + add64_out = AT; + add64_addend = insns[0].reloc[0].exp.X_add_number; + opcode &= ~ 0x1000; + opcode |= (AT << SB); + insns[0].reloc[0].code = BFD_RELOC_NONE; + } + else + as_bad ("overflow in 8-bit literal field in `operate' format insn"); + } + else if (insns[0].reloc[0].code == BFD_RELOC_16 + && insns[0].reloc[0].exp.X_op == O_constant + && !in_range_signed (insns[0].reloc[0].exp.X_add_number, + 16)) + { + bfd_vma val = insns[0].reloc[0].exp.X_add_number; + if (OPCODE (opcode) == 0x08) + { + do_add64 = 1; + add64_in = ZERO; + add64_out = AT; + add64_addend = val; + opcode &= ~0x1000; + opcode |= (AT << SB); + insns[0].reloc[0].code = BFD_RELOC_NONE; + } + else if (OPCODE (opcode) == 0x09 + && in_range_signed (val >> 16, 16)) + { + /* ldah with high operand - convert to low */ + insns[0].reloc[0].exp.X_add_number >>= 16; + } + else + as_bad ("I don't know how to handle 32+ bit constants here yet, sorry."); + } + else if (insns[0].reloc[0].code == BFD_RELOC_32 + && insns[0].reloc[0].exp.X_op == O_constant) + { + bfd_vma val = insns[0].reloc[0].exp.X_add_number; + bfd_signed_vma sval = val; + if (val >> 32 != 0 + && sval >> 32 != 0 + && sval >> 32 != -1) + as_bad ("I don't know how to handle 64 bit constants here yet, sorry."); + } + continue; + + case 'F': + { + int format, length, mode, i; + char temp[20 /*MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT*/]; + char *err; + static const char formats[4] = "FGfd"; + bfd_vma bits, offset; + char *old_input_line_pointer = input_line_pointer; + + input_line_pointer = s; + SKIP_WHITESPACE (); + memset (temp, 0, sizeof (temp)); + mode = (opcode >> 26) & 3; + format = formats[mode]; + err = md_atof (format, temp, &length); + if (err) + { + as_bad ("Bad floating literal: %s", err); + bits = 0; + } + else + { + /* Generate little-endian number from byte sequence. */ + bits = 0; + for (i = length - 1; i >= 0; i--) + bits += ((bfd_vma)(temp[i] & 0xff)) << (i * 8); + } + switch (length) + { + case 8: + offset = get_lit8_offset (bits) - 0x8000; + insns[0].reloc[0].exp.X_add_symbol = lit8_sym; + insns[0].reloc[0].exp.X_add_number = 0x8000; + break; + case 4: + offset = get_lit4_offset (bits) - 0x8000; + insns[0].reloc[0].exp.X_add_symbol = lit4_sym; + insns[0].reloc[0].exp.X_add_number = 0x8000; + break; + default: + abort (); + } + insns[0].reloc[0].exp.X_op = O_symbol; + offset &= 0xffff; + num_gen = load_expression (AT, &insns[0]); + if (lituse_pending) + { + insns[num_gen].reloc[0].code = BFD_RELOC_ALPHA_LITUSE; + insns[num_gen].reloc[0].exp = lituse_basereg; + lituse_pending = 0; + } + insns[num_gen++].opcode = opcode | (AT << SB) | offset; + opcode = insns[0].opcode; + s = input_line_pointer; + input_line_pointer = old_input_line_pointer; + } + continue; + + /* The following two.. take advantage of the fact that + opcode already contains most of what we need to know. + We just prepend to the instr an "ldah + $r,%ml(expr)($base)" and turn this one (done later + after we return) into something like "stq + $r,%lo(expr)(at)" or "ldq $r,%lo(expr)($r)". + + NOTE: This can fail later on at link time if the + offset from $base actually turns out to be more than + 2**31 or 2**47 if use_large_offsets is set. */ + case 'P': /* Addressing macros: PUT */ + mask = AT; /* register 'at' */ + /* fall through */ + + case 'G': /* Addressing macros: GET */ + /* All it is missing is the expression, which is what we + will get now */ + + if (*s == ' ') + s++; + getExpression (s, &insns[0]); + s = expr_end; + + /* Must check for "lda ..,number" too */ + if (insns[0].reloc[0].exp.X_op == O_big) + { + as_warn ("Sorry, not yet. Put bignums in .data section yourself."); + return -1; + } + if (insns[0].reloc[0].exp.X_op == O_constant) + { + bfd_vma val = insns[0].reloc[0].exp.X_add_number; + bfd_vma top, low; + + insns[0].reloc[0].code = BFD_RELOC_NONE; + insns[1].reloc[0].code = BFD_RELOC_NONE; + + low = val & 0xffff; + if (low & 0x8000) + low -= 0x10000; + top = val - low; + if (top) + { + do_add64 = 1; + add64_in = ZERO; + add64_out = AT; + add64_addend = top; + opcode |= AT << SB; + } + else + opcode |= ZERO << SB; + opcode &= ~0x1000; + opcode |= low & 0xffff; + } + else if (insns[0].reloc[0].exp.X_op == O_symbol) + { + unsigned long old_opcode = opcode; + int tmp_reg = -1; + + if (!macro_ok) + as_bad ("insn requires expansion but `nomacro' specified"); + else if (*args == 'G') + tmp_reg = mask; + else if (!at_ok) + as_bad ("insn expansion requires AT use, but `noat' specified"); + else + tmp_reg = AT; + num_gen = load_expression (tmp_reg, insns); + opcode = insns[0].opcode; + /* lda is opcode 8, 0x20000000, and the macros that use + this code have an opcode field of 0. The latter + require further processing, and we don't have the + true opcode here. */ + if (OPCODE (old_opcode) != 0 + && OPCODE (old_opcode) != 0x08) + { + struct alpha_it *i; + i = &insns[num_gen++]; + i->opcode = old_opcode | (tmp_reg << SB); + + if (lituse_pending) + { + i->reloc[0].code = BFD_RELOC_ALPHA_LITUSE; + i->reloc[0].exp = lituse_basereg; + lituse_pending = 0; + } + } + } + else + { + /* Not a number */ + num_gen = 2; + insns[1].reloc[0].exp = insns[0].reloc[0].exp; + + /* Generate: ldah REG,x1(GP); OP ?,x0(REG) */ + + abort (); /* relocs need fixing */ +#if 0 + insns[1].reloc = RELOC_0_15; + insns[1].opcode = opcode | mask << SB; + + insns[0].reloc = RELOC_16_31; + opcode = 0x24000000 /*ldah*/ | mask << SA | (base_register << SB); +#endif + } + + continue; + + /* Same failure modes as above, actually most of the + same code shared. */ + case 'B': /* Builtins */ + args++; + switch (*args) + { + + case 'a': /* ldgp */ + + if (first_32bit_quadrant || no_mixed_code) + return -1; + switch (OUTPUT_FLAVOR) + { + case bfd_target_aout_flavour: + /* this is cmu's a.out version */ + insns[0].reloc[0].code = BFD_RELOC_NONE; + /* generate "zap %r,0xf,%r" to take high 32 bits */ + opcode |= 0x48001600 /* zap ?,#,?*/ | (0xf << SN); + break; + case bfd_target_ecoff_flavour: + /* Given "ldgp R1,N(R2)", turn it into something + like "ldah R1,###(R2) ; lda R1,###(R1)" with + appropriate constants and relocations. */ + { + unsigned long r1, r2; + unsigned long addend = 0; + + num_gen = 2; + r2 = mask; + r1 = opcode & 0x3f; + insns[0].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_HI16; + insns[0].reloc[0].pcrel = 1; + insns[0].reloc[0].exp.X_op = O_symbol; + insns[0].reloc[0].exp.X_add_symbol = gp; + insns[0].reloc[0].exp.X_add_number = 0; + insns[0].opcode = (0x24000000 /* ldah */ + | (r1 << SA) + | (r2 << SB)); + insns[1].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_LO16; + insns[1].reloc[0].exp.X_op = O_symbol; + insns[1].reloc[0].exp.X_add_symbol = gp; + insns[1].reloc[0].exp.X_add_number = 4; + insns[1].reloc[0].pcrel = 1; + insns[1].opcode = 0x20000000 | (r1 << SA) | (r1 << SB); + opcode = insns[0].opcode; + /* merge in addend */ + insns[1].opcode |= addend & 0xffff; + insns[0].opcode |= ((addend >> 16) + + (addend & 0x8000 ? 1 : 0)); + if (r2 == PV) + ecoff_set_gp_prolog_size (0); + } + break; + default: + abort (); + } + continue; + + + case 'b': /* setgp */ + switch (OUTPUT_FLAVOR) + { + case bfd_target_aout_flavour: + /* generate "zap %r,0xf,$gp" to take high 32 bits */ + opcode |= 0x48001600 /* zap ?,#,?*/ + | (0xf << SN) | (base_register); + break; + default: + abort (); + } + continue; + + case 'c': /* jsr $r,foo becomes + lda $27,foo + jsr $r,($27),foo + Register 27, t12, is used by convention + here. */ + { + struct alpha_it *jsr; + expressionS etmp; + struct reloc_data *r; + + /* We still have to parse the function name */ + if (*s == ' ') + s++; + getExpression (s, &insns[0]); + etmp = insns[0].reloc[0].exp; + s = expr_end; + num_gen = load_expression (PV, &insns[0]); + note_gpreg (PV); + + jsr = &insns[num_gen++]; + jsr->opcode = (pattern->match + | (mask << SA) + | (PV << SB) + | 0); + if (lituse_pending) + { + /* LITUSE wasn't emitted yet */ + jsr->reloc[0].code = BFD_RELOC_ALPHA_LITUSE; + jsr->reloc[0].exp = lituse_jsr; + r = &jsr->reloc[1]; + lituse_pending = 0; + } + else + r = &jsr->reloc[0]; + r->exp = etmp; + r->code = BFD_RELOC_ALPHA_HINT; + r->pcrel = 1; + opcode = insns[0].opcode; + } + continue; + + case 'd': + /* Sub-word loads and stores. We load the address into + $at, which might involve using the `P' parameter + processing too, then emit a sequence to get the job + done, using unaligned memory accesses and byte + manipulation, with t9 and t10 as temporaries. */ + { + /* Characteristics of access. */ + int is_load = 99, is_unsigned = 0, is_unaligned = 0; + int mode_size, mode; + /* Register operand. */ + int reg = -1; + /* Addend for loads and stores. */ + valueT addend; + /* Which register do we use for the address? */ + int addr; + + { + /* Pick apart name and set flags. */ + const char *s = pattern->name; + + if (*s == 'u') + { + is_unaligned = 1; + s++; + } + + if (s[0] == 'l' && s[1] == 'd') + is_load = 1; + else if (s[0] == 's' && s[1] == 't') + is_load = 0; + else + as_fatal ("unrecognized sub-word access insn `%s'", + str); + s += 2; + + mode = *s++; + if (mode == 'b') mode_size = 1; + else if (mode == 'w') mode_size = 2; + else if (mode == 'l') mode_size = 4; + else if (mode == 'q') mode_size = 8; + else abort (); + + if (*s == 'u') + { + is_unsigned = 1; + s++; + } + + assert (*s == 0); + + /* Longwords are always kept sign-extended. */ + if (mode == 'l' && is_unsigned) + abort (); + /* There's no special unaligned byte handling. */ + if (mode == 'b' && is_unaligned) + abort (); + /* Stores don't care about signedness. */ + if (!is_load && is_unsigned) + abort (); + } + + if (args[-2] == 'P') + { + addr = AT; + addend = 0; + } + else + { + /* foo r1,num(r2) + r2 -> mask + r1 -> (opcode >> SA) & 31 + num -> insns->reloc[0].* + + We want to emit "lda at,num(r2)", since these + operations require the use of a single register + with the starting address of the memory operand + we want to access. + + We could probably get away without doing this + (and use r2 below, with the addend for the + actual reads and writes) in cases where the + addend is known to be a multiple of 8. */ + int r2 = mask; + int r1 = (opcode >> SA) & 31; + + if (insns[0].reloc[0].code == BFD_RELOC_NONE) + addend = 0; + else if (insns[0].reloc[0].code == BFD_RELOC_16) + { + if (insns[0].reloc[0].exp.X_op != O_constant) + abort (); + addend = insns[0].reloc[0].exp.X_add_number; + } + else + abort (); + + if (addend + mode_size - 1 < 0x7fff + && (addend % 8) == 0 + && (r2 < T9 || r2 > T12)) + { + addr = r2; + num_gen = 0; + } + else + { + /* Let later relocation processing deal + with the addend field. */ + insns[num_gen-1].opcode = (0x20000000 /* lda */ + | (AT << SA) + | (r2 << SB)); + addr = AT; + addend = 0; + } + reg = r1; + } + + /* Because the emit_* routines append directly to + the current frag, we now need to flush any + pending insns. */ + { + int i; + for (i = 0; i < num_gen; i++) + emit_insn (&insns[i]); + num_gen = 0; + } + + if (is_load) + { + int reg2, reg3 = -1; + + if (is_unaligned) + reg2 = T9, reg3 = T10; + else + reg2 = reg; + + emit_load_unal (addr, addend, T9); + if (is_unaligned) + emit_load_unal (addr, addend + mode_size - 1, T10); + emit_extract_r (T9, addr, reg2, mode, 'l'); + if (is_unaligned) + { + emit_extract_r (T10, addr, reg3, mode, 'h'); + emit_bis_r (T9, T10, reg); + } + if (!is_unsigned) + emit_sign_extend (reg, mode_size * 8); + } + else + { + /* The second word gets processed first + because if the address does turn out to be + aligned, the processing for the second word + will be pushing around all-zeros, and the + entire value will be handled as the `first' + word. So we want to store the `first' word + last. */ + /* Pair these up so that the memory loads get + separated from each other, as well as being + well in advance of the uses of the values + loaded. */ + if (is_unaligned) + { + emit_load_unal (addr, addend + mode_size - 1, T11); + emit_insert_r (reg, addr, T12, mode, 'h'); + } + emit_load_unal (addr, addend, T9); + emit_insert_r (reg, addr, T10, mode, 'l'); + if (is_unaligned) + emit_mask_r (T12, addr, T12, mode, 'h'); + emit_mask_r (T10, addr, T10, mode, 'l'); + if (is_unaligned) + emit_bis_r (T11, T12, T11); + emit_bis_r (T9, T10, T9); + if (is_unaligned) + emit_store_unal (addr, addend + mode_size - 1, T11); + emit_store_unal (addr, addend, T9); + } + } + return 0; + + /* DIVISION and MODULUS. Yech. + Convert OP x,y,result + to mov x,t10 + mov y,t11 + jsr t9, __OP + mov t12,result + + with appropriate optimizations if t10,t11,t12 + are the registers specified by the compiler. + We are missing an obvious optimization + opportunity here; if the ldq generated by the + jsr assembly requires a cycle or two to make + the value available, initiating it before one + or two of the mov instructions would result in + faster execution. */ + case '0': /* reml */ + case '1': /* divl */ + case '2': /* remq */ + case '3': /* divq */ + case '4': /* remlu */ + case '5': /* divlu */ + case '6': /* remqu */ + case '7': /* divqu */ + { + static char func[8][6] = { + "reml", "divl", "remq", "divq", + "remlu", "divlu", "remqu", "divqu" + }; + char expansion[64]; + int reg; + + /* All regs parsed, in opcode */ + + /* Do the expansions, one instr at a time */ + + reg = (opcode >> SA) & 31; + if (reg != T10) + { + /* x->t10 */ + sprintf (expansion, "mov $%d,$%d", reg, T10); + md_assemble (expansion); + } + reg = (opcode >> SB) & 31; + if (reg == T10) + /* we already overwrote it! */ + abort (); + else if (reg != T11) + { + /* y->t11 */ + sprintf (expansion, "mov $%d,$%d", reg, T11); + md_assemble (expansion); + } + sprintf (expansion, "lda $%d,__%s", PV, func[*args - '0']); + md_assemble (expansion); + sprintf (expansion, "jsr $%d,($%d),__%s", T9, PV, + func[*args - '0']); + md_assemble (expansion); +#if 0 /* huh? */ + if (!first_32bit_quadrant) + { + sprintf (expansion, + "zap $%d,0xf,$%d", + T9, base_register); + md_assemble (expansion); + } +#endif + sprintf (expansion, "ldgp $%d,0($%d)", + base_register, T9); + md_assemble (expansion); + + /* Use insns[0] to get at the result */ + if ((reg = (opcode & 31)) != PV) + opcode = (0x47e00400 /* or zero,zero,zero */ + | (PV << SB) + | reg /* Rc */ ); /* pv->z */ + else + num_gen = 0; + } + continue; + } + /* fall through */ + + default: + abort (); + } + break; + } + error: + if (match == 0) + { + /* Args don't match. */ + if (&pattern[1] - alpha_opcodes < NUMOPCODES + && !strcmp (pattern->name, pattern[1].name)) + { + ++pattern; + s = argsStart; + continue; + } + else + { + as_warn ("Illegal operands"); + return -1; + } + } + else + { + /* Args match, see if a float instructions and -nofloats */ + if (nofloats && pattern->isa_float) + return -1; + } + break; + } + + if (do_add64) + { + emit_add64 (add64_in, add64_out, add64_addend); + } + + insns[0].opcode = opcode; + return num_gen; +} + +/* Turn a string in input_line_pointer into a floating point constant + of type type, and store the appropriate bytes in *litP. The number + of LITTLENUMS emitted is stored in *sizeP. An error message is + returned, or NULL on OK. */ + +/* Equal to MAX_PRECISION in atof-ieee.c */ +#define MAX_LITTLENUMS 6 + +char * +md_atof (type, litP, sizeP) + char type; + char *litP; + int *sizeP; +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + char *atof_ieee (), *vax_md_atof (); + + switch (type) + { + /* VAX floats */ + case 'G': + /* VAX md_atof doesn't like "G" for some reason. */ + type = 'g'; + case 'F': + case 'D': + return vax_md_atof (type, litP, sizeP); + + /* IEEE floats */ + case 'f': + prec = 2; + break; + + case 'd': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return "Bad call to MD_ATOF()"; + } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + *sizeP = prec * sizeof (LITTLENUM_TYPE); + + for (wordP = words + prec - 1; prec--;) + { + md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + + return 0; +} + +void +md_bignum_to_chars (buf, bignum, nchars) + char *buf; + LITTLENUM_TYPE *bignum; + int nchars; +{ + while (nchars) + { + LITTLENUM_TYPE work = *bignum++; + int nb = CHARS_PER_LITTLENUM; + + do + { + *buf++ = work & ((1 << BITS_PER_CHAR) - 1); + if (--nchars == 0) + return; + work >>= BITS_PER_CHAR; + } + while (--nb); + } +} + +CONST char *md_shortopts = "Fm:g"; +struct option md_longopts[] = { +#define OPTION_32ADDR (OPTION_MD_BASE) + {"32addr", no_argument, NULL, OPTION_32ADDR}, + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof(md_longopts); + +int +md_parse_option (c, arg) + int c; + char *arg; +{ + switch (c) + { + case 'F': + nofloats = 1; + break; + + case OPTION_32ADDR: + addr32 = 1; + break; + + case 'g': + /* Ignore `-g' so gcc can provide this option to the Digital + UNIX assembler, which otherwise would throw away info that + mips-tfile needs. */ + break; + + default: + return 0; + } + + return 1; +} + +void +md_show_usage (stream) + FILE *stream; +{ + fprintf(stream, "\ +Alpha options:\n\ +-32addr treat addresses as 32-bit values\n\ +-F lack floating point instructions support\n\ +-m21064 | -m21066 | -m21164\n\ + specify variant of Alpha architecture\n"); +} + +static void +s_proc (is_static) + int is_static; +{ + /* XXXX Align to cache linesize XXXXX */ + char *name; + char c; + char *p; + symbolS *symbolP; + int temp; + + /* Takes ".proc name,nargs" */ + name = input_line_pointer; + c = get_symbol_end (); + p = input_line_pointer; + symbolP = symbol_find_or_make (name); + *p = c; + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + *p = 0; + as_warn ("Expected comma after name \"%s\"", name); + *p = c; + temp = 0; + ignore_rest_of_line (); + } + else + { + input_line_pointer++; + temp = get_absolute_expression (); + } + /* symbolP->sy_other = (signed char) temp; */ + as_warn ("unhandled: .proc %s,%d", name, temp); + demand_empty_rest_of_line (); +} + +static void +s_alpha_set (x) + int x; +{ + char *name = input_line_pointer, ch, *s; + int yesno = 1; + + while (!is_end_of_line[(unsigned char) *input_line_pointer]) + input_line_pointer++; + ch = *input_line_pointer; + *input_line_pointer = '\0'; + + s = name; + if (s[0] == 'n' && s[1] == 'o') + { + yesno = 0; + s += 2; + } + if (!strcmp ("reorder", s)) + /* ignore */ ; + else if (!strcmp ("at", s)) + at_ok = yesno; + else if (!strcmp ("macro", s)) + macro_ok = yesno; + else if (!strcmp ("move", s)) + /* ignore */ ; + else if (!strcmp ("volatile", s)) + /* ignore */ ; + else + as_warn ("Tried to .set unrecognized mode `%s'", name); + *input_line_pointer = ch; + demand_empty_rest_of_line (); +} + +/* @@ Is this right?? */ +long +md_pcrel_from (fixP) + fixS *fixP; +{ + valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; + switch (fixP->fx_r_type) + { + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + return addr; + default: + return fixP->fx_size + addr; + } +} + +/* Handle the .align pseudo-op. This aligns to a power of two. It + also adjusts any current instruction label. We treat this the same + way the MIPS port does: .align 0 turns off auto alignment. */ + +static void +s_alpha_align (ignore) + int ignore; +{ + register int temp; + register long temp_fill; + long max_alignment = 15; + + temp = get_absolute_expression (); + if (temp > max_alignment) + as_bad ("Alignment too large: %d. assumed.", temp = max_alignment); + else if (temp < 0) + { + as_warn ("Alignment negative: 0 assumed."); + temp = 0; + } + if (*input_line_pointer == ',') + { + input_line_pointer++; + temp_fill = get_absolute_expression (); + } + else + temp_fill = 0; + if (temp) + { + auto_align = 1; + alpha_align (temp, (int) temp_fill, insn_label); + } + else + { + auto_align = 0; + } + + demand_empty_rest_of_line (); +} + +static void +alpha_align (n, fill, label) + int n; + int fill; + symbolS *label; +{ + if (fill == 0 + && (now_seg == text_section + || !strcmp (now_seg->name, ".init") + || !strcmp (now_seg->name, ".fini")) + && n > 2) + { + static const unsigned char nop_pattern[] = { 0x1f, 0x04, 0xff, 0x47 }; + /* First, make sure we're on a four-byte boundary, in case + someone has been putting .byte values into the text section. + The DEC assembler silently fills with unaligned no-op + instructions. This will zero-fill, then nop-fill with proper + alignment. */ + frag_align (2, fill); + frag_align_pattern (n, nop_pattern, sizeof (nop_pattern)); + } + else + frag_align (n, fill); + + if (label != NULL) + { + assert (S_GET_SEGMENT (label) == now_seg); + label->sy_frag = frag_now; + S_SET_VALUE (label, (valueT) frag_now_fix ()); + } +} + +/* This function is called just before the generic pseudo-ops output + something. It just clears insn_label. */ + +void +alpha_flush_pending_output () +{ + insn_label = NULL; +} + +/* Handle data allocation pseudo-ops. This is like the generic + version, but it makes sure the current label, if any, is correctly + aligned. */ + +static void +s_alpha_cons (log_size) + int log_size; +{ + if (log_size > 0 && auto_align) + alpha_align (log_size, 0, insn_label); + insn_label = NULL; + cons (1 << log_size); +} + +/* Handle floating point allocation pseudo-ops. This is like the + generic vresion, but it makes sure the current label, if any, is + correctly aligned. */ + +static void +s_alpha_float_cons (type) + int type; +{ + if (auto_align) + { + int log_size; + + switch (type) + { + default: + case 'f': + case 'F': + log_size = 2; + break; + + case 'd': + case 'D': + case 'G': + log_size = 3; + break; + + case 'x': + case 'X': + case 'p': + case 'P': + log_size = 4; + break; + } + + alpha_align (log_size, 0, insn_label); + } + + insn_label = NULL; + float_cons (type); +} + +/* This function is called whenever a label is defined. It is used to + adjust the label when an automatic alignment occurs. */ + +void +alpha_define_label (sym) + symbolS *sym; +{ + insn_label = sym; +} + +int +md_apply_fix (fixP, valueP) + fixS *fixP; + valueT *valueP; +{ + valueT value; + int size; + valueT addend; + char *p = fixP->fx_frag->fr_literal + fixP->fx_where; + + value = *valueP; + + switch (fixP->fx_r_type) + { + /* The GPDISP relocations are processed internally with a symbol + referring to the current function; we need to drop in a value + which, when added to the address of the start of the function, + gives the desired GP. */ + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + addend = value; + if (fixP->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16) + { + assert (fixP->fx_next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16); +#ifdef DEBUG1 + printf ("hi16: "); + fprintf_vma (stdout, addend); + printf ("\n"); +#endif + if (addend & 0x8000) + addend += 0x10000; + addend >>= 16; + fixP->fx_offset = 4; /* @@ Compute this using fx_next. */ + } + else + { +#ifdef DEBUG1 + printf ("lo16: "); + fprintf_vma (stdout, addend); + printf ("\n"); +#endif + addend &= 0xffff; + fixP->fx_offset = 0; + } + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, + addend, 2); + fixP->fx_addsy = section_symbol (absolute_section); + fixP->fx_offset += fixP->fx_frag->fr_address + fixP->fx_where; + break; + + case BFD_RELOC_8: + /* Write 8 bits, shifted left 13 bit positions. */ + value &= 0xff; + p++; + *p &= 0x1f; + *p |= (value << 5) & 0xe0; + value >>= 3; + p++; + *p &= 0xe0; + *p |= value; + value >>= 5; + fixP->fx_done = 1; + if (value != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + "overflow in type-%d reloc", (int) fixP->fx_r_type); + return 3; + + case BFD_RELOC_32: + size = 4; + goto do_it; + case BFD_RELOC_64: + size = 8; + goto do_it; + case BFD_RELOC_16: + /* Don't want overflow checking. */ + size = 2; + do_it: + if (fixP->fx_pcrel == 0 + && fixP->fx_addsy == 0) + { + md_number_to_chars (p, value, size); + /* @@ Overflow checks?? */ + goto done; + } + break; + + case BFD_RELOC_26: + if (fixP->fx_addsy != 0 + && fixP->fx_addsy->bsym->section != absolute_section) + as_bad_where (fixP->fx_file, fixP->fx_line, + "PALcode instructions require immediate constant function code"); + else if (value >> 26 != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + "overflow in 26-bit PALcode function field"); + *p++ = value & 0xff; + value >>= 8; + *p++ = value & 0xff; + value >>= 8; + *p++ = value & 0xff; + value >>= 8; + { + char x = *p; + x &= ~3; + x |= (value & 3); + *p++ = x; + } + goto done; + + case BFD_RELOC_14: + if (fixP->fx_addsy != 0 + && fixP->fx_addsy->bsym->section != absolute_section) + as_bad_where (fixP->fx_file, fixP->fx_line, + "ret/jsr_coroutine requires constant in displacement field"); + else if (value >> 14 != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + "overflow in 14-bit operand field of ret or jsr_coroutine"); + *p++ = value & 0xff; + value >>= 8; + *p = (*p & 0xc0) | (value & 0x3f); + goto done; + + case BFD_RELOC_23_PCREL_S2: + /* Write 21 bits only. */ + value >>= 2; + *p++ = value & 0xff; + value >>= 8; + *p++ = value & 0xff; + value >>= 8; + *p &= 0xe0; + *p |= (value & 0x1f); + goto done; + + case BFD_RELOC_12_PCREL: + *p++ = value & 0xff; + value >>= 8; + *p &= 0xf0; + *p |= (value & 0x0f); + goto done; + + case BFD_RELOC_ALPHA_LITERAL: + case BFD_RELOC_ALPHA_LITUSE: + return 2; + + case BFD_RELOC_GPREL32: + assert (fixP->fx_subsy == gp); + value = - alpha_gp_value; /* huh? this works... */ + fixP->fx_subsy = 0; + md_number_to_chars (p, value, 4); + break; + + case BFD_RELOC_ALPHA_HINT: + if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0) + { + size = 2; + goto do_it; + } + return 2; + + default: + as_fatal ("unhandled relocation type %s", + bfd_get_reloc_code_name (fixP->fx_r_type)); + return 9; + } + + if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0) + { + printf ("type %d reloc done?\n", fixP->fx_r_type); + done: + fixP->fx_done = 1; + return 42; + } + + return 0x12345678; +} + +void +alpha_frob_ecoff_data () +{ + select_gp_value (); + /* $zero and $f31 are read-only */ + alpha_gprmask &= ~1; + alpha_fprmask &= ~1; +} + +/* The Alpha has support for some VAX floating point types, as well as for + IEEE floating point. We consider IEEE to be the primary floating point + format, and sneak in the VAX floating point support here. */ +#define md_atof vax_md_atof +#include "config/atof-vax.c" diff --git a/gnu/usr.bin/binutils/gas/config/tc-alpha.h b/gnu/usr.bin/binutils/gas/config/tc-alpha.h new file mode 100644 index 00000000000..3a0790d812d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-alpha.h @@ -0,0 +1,65 @@ +/* This file is tc-alpha.h + Copyright (C) 1994 Free Software Foundation, Inc. + Written by Ken Raeburn . + + 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 2, 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. */ + +#define TC_ALPHA + +#define TARGET_ARCH bfd_arch_alpha + +#define TARGET_FORMAT (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ + ? "ecoff-littlealpha" \ + : OUTPUT_FLAVOR == bfd_target_elf_flavour \ + ? "elf64-alpha" \ + : "unknown-format") + +#define NEED_LITERAL_POOL +#define TC_HANDLES_FX_DONE +#define REPEAT_CONS_EXPRESSIONS + +extern int alpha_force_relocation PARAMS ((struct fix *)); +extern int alpha_fix_adjustable PARAMS ((struct fix *)); + +extern unsigned long alpha_gprmask, alpha_fprmask; +extern valueT alpha_gp_value; + +#define TC_FORCE_RELOCATION(FIXP) alpha_force_relocation (FIXP) +#define tc_fix_adjustable(FIXP) alpha_fix_adjustable (FIXP) +#define RELOC_REQUIRES_SYMBOL + +#define md_convert_frag(b,s,f) as_fatal ("alpha convert_frag\n") +#define md_create_long_jump(p,f,t,fr,s) as_fatal("alpha_create_long_jump") +#define md_create_short_jump(p,f,t,fr,s) as_fatal("alpha_create_short_jump") +#define md_estimate_size_before_relax(f,s) \ + (as_fatal("estimate_size_before_relax called"),1) +#define md_operand(x) ((void) (0)) + +#define md_undefined_symbol(name) (0) + +#define LOCAL_LABEL(name) ((name)[0] == 'L') + +#define md_number_to_chars number_to_chars_littleendian + +extern int tc_get_register PARAMS ((int frame)); +extern void alpha_frob_ecoff_data PARAMS ((void)); + +#define tc_frob_label(sym) alpha_define_label (sym) +extern void alpha_define_label PARAMS ((struct symbol *)); + +#define md_flush_pending_output alpha_flush_pending_output +extern void alpha_flush_pending_output PARAMS ((void)); diff --git a/gnu/usr.bin/binutils/gas/config/tc-arm.c b/gnu/usr.bin/binutils/gas/config/tc-arm.c new file mode 100644 index 00000000000..aeaf9c4ea5c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-arm.c @@ -0,0 +1,4212 @@ +/* tc-arm.c All the arm specific stuff in one convenient, huge, + slow to compile, easy to find file. + Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) + Modified by David Taylor (dtaylor@armltd.co.uk) + + Copyright (C) 1994, 1995 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 2, 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. */ + +#include +#include +#define NO_RELOC 0 +#include "as.h" + +/* need TARGET_CPU */ +#include "config.h" +#include "subsegs.h" +#include "obstack.h" +#include "symbols.h" +#include "listing.h" + +/* ??? This is currently unused. */ +#ifdef __STDC__ +#define internalError() \ + as_fatal ("ARM Internal Error, line %d, %s", __LINE__, __FILE__) +#else +#define internalError() as_fatal ("ARM Internal Error") +#endif + +/* Types of processor to assemble for. */ +#define ARM_1 0x00000001 +#define ARM_2 0x00000002 +#define ARM_250 0x00000002 /* Checkme, should this be = ARM_3? */ +#define ARM_3 0x00000004 +#define ARM_6 0x00000008 +#define ARM_7 0x00000008 +#define ARM_7DM 0x00000010 + +/* Some useful combinations: */ +#define ARM_ANY 0x00ffffff +#define ARM_2UP 0x00fffffe +#define ARM_ALL ARM_2UP /* Not arm1 only */ +#define ARM_3UP 0x00fffffc +#define ARM_6UP 0x00fffff8 +#define ARM_LONGMUL 0x00000010 /* Don't know which will have this. */ + +#define FPU_CORE 0x80000000 +#define FPU_FPA10 0x40000000 +#define FPU_FPA11 0x40000000 +#define FPU_NONE 0 + +/* Some useful combinations */ +#define FPU_ALL 0xff000000 /* Note this is ~ARM_ANY */ +#define FPU_MEMMULTI 0x7f000000 /* Not fpu_core */ + +#ifndef CPU_DEFAULT +#define CPU_DEFAULT ARM_ALL +#endif + +#ifndef FPU_DEFAULT +#define FPU_DEFAULT FPU_ALL +#endif + +unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT; + +/* This array holds the chars that always start a comment. If the + pre-processor is disabled, these aren't very useful */ +CONST char comment_chars[] = "@"; + +/* This array holds the chars that only start a comment at the beginning of + a line. If the line seems to have the form '# 123 filename' + .line and .file directives will appear in the pre-processed output */ +/* Note that input_file.c hand checks for '#' at the beginning of the + first line of the input file. This is because the compiler outputs + #NO_APP at the beginning of its output. */ +/* Also note that comments like this one will always work. */ +CONST char line_comment_chars[] = "#"; + +CONST char line_separator_chars[] = ""; + +/* Chars that can be used to separate mant from exp in floating point nums */ +CONST char EXP_CHARS[] = "eE"; + +/* Chars that mean this number is a floating point constant */ +/* As in 0f12.456 */ +/* or 0d1.2345e12 */ + +CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP"; + +const int md_reloc_size = 8; /* Size of relocation record */ + +struct arm_it +{ + CONST char *error; + unsigned long instruction; + int suffix; + struct + { + bfd_reloc_code_real_type type; + expressionS exp; + int pc_rel; + } reloc; +}; + +struct arm_it inst; + +struct asm_shift +{ + CONST char *template; + unsigned long value; +}; + +static CONST struct asm_shift shift[] = +{ + {"asl", 0}, + {"lsl", 0}, + {"lsr", 0x00000020}, + {"asr", 0x00000040}, + {"ror", 0x00000060}, + {"rrx", 0x00000060}, + {"ASL", 0}, + {"LSL", 0}, + {"LSR", 0x00000020}, + {"ASR", 0x00000040}, + {"ROR", 0x00000060}, + {"RRX", 0x00000060} +}; + +#define NO_SHIFT_RESTRICT 1 +#define SHIFT_RESTRICT 0 + +#define NUM_FLOAT_VALS 8 + +CONST char *fp_const[] = +{ + "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0 +}; + +/* Number of littlenums required to hold an extended precision number */ +#define MAX_LITTLENUMS 6 + +LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS]; + +#define FAIL (-1) +#define SUCCESS (0) + +#define SUFF_S 1 +#define SUFF_D 2 +#define SUFF_E 3 +#define SUFF_P 4 + +#define CP_T_X 0x00008000 +#define CP_T_Y 0x00400000 +#define CP_T_Pre 0x01000000 +#define CP_T_UD 0x00800000 +#define CP_T_WB 0x00200000 + +#define TRANS_BIT (0x00200000) + +struct asm_cond +{ + CONST char *template; + unsigned long value; +}; + +/* This is to save a hash look-up in the common case */ +#define COND_ALWAYS 0xe0000000 + +static CONST struct asm_cond conds[] = +{ + {"eq", 0x00000000}, + {"ne", 0x10000000}, + {"cs", 0x20000000}, {"hs", 0x20000000}, + {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000}, + {"mi", 0x40000000}, + {"pl", 0x50000000}, + {"vs", 0x60000000}, + {"vc", 0x70000000}, + {"hi", 0x80000000}, + {"ls", 0x90000000}, + {"ge", 0xa0000000}, + {"lt", 0xb0000000}, + {"gt", 0xc0000000}, + {"le", 0xd0000000}, + {"al", 0xe0000000}, + {"nv", 0xf0000000} +}; + + +struct asm_flg +{ + CONST char *template; /* Basic flag string */ + unsigned long set_bits; /* Bits to set */ +}; + +static CONST struct asm_flg s_flag[] = +{ + {"s", 0x00100000}, + {NULL, 0} +}; + +static CONST struct asm_flg ldst_flags[] = +{ + {"b", 0x00400000}, + {"t", TRANS_BIT}, + {"bt", 0x00400000 | TRANS_BIT}, + {NULL, 0} +}; + +static CONST struct asm_flg byte_flag[] = +{ + {"b", 0x00400000}, + {NULL, 0} +}; + +static CONST struct asm_flg cmp_flags[] = +{ + {"s", 0x00100000}, + {"p", 0x0010f000}, + {NULL, 0} +}; + +static CONST struct asm_flg ldm_flags[] = +{ + {"ed", 0x01800000}, + {"fd", 0x00800000}, + {"ea", 0x01000000}, + {"fa", 0x08000000}, + {"ib", 0x01800000}, + {"ia", 0x00800000}, + {"db", 0x01000000}, + {"da", 0x08000000}, + {NULL, 0} +}; + +static CONST struct asm_flg stm_flags[] = +{ + {"ed", 0x08000000}, + {"fd", 0x01000000}, + {"ea", 0x00800000}, + {"fa", 0x01800000}, + {"ib", 0x01800000}, + {"ia", 0x00800000}, + {"db", 0x01000000}, + {"da", 0x08000000}, + {NULL, 0} +}; + +static CONST struct asm_flg lfm_flags[] = +{ + {"fd", 0x00800000}, + {"ea", 0x01000000}, + {NULL, 0} +}; + +static CONST struct asm_flg sfm_flags[] = +{ + {"fd", 0x01000000}, + {"ea", 0x00800000}, + {NULL, 0} +}; + +static CONST struct asm_flg round_flags[] = +{ + {"p", 0x00000020}, + {"m", 0x00000040}, + {"z", 0x00000060}, + {NULL, 0} +}; + +static CONST struct asm_flg except_flag[] = +{ + {"e", 0x00400000}, + {NULL, 0} +}; + +static CONST struct asm_flg cplong_flag[] = +{ + {"l", 0x00400000}, + {NULL, 0} +}; + +struct asm_psr +{ + CONST char *template; + unsigned long number; +}; + +#define PSR_ALL 0x00010000 + +static CONST struct asm_psr psrs[] = +{ + /* Valid 's */ + {"cpsr", 0}, + {"cpsr_all", 0}, + {"spsr", 1}, + {"spsr_all", 1}, + + /* Valid 's */ + {"cpsr_flg", 2}, + {"spsr_flg", 3} +}; + +/* Functions called by parser */ +/* ARM instructions */ +static void do_arit PARAMS ((char *operands, unsigned long flags)); +static void do_cmp PARAMS ((char *operands, unsigned long flags)); +static void do_mov PARAMS ((char *operands, unsigned long flags)); +static void do_ldst PARAMS ((char *operands, unsigned long flags)); +static void do_ldmstm PARAMS ((char *operands, unsigned long flags)); +static void do_branch PARAMS ((char *operands, unsigned long flags)); +static void do_swi PARAMS ((char *operands, unsigned long flags)); +/* Pseudo Op codes */ +static void do_adr PARAMS ((char *operands, unsigned long flags)); +static void do_nop PARAMS ((char *operands, unsigned long flags)); +/* ARM 2 */ +static void do_mul PARAMS ((char *operands, unsigned long flags)); +static void do_mla PARAMS ((char *operands, unsigned long flags)); +/* ARM 3 */ +static void do_swap PARAMS ((char *operands, unsigned long flags)); +/* ARM 6 */ +static void do_msr PARAMS ((char *operands, unsigned long flags)); +static void do_mrs PARAMS ((char *operands, unsigned long flags)); +/* ARM 7DM */ +static void do_mull PARAMS ((char *operands, unsigned long flags)); +/* Coprocessor Instructions */ +static void do_cdp PARAMS ((char *operands, unsigned long flags)); +static void do_lstc PARAMS ((char *operands, unsigned long flags)); +static void do_co_reg PARAMS ((char *operands, unsigned long flags)); +static void do_fp_ctrl PARAMS ((char *operands, unsigned long flags)); +static void do_fp_ldst PARAMS ((char *operands, unsigned long flags)); +static void do_fp_ldmstm PARAMS ((char *operands, unsigned long flags)); +static void do_fp_dyadic PARAMS ((char *operands, unsigned long flags)); +static void do_fp_monadic PARAMS ((char *operands, unsigned long flags)); +static void do_fp_cmp PARAMS ((char *operands, unsigned long flags)); +static void do_fp_from_reg PARAMS ((char *operands, unsigned long flags)); +static void do_fp_to_reg PARAMS ((char *operands, unsigned long flags)); + +static void fix_new_arm PARAMS ((fragS *frag, int where, + short int size, expressionS *exp, + int pc_rel, int reloc)); +static int arm_reg_parse PARAMS ((char **ccp)); +static int arm_psr_parse PARAMS ((char **ccp)); + +/* All instructions take 4 bytes in the object file */ + +#define INSN_SIZE 4 + +/* LONGEST_INST is the longest basic instruction name without conditions or + * flags. + * ARM7DM has 4 of length 5 + */ + +#define LONGEST_INST 5 + +struct asm_opcode +{ + CONST char *template; /* Basic string to match */ + unsigned long value; /* Basic instruction code */ + CONST char *comp_suffix; /* Compulsory suffix that must follow conds */ + CONST struct asm_flg *flags; /* Bits to toggle if flag 'n' set */ + unsigned long variants; /* Which CPU variants this exists for */ + void (*parms)(); /* Function to call to parse args */ +}; + +static CONST struct asm_opcode insns[] = +{ +/* ARM Instructions */ + {"and", 0x00000000, NULL, s_flag, ARM_ANY, do_arit}, + {"eor", 0x00200000, NULL, s_flag, ARM_ANY, do_arit}, + {"sub", 0x00400000, NULL, s_flag, ARM_ANY, do_arit}, + {"rsb", 0x00600000, NULL, s_flag, ARM_ANY, do_arit}, + {"add", 0x00800000, NULL, s_flag, ARM_ANY, do_arit}, + {"adc", 0x00a00000, NULL, s_flag, ARM_ANY, do_arit}, + {"sbc", 0x00c00000, NULL, s_flag, ARM_ANY, do_arit}, + {"rsc", 0x00e00000, NULL, s_flag, ARM_ANY, do_arit}, + {"orr", 0x01800000, NULL, s_flag, ARM_ANY, do_arit}, + {"bic", 0x01c00000, NULL, s_flag, ARM_ANY, do_arit}, + {"tst", 0x01000000, NULL, cmp_flags, ARM_ANY, do_cmp}, + {"teq", 0x01200000, NULL, cmp_flags, ARM_ANY, do_cmp}, + {"cmp", 0x01400000, NULL, cmp_flags, ARM_ANY, do_cmp}, + {"cmn", 0x01600000, NULL, cmp_flags, ARM_ANY, do_cmp}, + {"mov", 0x01a00000, NULL, s_flag, ARM_ANY, do_mov}, + {"mvn", 0x01e00000, NULL, s_flag, ARM_ANY, do_mov}, + {"str", 0x04000000, NULL, ldst_flags, ARM_ANY, do_ldst}, + {"ldr", 0x04100000, NULL, ldst_flags, ARM_ANY, do_ldst}, + {"stm", 0x08000000, NULL, stm_flags, ARM_ANY, do_ldmstm}, + {"ldm", 0x08100000, NULL, ldm_flags, ARM_ANY, do_ldmstm}, + {"swi", 0x0f000000, NULL, NULL, ARM_ANY, do_swi}, + {"bl", 0x0b000000, NULL, NULL, ARM_ANY, do_branch}, + {"b", 0x0a000000, NULL, NULL, ARM_ANY, do_branch}, + +/* Pseudo ops */ + {"adr", 0x028f0000, NULL, NULL, ARM_ANY, do_adr}, + {"nop", 0x01a00000, NULL, NULL, ARM_ANY, do_nop}, + +/* ARM 2 multiplies */ + {"mul", 0x00000090, NULL, s_flag, ARM_2UP, do_mul}, + {"mla", 0x00200090, NULL, s_flag, ARM_2UP, do_mla}, + +/* ARM 3 - swp instructions */ + {"swp", 0x01000090, NULL, byte_flag, ARM_3UP, do_swap}, + +/* ARM 6 Coprocessor instructions */ + {"mrs", 0x010f0000, NULL, NULL, ARM_6UP, do_mrs}, + {"msr", 0x0128f000, NULL, NULL, ARM_6UP, do_msr}, + +/* ARM 7DM long multiplies - need signed/unsigned flags! */ + {"smull", 0x00c00090, NULL, s_flag, ARM_LONGMUL, do_mull}, + {"umull", 0x00800090, NULL, s_flag, ARM_LONGMUL, do_mull}, + {"smlal", 0x00e00090, NULL, s_flag, ARM_LONGMUL, do_mull}, + {"umlal", 0x00a00090, NULL, s_flag, ARM_LONGMUL, do_mull}, + +/* Floating point instructions */ + {"wfs", 0x0e200110, NULL, NULL, FPU_ALL, do_fp_ctrl}, + {"rfs", 0x0e300110, NULL, NULL, FPU_ALL, do_fp_ctrl}, + {"wfc", 0x0e400110, NULL, NULL, FPU_ALL, do_fp_ctrl}, + {"rfc", 0x0e500110, NULL, NULL, FPU_ALL, do_fp_ctrl}, + {"ldf", 0x0c100100, "sdep", NULL, FPU_ALL, do_fp_ldst}, + {"stf", 0x0c000100, "sdep", NULL, FPU_ALL, do_fp_ldst}, + {"lfm", 0x0c100200, NULL, lfm_flags, FPU_MEMMULTI, do_fp_ldmstm}, + {"sfm", 0x0c000200, NULL, sfm_flags, FPU_MEMMULTI, do_fp_ldmstm}, + {"mvf", 0x0e008100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"mnf", 0x0e108100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"abs", 0x0e208100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"rnd", 0x0e308100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"sqt", 0x0e408100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"log", 0x0e508100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"lgn", 0x0e608100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"exp", 0x0e708100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"sin", 0x0e808100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"cos", 0x0e908100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"tan", 0x0ea08100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"asn", 0x0eb08100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"acs", 0x0ec08100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"atn", 0x0ed08100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"urd", 0x0ee08100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"nrm", 0x0ef08100, "sde", round_flags, FPU_ALL, do_fp_monadic}, + {"adf", 0x0e000100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"suf", 0x0e200100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"rsf", 0x0e300100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"muf", 0x0e100100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"dvf", 0x0e400100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"rdf", 0x0e500100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"pow", 0x0e600100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"rpw", 0x0e700100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"rmf", 0x0e800100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"fml", 0x0e900100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"fdv", 0x0ea00100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"frd", 0x0eb00100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"pol", 0x0ec00100, "sde", round_flags, FPU_ALL, do_fp_dyadic}, + {"cmf", 0x0e90f110, NULL, except_flag, FPU_ALL, do_fp_cmp}, + {"cnf", 0x0eb0f110, NULL, except_flag, FPU_ALL, do_fp_cmp}, +/* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should not + be an optional suffix, but part of the instruction. To be compatible, + we accept either. */ + {"cmfe", 0x0ed0f110, NULL, NULL, FPU_ALL, do_fp_cmp}, + {"cnfe", 0x0ef0f110, NULL, NULL, FPU_ALL, do_fp_cmp}, + {"flt", 0x0e000110, "sde", round_flags, FPU_ALL, do_fp_from_reg}, + {"fix", 0x0e100110, NULL, round_flags, FPU_ALL, do_fp_to_reg}, + +/* Generic copressor instructions */ + {"cdp", 0x0e000000, NULL, NULL, ARM_ANY, do_cdp}, + {"ldc", 0x0c100000, NULL, cplong_flag, ARM_ANY, do_lstc}, + {"stc", 0x0c000000, NULL, cplong_flag, ARM_ANY, do_lstc}, + {"mcr", 0x0e000010, NULL, NULL, ARM_ANY, do_co_reg}, + {"mrc", 0x0e100010, NULL, NULL, ARM_ANY, do_co_reg}, +}; + +/* defines for various bits that we will want to toggle */ + +#define INST_IMMEDIATE 0x02000000 +#define OFFSET_REG 0x02000000 +#define SHIFT_BY_REG 0x00000010 +#define PRE_INDEX 0x01000000 +#define INDEX_UP 0x00800000 +#define WRITE_BACK 0x00200000 +#define MULTI_SET_PSR 0x00400000 + +#define LITERAL_MASK 0xf000f000 +#define COND_MASK 0xf0000000 +#define OPCODE_MASK 0xfe1fffff +#define DATA_OP_SHIFT 21 + +/* 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 + +struct reg_entry +{ + CONST char *name; + int number; +}; + +#define int_register(reg) ((reg) >= 0 && (reg) <= 15) +#define cp_register(reg) ((reg) >= 32 && (reg) <= 47) +#define fp_register(reg) ((reg) >= 16 && (reg) <= 23) + +#define REG_PC 15 + +/* These are the standard names; Users can add aliases with .req */ +static CONST struct reg_entry reg_table[] = +{ + /* Processor Register Numbers */ + {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3}, + {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7}, + {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11}, + {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", REG_PC}, + /* APCS conventions */ + {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3}, + {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8}, + {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10}, + {"fp", 11}, {"ip", 12}, {"sp", 13}, {"lr", 14}, {"pc", REG_PC}, + /* FP Registers */ + {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19}, + {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23}, + {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35}, + {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39}, + {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43}, + {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47}, + {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35}, + {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39}, + {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43}, + {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47}, + {NULL, 0} +}; + +static CONST char *bad_args = "Bad arguments to instruction"; +static CONST char *bad_pc = "r15 not allowed here"; + +static struct hash_control *arm_ops_hsh = NULL; +static struct hash_control *arm_cond_hsh = NULL; +static struct hash_control *arm_shift_hsh = NULL; +static struct hash_control *arm_reg_hsh = NULL; +static struct hash_control *arm_psr_hsh = NULL; + +/* This table describes all the machine specific pseudo-ops the assembler + has to support. The fields are: + pseudo-op name without dot + function to call to execute this pseudo-op + Integer arg to pass to the function + */ + +static void s_req PARAMS ((int)); +static void s_align PARAMS ((int)); +static void s_bss PARAMS ((int)); +static void s_even PARAMS ((int)); +static void s_ltorg PARAMS ((int)); + +static int my_get_expression PARAMS ((expressionS *, char **)); + +CONST pseudo_typeS md_pseudo_table[] = +{ + {"req", s_req, 0}, /* Never called becasue '.req' does not start line */ + {"bss", s_bss, 0}, + {"align", s_align, 0}, + {"even", s_even, 0}, + {"ltorg", s_ltorg, 0}, + {"pool", s_ltorg, 0}, + {"word", cons, 4}, + {"extend", float_cons, 'x'}, + {"ldouble", float_cons, 'x'}, + {"packed", float_cons, 'p'}, + {0, 0, 0} +}; + +/* Stuff needed to resolve the label ambiguity + As: + ... + label: + may differ from: + ... + label: + +*/ + +symbolS *last_label_seen; + +/* Literal stuff */ + +#define MAX_LITERAL_POOL_SIZE 1024 + +typedef struct literalS +{ + struct expressionS exp; + struct arm_it *inst; +} literalT; + +literalT literals[MAX_LITERAL_POOL_SIZE]; +int next_literal_pool_place = 0; /* Next free entry in the pool */ +int lit_pool_num = 1; /* Next literal pool number */ +symbolS *current_poolP = NULL; +symbolS *symbol_make_empty (); + +static int +add_to_lit_pool () +{ + if (current_poolP == NULL) + current_poolP = symbol_make_empty(); + + if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE) + { + inst.error = "Literal Pool Overflow\n"; + return FAIL; + } + + literals[next_literal_pool_place].exp = inst.reloc.exp; + inst.reloc.exp.X_op = O_symbol; + inst.reloc.exp.X_add_number = (next_literal_pool_place++)*4-8; + inst.reloc.exp.X_add_symbol = current_poolP; + + return SUCCESS; +} + +/* Can't use symbol_new here, so have to create a symbol and them at + a later datete assign iot a value. Thats what these functions do */ +static void +symbol_locate (symbolP, name, segment, valu, frag) + symbolS *symbolP; + CONST char *name; /* It is copied, the caller can modify */ + segT segment; /* Segment identifier (SEG_) */ + valueT valu; /* Symbol value */ + fragS *frag; /* Associated fragment */ +{ + unsigned int name_length; + char *preserved_copy_of_name; + + name_length = strlen (name) + 1; /* +1 for \0 */ + obstack_grow (¬es, name, name_length); + preserved_copy_of_name = obstack_finish (¬es); +#ifdef STRIP_UNDERSCORE + if (preserved_copy_of_name[0] == '_') + preserved_copy_of_name++; +#endif + +#ifdef tc_canonicalize_symbol_name + preserved_copy_of_name = + tc_canonicalize_symbol_name (preserved_copy_of_name); +#endif + + S_SET_NAME (symbolP, preserved_copy_of_name); + + S_SET_SEGMENT (symbolP, segment); + S_SET_VALUE (symbolP, valu); + symbol_clear_list_pointers(symbolP); + + symbolP->sy_frag = frag; + + /* + * Link to end of symbol chain. + */ + { + extern int symbol_table_frozen; + if (symbol_table_frozen) + abort (); + } + + symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP); + + obj_symbol_new_hook (symbolP); + +#ifdef tc_symbol_new_hook + tc_symbol_new_hook (symbolP); +#endif + +#ifdef DEBUG_SYMS + verify_symbol_chain(symbol_rootP, symbol_lastP); +#endif /* DEBUG_SYMS */ +} + +symbolS * +symbol_make_empty () +{ + symbolS *symbolP; + + symbolP = (symbolS *) obstack_alloc (¬es, sizeof (symbolS)); + + /* symbol must be born in some fixed state. This seems as good as any. */ + memset (symbolP, 0, sizeof (symbolS)); + +#ifdef BFD_ASSEMBLER + symbolP->bsym = bfd_make_empty_symbol (stdoutput); + assert (symbolP->bsym != 0); + symbolP->bsym->udata.p = (PTR) symbolP; +#endif + + return symbolP; +} + +/* Check that an immediate is valid, and if so, convert it to the right format + */ + +/* OH, for a rotate instruction in C! */ + +static int +validate_immediate (val) + int val; +{ + unsigned int a = (unsigned int) val; + int i; + + /* Do the easy (and most common ones) quickly */ + for (i = 0; i <= 24; i += 2) + { + if ((a & (0xff << i)) == a) + return (int) (((32 - i) & 0x1e) << 7) | ((a >> i) & 0xff); + } + + /* Now do the harder ones */ + for (; i < 32; i += 2) + { + if ((a & ((0xff << i) | (0xff >> (32 - i)))) == a) + { + a = ((a >> i) & 0xff) | ((a << (32 - i)) & 0xff); + return (int) a | (((32 - i) >> 1) << 8); + } + } + return FAIL; +} + +static int +validate_offset_imm (val) + int val; +{ + if (val < -4095 || val > 4095) + as_bad ("bad immediate value for offset (%d)", val); + return val; +} + + +static void +s_req (a) + int a; +{ + as_bad ("Invalid syntax for .req directive."); +} + +static void +s_bss (ignore) + int ignore; +{ + /* We don't support putting frags in the BSS segment, we fake it by + marking in_bss, then looking at s_skip for clues?.. */ + subseg_set (bss_section, 0); + demand_empty_rest_of_line (); +} + +static void +s_even (ignore) + int ignore; +{ + if (!need_pass_2) /* Never make frag if expect extra pass. */ + frag_align (1, 0); + record_alignment (now_seg, 1); + demand_empty_rest_of_line (); +} + +static void +s_ltorg (internal) + int internal; +{ + int lit_count = 0; + char sym_name[20]; + + if (current_poolP == NULL) + { + /* Nothing to do */ + if (!internal) + as_tsktsk ("Nothing to put in the pool\n"); + return; + } + + /* Align pool as you have word accesses */ + /* Only make a frag if we have to ... */ + if (!need_pass_2) + frag_align (2, 0); + + record_alignment (now_seg, 2); + + if (internal) + as_tsktsk ("Inserting implicit pool at change of section"); + + sprintf (sym_name, "$$lit_\002%x", lit_pool_num++); + + symbol_locate (current_poolP, sym_name, now_seg, + (valueT) frag_now_fix (), frag_now); + symbol_table_insert (current_poolP); + + while (lit_count < next_literal_pool_place) + /* First output the expression in the instruction to the pool */ + emit_expr (&(literals[lit_count++].exp), 4); /* .word */ + + next_literal_pool_place = 0; + current_poolP = NULL; +} + +static void +arm_align (power, fill) + int power; + int fill; +{ + /* Only make a frag if we HAVE to ... */ + if (power && !need_pass_2) + frag_align (power, fill); + + record_alignment (now_seg, power); +} + +static void +s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */ + int unused; +{ + register int temp; + register long temp_fill; + long max_alignment = 15; + + temp = get_absolute_expression (); + if (temp > max_alignment) + as_bad ("Alignment too large: %d. assumed.", temp = max_alignment); + else if (temp < 0) + { + as_bad ("Alignment negative. 0 assumed."); + temp = 0; + } + + if (*input_line_pointer == ',') + { + input_line_pointer++; + temp_fill = get_absolute_expression (); + } + else + temp_fill = 0; + + if (!temp) + temp = 2; + + /* Only make a frag if we HAVE to. . . */ + if (temp && !need_pass_2) + frag_align (temp, (int) temp_fill); + demand_empty_rest_of_line (); + + record_alignment (now_seg, temp); +} + +static void +end_of_line (str) + char *str; +{ + while (*str == ' ') + str++; + + if (*str != '\0') + inst.error = "Garbage following instruction"; +} + +static int +skip_past_comma (str) + char **str; +{ + char *p = *str, c; + int comma = 0; + + while ((c = *p) == ' ' || c == ',') + { + p++; + if (c == ',' && comma++) + return FAIL; + } + + if (c == '\0') + return FAIL; + + *str = p; + return comma ? SUCCESS : FAIL; +} + +/* A standard register must be given at this point. Shift is the place to + put it in the instruction. */ + +static int +reg_required_here (str, shift) + char **str; + int shift; +{ + int reg; + char *start = *str; + + if ((reg = arm_reg_parse (str)) != FAIL && int_register (reg)) + { + inst.instruction |= reg << shift; + return reg; + } + + /* In the few cases where we might be able to accept something else + this error can be overridden */ + inst.error = "Register expected"; + + /* Restore the start point, we may have got a reg of the wrong class. */ + *str = start; + return FAIL; +} + +static int +psr_required_here (str, shift) + char **str; + int shift; +{ + int psr; + char *start = *str; + + if ((psr = arm_psr_parse (str)) != FAIL && psr < 2) + { + if (psr == 1) + inst.instruction |= 1 << shift; /* Should be bit 22 */ + return psr; + } + + /* In the few cases where we might be able to accept something else + this error can be overridden */ + inst.error = " expected"; + + /* Restore the start point. */ + *str = start; + return FAIL; +} + +static int +psrf_required_here (str, shift) + char **str; + int shift; +{ + int psrf; + char *start = *str; + + if ((psrf = arm_psr_parse (str)) != FAIL && psrf > 1) + { + if (psrf == 1 || psrf == 3) + inst.instruction |= 1 << shift; /* Should be bit 22 */ + return psrf; + } + + /* In the few cases where we might be able to accept something else + this error can be overridden */ + inst.error = " expected"; + + /* Restore the start point. */ + *str = start; + return FAIL; +} + +static int +co_proc_number (str) + char **str; +{ + int processor, pchar; + + while (**str == ' ') + (*str)++; + + /* The data sheet seems to imply that just a number on its own is valid + here, but the RISC iX assembler seems to accept a prefix 'p'. We will + accept either. */ + if (**str == 'p' || **str == 'P') + (*str)++; + + pchar = *(*str)++; + if (pchar >= '0' && pchar <= '9') + { + processor = pchar - '0'; + if (**str >= '0' && **str <= '9') + { + processor = processor * 10 + *(*str)++ - '0'; + if (processor > 15) + { + inst.error = "Illegal co-processor number"; + return FAIL; + } + } + } + else + { + inst.error = "Bad or missing co-processor number"; + return FAIL; + } + + inst.instruction |= processor << 8; + return SUCCESS; +} + +static int +cp_opc_expr (str, where, length) + char **str; + int where; + int length; +{ + expressionS expr; + + while (**str == ' ') + (*str)++; + + memset (&expr, '\0', sizeof (expr)); + + if (my_get_expression (&expr, str)) + return FAIL; + if (expr.X_op != O_constant) + { + inst.error = "bad or missing expression"; + return FAIL; + } + + if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number) + { + inst.error = "immediate co-processor expression too large"; + return FAIL; + } + + inst.instruction |= expr.X_add_number << where; + return SUCCESS; +} + +static int +cp_reg_required_here (str, where) + char **str; + int where; +{ + int reg; + char *start = *str; + + if ((reg = arm_reg_parse (str)) != FAIL && cp_register (reg)) + { + reg &= 15; + inst.instruction |= reg << where; + return reg; + } + + /* In the few cases where we might be able to accept something else + this error can be overridden */ + inst.error = "Co-processor register expected"; + + /* Restore the start point */ + *str = start; + return FAIL; +} + +static int +fp_reg_required_here (str, where) + char **str; + int where; +{ + int reg; + char *start = *str; + + if ((reg = arm_reg_parse (str)) != FAIL && fp_register (reg)) + { + reg &= 7; + inst.instruction |= reg << where; + return reg; + } + + /* In the few cases where we might be able to accept something else + this error can be overridden */ + inst.error = "Floating point register expected"; + + /* Restore the start point */ + *str = start; + return FAIL; +} + +static int +cp_address_offset (str) + char **str; +{ + int offset; + + while (**str == ' ') + (*str)++; + + if (**str != '#') + { + inst.error = "immediate expression expected"; + return FAIL; + } + + (*str)++; + if (my_get_expression (&inst.reloc.exp, str)) + return FAIL; + if (inst.reloc.exp.X_op == O_constant) + { + offset = inst.reloc.exp.X_add_number; + if (offset & 3) + { + inst.error = "co-processor address must be word aligned"; + return FAIL; + } + + if (offset > 1023 || offset < -1023) + { + inst.error = "offset too large"; + return FAIL; + } + + if (offset >= 0) + inst.instruction |= INDEX_UP; + else + offset = -offset; + + inst.instruction |= offset >> 2; + } + else + inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM; + + return SUCCESS; +} + +static int +cp_address_required_here (str) + char **str; +{ + char *p = *str; + int pre_inc = 0; + int write_back = 0; + + if (*p == '[') + { + int reg; + + p++; + while (*p == ' ') + p++; + + if ((reg = reg_required_here (&p, 16)) == FAIL) + { + inst.error = "Register required"; + return FAIL; + } + + while (*p == ' ') + p++; + + if (*p == ']') + { + p++; + if (skip_past_comma (&p) == SUCCESS) + { + /* [Rn], #expr */ + write_back = WRITE_BACK; + if (reg == REG_PC) + { + inst.error = "pc may not be used in post-increment"; + return FAIL; + } + + if (cp_address_offset (&p) == FAIL) + return FAIL; + } + else + pre_inc = PRE_INDEX | INDEX_UP; + } + else + { + /* '['Rn, #expr']'[!] */ + + if (skip_past_comma (&p) == FAIL) + { + inst.error = "pre-indexed expression expected"; + return FAIL; + } + + pre_inc = PRE_INDEX; + if (cp_address_offset (&p) == FAIL) + return FAIL; + + while (*p == ' ') + p++; + + if (*p++ != ']') + { + inst.error = "missing ]"; + return FAIL; + } + + while (*p == ' ') + p++; + + if (*p == '!') + { + if (reg == REG_PC) + { + inst.error = "pc may not be used with write-back"; + return FAIL; + } + + p++; + write_back = WRITE_BACK; + } + } + } + else + { + if (my_get_expression (&inst.reloc.exp, &p)) + return FAIL; + + inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM; + inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */ + inst.reloc.pc_rel = 1; + inst.instruction |= (REG_PC << 16); + } + + inst.instruction |= write_back | pre_inc; + *str = p; + return SUCCESS; +} + +static void +do_nop (str, flags) + char *str; + unsigned long flags; +{ + /* Do nothing really */ + inst.instruction |= flags; /* This is pointless */ + end_of_line (str); + return; +} + +static void +do_mrs (str, flags) + char *str; + unsigned long flags; +{ + /* Only one syntax */ + while (*str == ' ') + str++; + + if (reg_required_here (&str, 12) == FAIL) + { + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || psr_required_here (&str, 22) == FAIL) + { + inst.error = " expected"; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_msr (str, flags) + char *str; + unsigned long flags; +{ + int psr, psrf, reg; + /* Three possible forms: ", Rm", ", Rm", ", #expression" */ + + while (*str == ' ') + str++; + + if ((psr = psr_required_here (&str, 22)) != FAIL) + { + inst.instruction |= PSR_ALL; + /* Sytax should be ", Rm" */ + if (skip_past_comma (&str) == FAIL + || (reg = reg_required_here (&str, 0)) == FAIL) + { + inst.error = bad_args; + return; + } + } + else if ((psrf = psrf_required_here (&str, 22)) != FAIL) + /* Syntax could be ", rm", ", #expression" */ + { + if (skip_past_comma (&str) == FAIL) + { + inst.error = bad_args; + return; + } + if ((reg = reg_required_here (&str, 0)) != FAIL) + ; + /* Immediate expression */ + else if (*(str++) == '#') + { + inst.error = NULL; + if (my_get_expression (&inst.reloc.exp, &str)) + { + inst.error = "Register or shift expression expected"; + return; + } + + if (inst.reloc.exp.X_add_symbol) + { + inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE; + inst.reloc.pc_rel = 0; + } + else + { + int value = validate_immediate (inst.reloc.exp.X_add_number); + if (value == FAIL) + { + inst.error = "Invalid constant"; + return; + } + + inst.instruction |= value; + } + + flags |= INST_IMMEDIATE; + } + else + { + inst.error = "Error: the other"; + return; + } + } + else + { + inst.error = bad_args; + return; + } + + inst.error = NULL; + inst.instruction |= flags; + end_of_line (str); + return; +} + +/* Long Multiply Parser + UMULL RdLo, RdHi, Rm, Rs + SMULL RdLo, RdHi, Rm, Rs + UMLAL RdLo, RdHi, Rm, Rs + SMLAL RdLo, RdHi, Rm, Rs +*/ +static void +do_mull (str, flags) + char *str; + unsigned long flags; +{ + int rdlo, rdhi, rm, rs; + + /* only one format "rdlo, rdhi, rm, rs" */ + while (*str == ' ') + str++; + + if ((rdlo = reg_required_here (&str, 12)) == FAIL) + { + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || (rdhi = reg_required_here (&str, 16)) == FAIL) + { + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || (rm = reg_required_here (&str, 0)) == FAIL) + { + inst.error = bad_args; + return; + } + + /* rdhi, rdlo and rm must all be different */ + if (rdlo == rdhi || rdlo == rm || rdhi == rm) + as_tsktsk ("rdhi, rdlo and rm must all be different"); + + if (skip_past_comma (&str) == FAIL + || (rs = reg_required_here (&str, 8)) == FAIL) + { + inst.error = bad_args; + return; + } + + if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC) + { + inst.error = bad_pc; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_mul (str, flags) + char *str; + unsigned long flags; +{ + int rd, rm; + + /* only one format "rd, rm, rs" */ + while (*str == ' ') + str++; + + if ((rd = reg_required_here (&str, 16)) == FAIL) + { + inst.error = bad_args; + return; + } + + if (rd == REG_PC) + { + inst.error = bad_pc; + return; + } + + if (skip_past_comma (&str) == FAIL + || (rm = reg_required_here (&str, 0)) == FAIL) + { + inst.error = bad_args; + return; + } + + if (rm == REG_PC) + { + inst.error = bad_pc; + return; + } + + if (rm == rd) + as_tsktsk ("rd and rm should be different in mul"); + + if (skip_past_comma (&str) == FAIL + || (rm = reg_required_here (&str, 8)) == FAIL) + { + inst.error = bad_args; + return; + } + + if (rm == REG_PC) + { + inst.error = bad_pc; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_mla (str, flags) + char *str; + unsigned long flags; +{ + int rd, rm; + + /* only one format "rd, rm, rs, rn" */ + while (*str == ' ') + str++; + + if ((rd = reg_required_here (&str, 16)) == FAIL) + { + inst.error = bad_args; + return; + } + + if (rd == REG_PC) + { + inst.error = bad_pc; + return; + } + + if (skip_past_comma (&str) == FAIL + || (rm = reg_required_here (&str, 0)) == FAIL) + { + inst.error = bad_args; + return; + } + + if (rm == REG_PC) + { + inst.error = bad_pc; + return; + } + + if (rm == rd) + as_tsktsk ("rd and rm should be different in mla"); + + if (skip_past_comma (&str) == FAIL + || (rd = reg_required_here (&str, 8)) == FAIL + || skip_past_comma (&str) == FAIL + || (rm = reg_required_here (&str, 12)) == FAIL) + { + inst.error = bad_args; + return; + } + + if (rd == REG_PC || rm == REG_PC) + { + inst.error = bad_pc; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +/* Returns the index into fp_values of a floating point number, or -1 if + not in the table. */ +static int +my_get_float_expression (str) + char **str; +{ + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + char *save_in; + expressionS exp; + int i, j; + + memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE)); + /* Look for a raw floating point number */ + if ((save_in = atof_ieee (*str, 'x', words)) != NULL + && (is_end_of_line [(int)(*save_in)] || *save_in == '\0')) + { + for (i = 0; i < NUM_FLOAT_VALS; i++) + { + for (j = 0; j < MAX_LITTLENUMS; j++) + { + if (words[j] != fp_values[i][j]) + break; + } + + if (j == MAX_LITTLENUMS) + { + *str = save_in; + return i; + } + } + } + + /* Try and parse a more complex expression, this will probably fail + unless the code uses a floating point prefix (eg "0f") */ + save_in = input_line_pointer; + input_line_pointer = *str; + if (expression (&exp) == absolute_section + && exp.X_op == O_big + && exp.X_add_number < 0) + { + if (gen_to_words (words, 6, (long)15) == 0) + { + for (i = 0; i < NUM_FLOAT_VALS; i++) + { + for (j = 0; j < MAX_LITTLENUMS; j++) + { + if (words[j] != fp_values[i][j]) + break; + } + + if (j == MAX_LITTLENUMS) + { + *str = input_line_pointer; + input_line_pointer = save_in; + return i; + } + } + } + } + + *str = input_line_pointer; + input_line_pointer = save_in; + return -1; +} + +/* Return true if anything in the expression is a bignum */ +static int +walk_no_bignums (sp) + symbolS *sp; +{ + if (sp->sy_value.X_op == O_big) + return 1; + + if (sp->sy_value.X_add_symbol) + { + return (walk_no_bignums (sp->sy_value.X_add_symbol) + || (sp->sy_value.X_op_symbol + && walk_no_bignums (sp->sy_value.X_op_symbol))); + } + + return 0; +} + +static int +my_get_expression (ep, str) + expressionS *ep; + char **str; +{ + char *save_in; + segT seg; + + save_in = input_line_pointer; + input_line_pointer = *str; + seg = expression (ep); + if (seg != absolute_section + && seg != text_section + && seg != data_section + && seg != bss_section + && seg != undefined_section) + { + inst.error = "bad_segment"; + *str = input_line_pointer; + input_line_pointer = save_in; + return 1; + } + + /* Get rid of any bignums now, so that we don't generate an error for which + we can't establish a line number later on. Big numbers are never valid + in instructions, which is where is routine is always called. */ + if (ep->X_op == O_big + || (ep->X_add_symbol + && (walk_no_bignums (ep->X_add_symbol) + || (ep->X_op_symbol + && walk_no_bignums (ep->X_op_symbol))))) + { + inst.error = "Invalid constant"; + *str = input_line_pointer; + input_line_pointer = save_in; + return 1; + } + + *str = input_line_pointer; + input_line_pointer = save_in; + return 0; +} + +/* unrestrict should be one if is permitted for this + instruction */ + +static int +decode_shift (str, unrestrict) + char **str; + int unrestrict; +{ + struct asm_shift *shft; + char *p; + char c; + + while (**str == ' ') + (*str)++; + + for (p = *str; isalpha (*p); p++) + ; + + if (p == *str) + { + inst.error = "Shift expression expected"; + return FAIL; + } + + c = *p; + *p = '\0'; + shft = (struct asm_shift *) hash_find (arm_shift_hsh, *str); + *p = c; + if (shft) + { + if (!strcmp (*str, "rrx")) + { + *str = p; + inst.instruction |= shft->value; + return SUCCESS; + } + + while (*p == ' ') + p++; + + if (unrestrict && reg_required_here (&p, 8) != FAIL) + { + inst.instruction |= shft->value | SHIFT_BY_REG; + *str = p; + return SUCCESS; + } + else if (*p == '#') + { + inst.error = NULL; + p++; + if (my_get_expression (&inst.reloc.exp, &p)) + return FAIL; + + /* Validate some simple #expressions */ + if (! inst.reloc.exp.X_add_symbol) + { + int num = inst.reloc.exp.X_add_number; + if (num < 0 || num > 32 + || (num == 32 + && (shft->value == 0 || shft->value == 0x60))) + { + inst.error = "Invalid immediate shift"; + return FAIL; + } + + /* Shifts of zero should be converted to lsl (which is zero)*/ + if (num == 0) + { + *str = p; + return SUCCESS; + } + + /* Shifts of 32 are encoded as 0, for those shifts that + support it. */ + if (num == 32) + num = 0; + + inst.instruction |= (num << 7) | shft->value; + *str = p; + return SUCCESS; + } + + inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM; + inst.reloc.pc_rel = 0; + inst.instruction |= shft->value; + *str = p; + return SUCCESS; + } + else + { + inst.error = unrestrict ? "shift requires register or #expression" + : "shift requires #expression"; + *str = p; + return FAIL; + } + } + + inst.error = "Shift expression expected"; + return FAIL; +} + +/* Do those data_ops which can take a negative immediate constant */ +/* by altering the instuction. A bit of a hack really */ +/* MOV <-> MVN + AND <-> BIC + ADC <-> SBC + by inverting the second operand, and + ADD <-> SUB + CMP <-> CMN + by negating the second operand. +*/ +static int +negate_data_op (instruction, value) + unsigned long *instruction; + unsigned long value; +{ + int op, new_inst; + unsigned long negated, inverted; + + negated = validate_immediate (-value); + inverted = validate_immediate (~value); + + op = (*instruction >> DATA_OP_SHIFT) & 0xf; + switch (op) + { + /* First negates */ + case OPCODE_SUB: /* ADD <-> SUB */ + new_inst = OPCODE_ADD; + value = negated; + break; + + case OPCODE_ADD: + new_inst = OPCODE_SUB; + value = negated; + break; + + case OPCODE_CMP: /* CMP <-> CMN */ + new_inst = OPCODE_CMN; + value = negated; + break; + + case OPCODE_CMN: + new_inst = OPCODE_CMP; + value = negated; + break; + + /* Now Inverted ops */ + case OPCODE_MOV: /* MOV <-> MVN */ + new_inst = OPCODE_MVN; + value = inverted; + break; + + case OPCODE_MVN: + new_inst = OPCODE_MOV; + value = inverted; + break; + + case OPCODE_AND: /* AND <-> BIC */ + new_inst = OPCODE_BIC; + value = inverted; + break; + + case OPCODE_BIC: + new_inst = OPCODE_AND; + value = inverted; + break; + + case OPCODE_ADC: /* ADC <-> SBC */ + new_inst = OPCODE_SBC; + value = inverted; + break; + + case OPCODE_SBC: + new_inst = OPCODE_ADC; + value = inverted; + break; + + /* We cannot do anything */ + default: + return FAIL; + } + + if (value == FAIL) + return FAIL; + + *instruction &= OPCODE_MASK; + *instruction |= new_inst << DATA_OP_SHIFT; + return value; +} + +static int +data_op2 (str) + char **str; +{ + int value; + expressionS expr; + + while (**str == ' ') + (*str)++; + + if (reg_required_here (str, 0) != FAIL) + { + if (skip_past_comma (str) == SUCCESS) + { + /* Shift operation on register */ + return decode_shift (str, NO_SHIFT_RESTRICT); + } + return SUCCESS; + } + else + { + /* Immediate expression */ + if (*((*str)++) == '#') + { + inst.error = NULL; + if (my_get_expression (&inst.reloc.exp, str)) + return FAIL; + + if (inst.reloc.exp.X_add_symbol) + { + inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE; + inst.reloc.pc_rel = 0; + } + else + { + if (skip_past_comma (str) == SUCCESS) + { + /* #x, y -- ie explicit rotation by Y */ + if (my_get_expression (&expr, str)) + return FAIL; + + if (expr.X_op != O_constant) + { + inst.error = "Constant expression expected"; + return FAIL; + } + + /* Rotate must be a multiple of 2 */ + if (((unsigned) expr.X_add_number) > 30 + || (expr.X_add_number & 1) != 0 + || ((unsigned) inst.reloc.exp.X_add_number) > 255) + { + inst.error = "Invalid constant"; + return FAIL; + } + inst.instruction |= INST_IMMEDIATE; + inst.instruction |= inst.reloc.exp.X_add_number; + inst.instruction |= expr.X_add_number << 7; + return SUCCESS; + } + + /* Implicit rotation, select a suitable one */ + value = validate_immediate (inst.reloc.exp.X_add_number); + + if (value == FAIL) + { + /* Can't be done, perhaps the code reads something like + "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be ok */ + if ((value = negate_data_op (&inst.instruction, + inst.reloc.exp.X_add_number)) + == FAIL) + { + inst.error = "Invalid constant"; + return FAIL; + } + } + + inst.instruction |= value; + } + + inst.instruction |= INST_IMMEDIATE; + return SUCCESS; + } + + inst.error = "Register or shift expression expected"; + return FAIL; + } +} + +static int +fp_op2 (str, flags) + char **str; + unsigned long flags; +{ + while (**str == ' ') + (*str)++; + + if (fp_reg_required_here (str, 0) != FAIL) + return SUCCESS; + else + { + /* Immediate expression */ + if (*((*str)++) == '#') + { + int i; + + inst.error = NULL; + while (**str == ' ') + (*str)++; + + /* First try and match exact strings, this is to guarantee that + some formats will work even for cross assembly */ + + for (i = 0; fp_const[i]; i++) + { + if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0) + { + char *start = *str; + + *str += strlen (fp_const[i]); + if (is_end_of_line[(int)**str] || **str == '\0') + { + inst.instruction |= i + 8; + return SUCCESS; + } + *str = start; + } + } + + /* Just because we didn't get a match doesn't mean that the + constant isn't valid, just that it is in a format that we + don't automatically recognize. Try parsing it with + the standard expression routines. */ + if ((i = my_get_float_expression (str)) >= 0) + { + inst.instruction |= i + 8; + return SUCCESS; + } + + inst.error = "Invalid floating point immediate expression"; + return FAIL; + } + inst.error = "Floating point register or immediate expression expected"; + return FAIL; + } +} + +static void +do_arit (str, flags) + char *str; + unsigned long flags; +{ + while (*str == ' ') + str++; + + if (reg_required_here (&str, 12) == FAIL + || skip_past_comma (&str) == FAIL + || reg_required_here (&str, 16) == FAIL + || skip_past_comma (&str) == FAIL + || data_op2 (&str) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_adr (str, flags) + char *str; + unsigned long flags; +{ + /* This is a pseudo-op of the form "adr rd, label" to be converted into + a relative address of the form add rd, pc, #label-.-8 */ + + while (*str == ' ') + str++; + + if (reg_required_here (&str, 12) == FAIL + || skip_past_comma (&str) == FAIL + || my_get_expression (&inst.reloc.exp, &str)) + { + if (!inst.error) + inst.error = bad_args; + return; + } + /* Frag hacking will turn this into a sub instruction if the offset turns + out to be negative. */ + inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE; + inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */ + inst.reloc.pc_rel = 1; + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_cmp (str, flags) + char *str; + unsigned long flags; +{ + while (*str == ' ') + str++; + + if (reg_required_here (&str, 16) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || data_op2 (&str) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + inst.instruction |= flags; + if ((flags & 0x0000f000) == 0) + inst.instruction |= 0x00100000; + + end_of_line (str); + return; +} + +static void +do_mov (str, flags) + char *str; + unsigned long flags; +{ + while (*str == ' ') + str++; + + if (reg_required_here (&str, 12) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || data_op2 (&str) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static int +ldst_extend (str) + char **str; +{ + int add = INDEX_UP; + + switch (**str) + { + case '#': + (*str)++; + if (my_get_expression (&inst.reloc.exp, str)) + return FAIL; + + if (inst.reloc.exp.X_op == O_constant) + { + int value = inst.reloc.exp.X_add_number; + + if (value < -4095 || value > 4095) + { + inst.error = "address offset too large"; + return FAIL; + } + + if (value < 0) + { + value = -value; + add = 0; + } + + inst.instruction |= add | value; + } + else + { + inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM; + inst.reloc.pc_rel = 0; + } + return SUCCESS; + + case '-': + add = 0; /* and fall through */ + case '+': + (*str)++; /* and fall through */ + default: + if (reg_required_here (str, 0) == FAIL) + { + inst.error = "Register expected"; + return FAIL; + } + inst.instruction |= add | OFFSET_REG; + if (skip_past_comma (str) == SUCCESS) + return decode_shift (str, SHIFT_RESTRICT); + return SUCCESS; + } +} + +static void +do_ldst (str, flags) + char *str; + unsigned long flags; +{ + int pre_inc = 0; + int conflict_reg; + int value; + + while (*str == ' ') + str++; + + if ((conflict_reg = reg_required_here (&str, 12)) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL) + { + inst.error = "Address expected"; + return; + } + + if (*str == '[') + { + int reg; + + str++; + while (*str == ' ') + str++; + + if ((reg = reg_required_here (&str, 16)) == FAIL) + { + inst.error = "Register required"; + return; + } + + conflict_reg = (((conflict_reg == reg) + && (inst.instruction & 0x00100000)) + ? 1 : 0); + + while (*str == ' ') + str++; + + if (*str == ']') + { + str++; + if (skip_past_comma (&str) == SUCCESS) + { + /* [Rn],... (post inc) */ + if (ldst_extend (&str) == FAIL) + return; + if (conflict_reg) + as_warn ("destination register same as write-back base\n"); + } + else + { + /* [Rn] */ + flags |= INDEX_UP; + if (! (flags & TRANS_BIT)) + pre_inc = 1; + } + } + else + { + /* [Rn,...] */ + if (skip_past_comma (&str) == FAIL) + { + inst.error = "pre-indexed expression expected"; + return; + } + + pre_inc = 1; + if (ldst_extend (&str) == FAIL) + return; + + while (*str == ' ') + str++; + + if (*str++ != ']') + { + inst.error = "missing ]"; + return; + } + + while (*str == ' ') + str++; + + if (*str == '!') + { + if (conflict_reg) + as_warn ("destination register same as write-back base\n"); + str++; + inst.instruction |= WRITE_BACK; + } + } + } + else if (*str == '=') + { + /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */ + str++; + + while (*str == ' ') + str++; + + if (my_get_expression (&inst.reloc.exp, &str)) + return; + + if (inst.reloc.exp.X_op != O_constant + && inst.reloc.exp.X_op != O_symbol) + { + inst.error = "Constant expression expected"; + return; + } + + if (inst.reloc.exp.X_op == O_constant + && (value = validate_immediate(inst.reloc.exp.X_add_number)) != FAIL) + { + /* This can be done with a mov instruction */ + inst.instruction &= LITERAL_MASK; + inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT); + inst.instruction |= (flags & COND_MASK) | (value & 0xfff); + end_of_line(str); + return; + } + else + { + /* Insert into literal pool */ + if (add_to_lit_pool () == FAIL) + { + if (!inst.error) + inst.error = "literal pool insertion failed\n"; + return; + } + + /* Change the instruction exp to point to the pool */ + inst.reloc.type = BFD_RELOC_ARM_LITERAL; + inst.reloc.pc_rel = 1; + inst.instruction |= (REG_PC << 16); + pre_inc = 1; + } + } + else + { + if (my_get_expression (&inst.reloc.exp, &str)) + return; + + inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM; + inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */ + inst.reloc.pc_rel = 1; + inst.instruction |= (REG_PC << 16); + pre_inc = 1; + } + + if (pre_inc && (flags & TRANS_BIT)) + inst.error = "Pre-increment instruction with translate"; + + inst.instruction |= flags | (pre_inc ? PRE_INDEX : 0); + end_of_line (str); + return; +} + +static void +do_ldmstm (str, flags) + char *str; + unsigned long flags; +{ + int base_reg; + + while (*str == ' ') + str++; + + if ((base_reg = reg_required_here (&str, 16)) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (base_reg == REG_PC) + { + inst.error = "r15 not allowed as base register"; + return; + } + + while (*str == ' ') + str++; + if (*str == '!') + { + flags |= WRITE_BACK; + str++; + } + + if (skip_past_comma (&str) == FAIL) + { + inst.error = bad_args; + return; + } + + /* We come back here if we get ranges concatenated by '+' or '|' */ + another_range: + if (*str == '{') + { + int in_range = 0; + int cur_reg = -1; + + str++; + do + { + int reg; + + while (*str == ' ') + str++; + + if ((reg = arm_reg_parse (&str)) == FAIL || !int_register (reg)) + { + inst.error = "Register expected"; + return; + } + + if (in_range) + { + int i; + + if (reg <= cur_reg) + { + inst.error = "Bad range in register list"; + return; + } + + for (i = cur_reg + 1; i < reg; i++) + { + if (flags & (1 << i)) + as_tsktsk + ("Warning: Duplicated register (r%d) in register list", + i); + else + flags |= 1 << i; + } + in_range = 0; + } + + if (flags & (1 << reg)) + as_tsktsk ("Warning: Duplicated register (r%d) in register list", + reg); + else if (reg <= cur_reg) + as_tsktsk ("Warning: Register range not in ascending order"); + + flags |= 1 << reg; + cur_reg = reg; + } while (skip_past_comma (&str) != FAIL + || (in_range = 1, *str++ == '-')); + str--; + while (*str == ' ') + str++; + + if (*str++ != '}') + { + inst.error = "Missing `}'"; + return; + } + } + else + { + expressionS expr; + + if (my_get_expression (&expr, &str)) + return; + + if (expr.X_op == O_constant) + { + if (expr.X_add_number + != (expr.X_add_number & 0x0000ffff)) + { + inst.error = "invalid register mask"; + return; + } + + if ((flags & expr.X_add_number) != 0) + { + int regno = flags & expr.X_add_number; + + regno &= -regno; + regno = (1 << regno) - 1; + as_tsktsk ("Warning: Duplicated register (r%d) in register list", + regno); + } + + flags |= expr.X_add_number; + } + else + { + if (inst.reloc.type != 0) + { + inst.error = "expression too complex"; + return; + } + + memcpy (&inst.reloc.exp, &expr, sizeof (expressionS)); + inst.reloc.type = BFD_RELOC_ARM_MULTI; + inst.reloc.pc_rel = 0; + } + } + + while (*str == ' ') + str++; + + if (*str == '|' || *str == '+') + { + str++; + goto another_range; + } + + if (*str == '^') + { + str++; + flags |= MULTI_SET_PSR; + } + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_swi (str, flags) + char *str; + unsigned long flags; +{ + /* Allow optional leading '#'. */ + while (*str == ' ') + str++; + if (*str == '#') + str++; + + if (my_get_expression (&inst.reloc.exp, &str)) + return; + + inst.reloc.type = BFD_RELOC_ARM_SWI; + inst.reloc.pc_rel = 0; + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_swap (str, flags) + char *str; + unsigned long flags; +{ + int reg; + + while (*str == ' ') + str++; + + if ((reg = reg_required_here (&str, 12)) == FAIL) + return; + + if (reg == REG_PC) + { + inst.error = "r15 not allowed in swap"; + return; + } + + if (skip_past_comma (&str) == FAIL + || (reg = reg_required_here (&str, 0)) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (reg == REG_PC) + { + inst.error = "r15 not allowed in swap"; + return; + } + + if (skip_past_comma (&str) == FAIL + || *str++ != '[') + { + inst.error = bad_args; + return; + } + + while (*str == ' ') + str++; + + if ((reg = reg_required_here (&str, 16)) == FAIL) + return; + + if (reg == REG_PC) + { + inst.error = bad_pc; + return; + } + + while (*str == ' ') + str++; + + if (*str++ != ']') + { + inst.error = "missing ]"; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_branch (str, flags) + char *str; + unsigned long flags; +{ + if (my_get_expression (&inst.reloc.exp, &str)) + return; + inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH; + inst.reloc.pc_rel = 1; + inst.instruction |= flags | 0x00fffffe; /* PC-rel adjust */ + end_of_line (str); + return; +} + +static void +do_cdp (str, flags) + char *str; + unsigned long flags; +{ + /* Co-processor data operation. + Format: CDP{cond} CP#,,CRd,CRn,CRm{,} */ + while (*str == ' ') + str++; + + if (co_proc_number (&str) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_opc_expr (&str, 20,4) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_reg_required_here (&str, 12) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_reg_required_here (&str, 16) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_reg_required_here (&str, 0) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == SUCCESS) + { + if (cp_opc_expr (&str, 5, 3) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + } + + end_of_line (str); + return; +} + +static void +do_lstc (str, flags) + char *str; + unsigned long flags; +{ + /* Co-processor register load/store. + Format: */ + + while (*str == ' ') + str++; + + if (co_proc_number (&str) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_reg_required_here (&str, 12) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_address_required_here (&str) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_co_reg (str, flags) + char *str; + unsigned long flags; +{ + /* Co-processor register transfer. + Format: {cond} CP#,,Rd,CRn,CRm{,} */ + + while (*str == ' ') + str++; + + if (co_proc_number (&str) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_opc_expr (&str, 21, 3) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || reg_required_here (&str, 12) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_reg_required_here (&str, 16) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_reg_required_here (&str, 0) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == SUCCESS) + { + if (cp_opc_expr (&str, 5, 3) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + } + + end_of_line (str); + return; +} + +static void +do_fp_ctrl (str, flags) + char *str; + unsigned long flags; +{ + /* FP control registers. + Format: {cond} Rn */ + + while (*str == ' ') + str++; + + if (reg_required_here (&str, 12) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + end_of_line (str); + return; +} + +static void +do_fp_ldst (str, flags) + char *str; + unsigned long flags; +{ + while (*str == ' ') + str++; + + switch (inst.suffix) + { + case SUFF_S: + break; + case SUFF_D: + inst.instruction |= CP_T_X; + break; + case SUFF_E: + inst.instruction |= CP_T_Y; + break; + case SUFF_P: + inst.instruction |= CP_T_X | CP_T_Y; + break; + default: + abort (); + } + + if (fp_reg_required_here (&str, 12) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || cp_address_required_here (&str) == FAIL) + { + if (!inst.error) + inst.error = bad_args; + return; + } + + end_of_line (str); +} + +static void +do_fp_ldmstm (str, flags) + char *str; + unsigned long flags; +{ + int num_regs; + + while (*str == ' ') + str++; + + if (fp_reg_required_here (&str, 12) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + /* Get Number of registers to transfer */ + if (skip_past_comma (&str) == FAIL + || my_get_expression (&inst.reloc.exp, &str)) + { + if (! inst.error) + inst.error = "constant expression expected"; + return; + } + + if (inst.reloc.exp.X_op != O_constant) + { + inst.error = "Constant value required for number of registers"; + return; + } + + num_regs = inst.reloc.exp.X_add_number; + + if (num_regs < 1 || num_regs > 4) + { + inst.error = "number of registers must be in the range [1:4]"; + return; + } + + switch (num_regs) + { + case 1: + inst.instruction |= CP_T_X; + break; + case 2: + inst.instruction |= CP_T_Y; + break; + case 3: + inst.instruction |= CP_T_Y | CP_T_X; + break; + case 4: + break; + default: + abort (); + } + + if (flags) + { + int reg; + int write_back; + int offset; + + /* The instruction specified "ea" or "fd", so we can only accept + [Rn]{!}. The instruction does not really support stacking or + unstacking, so we have to emulate these by setting appropriate + bits and offsets. */ + if (skip_past_comma (&str) == FAIL + || *str != '[') + { + if (! inst.error) + inst.error = bad_args; + return; + } + + str++; + while (*str == ' ') + str++; + + if ((reg = reg_required_here (&str, 16)) == FAIL) + { + inst.error = "Register required"; + return; + } + + while (*str == ' ') + str++; + + if (*str != ']') + { + inst.error = bad_args; + return; + } + + str++; + if (*str == '!') + { + write_back = 1; + str++; + if (reg == REG_PC) + { + inst.error = "R15 not allowed as base register with write-back"; + return; + } + } + else + write_back = 0; + + if (flags & CP_T_Pre) + { + /* Pre-decrement */ + offset = 3 * num_regs; + if (write_back) + flags |= CP_T_WB; + } + else + { + /* Post-increment */ + if (write_back) + { + flags |= CP_T_WB; + offset = 3 * num_regs; + } + else + { + /* No write-back, so convert this into a standard pre-increment + instruction -- aesthetically more pleasing. */ + flags = CP_T_Pre | CP_T_UD; + offset = 0; + } + } + + inst.instruction |= flags | offset; + } + else if (skip_past_comma (&str) == FAIL + || cp_address_required_here (&str) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + end_of_line (str); +} + +static void +do_fp_dyadic (str, flags) + char *str; + unsigned long flags; +{ + while (*str == ' ') + str++; + + switch (inst.suffix) + { + case SUFF_S: + break; + case SUFF_D: + inst.instruction |= 0x00000080; + break; + case SUFF_E: + inst.instruction |= 0x00080000; + break; + default: + abort (); + } + + if (fp_reg_required_here (&str, 12) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || fp_reg_required_here (&str, 16) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || fp_op2 (&str) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_fp_monadic (str, flags) + char *str; + unsigned long flags; +{ + while (*str == ' ') + str++; + + switch (inst.suffix) + { + case SUFF_S: + break; + case SUFF_D: + inst.instruction |= 0x00000080; + break; + case SUFF_E: + inst.instruction |= 0x00080000; + break; + default: + abort (); + } + + if (fp_reg_required_here (&str, 12) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || fp_op2 (&str) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_fp_cmp (str, flags) + char *str; + unsigned long flags; +{ + while (*str == ' ') + str++; + + if (fp_reg_required_here (&str, 16) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || fp_op2 (&str) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_fp_from_reg (str, flags) + char *str; + unsigned long flags; +{ + while (*str == ' ') + str++; + + switch (inst.suffix) + { + case SUFF_S: + break; + case SUFF_D: + inst.instruction |= 0x00000080; + break; + case SUFF_E: + inst.instruction |= 0x00080000; + break; + default: + abort (); + } + + if (fp_reg_required_here (&str, 16) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || reg_required_here (&str, 12) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +do_fp_to_reg (str, flags) + char *str; + unsigned long flags; +{ + while (*str == ' ') + str++; + + if (reg_required_here (&str, 12) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + if (skip_past_comma (&str) == FAIL + || fp_reg_required_here (&str, 0) == FAIL) + { + if (! inst.error) + inst.error = bad_args; + return; + } + + inst.instruction |= flags; + end_of_line (str); + return; +} + +static void +insert_reg (entry) + int entry; +{ + int len = strlen (reg_table[entry].name) + 2; + char *buf = (char *) xmalloc (len); + char *buf2 = (char *) xmalloc (len); + int i = 0; + +#ifdef REGISTER_PREFIX + buf[i++] = REGISTER_PREFIX; +#endif + + strcpy (buf + i, reg_table[entry].name); + + for (i = 0; buf[i]; i++) + buf2[i] = islower (buf[i]) ? toupper (buf[i]) : buf[i]; + + buf2[i] = '\0'; + + hash_insert (arm_reg_hsh, buf, (PTR) ®_table[entry]); + hash_insert (arm_reg_hsh, buf2, (PTR) ®_table[entry]); +} + +static void +insert_reg_alias (str, regnum) + char *str; + int regnum; +{ + struct reg_entry *new = + (struct reg_entry *)xmalloc (sizeof (struct reg_entry)); + char *name = xmalloc (strlen (str) + 1); + strcpy (name, str); + + new->name = name; + new->number = regnum; + + hash_insert (arm_reg_hsh, name, (PTR) new); +} + +static void +set_constant_flonums () +{ + int i; + + for (i = 0; i < NUM_FLOAT_VALS; i++) + if (atof_ieee ((char *)fp_const[i], 'x', fp_values[i]) == NULL) + abort (); +} + +void +md_begin () +{ + int i; + + if ((arm_ops_hsh = hash_new ()) == NULL + || (arm_cond_hsh = hash_new ()) == NULL + || (arm_shift_hsh = hash_new ()) == NULL + || (arm_reg_hsh = hash_new ()) == NULL + || (arm_psr_hsh = hash_new ()) == NULL) + as_fatal ("Virtual memory exhausted"); + + for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++) + hash_insert (arm_ops_hsh, insns[i].template, (PTR) (insns + i)); + for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++) + hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i)); + for (i = 0; i < sizeof (shift) / sizeof (struct asm_shift); i++) + hash_insert (arm_shift_hsh, shift[i].template, (PTR) (shift + i)); + for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++) + hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i)); + + for (i = 0; reg_table[i].name; i++) + insert_reg (i); + + set_constant_flonums (); +} + +/* Turn an integer of n bytes (in val) into a stream of bytes appropriate + for use in the a.out file, and stores them in the array pointed to by buf. + This knows about the endian-ness of the target machine and does + THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) + 2 (short) and 4 (long) Floating numbers are put out as a series of + LITTLENUMS (shorts, here at least) + */ +void +md_number_to_chars (buf, val, n) + char *buf; + valueT val; + int n; +{ + if (target_big_endian) + number_to_chars_bigendian (buf, val, n); + else + number_to_chars_littleendian (buf, val, n); +} + +static valueT +md_chars_to_number (buf, n) + char *buf; + int n; +{ + valueT result = 0; + unsigned char *where = (unsigned char *) buf; + + if (target_big_endian) + { + while (n--) + { + result <<= 8; + result |= (*where++ & 255); + } + } + else + { + while (n--) + { + result <<= 8; + result |= (where[n] & 255); + } + } + + return result; +} + +/* Turn a string in input_line_pointer into a floating point constant + of type TYPE, and store the appropriate bytes in *litP. The number + of LITTLENUMS emitted is stored in *sizeP . An error message is + returned, or NULL on OK. + + Note that fp constants aren't represent in the normal way on the ARM. + In big endian mode, things are as expected. However, in little endian + mode fp constants are big-endian word-wise, and little-endian byte-wise + within the words. For example, (double) 1.1 in big endian mode is + the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is + the byte sequence 99 99 f1 3f 9a 99 99 99. + + ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */ + +char * +md_atof (type, litP, sizeP) + char type; + char *litP; + int *sizeP; +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + char *t; + int i; + + switch (type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return "Bad call to MD_ATOF()"; + } + + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + *sizeP = prec * 2; + + if (target_big_endian) + { + for (i = 0; i < prec; i++) + { + md_number_to_chars (litP, (valueT) words[i], 2); + litP += 2; + } + } + else + { + /* For a 4 byte float the order of elements in `words' is 1 0. For an + 8 byte float the order is 1 0 3 2. */ + for (i = 0; i < prec; i += 2) + { + md_number_to_chars (litP, (valueT) words[i + 1], 2); + md_number_to_chars (litP + 2, (valueT) words[i], 2); + litP += 4; + } + } + + return 0; +} + +/* We have already put the pipeline compensation in the instruction */ + +long +md_pcrel_from (fixP) + fixS *fixP; +{ + if (fixP->fx_addsy && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section + && fixP->fx_subsy == NULL) + return 0; /* HACK */ + + return fixP->fx_where + fixP->fx_frag->fr_address; +} + +/* Round up a section size to the appropriate boundary. */ +valueT +md_section_align (segment, size) + segT segment; + valueT size; +{ + /* Round all sects to multiple of 4 */ + return (size + 3) & ~3; +} + +/* We have no need to default values of symbols. */ + +/* ARGSUSED */ +symbolS * +md_undefined_symbol (name) + char *name; +{ + return 0; +} + +/* arm_reg_parse () := if it looks like a register, return its token and + advance the pointer. */ + +static int +arm_reg_parse (ccp) + register char **ccp; +{ + char *start = *ccp; + char c; + char *p; + struct reg_entry *reg; + +#ifdef REGISTER_PREFIX + if (*start != REGISTER_PREFIX) + return FAIL; + p = start + 1; +#else + p = start; +#ifdef OPTIONAL_REGISTER_PREFIX + if (*p == OPTIONAL_REGISTER_PREFIX) + p++, start++; +#endif +#endif + if (!isalpha (*p) || !is_name_beginner (*p)) + return FAIL; + + c = *p++; + while (isalpha (c) || isdigit (c) || c == '_') + c = *p++; + + *--p = 0; + reg = (struct reg_entry *) hash_find (arm_reg_hsh, start); + *p = c; + + if (reg) + { + *ccp = p; + return reg->number; + } + + return FAIL; +} + +static int +arm_psr_parse (ccp) + register char **ccp; +{ + char *start = *ccp; + char c, *p; + CONST struct asm_psr *psr; + + p = start; + c = *p++; + while (isalpha (c) || c == '_') + c = *p++; + + *--p = 0; + psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start); + *p = c; + + if (psr) + { + *ccp = p; + return psr->number; + } + + return FAIL; +} + +int +md_apply_fix (fixP, val) + fixS *fixP; + valueT *val; +{ + offsetT value = *val; + offsetT newval, temp; + int sign; + char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; + + assert (fixP->fx_r_type < BFD_RELOC_UNUSED); + + fixP->fx_addnumber = value; /* Remember value for emit_reloc */ + + /* Note whether this will delete the relocation. */ + if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) + fixP->fx_done = 1; + + switch (fixP->fx_r_type) + { + case BFD_RELOC_ARM_IMMEDIATE: + newval = validate_immediate (value); + temp = md_chars_to_number (buf, INSN_SIZE); + + /* If the instruction will fail, see if we can fix things up by + changing the opcode. */ + if (newval == FAIL + && (newval = negate_data_op (&temp, value)) == FAIL) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + "invalid constant after fixup\n"); + break; + } + + newval |= (temp & 0xfffff000); + md_number_to_chars (buf, newval, INSN_SIZE); + break; + + case BFD_RELOC_ARM_OFFSET_IMM: + sign = value >= 0; + value = validate_offset_imm (value); /* Should be OK ... but .... */ + if (value < 0) + value = -value; + + newval = md_chars_to_number (buf, INSN_SIZE); + newval &= 0xff7ff000; + newval |= value | (sign ? 0x00800000 : 0); + md_number_to_chars (buf, newval, INSN_SIZE); + break; + + case BFD_RELOC_ARM_LITERAL: + sign = value >= 0; + if (value < 0) + value = -value; + + if ((value = validate_immediate (value)) == FAIL) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + "invalid literal constant: pool needs to be closer\n"); + break; + } + + newval = md_chars_to_number (buf, INSN_SIZE); + newval &= 0xff7ff000; + newval |= value | (sign ? 0x00800000 : 0); + md_number_to_chars (buf, newval, INSN_SIZE); + break; + + case BFD_RELOC_ARM_SHIFT_IMM: + newval = md_chars_to_number (buf, INSN_SIZE); + if (((unsigned long) value) > 32 + || (value == 32 + && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60))) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + "shift expression is too large"); + break; + } + + if (value == 0) + newval &= ~0x60; /* Shifts of zero must be done as lsl */ + else if (value == 32) + value = 0; + newval &= 0xfffff07f; + newval |= (value & 0x1f) << 7; + md_number_to_chars (buf, newval , INSN_SIZE); + break; + + case BFD_RELOC_ARM_SWI: + if (((unsigned long) value) > 0x00ffffff) + as_bad_where (fixP->fx_file, fixP->fx_line, "Invalid swi expression"); + newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000; + newval |= value; + md_number_to_chars (buf, newval , INSN_SIZE); + break; + + case BFD_RELOC_ARM_MULTI: + if (((unsigned long) value) > 0xffff) + as_bad_where (fixP->fx_file, fixP->fx_line, + "Invalid expression in load/store multiple"); + newval = value | md_chars_to_number (buf, INSN_SIZE); + md_number_to_chars (buf, newval, INSN_SIZE); + break; + + case BFD_RELOC_ARM_PCREL_BRANCH: + value = (value >> 2) & 0x00ffffff; + newval = md_chars_to_number (buf, INSN_SIZE); + value = (value + (newval & 0x00ffffff)) & 0x00ffffff; + newval = value | (newval & 0xff000000); + md_number_to_chars (buf, newval, INSN_SIZE); + break; + + case BFD_RELOC_8: + if (fixP->fx_done || fixP->fx_pcrel) + md_number_to_chars (buf, value, 1); + break; + + case BFD_RELOC_16: + if (fixP->fx_done || fixP->fx_pcrel) + md_number_to_chars (buf, value, 2); + break; + + case BFD_RELOC_RVA: + case BFD_RELOC_32: + if (fixP->fx_done || fixP->fx_pcrel) + md_number_to_chars (buf, value, 4); + break; + + case BFD_RELOC_ARM_CP_OFF_IMM: + sign = value >= 0; + if (value < -1023 || value > 1023 || (value & 3)) + as_bad_where (fixP->fx_file, fixP->fx_line, + "Illegal value for co-processor offset"); + if (value < 0) + value = -value; + newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00; + newval |= (value >> 2) | (sign ? 0x00800000 : 0); + md_number_to_chars (buf, newval , INSN_SIZE); + break; + + case BFD_RELOC_NONE: + default: + as_bad_where (fixP->fx_file, fixP->fx_line, + "Bad relocation fixup type (%d)\n", fixP->fx_r_type); + } + + return 1; +} + +/* Translate internal representation of relocation info to BFD target + format. */ +arelent * +tc_gen_reloc (section, fixp) + asection *section; + fixS *fixp; +{ + arelent *reloc; + bfd_reloc_code_real_type code; + + reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent)); + assert (reloc != 0); + + reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + + /* @@ Why fx_addnumber sometimes and fx_offset other times? */ + if (fixp->fx_pcrel == 0) + reloc->addend = fixp->fx_offset; + else + reloc->addend = fixp->fx_offset = reloc->address; + + switch (fixp->fx_r_type) + { + case BFD_RELOC_8: + if (fixp->fx_pcrel) + { + code = BFD_RELOC_8_PCREL; + break; + } + + case BFD_RELOC_16: + if (fixp->fx_pcrel) + { + code = BFD_RELOC_16_PCREL; + break; + } + + case BFD_RELOC_32: + if (fixp->fx_pcrel) + { + code = BFD_RELOC_32_PCREL; + break; + } + + case BFD_RELOC_ARM_PCREL_BRANCH: + case BFD_RELOC_RVA: + code = fixp->fx_r_type; + break; + + case BFD_RELOC_ARM_LITERAL: + /* If this is called then the a literal has been referenced across + a section boundry - possibly due to an implicit dump */ + as_bad ("Literal referenced across section boundry (Implicit dump?)"); + return NULL; + + case BFD_RELOC_ARM_IMMEDIATE: + as_bad ("Internal_relocation (type %d) not fixed up (IMMEDIATE)" + , fixp->fx_r_type); + return NULL; + + case BFD_RELOC_ARM_OFFSET_IMM: + as_bad ("Internal_relocation (type %d) not fixed up (OFFSET_IMM)" + , fixp->fx_r_type); + return NULL; + + case BFD_RELOC_ARM_SHIFT_IMM: + as_bad ("Internal_relocation (type %d) not fixed up (SHIFT_IMM)" + , fixp->fx_r_type); + return NULL; + + case BFD_RELOC_ARM_SWI: + as_bad ("Internal_relocation (type %d) not fixed up (SWI)" + , fixp->fx_r_type); + return NULL; + + case BFD_RELOC_ARM_MULTI: + as_bad ("Internal_relocation (type %d) not fixed up (MULTI)" + , fixp->fx_r_type); + return NULL; + + case BFD_RELOC_ARM_CP_OFF_IMM: + as_bad ("Internal_relocation (type %d) not fixed up (CP_OFF_IMM)" + , fixp->fx_r_type); + return NULL; + + default: + abort (); + } + + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + assert (reloc->howto != 0); + + return reloc; +} + +CONST int md_short_jump_size = 4; +CONST int md_long_jump_size = 4; + +/* These should never be called on the arm */ +void +md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + as_fatal ("md_create_long_jump\n"); +} + +void +md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + as_fatal ("md_create_short_jump\n"); +} + +int +md_estimate_size_before_relax (fragP, segtype) + fragS *fragP; + segT segtype; +{ + as_fatal ("md_estimate_size_before_relax\n"); + return (1); +} + +void +output_inst (str) + char *str; +{ + char *to = NULL; + + if (inst.error) + { + as_bad ("%s -- statement `%s'\n", inst.error, str); + return; + } + + to = frag_more (INSN_SIZE); + md_number_to_chars (to, inst.instruction, INSN_SIZE); + + if (inst.reloc.type != BFD_RELOC_NONE) + fix_new_arm (frag_now, to - frag_now->fr_literal, + 4, &inst.reloc.exp, inst.reloc.pc_rel, + inst.reloc.type); + + return; +} + +void +md_assemble (str) + char *str; +{ + char c; + CONST struct asm_opcode *opcode; + char *p, *q, *start; + + /* Align the instruction */ + /* this may not be the right thing to do but ... */ + /* arm_align (2, 0); */ + listing_prev_line (); /* Defined in listing.h */ + + /* Align the previous label if needed */ + if (last_label_seen != NULL) + { + last_label_seen->sy_frag = frag_now; + S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ()); + S_SET_SEGMENT (last_label_seen, now_seg); + } + + memset (&inst, '\0', sizeof (inst)); + inst.reloc.type = BFD_RELOC_NONE; + + if (*str == ' ') + str++; /* Skip leading white space */ + + /* scan up to the end of the op-code, which must end in white space or + end of string */ + for (start = p = str; *p != '\0'; p++) + if (*p == ' ') + break; + + if (p == str) + { + as_bad ("No operator -- statement `%s'\n", str); + return; + } + + /* p now points to the end of the opcode, probably white space, but we have + to break the opcode up in case it contains condionals and flags; + keep trying with progressively smaller basic instructions until one + matches, or we run out of opcode. */ + q = (p - str > LONGEST_INST) ? str + LONGEST_INST : p; + for (; q != str; q--) + { + c = *q; + *q = '\0'; + opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str); + *q = c; + if (opcode && opcode->template) + { + unsigned long flag_bits = 0; + char *r; + + /* Check that this instruction is supported for this CPU */ + if ((opcode->variants & cpu_variant) == 0) + goto try_shorter; + + inst.instruction = opcode->value; + if (q == p) /* Just a simple opcode */ + { + if (opcode->comp_suffix != 0) + as_bad ("Opcode `%s' must have suffix from <%s>\n", str, + opcode->comp_suffix); + else + { + inst.instruction |= COND_ALWAYS; + (*opcode->parms)(q, 0); + } + output_inst (start); + return; + } + + /* Now check for a conditional */ + r = q; + if (p - r >= 2) + { + CONST struct asm_cond *cond; + char d = *(r + 2); + + *(r + 2) = '\0'; + cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r); + *(r + 2) = d; + if (cond) + { + if (cond->value == 0xf0000000) + as_tsktsk + ("Warning: Use of the 'nv' conditional is deprecated\n"); + + inst.instruction |= cond->value; + r += 2; + } + else + inst.instruction |= COND_ALWAYS; + } + else + inst.instruction |= COND_ALWAYS; + + /* if there is a compulsory suffix, it should come here, before + any optional flags. */ + if (opcode->comp_suffix) + { + CONST char *s = opcode->comp_suffix; + + while (*s) + { + inst.suffix++; + if (*r == *s) + break; + s++; + } + + if (*s == '\0') + { + as_bad ("Opcode `%s' must have suffix from <%s>\n", str, + opcode->comp_suffix); + return; + } + + r++; + } + + /* The remainder, if any should now be flags for the instruction; + Scan these checking each one found with the opcode. */ + if (r != p) + { + char d; + CONST struct asm_flg *flag = opcode->flags; + + if (flag) + { + int flagno; + + d = *p; + *p = '\0'; + + for (flagno = 0; flag[flagno].template; flagno++) + { + if (! strcmp (r, flag[flagno].template)) + { + flag_bits |= flag[flagno].set_bits; + break; + } + } + + *p = d; + if (! flag[flagno].template) + goto try_shorter; + } + else + goto try_shorter; + } + + (*opcode->parms) (p, flag_bits); + output_inst (start); + return; + } + + try_shorter: + ; + } + /* It wasn't an instruction, but it might be a register alias of the form + alias .req reg + */ + q = p; + while (*q == ' ') + q++; + + c = *p; + *p = '\0'; + + if (*q && !strncmp (q, ".req ", 4)) + { + int reg; + if ((reg = arm_reg_parse (&str)) == FAIL) + { + char *r; + + q += 4; + while (*q == ' ') + q++; + + for (r = q; *r != '\0'; r++) + if (*r == ' ') + break; + + if (r != q) + { + int regnum; + char d = *r; + + *r = '\0'; + regnum = arm_reg_parse (&q); + *r = d; + if (regnum != FAIL) + { + insert_reg_alias (str, regnum); + *p = c; + return; + } + } + } + else + { + *p = c; + return; + } + } + + *p = c; + as_bad ("bad instruction `%s'", start); +} + +/* + * md_parse_option + * Invocation line includes a switch not recognized by the base assembler. + * See if it's a processor-specific option. These are: + * Cpu variants, the arm part is optional: + * -m[arm]1 Currently not supported. + * -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor + * -m[arm]3 Arm 3 processor + * -m[arm]6, -m[arm]7 Arm 6 and 7 processors + * -m[arm]7dm Arm 7dm processors + * -mall All (except the ARM1) + * FP variants: + * -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions + * -mfpe-old (No float load/store multiples) + * -mno-fpu Disable all floating point instructions + * Run-time endian selection: + * -EB big endian cpu + * -EL little endian cpu + */ + +CONST char *md_shortopts = "m:"; +struct option md_longopts[] = { +#ifdef ARM_BI_ENDIAN +#define OPTION_EB (OPTION_MD_BASE + 0) + {"EB", no_argument, NULL, OPTION_EB}, +#define OPTION_EL (OPTION_MD_BASE + 1) + {"EL", no_argument, NULL, OPTION_EL}, +#endif + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof(md_longopts); + +int +md_parse_option (c, arg) + int c; + char *arg; +{ + char *str = arg; + + switch (c) + { +#ifdef ARM_BI_ENDIAN + case OPTION_EB: + target_big_endian = 1; + break; + case OPTION_EL: + target_big_endian = 0; + break; +#endif + + case 'm': + switch (*str) + { + case 'f': + if (! strcmp (str, "fpa10")) + cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA10; + else if (! strcmp (str, "fpa11")) + cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA11; + else if (! strcmp (str, "fpe-old")) + cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_CORE; + else + goto bad; + break; + + case 'n': + if (! strcmp (str, "no-fpu")) + cpu_variant &= ~FPU_ALL; + break; + + default: + if (! strcmp (str, "all")) + { + cpu_variant = ARM_ALL | FPU_ALL; + return 1; + } + + /* Strip off optional "arm" */ + if (! strncmp (str, "arm", 3)) + str += 3; + + switch (*str) + { + case '1': + if (! strcmp (str, "1")) + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1; + else + goto bad; + break; + + case '2': + if (! strcmp (str, "2")) + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2; + else if (! strcmp (str, "250")) + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250; + else + goto bad; + break; + + case '3': + if (! strcmp (str, "3")) + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3; + else + goto bad; + break; + + case '6': + if (! strcmp (str, "6")) + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6; + else + goto bad; + break; + + case '7': + if (! strcmp (str, "7")) + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7; + else if (! strcmp (str, "7dm")) + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7DM; + else + goto bad; + break; + + default: + bad: + as_bad ("Invalid architecture -m%s", arg); + return 0; + } + } + break; + + default: + return 0; + } + + return 1; +} + +void +md_show_usage (fp) + FILE *fp; +{ + fprintf (fp, +"-m[arm]1, -m[arm]2, -m[arm]250,\n-m[arm]3, -m[arm]6, -m[arm]7, -m[arm]7dm\n\ +\t\t\tselect processor architecture\n\ +-mall\t\t\tallow any instruction\n\ +-mfpa10, -mfpa11\tselect floating point architecture\n\ +-mfpe-old\t\tdon't allow floating-point multiple instructions\n\ +-mno-fpu\t\tdon't allow any floating-point instructions.\n"); +#ifdef ARM_BI_ENDIAN + fprintf (fp, +"-EB\t\t\tassemble code for a big endian cpu\n\ +-EL\t\t\tassemble code for a little endian cpu\n"); +#endif +} + +/* We need to be able to fix up arbitrary expressions in some statements. + This is so that we can handle symbols that are an arbitrary distance from + the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask), + which returns part of an address in a form which will be valid for + a data instruction. We do this by pushing the expression into a symbol + in the expr_section, and creating a fix for that. */ + +static void +fix_new_arm (frag, where, size, exp, pc_rel, reloc) + fragS *frag; + int where; + short int size; + expressionS *exp; + int pc_rel; + int reloc; +{ + fixS *new_fix; + + switch (exp->X_op) + { + case O_constant: + case O_symbol: + case O_add: + case O_subtract: + new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc); + break; + + default: + { + const char *fake; + symbolS *symbolP; + + /* FIXME: This should be something which decode_local_label_name + will handle. */ + fake = FAKE_LABEL_NAME; + + /* Putting constant symbols in absolute_section rather than + expr_section is convenient for the old a.out code, for which + S_GET_SEGMENT does not always retrieve the value put in by + S_SET_SEGMENT. */ + symbolP = symbol_new (fake, expr_section, 0, &zero_address_frag); + symbolP->sy_value = *exp; + new_fix = fix_new (frag, where, size, symbolP, 0, pc_rel, reloc); + } + break; + } + + return; +} + +/* A good place to do this, although this was probably not intended + * for this kind of use. We need to dump the literal pool before + * references are made to a null symbol pointer. */ +void +arm_after_pass_hook (ignore) + asection *ignore; +{ + if (current_poolP != NULL) + { + subseg_set (text_section, 0); /* Put it at the end of text section */ + s_ltorg (0); + listing_prev_line (); + } +} + +void +arm_start_line_hook () +{ + last_label_seen = NULL; +} + +void +arm_frob_label (sym) + symbolS *sym; +{ + last_label_seen = sym; +} diff --git a/gnu/usr.bin/binutils/gas/config/tc-arm.h b/gnu/usr.bin/binutils/gas/config/tc-arm.h new file mode 100644 index 00000000000..12f35abc9fc --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-arm.h @@ -0,0 +1,108 @@ +/* This file is tc-arm.h + Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) + Modified by David Taylor (dtaylor@armltd.co.uk) + + Copyright (C) 1994, 1995 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 2, 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. */ + +#define TC_ARM 1 + +#define COFF_MAGIC ARMMAGIC +#define TARGET_ARCH bfd_arch_arm + +#define AOUT_MACHTYPE 0 + +#define DIFF_EXPR_OK + +#define LITTLE_ENDIAN 1234 +#define BIG_ENDIAN 4321 + +/* If neither TARGET_BYTES_BIG_ENDIAN nor TARGET_BYTES_LITTLE_ENDIAN + is specified, default to little endian. */ +#ifndef TARGET_BYTES_BIG_ENDIAN +#ifndef TARGET_BYTES_LITTLE_ENDIAN +#define TARGET_BYTES_LITTLE_ENDIAN +#endif +#endif + +#ifdef OBJ_AOUT +#ifdef TE_RISCIX +#define TARGET_FORMAT "a.out-riscix" +#else +#ifdef TARGET_BYTES_BIG_ENDIAN +#define TARGET_FORMAT "a.out-arm-big" +#else +#define TARGET_FORMAT "a.out-arm-little" +#endif +#endif +#endif + +#ifdef OBJ_AIF +#define TARGET_FORMAT "aif" +#endif + +#ifdef OBJ_COFF +#define ARM_BI_ENDIAN +#ifdef TE_PE +#define TC_FORCE_RELOCATION(x) ((x)->fx_r_type==BFD_RELOC_RVA) +#define TARGET_FORMAT (target_big_endian ? "pe-arm-big" : "pe-arm-little") +#else +#define TARGET_FORMAT (target_big_endian ? "coff-arm-big" : "coff-arm-little") +/* Tell tc-arm.c to support runtime endian selection. */ +#endif +#endif + +#define md_convert_frag(b,s,f) {as_fatal ("arm convert_frag\n");} + +#define md_after_pass_hook() arm_after_pass_hook () +#define md_start_line_hook() arm_start_line_hook () +#define tc_frob_label(S) arm_frob_label (S) + +#define obj_fix_adjustable(fixP) 0 + +#if 0 /* It isn't as simple as this */ +#define tc_frob_symbol(sym,punt) \ +{ if (S_IS_LOCAL (sym)) \ + { \ + punt = 1; \ + sym->sy_used_in_reloc = 0; \ + }} +#endif + +#if 0 +#define tc_crawl_symbol_chain(a) {;} /* not used */ +#define tc_headers_hook(a) {;} /* not used */ +#endif + +#define tc_aout_pre_write_hook(x) {;} /* not used */ + +#define LISTING_HEADER "ARM GAS " + +#define OPTIONAL_REGISTER_PREFIX '%' + +#define md_operand(x) + +#define LOCAL_LABELS_FB 1 + +/* Use defaults for OBJ_AOUT. */ +#ifndef OBJ_AOUT +#define LOCAL_LABEL(name) ((name)[0] == '.' && (name)[1] == 'L') +#define FAKE_LABEL_NAME ".L0\001" +#endif + +/* end of tc-arm.h */ diff --git a/gnu/usr.bin/binutils/gas/config/tc-generic.c b/gnu/usr.bin/binutils/gas/config/tc-generic.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/gnu/usr.bin/binutils/gas/config/tc-generic.h b/gnu/usr.bin/binutils/gas/config/tc-generic.h new file mode 100644 index 00000000000..818085650a9 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-generic.h @@ -0,0 +1,38 @@ + +/* This file is tc-generic.h + + Copyright (C) 1987-1992 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 2, 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. */ + +/* + * This file is tc-generic.h and is intended to be a template for target cpu + * specific header files. It is my intent that this file compile. It is also + * my intent that this file grow into something that can be used as both a + * template for porting, and a stub for testing. xoxorich. + */ + +#define TC_GENERIC 1 + +/* + * Local Variables: + * comment-column: 0 + * fill-column: 131 + * End: + */ + +/* end of tc-generic.h */ diff --git a/gnu/usr.bin/binutils/gas/config/tc-h8300.c b/gnu/usr.bin/binutils/gas/config/tc-h8300.c new file mode 100644 index 00000000000..cab657b00e3 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-h8300.c @@ -0,0 +1,1458 @@ +/* tc-h8300.c -- Assemble code for the Hitachi H8/300 + Copyright (C) 1991, 1992 Free Software Foundation. + + 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 2, 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. */ + + +/* + Written By Steve Chamberlain + sac@cygnus.com + */ + +#include +#include "as.h" +#include "bfd.h" +#define DEFINE_TABLE +#define h8_opcodes ops +#include "opcode/h8300.h" +#include + +const char comment_chars[] = +{';', 0}; +const char line_separator_chars[] = +{0}; +const char line_comment_chars[] = "#"; + +/* This table describes all the machine specific pseudo-ops the assembler + has to support. The fields are: + pseudo-op name without dot + function to call to execute this pseudo-op + Integer arg to pass to the function + */ + +void cons (); + +int Hmode; +#define PSIZE (Hmode ? L_32 : L_16) +#define DMODE (L_16) +#define DSYMMODE (Hmode ? L_24 : L_16) +int bsize = L_8; /* default branch displacement */ + + +void +h8300hmode () +{ + Hmode = 1; +} + + +void +sbranch (size) + int size; +{ + bsize = size; +} + +static void pint () +{ + cons (Hmode ? 4 : 2); +} + +const pseudo_typeS md_pseudo_table[] = +{ + + {"h8300h", h8300hmode, 0}, + {"sbranch", sbranch, L_8}, + {"lbranch", sbranch, L_16}, + + {"int", pint, 0}, + {"data.b", cons, 1}, + {"data.w", cons, 2}, + {"data.l", cons, 4}, + {"form", listing_psize, 0}, + {"heading", listing_title, 0}, + {"import", s_ignore, 0}, + {"page", listing_eject, 0}, + {"program", s_ignore, 0}, + {0, 0, 0} +}; + +const int md_reloc_size; + +const char EXP_CHARS[] = "eE"; + +/* Chars that mean this number is a floating point constant */ +/* As in 0f12.456 */ +/* or 0d1.2345e12 */ +const char FLT_CHARS[] = "rRsSfFdDxXpP"; + +static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ + +/* + This function is called once, at assembler startup time. This should + set up all the tables, etc that the MD part of the assembler needs + */ + + +void +md_begin () +{ + struct h8_opcode *opcode; + char prev_buffer[100]; + int idx = 0; + + opcode_hash_control = hash_new (); + prev_buffer[0] = 0; + + for (opcode = h8_opcodes; opcode->name; opcode++) + { + /* Strip off any . part when inserting the opcode and only enter + unique codes into the hash table + */ + char *src = opcode->name; + unsigned int len = strlen (src); + char *dst = malloc (len + 1); + char *buffer = dst; + + opcode->size = 0; + while (*src) + { + if (*src == '.') + { + src++; + opcode->size = *src; + break; + } + *dst++ = *src++; + } + *dst++ = 0; + if (strcmp (buffer, prev_buffer)) + { + hash_insert (opcode_hash_control, buffer, (char *) opcode); + strcpy (prev_buffer, buffer); + idx++; + } + opcode->idx = idx; + + + /* Find the number of operands */ + opcode->noperands = 0; + while (opcode->args.nib[opcode->noperands] != E) + opcode->noperands++; + /* Find the length of the opcode in bytes */ + opcode->length = 0; + while (opcode->data.nib[opcode->length * 2] != E) + opcode->length++; + } + + linkrelax = 1; +} + + +struct h8_exp +{ + char *e_beg; + char *e_end; + expressionS e_exp; +}; +int dispreg; +int opsize; /* Set when a register size is seen */ + + +struct h8_op +{ + op_type mode; + unsigned reg; + expressionS exp; +}; + +/* + parse operands + WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp + r0l,r0h,..r7l,r7h + @WREG + @WREG+ + @-WREG + #const + + */ + +/* try and parse a reg name, returns number of chars consumed */ +int +parse_reg (src, mode, reg, direction) + char *src; + op_type *mode; + unsigned int *reg; + int direction; + +{ + if (src[0] == 's' && src[1] == 'p') + { + *mode = PSIZE | REG | direction; + *reg = 7; + return 2; + } + if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') + { + *mode = CCR; + *reg = 0; + return 3; + } + if (src[0] == 'f' && src[1] == 'p') + { + *mode = PSIZE | REG | direction; + *reg = 6; + return 2; + } + if (src[0] == 'e' + && src[1] == 'r' + && src[2] >= '0' && src[2] <= '7') + { + *mode = L_32 | REG | direction; + *reg = src[2] - '0'; + if (!Hmode) + as_warn ("Reg only legal for H8/300-H"); + + return 3; + } + if (src[0] == 'e' + && src[1] >= '0' && src[1] <= '7') + { + *mode = L_16 | REG | direction; + *reg = src[1] - '0' + 8; + if (!Hmode) + as_warn ("Reg only legal for H8/300-H"); + return 2; + } + + if (src[0] == 'r') + { + if (src[1] >= '0' && src[1] <= '7') + { + if (src[2] == 'l') + { + *mode = L_8 | REG | direction; + *reg = (src[1] - '0') + 8; + return 3; + } + if (src[2] == 'h') + { + *mode = L_8 | REG | direction; + *reg = (src[1] - '0'); + return 3; + } + *mode = L_16 | REG | direction; + *reg = (src[1] - '0'); + return 2; + } + } + return 0; +} + +char * +parse_exp (s, op) + char *s; + expressionS * op; +{ + char *save = input_line_pointer; + char *new; + + input_line_pointer = s; + expression (op); + if (op->X_op == O_absent) + as_bad ("missing operand"); + new = input_line_pointer; + input_line_pointer = save; + return new; +} + +static char * +skip_colonthing (ptr, exp, mode) + char *ptr; + expressionS *exp; + int *mode; +{ + if (*ptr == ':') + { + ptr++; + *mode &= ~SIZE; + if (*ptr == '8') + { + ptr++; + /* ff fill any 8 bit quantity */ + /* exp->X_add_number -= 0x100;*/ + *mode |= L_8; + } + else + { + if (*ptr == '2') + { + *mode |= L_24; + } + else if (*ptr == '1') + { + *mode |= L_16; + } + while (isdigit (*ptr)) + ptr++; + } + } + return ptr; +} + +/* The many forms of operand: + + Rn Register direct + @Rn Register indirect + @(exp[:16], Rn) Register indirect with displacement + @Rn+ + @-Rn + @aa:8 absolute 8 bit + @aa:16 absolute 16 bit + @aa absolute 16 bit + + #xx[:size] immediate data + @(exp:[8], pc) pc rel + @@aa[:8] memory indirect + + */ + +char * +colonmod24 (op, src) + struct h8_op *op; + char *src; + +{ + int mode = 0; + src = skip_colonthing (src, &op->exp, &mode); + + if (!mode) + { + /* Choose a default mode */ + if (op->exp.X_add_number < -32768 + || op->exp.X_add_number > 32767) + { + if (Hmode) + mode = L_24; + else + mode = L_16; + } + else if (op->exp.X_add_symbol + || op->exp.X_op_symbol) + mode = DSYMMODE; + else + mode = DMODE; + } + op->mode |= mode; + return src; + +} + + +static void +get_operand (ptr, op, dst, direction) + char **ptr; + struct h8_op *op; + unsigned int dst; + int direction; +{ + char *src = *ptr; + op_type mode; + unsigned int num; + unsigned int len; + + op->mode = E; + + len = parse_reg (src, &op->mode, &op->reg, direction); + if (len) + { + *ptr = src + len; + return; + } + + if (*src == '@') + { + src++; + if (*src == '@') + { + src++; + src = parse_exp (src, &op->exp); + + src = skip_colonthing (src, &op->exp, &op->mode); + + *ptr = src; + + op->mode = MEMIND; + return; + + } + + + if (*src == '-') + { + src++; + len = parse_reg (src, &mode, &num, direction); + if (len == 0) + { + /* Oops, not a reg after all, must be ordinary exp */ + src--; + /* must be a symbol */ + op->mode = ABS | PSIZE | direction; + *ptr = skip_colonthing (parse_exp (src, &op->exp), + &op->exp, &op->mode); + + return; + + + } + + + if ((mode & SIZE) != PSIZE) + as_bad ("Wrong size pointer register for architecture."); + op->mode = RDDEC; + op->reg = num; + *ptr = src + len; + return; + } + if (*src == '(') + { + /* Disp */ + src++; + + /* Start off assuming a 16 bit offset */ + + + src = parse_exp (src, &op->exp); + + src = colonmod24 (op, src); + + if (*src == ')') + { + src++; + op->mode |= ABS | direction; + *ptr = src; + return; + } + + if (*src != ',') + { + as_bad ("expected @(exp, reg16)"); + return; + + } + src++; + + len = parse_reg (src, &mode, &op->reg, direction); + if (len == 0 || !(mode & REG)) + { + as_bad ("expected @(exp, reg16)"); + return; + } + op->mode |= DISP | direction; + dispreg = op->reg; + src += len; + src = skip_colonthing (src, &op->exp, &op->mode); + + if (*src != ')' && '(') + { + as_bad ("expected @(exp, reg16)"); + return; + } + *ptr = src + 1; + + return; + } + len = parse_reg (src, &mode, &num, direction); + + if (len) + { + src += len; + if (*src == '+') + { + src++; + if ((mode & SIZE) != PSIZE) + as_bad ("Wrong size pointer register for architecture."); + op->mode = RSINC; + op->reg = num; + *ptr = src; + return; + } + if ((mode & SIZE) != PSIZE) + as_bad ("Wrong size pointer register for architecture."); + + op->mode = direction | IND | PSIZE; + op->reg = num; + *ptr = src; + + return; + } + else + { + /* must be a symbol */ + + op->mode = ABS | direction; + src = parse_exp (src, &op->exp); + + *ptr = colonmod24 (op, src); + + return; + } + } + + + if (*src == '#') + { + src++; + op->mode = IMM; + src = parse_exp (src, &op->exp); + *ptr = skip_colonthing (src, &op->exp, &op->mode); + + return; + } + else + { + src = parse_exp (src, &op->exp); + /* Trailing ':' size ? */ + if (*src == ':') + { + if (src[1] == '1' && src[2] == '6') + { + op->mode = PCREL | L_16; + src += 3; + } + else if (src[1] == '8') + { + op->mode = PCREL | L_8; + src += 2; + } + else + { + as_bad ("expect :8 or :16 here"); + } + } + else + { + op->mode = PCREL | bsize; + } + *ptr = src; + } +} + + +static +char * +get_operands (noperands, op_end, operand) + unsigned int noperands; + char *op_end; + struct h8_op *operand; +{ + char *ptr = op_end; + + switch (noperands) + { + case 0: + operand[0].mode = 0; + operand[1].mode = 0; + break; + + case 1: + ptr++; + get_operand (&ptr, operand + 0, 0, SRC); + if (*ptr == ',') + { + ptr++; + get_operand (&ptr, operand + 1, 1, DST); + } + else + { + operand[1].mode = 0; + } + + break; + case 2: + ptr++; + get_operand (&ptr, operand + 0, 0, SRC); + if (*ptr == ',') + ptr++; + get_operand (&ptr, operand + 1, 1, DST); + break; + + default: + abort (); + } + + + return ptr; +} + +/* Passed a pointer to a list of opcodes which use different + addressing modes, return the opcode which matches the opcodes + provided + */ +static +struct h8_opcode * +get_specific (opcode, operands) + struct h8_opcode *opcode; + struct h8_op *operands; +{ + struct h8_opcode *this_try = opcode; + int found = 0; + + unsigned int this_index = opcode->idx; + + while (this_index == opcode->idx && !found) + { + unsigned int i; + found = 1; + + this_try = opcode++; + for (i = 0; i < this_try->noperands && found; i++) + { + op_type op = this_try->args.nib[i]; + int x = operands[i].mode; + + if ((op & (DISP | REG)) == (DISP | REG) + && ((x & (DISP | REG)) == (DISP | REG))) + { + dispreg = operands[i].reg; + } + else if (op & REG) + { + if (!(x & REG)) + found = 0; + + if (x & L_P) + { + x = (x & ~L_P) | (Hmode ? L_32 : L_16); + } + if (op & L_P) + { + op = (op & ~L_P) | (Hmode ? L_32 : L_16); + } + + opsize = op & SIZE; + + /* The size of the reg is v important */ + if ((op & SIZE) != (x & SIZE)) + found = 0; + } + else if ((op & ABSJMP) && (x & ABS)) + { + operands[i].mode &= ~ABS; + operands[i].mode |= ABSJMP; + /* But it may not be 24 bits long */ + if (!Hmode) + { + operands[i].mode &= ~SIZE; + operands[i].mode |= L_16; + } + + + } + else if ((op & (KBIT | DBIT)) && (x & IMM)) + { + /* This is ok if the immediate value is sensible */ + + } + else if (op & PCREL) + { + + /* The size of the displacement is important */ + if ((op & SIZE) != (x & SIZE)) + found = 0; + + } + else if ((op & (DISP | IMM | ABS)) + && (op & (DISP | IMM | ABS)) == (x & (DISP | IMM | ABS))) + { + /* Got a diplacement,will fit if no size or same size as try */ + if (op & ABS && op & L_8) + { + /* We want an 8 bit abs here, but one which looks like 16 bits will do fine */ + if (x & L_16) + found= 1; + } + else + if ((x & SIZE) != 0 + && ((op & SIZE) != (x & SIZE))) + found = 0; + } +#if 0 + else if ((op & ABSMOV) && (x & ABS)) + { + /* An absmov is only */ + /* Ok */ + } +#endif + else if ((op & MODE) != (x & MODE)) + { + found = 0; + } + + } + } + if (found) + return this_try; + else + return 0; +} + +static void +check_operand (operand, width, string) + struct h8_op *operand; + unsigned int width; + char *string; +{ + if (operand->exp.X_add_symbol == 0 + && operand->exp.X_op_symbol == 0) + { + + /* No symbol involved, let's look at offset, it's dangerous if any of + the high bits are not 0 or ff's, find out by oring or anding with + the width and seeing if the answer is 0 or all fs*/ + + if ((operand->exp.X_add_number & ~width) != 0 && + (operand->exp.X_add_number | width) != (~0)) + { + if (width == 255 + && (operand->exp.X_add_number & 0xff00) == 0xff00) + { + /* Just ignore this one - which happens when trying to + fit a 16 bit address truncated into an 8 bit address + of something like bset. */ + } + else + { + as_warn ("operand %s0x%lx out of range.", string, + (unsigned long) operand->exp.X_add_number); + } + } + } + +} + +static void +do_a_fix_imm (offset, operand, relaxing) + int offset; + struct h8_op *operand; + int relaxing; +{ + int idx; + int size; + int where; + + + char *t = operand->mode & IMM ? "#" : "@"; + + if (operand->exp.X_add_symbol == 0) + { + char *bytes = frag_now->fr_literal + offset; + switch (operand->mode & SIZE) + { + case L_2: + check_operand (operand, 0x3, t); + bytes[0] |= (operand->exp.X_add_number) << 4; + break; + case L_3: + check_operand (operand, 0x7, t); + bytes[0] |= (operand->exp.X_add_number) << 4; + break; + case L_8: + check_operand (operand, 0xff, t); + bytes[0] = operand->exp.X_add_number; + break; + case L_16: + check_operand (operand, 0xffff, t); + bytes[0] = operand->exp.X_add_number >> 8; + bytes[1] = operand->exp.X_add_number >> 0; + break; + case L_24: + check_operand (operand, 0xffffff, t); + bytes[0] = operand->exp.X_add_number >> 16; + bytes[1] = operand->exp.X_add_number >> 8; + bytes[2] = operand->exp.X_add_number >> 0; + break; + + case L_32: + /* This should be done with bfd */ + bytes[0] = operand->exp.X_add_number >> 24; + bytes[1] = operand->exp.X_add_number >> 16; + bytes[2] = operand->exp.X_add_number >> 8; + bytes[3] = operand->exp.X_add_number >> 0; + break; + } + + } + else + { + switch (operand->mode & SIZE) + { + + case L_24: + size = 4; + where = -1; + idx = relaxing ? R_MOVLB1 : R_RELLONG; + break; + default: + as_bad("Can't work out size of operand.\n"); + case L_32: + size = 4; + where = 0; + idx = R_RELLONG; + break; + case L_16: + size = 2; + where = 0; + idx = relaxing ? R_MOVB1 : R_RELWORD; + break; + case L_8: + size = 1; + where = 0; + idx = R_RELBYTE; + } + + /* Sign extend any expression */ + operand->exp.X_add_number = (short)operand->exp.X_add_number; + fix_new_exp (frag_now, + offset + where, + size, + &operand->exp, + 0, + idx); + } + +} + +/* Now we know what sort of opcodes it is, lets build the bytes - + */ +static void +build_bytes (this_try, operand) + struct h8_opcode *this_try; + struct h8_op *operand; +{ + unsigned int i; + + char *output = frag_more (this_try->length); + op_type *nibble_ptr = this_try->data.nib; + op_type c; + unsigned int nibble_count = 0; + int absat; + int immat; + int nib; + char asnibbles[30]; + char *p = asnibbles; + + if (!(this_try->inbase || Hmode)) + { + as_warn ("Opcode `%s' only available in this mode on H8/300-H", + this_try->name); + } + + while (*nibble_ptr != E) + { + int d; + c = *nibble_ptr++; + + d = (c & DST) != 0; + + if (c < 16) + { + nib = c; + } + else + { + + if (c & (REG | IND | INC | DEC)) + { + nib = operand[d].reg; + } + else if ((c & DISPREG) == (DISPREG)) + { + nib = dispreg; + } + + else if (c & ABSMOV) + { + operand[d].mode &= ~ABS; + operand[d].mode |= ABSMOV; + immat = nibble_count / 2; + nib = 0; + } + else if (c & ABS ) + { + operand[d].mode = c; + absat = nibble_count / 2; + nib = 0; + } + else if (c & (IMM | PCREL | ABS | ABSJMP | DISP)) + { + operand[d].mode = c; + immat = nibble_count / 2; + nib = 0; + } + else if (c & IGNORE) + { + nib = 0; + } + else if (c & DBIT) + { + switch (operand[0].exp.X_add_number) + { + case 1: + nib = c; + break; + case 2: + nib = 0x8 | c; + break; + default: + as_bad ("Need #1 or #2 here"); + } + } + else if (c & KBIT) + { + switch (operand[0].exp.X_add_number) + { + case 1: + nib = 0; + break; + case 2: + nib = 8; + break; + case 4: + if (!Hmode) + as_warn ("#4 only valid in h8/300 mode."); + nib = 9; + break; + + default: + as_bad ("Need #1 or #2 here"); + break; + } + /* stop it making a fix */ + operand[0].mode = 0; + } + + if (c & B31) + { + nib |= 0x8; + } + } + nibble_count++; + + *p++ = nib; + } + + for (i = 0; i < this_try->length; i++) + { + output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1]; + } + + /* output any fixes */ + for (i = 0; i < 2; i++) + { + int x = operand[i].mode; + + if (x & (IMM | DISP)) + { + do_a_fix_imm (output - frag_now->fr_literal + immat, operand + i, 0); + } + else if (x & ABS) + { + do_a_fix_imm (output - frag_now->fr_literal + absat, operand + i, 0); + } + else if (x & PCREL) + { + int size16 = x & L_16; + int where = size16 ? 2 : 1; + int size = size16 ? 2 : 1; + int type = size16 ? R_PCRWORD : R_PCRBYTE; + + check_operand (operand + i, size16 ? 0x7fff : 0x7f, "@"); + + if (operand[i].exp.X_add_number & 1) + { + as_warn ("branch operand has odd offset (%lx)\n", + (unsigned long) operand->exp.X_add_number); + } + + operand[i].exp.X_add_number = + (char) (operand[i].exp.X_add_number - 1); + fix_new_exp (frag_now, + output - frag_now->fr_literal + where, + size, + &operand[i].exp, + 1, + type); + } + else if (x & MEMIND) + { + + check_operand (operand + i, 0xff, "@@"); + fix_new_exp (frag_now, + output - frag_now->fr_literal + 1, + 1, + &operand[i].exp, + 0, + R_RELBYTE); + } + + else if (x & ABSMOV) + { + /* This mov is either absolute long or thru a memory loc */ + do_a_fix_imm (output - frag_now->fr_literal + immat, operand + i, 1); + } + + else if (x & ABSJMP) + { + /* This jmp may be a jump or a branch */ + + check_operand (operand + i, Hmode ? 0xffffff : 0xffff, "@"); + if (operand[i].exp.X_add_number & 1) + { + as_warn ("branch operand has odd offset (%lx)\n", + (unsigned long) operand->exp.X_add_number); + } + if (!Hmode) + operand[i].exp.X_add_number = (short) operand[i].exp.X_add_number; + fix_new_exp (frag_now, + output - frag_now->fr_literal, + 4, + &operand[i].exp, + 0, + R_JMPL1); + } + } + +} + +/* + try and give an intelligent error message for common and simple to + detect errors + */ + +static void +clever_message (opcode, operand) + struct h8_opcode *opcode; + struct h8_op *operand; +{ + /* Find out if there was more than one possible opccode */ + + if ((opcode + 1)->idx != opcode->idx) + { + unsigned int argn; + + /* Only one opcode of this flavour, try and guess which operand + didn't match */ + for (argn = 0; argn < opcode->noperands; argn++) + { + switch (opcode->args.nib[argn]) + { + case RD16: + if (operand[argn].mode != RD16) + { + as_bad ("destination operand must be 16 bit register"); + return; + + } + break; + + case RS8: + + if (operand[argn].mode != RS8) + { + as_bad ("source operand must be 8 bit register"); + return; + } + break; + + case ABS16DST: + if (operand[argn].mode != ABS16DST) + { + as_bad ("destination operand must be 16bit absolute address"); + return; + } + break; + case RD8: + if (operand[argn].mode != RD8) + { + as_bad ("destination operand must be 8 bit register"); + return; + } + break; + + + case ABS16SRC: + if (operand[argn].mode != ABS16SRC) + { + as_bad ("source operand must be 16bit absolute address"); + return; + } + break; + + } + } + } + as_bad ("invalid operands"); +} + +/* This is the guts of the machine-dependent assembler. STR points to a + machine dependent instruction. This funciton is supposed to emit + the frags/bytes it assembles to. + */ + + + +void +md_assemble (str) + char *str; +{ + char *op_start; + char *op_end; + struct h8_op operand[2]; + struct h8_opcode *opcode; + struct h8_opcode *prev_opcode; + + char *dot = 0; + char c; + + /* Drop leading whitespace */ + while (*str == ' ') + str++; + + /* find the op code end */ + for (op_start = op_end = str; + *op_end != 0 && *op_end != ' '; + op_end++) + { + if (*op_end == '.') + { + dot = op_end + 1; + *op_end = 0; + op_end += 2; + break; + } + } + + ; + + if (op_end == op_start) + { + as_bad ("can't find opcode "); + } + c = *op_end; + + *op_end = 0; + + opcode = (struct h8_opcode *) hash_find (opcode_hash_control, + op_start); + + if (opcode == NULL) + { + as_bad ("unknown opcode"); + return; + } + + /* We use to set input_line_pointer to the result of get_operands, + but that is wrong. Our caller assumes we don't change it. */ + + (void) get_operands (opcode->noperands, op_end, operand); + *op_end = c; + prev_opcode = opcode; + + opcode = get_specific (opcode, operand); + + if (opcode == 0) + { + /* Couldn't find an opcode which matched the operands */ + char *where = frag_more (2); + + where[0] = 0x0; + where[1] = 0x0; + clever_message (prev_opcode, operand); + + return; + } + if (opcode->size && dot) + { + if (opcode->size != *dot) + { + as_warn ("mismatch between opcode size and operand size"); + } + } + + build_bytes (opcode, operand); + +} + +void +tc_crawl_symbol_chain (headers) + object_headers * headers; +{ + printf ("call to tc_crawl_symbol_chain \n"); +} + +symbolS * +md_undefined_symbol (name) + char *name; +{ + return 0; +} + +void +tc_headers_hook (headers) + object_headers * headers; +{ + printf ("call to tc_headers_hook \n"); +} + +/* Various routines to kill one day */ +/* Equal to MAX_PRECISION in atof-ieee.c */ +#define MAX_LITTLENUMS 6 + +/* Turn a string in input_line_pointer into a floating point constant of type + type, and store the appropriate bytes in *litP. The number of LITTLENUMS + emitted is stored in *sizeP . An error message is returned, or NULL on OK. + */ +char * +md_atof (type, litP, sizeP) + char type; + char *litP; + int *sizeP; +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + char *atof_ieee (); + + switch (type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return "Bad call to MD_ATOF()"; + } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + + *sizeP = prec * sizeof (LITTLENUM_TYPE); + for (wordP = words; prec--;) + { + md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + return 0; +} + +CONST char *md_shortopts = ""; +struct option md_longopts[] = { + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof(md_longopts); + +int +md_parse_option (c, arg) + int c; + char *arg; +{ + return 0; +} + +void +md_show_usage (stream) + FILE *stream; +{ +} + +int md_short_jump_size; + +void +tc_aout_fix_to_chars () +{ + printf ("call to tc_aout_fix_to_chars \n"); + abort (); +} + +void +md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr; + addressT to_addr; + fragS *frag; + symbolS *to_symbol; +{ + as_fatal ("failed sanity check."); +} + +void +md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + as_fatal ("failed sanity check."); +} + +void +md_convert_frag (headers, seg, fragP) + object_headers *headers; + segT seg; + fragS *fragP; +{ + printf ("call to md_convert_frag \n"); + abort (); +} + +valueT +md_section_align (seg, size) + segT seg; + valueT size; +{ + return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg])); + +} + +void +md_apply_fix (fixP, val) + fixS *fixP; + long val; +{ + char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; + + switch (fixP->fx_size) + { + case 1: + *buf++ = val; + break; + case 2: + *buf++ = (val >> 8); + *buf++ = val; + break; + case 4: + *buf++ = (val >> 24); + *buf++ = (val >> 16); + *buf++ = (val >> 8); + *buf++ = val; + break; + default: + abort (); + } +} + +int md_long_jump_size; + +int +md_estimate_size_before_relax (fragP, segment_type) + register fragS *fragP; + register segT segment_type; +{ + printf ("call tomd_estimate_size_before_relax \n"); + abort (); +} + +/* Put number into target byte order */ + +void +md_number_to_chars (ptr, use, nbytes) + char *ptr; + valueT use; + int nbytes; +{ + number_to_chars_bigendian (ptr, use, nbytes); +} +long +md_pcrel_from (fixP) + fixS *fixP; +{ + abort (); +} + + +void +tc_reloc_mangle (fix_ptr, intr, base) + fixS *fix_ptr; + struct internal_reloc *intr; + bfd_vma base; + +{ + symbolS *symbol_ptr; + + symbol_ptr = fix_ptr->fx_addsy; + + /* If this relocation is attached to a symbol then it's ok + to output it */ + if (fix_ptr->fx_r_type == RELOC_32) + { + /* cons likes to create reloc32's whatever the size of the reloc.. + */ + switch (fix_ptr->fx_size) + { + + case 2: + intr->r_type = R_RELWORD; + break; + case 1: + intr->r_type = R_RELBYTE; + break; + default: + abort (); + + } + + } + else + { + intr->r_type = fix_ptr->fx_r_type; + } + + intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base; + intr->r_offset = fix_ptr->fx_offset; + + if (symbol_ptr) + intr->r_symndx = symbol_ptr->sy_number; + else + intr->r_symndx = -1; + + +} + +/* end of tc-h8300.c */ diff --git a/gnu/usr.bin/binutils/gas/config/tc-h8300.h b/gnu/usr.bin/binutils/gas/config/tc-h8300.h new file mode 100644 index 00000000000..bb81a6223d8 --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-h8300.h @@ -0,0 +1,50 @@ +/* This file is tc-h8300.h + + Copyright (C) 1987-1992 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 2, 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. */ + + +#define TC_H8300 + +#define TARGET_BYTES_BIG_ENDIAN 1 + +/* This macro translates between an internal fix and an coff reloc type */ +#define TC_COFF_FIX2RTYPE(fixP) abort(); + +#define BFD_ARCH bfd_arch_h8300 +#define COFF_MAGIC Hmode ? 0x8301 : 0x8300 +#define TC_COUNT_RELOC(x) (1) +#define IGNORE_NONSTANDARD_ESCAPES + +#define tc_coff_symbol_emit_hook(a) ; /* not used */ +#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c) +extern void tc_reloc_mangle (); + +#define TC_CONS_RELOC (Hmode ? R_RELLONG: R_RELWORD) + +#define DO_NOT_STRIP 0 +#define DO_STRIP 0 +#define LISTING_HEADER "Hitachi H8/300 GAS " +#define NEED_FX_R_TYPE 1 +#define RELOC_32 1234 + +extern int Hmode; + +#define md_operand(x) + +/* end of tc-h8300.h */ diff --git a/gnu/usr.bin/binutils/gas/config/tc-h8500.c b/gnu/usr.bin/binutils/gas/config/tc-h8500.c new file mode 100644 index 00000000000..5a09e4ad40a --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-h8500.c @@ -0,0 +1,1652 @@ +/* tc-h8500.c -- Assemble code for the Hitachi H8/500 + Copyright (C) 1993 Free Software Foundation. + + 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 2, 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. */ + +/* + Written By Steve Chamberlain + sac@cygnus.com + */ + +#include +#include "as.h" +#include "bfd.h" +#include "subsegs.h" +#define DEFINE_TABLE +#define ASSEMBLER_TABLE +#include "opcodes/h8500-opc.h" +#include + +const char comment_chars[] = "!"; +const char line_separator_chars[] = ";"; +const char line_comment_chars[] = "!#"; + +/* This table describes all the machine specific pseudo-ops the assembler + has to support. The fields are: + pseudo-op name without dot + function to call to execute this pseudo-op + Integer arg to pass to the function + */ + +void cons (); + +const pseudo_typeS md_pseudo_table[] = +{ + {"int", cons, 2}, + {"data.b", cons, 1}, + {"data.w", cons, 2}, + {"data.l", cons, 4}, + {"form", listing_psize, 0}, + {"heading", listing_title, 0}, + {"import", s_ignore, 0}, + {"page", listing_eject, 0}, + {"program", s_ignore, 0}, + {0, 0, 0} +}; + +const int md_reloc_size; + +const char EXP_CHARS[] = "eE"; + +/* Chars that mean this number is a floating point constant */ +/* As in 0f12.456 */ +/* or 0d1.2345e12 */ +const char FLT_CHARS[] = "rRsSfFdDxXpP"; + +#define C(a,b) ENCODE_RELAX(a,b) +#define ENCODE_RELAX(what,length) (((what) << 2) + (length)) + +#define GET_WHAT(x) ((x>>2)) + +#define BYTE_DISP 1 +#define WORD_DISP 2 +#define UNDEF_BYTE_DISP 0 +#define UNDEF_WORD_DISP 3 + +#define BRANCH 1 +#define SCB_F 2 +#define SCB_TST 3 +#define END 4 + +#define BYTE_F 127 +#define BYTE_B -126 +#define WORD_F 32767 +#define WORD_B 32768 + +relax_typeS md_relax_table[C (END, 0)]; + +static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ + +/* + This function is called once, at assembler startup time. This should + set up all the tables, etc that the MD part of the assembler needs + */ + +void +md_begin () +{ + h8500_opcode_info *opcode; + char prev_buffer[100]; + int idx = 0; + register relax_typeS *table; + + opcode_hash_control = hash_new (); + prev_buffer[0] = 0; + + /* Insert unique names into hash table */ + for (opcode = h8500_table; opcode->name; opcode++) + { + if (idx != opcode->idx) + { + hash_insert (opcode_hash_control, opcode->name, (char *) opcode); + idx++; + } + } + + /* Initialize the relax table. We use a local variable to avoid + warnings about modifying a supposedly const data structure. */ + table = (relax_typeS *) md_relax_table; + table[C (BRANCH, BYTE_DISP)].rlx_forward = BYTE_F; + table[C (BRANCH, BYTE_DISP)].rlx_backward = BYTE_B; + table[C (BRANCH, BYTE_DISP)].rlx_length = 2; + table[C (BRANCH, BYTE_DISP)].rlx_more = C (BRANCH, WORD_DISP); + + table[C (BRANCH, WORD_DISP)].rlx_forward = WORD_F; + table[C (BRANCH, WORD_DISP)].rlx_backward = WORD_B; + table[C (BRANCH, WORD_DISP)].rlx_length = 3; + table[C (BRANCH, WORD_DISP)].rlx_more = 0; + + table[C (SCB_F, BYTE_DISP)].rlx_forward = BYTE_F; + table[C (SCB_F, BYTE_DISP)].rlx_backward = BYTE_B; + table[C (SCB_F, BYTE_DISP)].rlx_length = 3; + table[C (SCB_F, BYTE_DISP)].rlx_more = C (SCB_F, WORD_DISP); + + table[C (SCB_F, WORD_DISP)].rlx_forward = WORD_F; + table[C (SCB_F, WORD_DISP)].rlx_backward = WORD_B; + table[C (SCB_F, WORD_DISP)].rlx_length = 8; + table[C (SCB_F, WORD_DISP)].rlx_more = 0; + + table[C (SCB_TST, BYTE_DISP)].rlx_forward = BYTE_F; + table[C (SCB_TST, BYTE_DISP)].rlx_backward = BYTE_B; + table[C (SCB_TST, BYTE_DISP)].rlx_length = 3; + table[C (SCB_TST, BYTE_DISP)].rlx_more = C (SCB_TST, WORD_DISP); + + table[C (SCB_TST, WORD_DISP)].rlx_forward = WORD_F; + table[C (SCB_TST, WORD_DISP)].rlx_backward = WORD_B; + table[C (SCB_TST, WORD_DISP)].rlx_length = 10; + table[C (SCB_TST, WORD_DISP)].rlx_more = 0; + +} + +static int rn; /* register number used by RN */ +static int rs; /* register number used by RS */ +static int rd; /* register number used by RD */ +static int crb; /* byte size cr */ +static int crw; /* word sized cr */ +static int cr; /* unknown size cr */ + +static expressionS displacement;/* displacement expression */ +static int displacement_size; /* and size if given */ + +static int immediate_inpage; +static expressionS immediate; /* immediate expression */ +static int immediate_size; /* and size if given */ + +static expressionS absolute; /* absolute expression */ +static int absolute_size; /* and size if given */ + +typedef struct +{ + int type; + int reg; + expressionS exp; + int page; +} + +h8500_operand_info; + +/* try and parse a reg name, returns number of chars consumed */ +static int +parse_reg (src, mode, reg) + char *src; + int *mode; + int *reg; +{ + if (src[0] == 'r') + { + if (src[1] >= '0' && src[1] <= '7') + { + *mode = RN; + *reg = (src[1] - '0'); + return 2; + } + } + + if (src[0] == 's' && src[1] == 'p') + { + *mode = RN; + *reg = 7; + return 2; + } + if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') + { + *mode = CRB; + *reg = 1; + return 3; + } + if (src[0] == 's' && src[1] == 'r') + { + *mode = CRW; + *reg = 0; + return 2; + } + + if (src[0] == 'b' && src[1] == 'r') + { + *mode = CRB; + *reg = 3; + return 2; + } + + if (src[0] == 'e' && src[1] == 'p') + { + *mode = CRB; + *reg = 4; + return 2; + } + + if (src[0] == 'd' && src[1] == 'p') + { + *mode = CRB; + *reg = 5; + return 2; + } + + if (src[0] == 't' && src[1] == 'p') + { + *mode = CRB; + *reg = 7; + return 2; + } + + if (src[0] == 'f' && src[1] == 'p') + { + *mode = RN; + *reg = 6; + return 2; + } + return 0; +} + +static +char * +parse_exp (s, op, page) + char *s; + expressionS *op; + int *page; +{ + char *save; + char *new; + + save = input_line_pointer; + + *page = 0; + if (s[0] == '%') + { + if (s[1] == 'p' && s[2] == 'a' && s[3] == 'g' && s[4] == 'e') + { + s += 5; + *page = 'p'; + } + if (s[1] == 'h' && s[2] == 'i' && s[3] == '1' && s[4] == '6') + { + s += 5; + *page = 'h'; + } + else if (s[1] == 'o' && s[2] == 'f' && s[3] == 'f') + { + s += 4; + *page = 'o'; + } + } + + input_line_pointer = s; + + expression (op); + if (op->X_op == O_absent) + as_bad ("missing operand"); + new = input_line_pointer; + input_line_pointer = save; + return new; +} + +typedef enum + { + exp_signed, exp_unsigned, exp_sandu + } sign_type; + + +static char * +skip_colonthing (sign, ptr, exp, def, size8, size16, size24) + sign_type sign; + char *ptr; + h8500_operand_info *exp; + int def; + int size8; + int size16; + int size24; +{ + ptr = parse_exp (ptr, &exp->exp, &exp->page); + if (*ptr == ':') + { + ptr++; + if (*ptr == '8') + { + ptr++; + exp->type = size8; + } + else if (ptr[0] == '1' & ptr[1] == '6') + { + ptr += 2; + exp->type = size16; + } + else if (ptr[0] == '2' & ptr[1] == '4') + { + if (!size24) + { + as_bad (":24 not valid for this opcode"); + } + ptr += 2; + exp->type = size24; + } + else + { + as_bad ("expect :8,:16 or :24"); + exp->type = size16; + } + } + else + { + if (exp->page == 'p') + { + exp->type = IMM8; + } + else if (exp->page == 'h') + { + exp->type = IMM16; + } + else + { + /* Let's work out the size from the context */ + int n = exp->exp.X_add_number; + if (size8 + && exp->exp.X_op == O_constant + && ((sign == exp_signed && (n >= -128 && n <= 127)) + || (sign == exp_unsigned && (n >= 0 && (n <= 255))) + || (sign == exp_sandu && (n >= -128 && (n <= 255))))) + { + exp->type = size8; + } + else + { + exp->type = def; + } + } + } + return ptr; +} + +static int +parse_reglist (src, op) + char *src; + h8500_operand_info *op; +{ + int mode; + int rn; + int mask = 0; + int rm; + int idx = 1; /* skip ( */ + + while (src[idx] && src[idx] != ')') + { + int done = parse_reg (src + idx, &mode, &rn); + + if (done) + { + idx += done; + mask |= 1 << rn; + } + else + { + as_bad ("syntax error in reg list"); + return 0; + } + if (src[idx] == '-') + { + idx++; + done = parse_reg (src + idx, &mode, &rm); + if (done) + { + idx += done; + while (rn <= rm) + { + mask |= 1 << rn; + rn++; + } + } + else + { + as_bad ("missing final register in range"); + } + } + if (src[idx] == ',') + idx++; + } + idx++; + op->exp.X_add_symbol = 0; + op->exp.X_op_symbol = 0; + op->exp.X_add_number = mask; + op->exp.X_op = O_constant; + op->exp.X_unsigned = 1; + op->type = IMM8; + return idx; + +} + +/* The many forms of operand: + + Rn Register direct + @Rn Register indirect + @(disp[:size], Rn) Register indirect with displacement + @Rn+ + @-Rn + @aa[:size] absolute + #xx[:size] immediate data + + */ + +static void +get_operand (ptr, op, ispage) + char **ptr; + h8500_operand_info *op; + char ispage; +{ + char *src = *ptr; + int mode; + unsigned int num; + unsigned int len; + op->page = 0; + if (src[0] == '(' && src[1] == 'r') + { + /* This is a register list */ + *ptr = src + parse_reglist (src, op); + return; + } + + len = parse_reg (src, &op->type, &op->reg); + + if (len) + { + *ptr = src + len; + return; + } + + if (*src == '@') + { + src++; + if (*src == '-') + { + src++; + len = parse_reg (src, &mode, &num); + if (len == 0) + { + /* Oops, not a reg after all, must be ordinary exp */ + src--; + /* must be a symbol */ + *ptr = skip_colonthing (exp_unsigned, src, + op, ABS16, ABS8, ABS16, ABS24); + return; + } + + op->type = RNDEC; + op->reg = num; + *ptr = src + len; + return; + } + if (*src == '(') + { + /* Disp */ + src++; + + src = skip_colonthing (exp_signed, src, + op, RNIND_D16, RNIND_D8, RNIND_D16, 0); + + if (*src != ',') + { + as_bad ("expected @(exp, Rn)"); + return; + } + src++; + len = parse_reg (src, &mode, &op->reg); + if (len == 0 || mode != RN) + { + as_bad ("expected @(exp, Rn)"); + return; + } + src += len; + if (*src != ')') + { + as_bad ("expected @(exp, Rn)"); + return; + } + *ptr = src + 1; + return; + } + len = parse_reg (src, &mode, &num); + + if (len) + { + src += len; + if (*src == '+') + { + src++; + if (mode != RN) + { + as_bad ("@Rn+ needs word register"); + return; + } + op->type = RNINC; + op->reg = num; + *ptr = src; + return; + } + if (mode != RN) + { + as_bad ("@Rn needs word register"); + return; + } + op->type = RNIND; + op->reg = num; + *ptr = src; + return; + } + else + { + /* must be a symbol */ + *ptr = + skip_colonthing (exp_unsigned, src, op, + ispage ? ABS24 : ABS16, ABS8, ABS16, ABS24); + return; + } + } + + if (*src == '#') + { + src++; + *ptr = skip_colonthing (exp_sandu, src, op, IMM16, IMM8, IMM16, ABS24); + return; + } + else + { + *ptr = skip_colonthing (exp_signed, src, op, + ispage ? ABS24 : PCREL8, PCREL8, PCREL16, ABS24); + } +} + +static +char * +get_operands (info, args, operand) + h8500_opcode_info *info; + char *args; + h8500_operand_info *operand; + +{ + char *ptr = args; + + switch (info->nargs) + { + case 0: + operand[0].type = 0; + operand[1].type = 0; + break; + + case 1: + ptr++; + get_operand (&ptr, operand + 0, info->name[0] == 'p'); + operand[1].type = 0; + break; + + case 2: + ptr++; + get_operand (&ptr, operand + 0, 0); + if (*ptr == ',') + ptr++; + get_operand (&ptr, operand + 1, 0); + break; + + default: + abort (); + } + + return ptr; +} + +/* Passed a pointer to a list of opcodes which use different + addressing modes, return the opcode which matches the opcodes + provided + */ + +int pcrel8; /* Set when we've seen a pcrel operand */ + +static +h8500_opcode_info * +get_specific (opcode, operands) + h8500_opcode_info *opcode; + h8500_operand_info *operands; +{ + h8500_opcode_info *this_try = opcode; + int found = 0; + unsigned int noperands = opcode->nargs; + + unsigned int this_index = opcode->idx; + + while (this_index == opcode->idx && !found) + { + unsigned int i; + + this_try = opcode++; + + /* look at both operands needed by the opcodes and provided by + the user*/ + for (i = 0; i < noperands; i++) + { + h8500_operand_info *user = operands + i; + + switch (this_try->arg_type[i]) + { + case FPIND_D8: + /* Opcode needs (disp:8,fp) */ + if (user->type == RNIND_D8 && user->reg == 6) + { + displacement = user->exp; + continue; + } + break; + case RDIND_D16: + if (user->type == RNIND_D16) + { + displacement = user->exp; + rd = user->reg; + continue; + } + break; + case RDIND_D8: + if (user->type == RNIND_D8) + { + displacement = user->exp; + rd = user->reg; + continue; + } + break; + case RNIND_D16: + case RNIND_D8: + if (user->type == this_try->arg_type[i]) + { + displacement = user->exp; + rn = user->reg; + continue; + } + break; + + case SPDEC: + if (user->type == RNDEC && user->reg == 7) + { + continue; + } + break; + case SPINC: + if (user->type == RNINC && user->reg == 7) + { + continue; + } + break; + case ABS16: + if (user->type == ABS16) + { + absolute = user->exp; + continue; + } + break; + case ABS8: + if (user->type == ABS8) + { + absolute = user->exp; + continue; + } + break; + case ABS24: + if (user->type == ABS24) + { + absolute = user->exp; + continue; + } + break; + + case CRB: + if ((user->type == CRB || user->type == CR) && user->reg != 0) + { + crb = user->reg; + continue; + } + break; + case CRW: + if ((user->type == CRW || user->type == CR) && user->reg == 0) + { + crw = user->reg; + continue; + } + break; + case DISP16: + if (user->type == DISP16) + { + displacement = user->exp; + continue; + } + break; + case DISP8: + if (user->type == DISP8) + { + displacement = user->exp; + continue; + } + break; + case FP: + if (user->type == RN && user->reg == 6) + { + continue; + } + break; + case PCREL16: + if (user->type == PCREL16) + { + displacement = user->exp; + continue; + } + break; + case PCREL8: + if (user->type == PCREL8) + { + displacement = user->exp; + pcrel8 = 1; + continue; + } + break; + + case IMM16: + if (user->type == IMM16 + || user->type == IMM8) + { + immediate_inpage = user->page; + immediate = user->exp; + continue; + } + break; + case RLIST: + case IMM8: + if (user->type == IMM8) + { + immediate_inpage = user->page; + immediate = user->exp; + continue; + } + break; + case IMM4: + if (user->type == IMM8) + { + immediate_inpage = user->page; + immediate = user->exp; + continue; + } + break; + case QIM: + if (user->type == IMM8 + && user->exp.X_op == O_constant + && + (user->exp.X_add_number == -2 + || user->exp.X_add_number == -1 + || user->exp.X_add_number == 1 + || user->exp.X_add_number == 2)) + { + immediate_inpage = user->page; + immediate = user->exp; + continue; + } + break; + case RD: + if (user->type == RN) + { + rd = user->reg; + continue; + } + break; + case RS: + if (user->type == RN) + { + rs = user->reg; + continue; + } + break; + case RDIND: + if (user->type == RNIND) + { + rd = user->reg; + continue; + + } + break; + case RNINC: + case RNIND: + case RNDEC: + case RN: + + if (user->type == this_try->arg_type[i]) + { + rn = user->reg; + continue; + } + break; + case SP: + if (user->type == RN && user->reg == 7) + { + continue; + } + break; + default: + printf ("unhandled %d\n", this_try->arg_type[i]); + break; + } + + /* If we get here this didn't work out */ + goto fail; + } + found = 1; + fail:; + + } + + if (found) + return this_try; + else + return 0; +} + +int +check (operand, low, high) + expressionS *operand; + int low; + int high; +{ + if (operand->X_op != O_constant + || operand->X_add_number < low + || operand->X_add_number > high) + { + as_bad ("operand must be absolute in range %d..%d", low, high); + } + return operand->X_add_number; +} + +static +void +insert (output, index, exp, reloc, pcrel) + char *output; + int index; + expressionS *exp; + int reloc; + int pcrel; +{ + fix_new_exp (frag_now, + output - frag_now->fr_literal + index, + 4, /* always say size is 4, but we know better */ + exp, + pcrel, + reloc); +} + +void +build_relaxable_instruction (opcode, operand) + h8500_opcode_info *opcode; + h8500_operand_info *operand; +{ + /* All relaxable instructions start life as two bytes but can become + three bytes long if a lonely branch and up to 9 bytes if long scb + */ + char *p; + int len; + int type; + + if (opcode->bytes[0].contents == 0x01) + { + type = SCB_F; + } + else if (opcode->bytes[0].contents == 0x06 + || opcode->bytes[0].contents == 0x07) + { + type = SCB_TST; + } + else + { + type = BRANCH; + } + + p = frag_var (rs_machine_dependent, + md_relax_table[C (type, WORD_DISP)].rlx_length, + len = md_relax_table[C (type, BYTE_DISP)].rlx_length, + C (type, UNDEF_BYTE_DISP), + displacement.X_add_symbol, + displacement.X_add_number, + 0); + + p[0] = opcode->bytes[0].contents; + if (type != BRANCH) + { + p[1] = opcode->bytes[1].contents | rs; + } +} + +/* Now we know what sort of opcodes it is, lets build the bytes - + */ +static void +build_bytes (opcode, operand) + h8500_opcode_info *opcode; + h8500_operand_info *operand; + +{ + int index; + + if (pcrel8) + { + pcrel8 = 0; + build_relaxable_instruction (opcode, operand); + } + else + { + char *output = frag_more (opcode->length); + + memset (output, 0, opcode->length); + for (index = 0; index < opcode->length; index++) + { + output[index] = opcode->bytes[index].contents; + + switch (opcode->bytes[index].insert) + { + default: + printf ("failed for %d\n", opcode->bytes[index].insert); + break; + case 0: + break; + case RN: + output[index] |= rn; + break; + case RD: + case RDIND: + + output[index] |= rd; + break; + case RS: + output[index] |= rs; + break; + case DISP16: + insert (output, index, &displacement, R_H8500_IMM16, 0); + index++; + break; + case DISP8: + case FPIND_D8: + insert (output, index, &displacement, R_H8500_IMM8, 0); + break; + + case IMM16: + { + int p; + switch (immediate_inpage) { + case 'p': + p = R_H8500_HIGH16; + break; + case 'h': + p = R_H8500_HIGH16; + break; + default: + p = R_H8500_IMM16; + break; + } + + insert (output, index, &immediate,p, 0); + } + + index++; + break; + case RLIST: + case IMM8: + if (immediate_inpage) + { + insert (output, index, &immediate, R_H8500_HIGH8, 0); + } + else + { + insert (output, index, &immediate, R_H8500_IMM8, 0); + } + break; + case PCREL16: + insert (output, index, &displacement, R_H8500_PCREL16, 1); + index++; + break; + case PCREL8: + insert (output, index, &displacement, R_H8500_PCREL8, 1); + break; + case IMM4: + output[index] |= check (&immediate, 0, 15); + break; + case CR: + + output[index] |= cr; + if (cr == 0) + { + output[0] |= 0x8; + } + else + { + output[0] &= ~0x8; + } + + break; + + case CRB: + output[index] |= crb; + output[0] &= ~0x8; + break; + case CRW: + output[index] |= crw; + output[0] |= 0x8; + break; + case ABS24: + insert (output, index, &absolute, R_H8500_IMM24, 0); + index += 2; + break; + case ABS16: + insert (output, index, &absolute, R_H8500_IMM16, 0); + index++; + break; + case ABS8: + insert (output, index, &absolute, R_H8500_IMM8, 0); + break; + case QIM: + switch (immediate.X_add_number) + { + case -2: + output[index] |= 0x5; + break; + case -1: + output[index] |= 0x4; + break; + case 1: + output[index] |= 0; + break; + case 2: + output[index] |= 1; + break; + } + break; + } + } + } +} + +/* This is the guts of the machine-dependent assembler. STR points to a + machine dependent instruction. This funciton is supposed to emit + the frags/bytes it assembles to. + */ + +void +DEFUN (md_assemble, (str), + char *str) +{ + char *op_start; + char *op_end; + h8500_operand_info operand[2]; + h8500_opcode_info *opcode; + h8500_opcode_info *prev_opcode; + char name[11]; + + int nlen = 0; + + /* Drop leading whitespace */ + while (*str == ' ') + str++; + + /* find the op code end */ + for (op_start = op_end = str; + *op_end && + !is_end_of_line[*op_end] && *op_end != ' '; + op_end++) + { + if ( /**op_end != '.' + && *op_end != ':' + && */ nlen < 10) + { + name[nlen++] = *op_end; + } + } + name[nlen] = 0; + + if (op_end == op_start) + { + as_bad ("can't find opcode "); + } + + opcode = (h8500_opcode_info *) hash_find (opcode_hash_control, name); + + if (opcode == NULL) + { + as_bad ("unknown opcode"); + return; + } + + get_operands (opcode, op_end, operand); + prev_opcode = opcode; + + opcode = get_specific (opcode, operand); + + if (opcode == 0) + { + /* Couldn't find an opcode which matched the operands */ + char *where = frag_more (2); + + where[0] = 0x0; + where[1] = 0x0; + as_bad ("invalid operands for opcode"); + return; + } + + build_bytes (opcode, operand); + +} + +void +DEFUN (tc_crawl_symbol_chain, (headers), + object_headers * headers) +{ + printf ("call to tc_crawl_symbol_chain \n"); +} + +symbolS * +DEFUN (md_undefined_symbol, (name), + char *name) +{ + return 0; +} + +void +DEFUN (tc_headers_hook, (headers), + object_headers * headers) +{ + printf ("call to tc_headers_hook \n"); +} + +/* Various routines to kill one day */ +/* Equal to MAX_PRECISION in atof-ieee.c */ +#define MAX_LITTLENUMS 6 + +/* Turn a string in input_line_pointer into a floating point constant of type + type, and store the appropriate bytes in *litP. The number of LITTLENUMS + emitted is stored in *sizeP . An error message is returned, or NULL on OK. + */ +char * +md_atof (type, litP, sizeP) + char type; + char *litP; + int *sizeP; +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + char *atof_ieee (); + + switch (type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return "Bad call to MD_ATOF()"; + } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + + *sizeP = prec * sizeof (LITTLENUM_TYPE); + for (wordP = words; prec--;) + { + md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + return 0; +} + +CONST char *md_shortopts = ""; +struct option md_longopts[] = { + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof(md_longopts); + +int +md_parse_option (c, arg) + int c; + char *arg; +{ + return 0; +} + +void +md_show_usage (stream) + FILE *stream; +{ +} + +int md_short_jump_size; + +void +tc_aout_fix_to_chars () +{ + printf ("call to tc_aout_fix_to_chars \n"); + abort (); +} + +void +md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr; + addressT to_addr; + fragS *frag; + symbolS *to_symbol; +{ + as_fatal ("failed sanity check."); +} + +void +md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + as_fatal ("failed sanity check."); +} + +static +void +wordify_scb (buffer, disp_size, inst_size) + char *buffer; + int *disp_size; + int *inst_size; +{ + int rn = buffer[1] & 0x7; + + switch (buffer[0]) + { + case 0x0e: /* BSR */ + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + buffer[0] |= 0x10; + buffer[1] = 0; + buffer[2] = 0; + *disp_size = 2; + *inst_size = 1; + return; + default: + abort (); + + case 0x01: + *inst_size = 6; + *disp_size = 2; + break; + case 0x06: + *inst_size = 8; + *disp_size = 2; + + *buffer++ = 0x26; /* bne + 8 */ + *buffer++ = 0x08; + break; + case 0x07: + *inst_size = 8; + *disp_size = 2; + *buffer++ = 0x27; /* bne + 8 */ + *buffer++ = 0x08; + break; + + } + *buffer++ = 0xa8 | rn; /* addq -1,rn */ + *buffer++ = 0x0c; + *buffer++ = 0x04; /* cmp #0xff:8, rn */ + *buffer++ = 0xff; + *buffer++ = 0x70 | rn; + *buffer++ = 0x36; /* bne ... */ + *buffer++ = 0; + *buffer++ = 0; +} + +/* +called after relaxing, change the frags so they know how big they are +*/ +void +md_convert_frag (headers, seg, fragP) + object_headers *headers; + segT seg; + fragS *fragP; +{ + int disp_size = 0; + int inst_size = 0; + char *buffer = fragP->fr_fix + fragP->fr_literal; + + switch (fragP->fr_subtype) + { + case C (BRANCH, BYTE_DISP): + disp_size = 1; + inst_size = 1; + break; + + case C (SCB_F, BYTE_DISP): + case C (SCB_TST, BYTE_DISP): + disp_size = 1; + inst_size = 2; + break; + + /* Branches to a known 16 bit displacement */ + + /* Turn on the 16bit bit */ + case C (BRANCH, WORD_DISP): + case C (SCB_F, WORD_DISP): + case C (SCB_TST, WORD_DISP): + wordify_scb (buffer, &disp_size, &inst_size); + break; + + case C (BRANCH, UNDEF_WORD_DISP): + case C (SCB_F, UNDEF_WORD_DISP): + case C (SCB_TST, UNDEF_WORD_DISP): + /* This tried to be relaxed, but didn't manage it, it now needs a + fix */ + wordify_scb (buffer, &disp_size, &inst_size); + + /* Make a reloc */ + fix_new (fragP, + fragP->fr_fix + inst_size, + 4, + fragP->fr_symbol, + fragP->fr_offset, + 0, + R_H8500_PCREL16); + + fragP->fr_fix += disp_size + inst_size; + fragP->fr_var = 0; + return; + break; + default: + abort (); + } + if (inst_size) + { + /* Get the address of the end of the instruction */ + int next_inst = fragP->fr_fix + fragP->fr_address + disp_size + inst_size; + int targ_addr = (S_GET_VALUE (fragP->fr_symbol) + + fragP->fr_offset); + int disp = targ_addr - next_inst; + + md_number_to_chars (buffer + inst_size, disp, disp_size); + fragP->fr_fix += disp_size + inst_size; + fragP->fr_var = 0; + } +} + +valueT +md_section_align (seg, size) + segT seg ; + valueT size; +{ + return ((size + (1 << section_alignment[(int) seg]) - 1) + & (-1 << section_alignment[(int) seg])); + +} + +void +md_apply_fix (fixP, val) + fixS *fixP; + long val; +{ + char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; + + if (fixP->fx_r_type == 0) + { + fixP->fx_r_type = fixP->fx_size == 4 ? R_H8500_IMM32 : R_H8500_IMM16; + } + + switch (fixP->fx_r_type) + { + + case R_H8500_IMM8: + case R_H8500_PCREL8: + *buf++ = val; + break; + case R_H8500_IMM16: + case R_H8500_LOW16: + case R_H8500_PCREL16: + *buf++ = (val >> 8); + *buf++ = val; + break; + case R_H8500_HIGH8: + *buf++ = val >> 16; + break; + case R_H8500_HIGH16: + *buf++ = val >> 24; + *buf++ = val >> 16; + break; + case R_H8500_IMM24: + *buf++ = (val >> 16); + *buf++ = (val >> 8); + *buf++ = val; + break; + case R_H8500_IMM32: + *buf++ = (val >> 24); + *buf++ = (val >> 16); + *buf++ = (val >> 8); + *buf++ = val; + break; + default: + abort (); + + } +} + +int md_long_jump_size; + +/* +called just before address relaxation, return the length +by which a fragment must grow to reach it's destination +*/ +int +md_estimate_size_before_relax (fragP, segment_type) + register fragS *fragP; + register segT segment_type; +{ + int what = GET_WHAT (fragP->fr_subtype); + + switch (fragP->fr_subtype) + { + default: + abort (); + case C (BRANCH, UNDEF_BYTE_DISP): + case C (SCB_F, UNDEF_BYTE_DISP): + case C (SCB_TST, UNDEF_BYTE_DISP): + /* used to be a branch to somewhere which was unknown */ + if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) + { + /* Got a symbol and it's defined in this segment, become byte + sized - maybe it will fix up */ + fragP->fr_subtype = C (what, BYTE_DISP); + fragP->fr_var = md_relax_table[C (what, BYTE_DISP)].rlx_length; + } + else + { + /* Its got a segment, but its not ours, so it will always be long */ + fragP->fr_subtype = C (what, UNDEF_WORD_DISP); + fragP->fr_var = md_relax_table[C (what, WORD_DISP)].rlx_length; + return md_relax_table[C (what, WORD_DISP)].rlx_length; + } + } + return fragP->fr_var; +} + +/* Put number into target byte order */ + +void +md_number_to_chars (ptr, use, nbytes) + char *ptr; + valueT use; + int nbytes; +{ + number_to_chars_bigendian (ptr, use, nbytes); +} + +long +md_pcrel_from (fixP) + fixS *fixP; +{ + return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; +} + +/*ARGSUSED*/ +void +tc_coff_symbol_emit_hook (ignore) + symbolS *ignore; +{ +} + +short +tc_coff_fix2rtype (fix_ptr) + fixS *fix_ptr; +{ + if (fix_ptr->fx_r_type == RELOC_32) + { + /* cons likes to create reloc32's whatever the size of the reloc.. + */ + switch (fix_ptr->fx_size) + { + case 2: + return R_H8500_IMM16; + break; + case 1: + return R_H8500_IMM8; + break; + default: + abort (); + } + } + return fix_ptr->fx_r_type; +} + +void +tc_reloc_mangle (fix_ptr, intr, base) + fixS *fix_ptr; + struct internal_reloc *intr; + bfd_vma base; + +{ + symbolS *symbol_ptr; + + symbol_ptr = fix_ptr->fx_addsy; + + /* If this relocation is attached to a symbol then it's ok + to output it */ + if (fix_ptr->fx_r_type == RELOC_32) + { + /* cons likes to create reloc32's whatever the size of the reloc.. + */ + switch (fix_ptr->fx_size) + { + case 2: + intr->r_type = R_IMM16; + break; + case 1: + intr->r_type = R_IMM8; + break; + default: + abort (); + } + } + else + { + intr->r_type = fix_ptr->fx_r_type; + } + + intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base; + intr->r_offset = fix_ptr->fx_offset; + + /* Turn the segment of the symbol into an offset. */ + if (symbol_ptr) + { + symbolS *dot; + + dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot; + if (dot) + { + /* intr->r_offset -= + segment_info[S_GET_SEGMENT(symbol_ptr)].scnhdr.s_paddr;*/ + intr->r_offset += S_GET_VALUE (symbol_ptr); + intr->r_symndx = dot->sy_number; + } + else + { + intr->r_symndx = symbol_ptr->sy_number; + } + + } + else + { + intr->r_symndx = -1; + } + +} + + + +int +start_label (ptr) + char *ptr; +{ + /* Check for :s.w */ + if (isalpha (ptr[1]) && ptr[2] == '.') + return 0; + /* Check for :s */ + if (isalpha (ptr[1]) && !isalpha (ptr[2])) + return 0; + return 1; +} + + +int +tc_coff_sizemachdep (frag) + fragS *frag; +{ + return md_relax_table[frag->fr_subtype].rlx_length; +} + +/* end of tc-h8500.c */ + diff --git a/gnu/usr.bin/binutils/gas/config/tc-h8500.h b/gnu/usr.bin/binutils/gas/config/tc-h8500.h new file mode 100644 index 00000000000..db241f07c5d --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-h8500.h @@ -0,0 +1,50 @@ +/* This file is tc-h8500.h + + Copyright (C) 1993 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 2, 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. */ + + +#define TC_H8500 + +#define TARGET_BYTES_BIG_ENDIAN 1 + +/* This macro translates between an internal fix and an coff reloc type */ +#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP) + +#define BFD_ARCH bfd_arch_h8500 +#define COFF_MAGIC 0x8500 +#define TC_COUNT_RELOC(x) ((x)->fx_addsy||(x)->fx_subsy) +#define IGNORE_NONSTANDARD_ESCAPES + +#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c) + +#define DO_NOT_STRIP 0 +#define DO_STRIP 0 +#define LISTING_HEADER "Hitachi H8/500 GAS " +#define NEED_FX_R_TYPE 1 +#define RELOC_32 1234 + +#define TC_START_LABEL(ch, ptr) (ch == ':' && start_label(ptr)) +#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag) + +#define md_operand(x) + +extern struct relax_type md_relax_table[]; +#define TC_GENERIC_RELAX_TABLE md_relax_table + +/* end of tc-h8500.h */ diff --git a/gnu/usr.bin/binutils/gas/config/tc-hppa.c b/gnu/usr.bin/binutils/gas/config/tc-hppa.c new file mode 100644 index 00000000000..65ed66bfb1c --- /dev/null +++ b/gnu/usr.bin/binutils/gas/config/tc-hppa.c @@ -0,0 +1,6438 @@ +/* tc-hppa.c -- Assemble for the PA + Copyright (C) 1989 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. */ + + +/* HP PA-RISC support was contributed by the Center for Software Science + at the University of Utah. */ + +#include +#include + +#include "as.h" +#include "subsegs.h" + +#include "bfd/libhppa.h" +#include "bfd/libbfd.h" + +/* Be careful, this file includes data *declarations*. */ +#include "opcode/hppa.h" + +/* A "convient" place to put object file dependencies which do + not need to be seen outside of tc-hppa.c. */ +#ifdef OBJ_ELF +/* Names of various debugging spaces/subspaces. */ +#define GDB_DEBUG_SPACE_NAME ".stab" +#define GDB_STRINGS_SUBSPACE_NAME ".stabstr" +#define GDB_SYMBOLS_SUBSPACE_NAME ".stab" +#define UNWIND_SECTION_NAME ".PARISC.unwind" +/* Nonzero if CODE is a fixup code needing further processing. */ + +/* Object file formats specify relocation types. */ +typedef elf32_hppa_reloc_type reloc_type; + +/* Object file formats specify BFD symbol types. */ +typedef elf_symbol_type obj_symbol_type; + +/* How to generate a relocation. */ +#define hppa_gen_reloc_type hppa_elf_gen_reloc_type + +/* ELF objects can have versions, but apparently do not have anywhere + to store a copyright string. */ +#define obj_version obj_elf_version +#define obj_copyright obj_elf_version + +/* Use space aliases. */ +#define USE_ALIASES 1 +#endif + +#ifdef OBJ_SOM +/* Names of various debugging spaces/subspaces. */ +#define GDB_DEBUG_SPACE_NAME "$GDB_DEBUG$" +#define GDB_STRINGS_SUBSPACE_NAME "$GDB_STRINGS$" +#define GDB_SYMBOLS_SUBSPACE_NAME "$GDB_SYMBOLS$" +#define UNWIND_SECTION_NAME "$UNWIND$" + +/* Object file formats specify relocation types. */ +typedef int reloc_type; + +/* SOM objects can have both a version string and a copyright string. */ +#define obj_version obj_som_version +#define obj_copyright obj_som_copyright + +/* Do not use space aliases. */ +#define USE_ALIASES 0 + +/* How to generate a relocation. */ +#define hppa_gen_reloc_type hppa_som_gen_reloc_type + +/* Object file formats specify BFD symbol types. */ +typedef som_symbol_type obj_symbol_type; + +/* This apparently isn't in older versions of hpux reloc.h. */ +#ifndef R_DLT_REL +#define R_DLT_REL 0x78 +#endif +#endif + +/* Various structures and types used internally in tc-hppa.c. */ + +/* Unwind table and descriptor. FIXME: Sync this with GDB version. */ + +struct unwind_desc + { + unsigned int cannot_unwind:1; + unsigned int millicode:1; + unsigned int millicode_save_rest:1; + unsigned int region_desc:2; + unsigned int save_sr:2; + unsigned int entry_fr:4; + unsigned int entry_gr:5; + unsigned int args_stored:1; + unsigned int call_fr:5; + unsigned int call_gr:5; + unsigned int save_sp:1; + unsigned int save_rp:1; + unsigned int save_rp_in_frame:1; + unsigned int extn_ptr_defined:1; + unsigned int cleanup_defined:1; + + unsigned int hpe_interrupt_marker:1; + unsigned int hpux_interrupt_marker:1; + unsigned int reserved:3; + unsigned int frame_size:27; + }; + +struct unwind_table + { + /* Starting and ending offsets of the region described by + descriptor. */ + unsigned int start_offset; + unsigned int end_offset; + struct unwind_desc descriptor; + }; + +/* This structure is used by the .callinfo, .enter, .leave pseudo-ops to + control the entry and exit code they generate. It is also used in + creation of the correct stack unwind descriptors. + + NOTE: GAS does not support .enter and .leave for the generation of + prologues and epilogues. FIXME. + + The fields in structure roughly correspond to the arguments available on the + .callinfo pseudo-op. */ + +struct call_info + { + /* The unwind descriptor being built. */ + struct unwind_table ci_unwind; + + /* Name of this function. */ + symbolS *start_symbol; + + /* (temporary) symbol used to mark the end of this function. */ + symbolS *end_symbol; + + /* Next entry in the chain. */ + struct call_info *ci_next; + }; + +/* Operand formats for FP instructions. Note not all FP instructions + allow all four formats to be used (for example fmpysub only allows + SGL and DBL). */ +typedef enum + { + SGL, DBL, ILLEGAL_FMT, QUAD + } +fp_operand_format; + +/* 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; + +/* This structure contains information needed to assemble + individual instructions. */ +struct pa_it + { + /* Holds the opcode after parsing by pa_ip. */ + unsigned long opcode; + + /* Holds an expression associated with the current instruction. */ + expressionS exp; + + /* Does this instruction use PC-relative addressing. */ + int pcrel; + + /* Floating point formats for operand1 and operand2. */ + fp_operand_format fpof1; + fp_operand_format fpof2; + + /* Holds the field selector for this instruction + (for example L%, LR%, etc). */ + long field_selector; + + /* Holds any argument relocation bits associated with this + instruction. (instruction should be some sort of call). */ + long arg_reloc; + + /* The format specification for this instruction. */ + int format; + + /* The relocation (if any) associated with this instruction. */ + reloc_type reloc; + }; + +/* PA-89 floating point registers are arranged like this: + + + +--------------+--------------+ + | 0 or 16L | 16 or 16R | + +--------------+--------------+ + | 1 or 17L | 17 or 17R | + +--------------+--------------+ + | | | + + . . . + . . . + . . . + + | | | + +--------------+--------------+ + | 14 or 30L | 30 or 30R | + +--------------+--------------+ + | 15 or 31L | 31 or 31R | + +--------------+--------------+ + + + The following is a version of pa_parse_number that + handles the L/R notation and returns the correct + value to put into the instruction register field. + The correct value to put into the instruction is + encoded in the structure 'pa_11_fp_reg_struct'. */ + +struct pa_11_fp_reg_struct + { + /* The register number. */ + char number_part; + + /* L/R selector. */ + char l_r_select; + }; + +/* Additional information needed to build argument relocation stubs. */ +struct call_desc + { + /* The argument relocation specification. */ + unsigned int arg_reloc; + + /* Number of arguments. */ + unsigned int arg_count; + }; + +/* This structure defines an entry in the subspace dictionary + chain. */ + +struct subspace_dictionary_chain + { + /* Nonzero if this space has been defined by the user code. */ + unsigned int ssd_defined; + + /* Name of this subspace. */ + char *ssd_name; + + /* GAS segment and subsegment associated with this subspace. */ + asection *ssd_seg; + int ssd_subseg; + + /* Next space in the subspace dictionary chain. */ + struct subspace_dictionary_chain *ssd_next; + }; + +typedef struct subspace_dictionary_chain ssd_chain_struct; + +/* This structure defines an entry in the subspace dictionary + chain. */ + +struct space_dictionary_chain + { + /* Nonzero if this space has been defined by the user code or + as a default space. */ + unsigned int sd_defined; + + /* Nonzero if this spaces has been defined by the user code. */ + unsigned int sd_user_defined; + + /* The space number (or index). */ + unsigned int sd_spnum; + + /* The name of this subspace. */ + char *sd_name; + + /* GAS segment to which this subspace corresponds. */ + asection *sd_seg; + + /* Current subsegment number being used. */ + int sd_last_subseg; + + /* The chain of subspaces contained within this space. */ + ssd_chain_struct *sd_subspaces; + + /* The next entry in the space dictionary chain. */ + struct space_dictionary_chain *sd_next; + }; + +typedef struct space_dictionary_chain sd_chain_struct; + +/* Structure for previous label tracking. Needed so that alignments, + callinfo declarations, etc can be easily attached to a particular + label. */ +typedef struct label_symbol_struct + { + struct symbol *lss_label; + sd_chain_struct *lss_space; + struct label_symbol_struct *lss_next; + } +label_symbol_struct; + +/* This structure defines attributes of the default subspace + dictionary entries. */ + +struct default_subspace_dict + { + /* Name of the subspace. */ + char *name; + + /* FIXME. Is this still needed? */ + char defined; + + /* Nonzero if this subspace is loadable. */ + char loadable; + + /* Nonzero if this subspace contains only code. */ + char code_only; + + /* Nonzero if this is a common subspace. */ + char common; + + /* Nonzero if this is a common subspace which allows symbols + to be multiply defined. */ + char dup_common; + + /* Nonzero if this subspace should be zero filled. */ + char zero; + + /* Sort key for this subspace. */ + unsigned char sort; + + /* Access control bits for this subspace. Can represent RWX access + as well as privilege level changes for gateways. */ + int access; + + /* Index of containing space. */ + int space_index; + + /* Alignment (in bytes) of this subspace. */ + int alignment; + + /* Quadrant within space where this subspace should be loaded. */ + int quadrant; + + /* An index into the default spaces array. */ + int def_space_index; + + /* An alias for this section (or NULL if no alias exists). */ + char *alias; + + /* Subsegment associated with this subspace. */ + subsegT subsegment; + }; + +/* This structure defines attributes of the default space + dictionary entries. */ + +struct default_space_dict + { + /* Name of the space. */ + char *name; + + /* Space number. It is possible to identify spaces within + assembly code numerically! */ + int spnum; + + /* Nonzero if this space is loadable. */ + char loadable; + + /* Nonzero if this space is "defined". FIXME is still needed */ + char defined; + + /* Nonzero if this space can not be shared. */ + char private; + + /* Sort key for this space. */ + unsigned char sort; + + /* Segment associated with this space. */ + asection *segment; + + /* An alias for this section (or NULL if no alias exists). */ + char *alias; + }; + +/* Extra information needed to perform fixups (relocations) on the PA. */ +struct hppa_fix_struct + { + /* The field selector. */ + enum hppa_reloc_field_selector_type fx_r_field; + + /* Type of fixup. */ + int fx_r_type; + + /* Format of fixup. */ + int fx_r_format; + + /* Argument relocation bits. */ + long fx_arg_reloc; + + /* The segment this fixup appears in. */ + segT segment; + }; + +/* Structure to hold information about predefined registers. */ + +struct pd_reg + { + char *name; + int value; + }; + +/* This structure defines the mapping from a FP condition string + to a condition number which can be recorded in an instruction. */ +struct fp_cond_map + { + char *string; + int cond; + }; + +/* This structure defines a mapping from a field selector + string to a field selector type. */ +struct selector_entry + { + char *prefix; + int field_selector; + }; + +/* Prototypes for functions local to tc-hppa.c. */ + +static void pa_check_current_space_and_subspace PARAMS ((void)); +static fp_operand_format pa_parse_fp_format PARAMS ((char **s)); +static void pa_cons PARAMS ((int)); +static void pa_data PARAMS ((int)); +static void pa_float_cons PARAMS ((int)); +static void pa_fill PARAMS ((int)); +static void pa_lcomm PARAMS ((int)); +static void pa_lsym PARAMS ((int)); +static void pa_stringer PARAMS ((int)); +static void pa_text PARAMS ((int)); +static void pa_version PARAMS ((int)); +static int pa_parse_fp_cmp_cond PARAMS ((char **)); +static int get_expression PARAMS ((char *)); +static int pa_get_absolute_expression PARAMS ((struct pa_it *, char **)); +static int evaluate_absolute PARAMS ((struct pa_it *)); +static unsigned int pa_build_arg_reloc PARAMS ((char *)); +static unsigned int pa_align_arg_reloc PARAMS ((unsigned int, unsigned int)); +static int pa_parse_nullif PARAMS ((char **)); +static int pa_parse_nonneg_cmpsub_cmpltr PARAMS ((char **, int)); +static int pa_parse_neg_cmpsub_cmpltr PARAMS ((char **, int)); +static int pa_parse_neg_add_cmpltr PARAMS ((char **, int)); +static int pa_parse_nonneg_add_cmpltr PARAMS ((char **, int)); +static void pa_align PARAMS ((int)); +static void pa_block PARAMS ((int)); +static void pa_brtab PARAMS ((int)); +static void pa_call PARAMS ((int)); +static void pa_call_args PARAMS ((struct call_desc *)); +static void pa_callinfo PARAMS ((int)); +static void pa_code PARAMS ((int)); +static void pa_comm PARAMS ((int)); +static void pa_copyright PARAMS ((int)); +static void pa_end PARAMS ((int)); +static void pa_enter PARAMS ((int)); +static void pa_entry PARAMS ((int)); +static void pa_equ PARAMS ((int)); +static void pa_exit PARAMS ((int)); +static void pa_export PARAMS ((int)); +static void pa_type_args PARAMS ((symbolS *, int)); +static void pa_import PARAMS ((int)); +static void pa_label PARAMS ((int)); +static void pa_leave PARAMS ((int)); +static void pa_origin PARAMS ((int)); +static void pa_proc PARAMS ((int)); +static void pa_procend PARAMS ((int)); +static void pa_space PARAMS ((int)); +static void pa_spnum PARAMS ((int)); +static void pa_subspace PARAMS ((int)); +static void pa_param PARAMS ((int)); +static void pa_undefine_label PARAMS ((void)); +static int need_pa11_opcode PARAMS ((struct pa_it *, + struct pa_11_fp_reg_struct *)); +static int pa_parse_number PARAMS ((char **, struct pa_11_fp_reg_struct *)); +static label_symbol_struct *pa_get_label PARAMS ((void)); +static sd_chain_struct *create_new_space PARAMS ((char *, int, int, + int, int, int, + asection *, int)); +static ssd_chain_struct *create_new_subspace PARAMS ((sd_chain_struct *, + char *, int, int, + int, int, int, + int, int, int, int, + int, asection *)); +static ssd_chain_struct *update_subspace PARAMS ((sd_chain_struct *, + char *, int, int, int, + int, int, int, int, + int, int, int, + asection *)); +static sd_chain_struct *is_defined_space PARAMS ((char *)); +static ssd_chain_struct *is_defined_subspace PARAMS ((char *)); +static sd_chain_struct *pa_segment_to_space PARAMS ((asection *)); +static ssd_chain_struct *pa_subsegment_to_subspace PARAMS ((asection *, + subsegT)); +static sd_chain_struct *pa_find_space_by_number PARAMS ((int)); +static unsigned int pa_subspace_start PARAMS ((sd_chain_struct *, int)); +static void pa_ip PARAMS ((char *)); +static void fix_new_hppa PARAMS ((fragS *, int, int, symbolS *, + long, expressionS *, int, + bfd_reloc_code_real_type, + enum hppa_reloc_field_selector_type, + int, long, int *)); +static int is_end_of_statement PARAMS ((void)); +static int reg_name_search PARAMS ((char *)); +static int pa_chk_field_selector PARAMS ((char **)); +static int is_same_frag PARAMS ((fragS *, fragS *)); +static void pa_build_unwind_subspace PARAMS ((struct call_info *)); +static void process_exit PARAMS ((void)); +static sd_chain_struct *pa_parse_space_stmt PARAMS ((char *, int)); +static int log2 PARAMS ((int)); +static int pa_next_subseg PARAMS ((sd_chain_struct *)); +static unsigned int pa_stringer_aux PARAMS ((char *)); +static void pa_spaces_begin PARAMS ((void)); +static void hppa_elf_mark_end_of_function PARAMS ((void)); + +/* File and gloally scoped variable declarations. */ + +/* Root and final entry in the space chain. */ +static sd_chain_struct *space_dict_root; +static sd_chain_struct *space_dict_last; + +/* The current space and subspace. */ +static sd_chain_struct *current_space; +static ssd_chain_struct *current_subspace; + +/* Root of the call_info chain. */ +static struct call_info *call_info_root; + +/* The last call_info (for functions) structure + seen so it can be associated with fixups and + function labels. */ +static struct call_info *last_call_info; + +/* The last call description (for actual calls). */ +static struct call_desc last_call_desc; + +/* Jumps are always the same size -- one instruction. */ +int md_short_jump_size = 4; +int md_long_jump_size = 4; + +/* handle of the OPCODE hash table */ +static struct hash_control *op_hash = NULL; + +/* This array holds the chars that always start a comment. If the + pre-processor is disabled, these aren't very useful. */ +const char comment_chars[] = ";"; + +/* Table of pseudo ops for the PA. FIXME -- how many of these + are now redundant with the overall GAS and the object file + dependent tables? */ +const pseudo_typeS md_pseudo_table[] = +{ + /* align pseudo-ops on the PA specify the actual alignment requested, + not the log2 of the requested alignment. */ + {"align", pa_align, 8}, + {"begin_brtab", pa_brtab, 1}, + {"block", pa_block, 1}, + {"blockz", pa_block, 0}, + {"byte", pa_cons, 1}, + {"call", pa_call, 0}, + {"callinfo", pa_callinfo, 0}, + {"code", pa_code, 0}, + {"comm", pa_comm, 0}, + {"copyright", pa_copyright, 0}, + {"data", pa_data, 0}, + {"double", pa_float_cons, 'd'}, + {"end", pa_end, 0}, + {"end_brtab", pa_brtab, 0}, + {"enter", pa_enter, 0}, + {"entry", pa_entry, 0}, + {"equ", pa_equ, 0}, + {"exit", pa_exit, 0}, + {"export", pa_export, 0}, + {"fill", pa_fill, 0}, + {"float", pa_float_cons, 'f'}, + {"half", pa_cons, 2}, + {"import", pa_import, 0}, + {"int", pa_cons, 4}, + {"label", pa_label, 0}, + {"lcomm", pa_lcomm, 0}, + {"leave", pa_leave, 0}, + {"long", pa_cons, 4}, + {"lsym", pa_lsym, 0}, + {"nsubspa", pa_subspace, 1}, + {"octa", pa_cons, 16}, + {"org", pa_origin, 0}, + {"origin", pa_origin, 0}, + {"param", pa_param, 0}, + {"proc", pa_proc, 0}, + {"procend", pa_procend, 0}, + {"quad", pa_cons, 8}, + {"reg", pa_equ, 1}, + {"short", pa_cons, 2}, + {"single", pa_float_cons, 'f'}, + {"space", pa_space, 0}, + {"spnum", pa_spnum, 0}, + {"string", pa_stringer, 0}, + {"stringz", pa_stringer, 1}, + {"subspa", pa_subspace, 0}, + {"text", pa_text, 0}, + {"version", pa_version, 0}, + {"word", pa_cons, 4}, + {NULL, 0, 0} +}; + +/* This array holds the chars that only start a comment at the beginning of + a line. If the line seems to have the form '# 123 filename' + .line and .file directives will appear in the pre-processed output. + + Note that input_file.c hand checks for '#' at the beginning of the + first line of the input file. This is because the compiler outputs + #NO_APP at the beginning of its output. + + Also note that '/*' will always start a comment. */ +const char line_comment_chars[] = "#"; + +/* This array holds the characters which act as line separators. */ +const char line_separator_chars[] = "!"; + +/* Chars that can be used to separate mant from exp in floating point nums. */ +const char EXP_CHARS[] = "eE"; + +/* Chars that mean this number is a floating point constant. + As in 0f12.456 or 0d1.2345e12. + + Be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be + changed in read.c. Ideally it shouldn't hae to know abou it at + all, but nothing is ideal around here. */ +const char FLT_CHARS[] = "rRsSfFdDxXpP"; + +static struct pa_it the_insn; + +/* Points to the end of an expression just parsed by get_expressoin + and friends. FIXME. This shouldn't be handled with a file-global + variable. */ +static char *expr_end; + +/* Nonzero if a .callinfo appeared within the current procedure. */ +static int callinfo_found; + +/* Nonzero if the assembler is currently within a .entry/.exit pair. */ +static int within_entry_exit; + +/* Nonzero if the assembler is currently within a procedure definition. */ +static int within_procedure; + +/* Handle on strucutre which keep track of the last symbol + seen in each subspace. */ +static label_symbol_struct *label_symbols_rootp = NULL; + +/* Holds the last field selector. */ +static int hppa_field_selector; + +/* A dummy bfd symbol so that all relocations have symbols of some kind. */ +static symbolS *dummy_symbol; + +/* Nonzero if errors are to be printed. */ +static int print_errors = 1; + +/* List of registers that are pre-defined: + + Each general register has one predefined name of the form + %r which has the value . + + Space and control registers are handled in a similar manner, + but use %sr and %cr as their predefined names. + + Likewise for the floating point registers, but of the form + %fr. Floating point registers have additional predefined + names with 'L' and 'R' suffixes (e.g. %fr19L, %fr19R) which + again have the value . + + Many registers also have synonyms: + + %r26 - %r23 have %arg0 - %arg3 as synonyms + %r28 - %r29 have %ret0 - %ret1 as synonyms + %r30 has %sp as a synonym + %r27 has %dp as a synonym + %r2 has %rp as a synonym + + Almost every control register has a synonym; they are not listed + here for brevity. + + The table is sorted. Suitable for searching by a binary search. */ + +static const struct pd_reg pre_defined_registers[] = +{ + {"%arg0", 26}, + {"%arg1", 25}, + {"%arg2", 24}, + {"%arg3", 23}, + {"%cr0", 0}, + {"%cr10", 10}, + {"%cr11", 11}, + {"%cr12", 12}, + {"%cr13", 13}, + {"%cr14", 14}, + {"%cr15", 15}, + {"%cr16", 16}, + {"%cr17", 17}, + {"%cr18", 18}, + {"%cr19", 19}, + {"%cr20", 20}, + {"%cr21", 21}, + {"%cr22", 22}, + {"%cr23", 23}, + {"%cr24", 24}, + {"%cr25", 25}, + {"%cr26", 26}, + {"%cr27", 27}, + {"%cr28", 28}, + {"%cr29", 29}, + {"%cr30", 30}, + {"%cr31", 31}, + {"%cr8", 8}, + {"%cr9", 9}, + {"%dp", 27}, + {"%eiem", 15}, + {"%eirr", 23}, + {"%fr0", 0}, + {"%fr0l", 0}, + {"%fr0r", 0}, + {"%fr1", 1}, + {"%fr10", 10}, + {"%fr10l", 10}, + {"%fr10r", 10}, + {"%fr11", 11}, + {"%fr11l", 11}, + {"%fr11r", 11}, + {"%fr12", 12}, + {"%fr12l", 12}, + {"%fr12r", 12}, + {"%fr13", 13}, + {"%fr13l", 13}, + {"%fr13r", 13}, + {"%fr14", 14}, + {"%fr14l", 14}, + {"%fr14r", 14}, + {"%fr15", 15}, + {"%fr15l", 15}, + {"%fr15r", 15}, + {"%fr16", 16}, + {"%fr16l", 16}, + {"%fr16r", 16}, + {"%fr17", 17}, + {"%fr17l", 17}, + {"%fr17r", 17}, + {"%fr18", 18}, + {"%fr18l", 18}, + {"%fr18r", 18}, + {"%fr19", 19}, + {"%fr19l", 19}, + {"%fr19r", 19}, + {"%fr1l", 1}, + {"%fr1r", 1}, + {"%fr2", 2}, + {"%fr20", 20}, + {"%fr20l", 20}, + {"%fr20r", 20}, + {"%fr21", 21}, + {"%fr21l", 21}, + {"%fr21r", 21}, + {"%fr22", 22}, + {"%fr22l", 22}, + {"%fr22r", 22}, + {"%fr23", 23}, + {"%fr23l", 23}, + {"%fr23r", 23}, + {"%fr24", 24}, + {"%fr24l", 24}, + {"%fr24r", 24}, + {"%fr25", 25}, + {"%fr25l", 25}, + {"%fr25r", 25}, + {"%fr26", 26}, + {"%fr26l", 26}, + {"%fr26r", 26}, + {"%fr27", 27}, + {"%fr27l", 27}, + {"%fr27r", 27}, + {"%fr28", 28}, + {"%fr28l", 28}, + {"%fr28r", 28}, + {"%fr29", 29}, + {"%fr29l", 29}, + {"%fr29r", 29}, + {"%fr2l", 2}, + {"%fr2r", 2}, + {"%fr3", 3}, + {"%fr30", 30}, + {"%fr30l", 30}, + {"%fr30r", 30}, + {"%fr31", 31}, + {"%fr31l", 31}, + {"%fr31r", 31}, + {"%fr3l", 3}, + {"%fr3r", 3}, + {"%fr4", 4}, + {"%fr4l", 4}, + {"%fr4r", 4}, + {"%fr5", 5}, + {"%fr5l", 5}, + {"%fr5r", 5}, + {"%fr6", 6}, + {"%fr6l", 6}, + {"%fr6r", 6}, + {"%fr7", 7}, + {"%fr7l", 7}, + {"%fr7r", 7}, + {"%fr8", 8}, + {"%fr8l", 8}, + {"%fr8r", 8}, + {"%fr9", 9}, + {"%fr9l", 9}, + {"%fr9r", 9}, + {"%hta", 25}, + {"%iir", 19}, + {"%ior", 21}, + {"%ipsw", 22}, + {"%isr", 20}, + {"%itmr", 16}, + {"%iva", 14}, + {"%pcoq", 18}, + {"%pcsq", 17}, + {"%pidr1", 8}, + {"%pidr2", 9}, + {"%pidr3", 12}, + {"%pidr4", 13}, + {"%ppda", 24}, + {"%r0", 0}, + {"%r1", 1}, + {"%r10", 10}, + {"%r11", 11}, + {"%r12", 12}, + {"%r13", 13}, + {"%r14", 14}, + {"%r15", 15}, + {"%r16", 16}, + {"%r17", 17}, + {"%r18", 18}, + {"%r19", 19}, + {"%r2", 2}, + {"%r20", 20}, + {"%r21", 21}, + {"%r22", 22}, + {"%r23", 23}, + {"%r24", 24}, + {"%r25", 25}, + {"%r26", 26}, + {"%r27", 27}, + {"%r28", 28}, + {"%r29", 29}, + {"%r3", 3}, + {"%r30", 30}, + {"%r31", 31}, + {"%r4", 4}, + {"%r5", 5}, + {"%r6", 6}, + {"%r7", 7}, + {"%r8", 8}, + {"%r9", 9}, + {"%rctr", 0}, + {"%ret0", 28}, + {"%ret1", 29}, + {"%rp", 2}, + {"%sar", 11}, + {"%sp", 30}, + {"%sr0", 0}, + {"%sr1", 1}, + {"%sr2", 2}, + {"%sr3", 3}, + {"%sr4", 4}, + {"%sr5", 5}, + {"%sr6", 6}, + {"%sr7", 7}, + {"%tr0", 24}, + {"%tr1", 25}, + {"%tr2", 26}, + {"%tr3", 27}, + {"%tr4", 28}, + {"%tr5", 29}, + {"%tr6", 30}, + {"%tr7", 31} +}; + +/* This table is sorted by order of the length of the string. This is + so we check for <> before we check for <. If we had a <> and checked + for < first, we would get a false match. */ +static const struct fp_cond_map fp_cond_map[] = +{ + {"false?", 0}, + {"false", 1}, + {"true?", 30}, + {"true", 31}, + {"!<=>", 3}, + {"!?>=", 8}, + {"!?<=", 16}, + {"!<>", 7}, + {"!>=", 11}, + {"!?>", 12}, + {"?<=", 14}, + {"!<=", 19}, + {"!?<", 20}, + {"?>=", 22}, + {"!?=", 24}, + {"!=t", 27}, + {"<=>", 29}, + {"=t", 5}, + {"?=", 6}, + {"?<", 10}, + {"<=", 13}, + {"!>", 15}, + {"?>", 18}, + {">=", 21}, + {"!<", 23}, + {"<>", 25}, + {"!=", 26}, + {"!?", 28}, + {"?", 2}, + {"=", 4}, + {"<", 9}, + {">", 17} +}; + +static const struct selector_entry selector_table[] = +{ + {"f", e_fsel}, + {"l", e_lsel}, + {"ld", e_ldsel}, + {"lp", e_lpsel}, + {"lr", e_lrsel}, + {"ls", e_lssel}, + {"lt", e_ltsel}, + {"p", e_psel}, + {"r", e_rsel}, + {"rd", e_rdsel}, + {"rp", e_rpsel}, + {"rr", e_rrsel}, + {"rs", e_rssel}, + {"rt", e_rtsel}, + {"t", e_tsel}, +}; + +/* default space and subspace dictionaries */ + +#define GDB_SYMBOLS GDB_SYMBOLS_SUBSPACE_NAME +#define GDB_STRINGS GDB_STRINGS_SUBSPACE_NAME + +/* pre-defined subsegments (subspaces) for the HPPA. */ +#define SUBSEG_CODE 0 +#define SUBSEG_DATA 0 +#define SUBSEG_LIT 1 +#define SUBSEG_BSS 2 +#define SUBSEG_UNWIND 3 +#define SUBSEG_GDB_STRINGS 0 +#define SUBSEG_GDB_SYMBOLS 1 + +static struct default_subspace_dict pa_def_subspaces[] = +{ + {"$CODE$", 1, 1, 1, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_CODE}, + {"$DATA$", 1, 1, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, ".data", SUBSEG_DATA}, + {"$LIT$", 1, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_LIT}, + {"$BSS$", 1, 1, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, ".bss", SUBSEG_BSS}, +#ifdef OBJ_ELF + {"$UNWIND$", 1, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, 0, ".PARISC.unwind", SUBSEG_UNWIND}, +#endif + {NULL, 0, 1, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0} +}; + +static struct default_space_dict pa_def_spaces[] = +{ + {"$TEXT$", 0, 1, 1, 0, 8, ASEC_NULL, ".text"}, + {"$PRIVATE$", 1, 1, 1, 1, 16, ASEC_NULL, ".data"}, + {NULL, 0, 0, 0, 0, 0, ASEC_NULL, NULL} +}; + +/* Misc local definitions used by the assembler. */ + +/* Return nonzero if the string pointed to by S potentially represents + a right or left half of a FP register */ +#define IS_R_SELECT(S) (*(S) == 'R' || *(S) == 'r') +#define IS_L_SELECT(S) (*(S) == 'L' || *(S) == 'l') + +/* These macros are used to maintain spaces/subspaces. */ +#define SPACE_DEFINED(space_chain) (space_chain)->sd_defined +#define SPACE_USER_DEFINED(space_chain) (space_chain)->sd_user_defined +#define SPACE_SPNUM(space_chain) (space_chain)->sd_spnum +#define SPACE_NAME(space_chain) (space_chain)->sd_name + +#define SUBSPACE_DEFINED(ss_chain) (ss_chain)->ssd_defined +#define SUBSPACE_NAME(ss_chain) (ss_chain)->ssd_name + +/* Insert FIELD into OPCODE starting at bit START. Continue pa_ip + main loop after insertion. */ + +#define INSERT_FIELD_AND_CONTINUE(OPCODE, FIELD, START) \ + { \ + ((OPCODE) |= (FIELD) << (START)); \ + continue; \ + } + +/* Simple range checking for FIELD againt HIGH and LOW bounds. + IGNORE is used to suppress the error message. */ + +#define CHECK_FIELD(FIELD, HIGH, LOW, IGNORE) \ + { \ + if ((FIELD) > (HIGH) || (FIELD) < (LOW)) \ + { \ + if (! IGNORE) \ + as_bad ("Field out of range [%d..%d] (%d).", (LOW), (HIGH), \ + (int) (FIELD));\ + break; \ + } \ + } + +#define is_DP_relative(exp) \ + ((exp).X_op == O_subtract \ + && strcmp((exp).X_op_symbol->bsym->name, "$global$") == 0) + +#define is_PC_relative(exp) \ + ((exp).X_op == O_subtract \ + && strcmp((exp).X_op_symbol->bsym->name, "$PIC_pcrel$0") == 0) + +/* We need some complex handling for stabs (sym1 - sym2). Luckily, we'll + always be able to reduce the expression to a constant, so we don't + need real complex handling yet. */ +#define is_complex(exp) \ + ((exp).X_op != O_constant && (exp).X_op != O_symbol) + +/* Actual functions to implement the PA specific code for the assembler. */ + +/* Called before writing the object file. Make sure entry/exit and + proc/procend pairs match. */ + +void +pa_check_eof () +{ + if (within_entry_exit) + as_fatal ("Missing .exit\n"); + + if (within_procedure) + as_fatal ("Missing .procend\n"); +} + +/* Check to make sure we have a valid space and subspace. */ + +static void +pa_check_current_space_and_subspace () +{ + if (current_space == NULL) + as_fatal ("Not in a space.\n"); + + if (current_subspace == NULL) + as_fatal ("Not in a subspace.\n"); +} + +/* Returns a pointer to the label_symbol_struct for the current space. + or NULL if no label_symbol_struct exists for the current space. */ + +static label_symbol_struct * +pa_get_label () +{ + label_symbol_struct *label_chain; + sd_chain_struct *space_chain = current_space; + + for (label_chain = label_symbols_rootp; + label_chain; + label_chain = label_chain->lss_next) + if (space_chain == label_chain->lss_space && label_chain->lss_label) + return label_chain; + + return NULL; +} + +/* Defines a label for the current space. If one is already defined, + this function will replace it with the new label. */ + +void +pa_define_label (symbol) + symbolS *symbol; +{ + label_symbol_struct *label_chain = pa_get_label (); + sd_chain_struct *space_chain = current_space; + + if (label_chain) + label_chain->lss_label = symbol; + else + { + /* Create a new label entry and add it to the head of the chain. */ + label_chain + = (label_symbol_struct *) xmalloc (sizeof (label_symbol_struct)); + label_chain->lss_label = symbol; + label_chain->lss_space = space_chain; + label_chain->lss_next = NULL; + + if (label_symbols_rootp) + label_chain->lss_next = label_symbols_rootp; + + label_symbols_rootp = label_chain; + } +} + +/* Removes a label definition for the current space. + If there is no label_symbol_struct entry, then no action is taken. */ + +static void +pa_undefine_label () +{ + label_symbol_struct *label_chain; + label_symbol_struct *prev_label_chain = NULL; + sd_chain_struct *space_chain = current_space; + + for (label_chain = label_symbols_rootp; + label_chain; + label_chain = label_chain->lss_next) + { + if (space_chain == label_chain->lss_space && label_chain->lss_label) + { + /* Remove the label from the chain and free its memory. */ + if (prev_label_chain) + prev_label_chain->lss_next = label_chain->lss_next; + else + label_symbols_rootp = label_chain->lss_next; + + free (label_chain); + break; + } + prev_label_chain = label_chain; + } +} + + +/* An HPPA-specific version of fix_new. This is required because the HPPA + code needs to keep track of some extra stuff. Each call to fix_new_hppa + results in the creation of an instance of an hppa_fix_struct. An + hppa_fix_struct stores the extra information along with a pointer to the + original fixS. This is attached to the original fixup via the + tc_fix_data field. */ + +static void +fix_new_hppa (frag, where, size, add_symbol, offset, exp, pcrel, + r_type, r_field, r_format, arg_reloc, unwind_bits) + fragS *frag; + int where; + int size; + symbolS *add_symbol; + long offset; + expressionS *exp; + int pcrel; + bfd_reloc_code_real_type r_type; + enum hppa_reloc_field_selector_type r_field; + int r_format; + long arg_reloc; + int* unwind_bits; +{ + fixS *new_fix; + + struct hppa_fix_struct *hppa_fix = (struct hppa_fix_struct *) + obstack_alloc (¬es, sizeof (struct hppa_fix_struct)); + + if (exp != NULL) + new_fix = fix_new_exp (frag, where, size, exp, pcrel, r_type); + else + new_fix = fix_new (frag, where, size, add_symbol, offset, pcrel, r_type); + new_fix->tc_fix_data = (void *) hppa_fix; + hppa_fix->fx_r_type = r_type; + hppa_fix->fx_r_field = r_field; + hppa_fix->fx_r_format = r_format; + hppa_fix->fx_arg_reloc = arg_reloc; + hppa_fix->segment = now_seg; +#ifdef OBJ_SOM + if (r_type == R_ENTRY || r_type == R_EXIT) + new_fix->fx_offset = *unwind_bits; +#endif + + /* foo-$global$ is used to access non-automatic storage. $global$ + is really just a marker and has served its purpose, so eliminate + it now so as not to confuse write.c. */ + if (new_fix->fx_subsy + && !strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$")) + new_fix->fx_subsy = NULL; +} + +/* Parse a .byte, .word, .long expression for the HPPA. Called by + cons via the TC_PARSE_CONS_EXPRESSION macro. */ + +void +parse_cons_expression_hppa (exp) + expressionS *exp; +{ + hppa_field_selector = pa_chk_field_selector (&input_line_pointer); + expression (exp); +} + +/* This fix_new is called by cons via TC_CONS_FIX_NEW. + hppa_field_selector is set by the parse_cons_expression_hppa. */ + +void +cons_fix_new_hppa (frag, where, size, exp) + fragS *frag; + int where; + int size; + expressionS *exp; +{ + unsigned int rel_type; + + /* Get a base relocation type. */ + if (is_DP_relative (*exp)) + rel_type = R_HPPA_GOTOFF; + else if (is_complex (*exp)) + rel_type = R_HPPA_COMPLEX; + else + rel_type = R_HPPA; + + if (hppa_field_selector != e_psel && hppa_field_selector != e_fsel) + as_warn ("Invalid field selector. Assuming F%%."); + + fix_new_hppa (frag, where, size, + (symbolS *) NULL, (offsetT) 0, exp, 0, rel_type, + hppa_field_selector, 32, 0, NULL); + + /* Reset field selector to its default state. */ + hppa_field_selector = 0; +} + +/* This function is called once, at assembler startup time. It should + set up all the tables, etc. that the MD part of the assembler will need. */ + +void +md_begin () +{ + const char *retval = NULL; + int lose = 0; + unsigned int i = 0; + + last_call_info = NULL; + call_info_root = NULL; + + /* Set the default machine type. */ + if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 10)) + as_warn ("could not set architecture and machine"); + + /* Folding of text and data segments fails miserably on the PA. + Warn user and disable "-R" option. */ + if (flag_readonly_data_in_text) + { + as_warn ("-R option not supported on this target."); + flag_readonly_data_in_text = 0; + } + + pa_spaces_begin (); + + op_hash = hash_new (); + + while (i < NUMOPCODES) + { + const char *name = pa_opcodes[i].name; + retval = hash_insert (op_hash, name, (struct pa_opcode *) &pa_opcodes[i]); + if (retval != NULL && *retval != '\0') + { + as_fatal ("Internal error: can't hash `%s': %s\n", name, retval); + lose = 1; + } + do + { + if ((pa_opcodes[i].match & pa_opcodes[i].mask) + != pa_opcodes[i].match) + { + fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n", + pa_opcodes[i].name, pa_opcodes[i].args); + lose = 1; + } + ++i; + } + while (i < NUMOPCODES && !strcmp (pa_opcodes[i].name, name)); + } + + if (lose) + as_fatal ("Broken assembler. No assembly attempted."); + + /* SOM will change text_section. To make sure we never put + anything into the old one switch to the new one now. */ + subseg_set (text_section, 0); + + dummy_symbol = symbol_find_or_make ("L$dummy"); + S_SET_SEGMENT (dummy_symbol, text_section); +} + +/* Assemble a single instruction storing it into a frag. */ +void +md_assemble (str) + char *str; +{ + char *to; + + /* The had better be something to assemble. */ + assert (str); + + /* If we are within a procedure definition, make sure we've + defined a label for the procedure; handle case where the + label was defined after the .PROC directive. + + Note there's not need to diddle with the segment or fragment + for the label symbol in this case. We have already switched + into the new $CODE$ subspace at this point. */ + if (within_procedure && last_call_info->start_symbol == NULL) + { + label_symbol_struct *label_symbol = pa_get_label (); + + if (label_symbol) + { + if (label_symbol->lss_label) + { + last_call_info->start_symbol = label_symbol->lss_label; + label_symbol->lss_label->bsym->flags |= BSF_FUNCTION; +#ifdef OBJ_SOM + /* Also handle allocation of a fixup to hold the unwind + information when the label appears after the proc/procend. */ + if (within_entry_exit) + { + char *where = frag_more (0); + + fix_new_hppa (frag_now, where - frag_now->fr_literal, 0, + NULL, (offsetT) 0, NULL, + 0, R_HPPA_ENTRY, e_fsel, 0, 0, + (int *)&last_call_info->ci_unwind.descriptor); + } +#endif + } + else + as_bad ("Missing function name for .PROC (corrupted label chain)"); + } + else + as_bad ("Missing function name for .PROC"); + } + + /* Assemble the instruction. Results are saved into "the_insn". */ + pa_ip (str); + + /* Get somewhere to put the assembled instrution. */ + to = frag_more (4); + + /* Output the opcode. */ + md_number_to_chars (to, the_insn.opcode, 4); + + /* If necessary output more stuff. */ + if (the_insn.reloc != R_HPPA_NONE) + fix_new_hppa (frag_now, (to - frag_now->fr_literal), 4, NULL, + (offsetT) 0, &the_insn.exp, the_insn.pcrel, + the_insn.reloc, the_insn.field_selector, + the_insn.format, the_insn.arg_reloc, NULL); +} + +/* Do the real work for assembling a single instruction. Store results + into the global "the_insn" variable. */ + +static void +pa_ip (str) + char *str; +{ + char *error_message = ""; + char *s, c, *argstart, *name, *save_s; + const char *args; + int match = FALSE; + int comma = 0; + int cmpltr, nullif, flag, cond, num; + unsigned long opcode; + struct pa_opcode *insn; + + /* We must have a valid space and subspace. */ + pa_check_current_space_and_subspace (); + + /* Skip to something interesting. */ + for (s = str; isupper (*s) || islower (*s) || (*s >= '0' && *s <= '3'); ++s) + ; + + switch (*s) + { + + case '\0': + break; + + case ',': + comma = 1; + + /*FALLTHROUGH */ + + case ' ': + *s++ = '\0'; + break; + + default: + as_fatal ("Unknown opcode: `%s'", str); + } + + save_s = str; + + /* Convert everything into lower case. */ + while (*save_s) + { + if (isupper (*save_s)) + *save_s = tolower (*save_s); + save_s++; + } + + /* Look up the opcode in the has table. */ + if ((insn = (struct pa_opcode *) hash_find (op_hash, str)) == NULL) + { + as_bad ("Unknown opcode: `%s'", str); + return; + } + + if (comma) + { + *--s = ','; + } + + /* Mark the location where arguments for the instruction start, then + start processing them. */ + argstart = s; + for (;;) + { + /* Do some initialization. */ + opcode = insn->match; + bzero (&the_insn, sizeof (the_insn)); + + the_insn.reloc = R_HPPA_NONE; + + /* If this instruction is specific to a particular architecture, + then set a new architecture. */ + if (bfd_get_mach (stdoutput) < insn->arch) + { + if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, insn->arch)) + as_warn ("could not update architecture and machine"); + } + + /* Build the opcode, checking as we go to make + sure that the operands match. */ + for (args = insn->args;; ++args) + { + switch (*args) + { + + /* End of arguments. */ + case '\0': + if (*s == '\0') + match = TRUE; + break; + + case '+': + if (*s == '+') + { + ++s; + continue; + } + if (*s == '-') + continue; + break; + + /* These must match exactly. */ + case '(': + case ')': + case ',': + case ' ': + if (*s++ == *args) + continue; + break; + + /* Handle a 5 bit register or control register field at 10. */ + case 'b': + case '^': + num = pa_parse_number (&s, 0); + CHECK_FIELD (num, 31, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 21); + + /* Handle a 5 bit register field at 15. */ + case 'x': + num = pa_parse_number (&s, 0); + CHECK_FIELD (num, 31, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 16); + + /* Handle a 5 bit register field at 31. */ + case 'y': + case 't': + num = pa_parse_number (&s, 0); + CHECK_FIELD (num, 31, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + + /* Handle a 5 bit field length at 31. */ + case 'T': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 32, 1, 0); + INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0); + + /* Handle a 5 bit immediate at 15. */ + case '5': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 15, -16, 0); + low_sign_unext (num, 5, &num); + INSERT_FIELD_AND_CONTINUE (opcode, num, 16); + + /* Handle a 5 bit immediate at 31. */ + case 'V': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 15, -16, 0) + low_sign_unext (num, 5, &num); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + + /* Handle an unsigned 5 bit immediate at 31. */ + case 'r': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 31, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + + /* Handle an unsigned 5 bit immediate at 15. */ + case 'R': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 31, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 16); + + /* Handle a 2 bit space identifier at 17. */ + case 's': + num = pa_parse_number (&s, 0); + CHECK_FIELD (num, 3, 0, 1); + INSERT_FIELD_AND_CONTINUE (opcode, num, 14); + + /* Handle a 3 bit space identifier at 18. */ + case 'S': + num = pa_parse_number (&s, 0); + CHECK_FIELD (num, 7, 0, 1); + dis_assemble_3 (num, &num); + INSERT_FIELD_AND_CONTINUE (opcode, num, 13); + + /* Handle a completer for an indexing load or store. */ + case 'c': + { + int uu = 0; + int m = 0; + int i = 0; + while (*s == ',' && i < 2) + { + s++; + if (strncasecmp (s, "sm", 2) == 0) + { + uu = 1; + m = 1; + s++; + i++; + } + else if (strncasecmp (s, "m", 1) == 0) + m = 1; + else if (strncasecmp (s, "s", 1) == 0) + uu = 1; + else + as_bad ("Invalid Indexed Load Completer."); + s++; + i++; + } + if (i > 2) + as_bad ("Invalid Indexed Load Completer Syntax."); + opcode |= m << 5; + INSERT_FIELD_AND_CONTINUE (opcode, uu, 13); + } + + /* Handle a short load/store completer. */ + case 'C': + { + int a = 0; + int m = 0; + if (*s == ',') + { + s++; + if (strncasecmp (s, "ma", 2) == 0) + { + a = 0; + m = 1; + } + else if (strncasecmp (s, "mb", 2) == 0) + { + a = 1; + m = 1; + } + else + as_bad ("Invalid Short Load/Store Completer."); + s += 2; + } + opcode |= m << 5; + INSERT_FIELD_AND_CONTINUE (opcode, a, 13); + } + + /* Handle a stbys completer. */ + case 'Y': + { + int a = 0; + int m = 0; + int i = 0; + while (*s == ',' && i < 2) + { + s++; + if (strncasecmp (s, "m", 1) == 0) + m = 1; + else if (strncasecmp (s, "b", 1) == 0) + a = 0; + else if (strncasecmp (s, "e", 1) == 0) + a = 1; + else + as_bad ("Invalid Store Bytes Short Completer"); + s++; + i++; + } + if (i > 2) + as_bad ("Invalid Store Bytes Short Completer"); + opcode |= m << 5; + INSERT_FIELD_AND_CONTINUE (opcode, a, 13); + } + + /* Handle a non-negated compare/stubtract condition. */ + case '<': + cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1); + if (cmpltr < 0) + { + as_bad ("Invalid Compare/Subtract Condition: %c", *s); + cmpltr = 0; + } + INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); + + /* Handle a negated or non-negated compare/subtract condition. */ + case '?': + save_s = s; + cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1); + if (cmpltr < 0) + { + s = save_s; + cmpltr = pa_parse_neg_cmpsub_cmpltr (&s, 1); + if (cmpltr < 0) + { + as_bad ("Invalid Compare/Subtract Condition."); + cmpltr = 0; + } + else + { + /* Negated condition requires an opcode change. */ + opcode |= 1 << 27; + } + } + INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); + + /* Handle non-negated add condition. */ + case '!': + cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1); + if (cmpltr < 0) + { + as_bad ("Invalid Compare/Subtract Condition: %c", *s); + cmpltr = 0; + } + INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); + + /* Handle a negated or non-negated add condition. */ + case '@': + save_s = s; + cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1); + if (cmpltr < 0) + { + s = save_s; + cmpltr = pa_parse_neg_add_cmpltr (&s, 1); + if (cmpltr < 0) + { + as_bad ("Invalid Compare/Subtract Condition"); + cmpltr = 0; + } + else + { + /* Negated condition requires an opcode change. */ + opcode |= 1 << 27; + } + } + INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); + + /* Handle a compare/subtract condition. */ + case 'a': + cmpltr = 0; + flag = 0; + save_s = s; + if (*s == ',') + { + cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 0); + if (cmpltr < 0) + { + flag = 1; + s = save_s; + cmpltr = pa_parse_neg_cmpsub_cmpltr (&s, 0); + if (cmpltr < 0) + { + as_bad ("Invalid Compare/Subtract Condition"); + } + } + } + opcode |= cmpltr << 13; + INSERT_FIELD_AND_CONTINUE (opcode, flag, 12); + + /* Handle a non-negated add condition. */ + case 'd': + cmpltr = 0; + nullif = 0; + flag = 0; + if (*s == ',') + { + s++; + name = s; + while (*s != ',' && *s != ' ' && *s != '\t') + s += 1; + c = *s; + *s = 0x00; + if (strcmp (name, "=") == 0) + cmpltr = 1; + else if (strcmp (name, "<") == 0) + cmpltr = 2; + else if (strcmp (name, "<=") == 0) + cmpltr = 3; + else if (strcasecmp (name, "nuv") == 0) + cmpltr = 4; + else if (strcasecmp (name, "znv") == 0) + cmpltr = 5; + else if (strcasecmp (name, "sv") == 0) + cmpltr = 6; + else if (strcasecmp (name, "od") == 0) + cmpltr = 7; + else if (strcasecmp (name, "n") == 0) + nullif = 1; + else if (strcasecmp (name, "tr") == 0) + { + cmpltr = 0; + flag = 1; + } + else if (strcmp (name, "<>") == 0) + { + cmpltr = 1; + flag = 1; + } + else if (strcmp (name, ">=") == 0) + { + cmpltr = 2; + flag = 1; + } + else if (strcmp (name, ">") == 0) + { + cmpltr = 3; + flag = 1; + } + else if (strcasecmp (name, "uv") == 0) + { + cmpltr = 4; + flag = 1; + } + else if (strcasecmp (name, "vnz") == 0) + { + cmpltr = 5; + flag = 1; + } + else if (strcasecmp (name, "nsv") == 0) + { + cmpltr = 6; + flag = 1; + } + else if (strcasecmp (name, "ev") == 0) + { + cmpltr = 7; + flag = 1; + } + else + as_bad ("Invalid Add Condition: %s", name); + *s = c; + } + nullif = pa_parse_nullif (&s); + opcode |= nullif << 1; + opcode |= cmpltr << 13; + INSERT_FIELD_AND_CONTINUE (opcode, flag, 12); + + /* HANDLE a logical instruction condition. */ + case '&': + cmpltr = 0; + flag = 0; + if (*s == ',') + { + s++; + name = s; + while (*s != ',' && *s != ' ' && *s != '\t') + s += 1; + c = *s; + *s = 0x00; + if (strcmp (name, "=") == 0) + cmpltr = 1; + else if (strcmp (name, "<") == 0) + cmpltr = 2; + else if (strcmp (name, "<=") == 0) + cmpltr = 3; + else if (strcasecmp (name, "od") == 0) + cmpltr = 7; + else if (strcasecmp (name, "tr") == 0) + { + cmpltr = 0; + flag = 1; + } + else if (strcmp (name, "<>") == 0) + { + cmpltr = 1; + flag = 1; + } + else if (strcmp (name, ">=") == 0) + { + cmpltr = 2; + flag = 1; + } + else if (strcmp (name, ">") == 0) + { + cmpltr = 3; + flag = 1; + } + else if (strcasecmp (name, "ev") == 0) + { + cmpltr = 7; + flag = 1; + } + else + as_bad ("Invalid Logical Instruction Condition."); + *s = c; + } + opcode |= cmpltr << 13; + INSERT_FIELD_AND_CONTINUE (opcode, flag, 12); + + /* Handle a unit instruction condition. */ + case 'U': + cmpltr = 0; + flag = 0; + if (*s == ',') + { + s++; + if (strncasecmp (s, "sbz", 3) == 0) + { + cmpltr = 2; + s += 3; + } + else if (strncasecmp (s, "shz", 3) == 0) + { + cmpltr = 3; + s += 3; + } + else if (strncasecmp (s, "sdc", 3) == 0) + { + cmpltr = 4; + s += 3; + } + else if (strncasecmp (s, "sbc", 3) == 0) + { + cmpltr = 6; + s += 3; + } + else if (strncasecmp (s, "shc", 3) == 0) + { + cmpltr = 7; + s += 3; + } + else if (strncasecmp (s, "tr", 2) == 0) + { + cmpltr = 0; + flag = 1; + s += 2; + } + else if (strncasecmp (s, "nbz", 3) == 0) + { + cmpltr = 2; + flag = 1; + s += 3; + } + else if (strncasecmp (s, "nhz", 3) == 0) + { + cmpltr = 3; + flag = 1; + s += 3; + } + else if (strncasecmp (s, "ndc", 3) == 0) + { + cmpltr = 4; + flag = 1; + s += 3; + } + else if (strncasecmp (s, "nbc", 3) == 0) + { + cmpltr = 6; + flag = 1; + s += 3; + } + else if (strncasecmp (s, "nhc", 3) == 0) + { + cmpltr = 7; + flag = 1; + s += 3; + } + else + as_bad ("Invalid Logical Instruction Condition."); + } + opcode |= cmpltr << 13; + INSERT_FIELD_AND_CONTINUE (opcode, flag, 12); + + /* Handle a shift/extract/deposit condition. */ + case '|': + case '>': + cmpltr = 0; + if (*s == ',') + { + save_s = s++; + name = s; + while (*s != ',' && *s != ' ' && *s != '\t') + s += 1; + c = *s; + *s = 0x00; + if (strcmp (name, "=") == 0) + cmpltr = 1; + else if (strcmp (name, "<") == 0) + cmpltr = 2; + else if (strcasecmp (name, "od") == 0) + cmpltr = 3; + else if (strcasecmp (name, "tr") == 0) + cmpltr = 4; + else if (strcmp (name, "<>") == 0) + cmpltr = 5; + else if (strcmp (name, ">=") == 0) + cmpltr = 6; + else if (strcasecmp (name, "ev") == 0) + cmpltr = 7; + /* Handle movb,n. Put things back the way they were. + This includes moving s back to where it started. */ + else if (strcasecmp (name, "n") == 0 && *args == '|') + { + *s = c; + s = save_s; + continue; + } + else + as_bad ("Invalid Shift/Extract/Deposit Condition."); + *s = c; + } + INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); + + /* Handle bvb and bb conditions. */ + case '~': + cmpltr = 0; + if (*s == ',') + { + s++; + if (strncmp (s, "<", 1) == 0) + { + cmpltr = 2; + s++; + } + else if (strncmp (s, ">=", 2) == 0) + { + cmpltr = 6; + s += 2; + } + else + as_bad ("Invalid Bit Branch Condition: %c", *s); + } + INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); + + /* Handle a system control completer. */ + case 'Z': + if (*s == ',' && (*(s + 1) == 'm' || *(s + 1) == 'M')) + { + flag = 1; + s += 2; + } + else + flag = 0; + + INSERT_FIELD_AND_CONTINUE (opcode, flag, 5); + + /* Handle a nullification completer for branch instructions. */ + case 'n': + nullif = pa_parse_nullif (&s); + INSERT_FIELD_AND_CONTINUE (opcode, nullif, 1); + + /* Handle a nullification completer for copr and spop insns. */ + case 'N': + nullif = pa_parse_nullif (&s); + INSERT_FIELD_AND_CONTINUE (opcode, nullif, 5); + + /* Handle a 11 bit immediate at 31. */ + case 'i': + the_insn.field_selector = pa_chk_field_selector (&s); + get_expression (s); + s = expr_end; + if (the_insn.exp.X_op == O_constant) + { + num = evaluate_absolute (&the_insn); + CHECK_FIELD (num, 1023, -1024, 0); + low_sign_unext (num, 11, &num); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + } + else + { + if (is_DP_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_GOTOFF; + else if (is_PC_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_PCREL_CALL; + else + the_insn.reloc = R_HPPA; + the_insn.format = 11; + continue; + } + + /* Handle a 14 bit immediate at 31. */ + case 'j': + the_insn.field_selector = pa_chk_field_selector (&s); + get_expression (s); + s = expr_end; + if (the_insn.exp.X_op == O_constant) + { + num = evaluate_absolute (&the_insn); + CHECK_FIELD (num, 8191, -8192, 0); + low_sign_unext (num, 14, &num); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + } + else + { + if (is_DP_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_GOTOFF; + else if (is_PC_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_PCREL_CALL; + else + the_insn.reloc = R_HPPA; + the_insn.format = 14; + continue; + } + + /* Handle a 21 bit immediate at 31. */ + case 'k': + the_insn.field_selector = pa_chk_field_selector (&s); + get_expression (s); + s = expr_end; + if (the_insn.exp.X_op == O_constant) + { + num = evaluate_absolute (&the_insn); + CHECK_FIELD (num >> 11, 1048575, -1048576, 0); + dis_assemble_21 (num, &num); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + } + else + { + if (is_DP_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_GOTOFF; + else if (is_PC_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_PCREL_CALL; + else + the_insn.reloc = R_HPPA; + the_insn.format = 21; + continue; + } + + /* Handle a 12 bit branch displacement. */ + case 'w': + the_insn.field_selector = pa_chk_field_selector (&s); + get_expression (s); + s = expr_end; + the_insn.pcrel = 1; + if (!strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), "L$0\001")) + { + unsigned int w1, w, result; + + num = evaluate_absolute (&the_insn); + if (num % 4) + { + as_bad ("Branch to unaligned address"); + break; + } + CHECK_FIELD (num, 8199, -8184, 0); + sign_unext ((num - 8) >> 2, 12, &result); + dis_assemble_12 (result, &w1, &w); + INSERT_FIELD_AND_CONTINUE (opcode, ((w1 << 2) | w), 0); + } + else + { + the_insn.reloc = R_HPPA_PCREL_CALL; + the_insn.format = 12; + the_insn.arg_reloc = last_call_desc.arg_reloc; + bzero (&last_call_desc, sizeof (struct call_desc)); + s = expr_end; + continue; + } + + /* Handle a 17 bit branch displacement. */ + case 'W': + the_insn.field_selector = pa_chk_field_selector (&s); + get_expression (s); + s = expr_end; + the_insn.pcrel = 1; + if (!the_insn.exp.X_add_symbol + || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), + "L$0\001")) + { + unsigned int w2, w1, w, result; + + num = evaluate_absolute (&the_insn); + if (num % 4) + { + as_bad ("Branch to unaligned address"); + break; + } + CHECK_FIELD (num, 262143, -262144, 0); + + if (the_insn.exp.X_add_symbol) + num -= 8; + + sign_unext (num >> 2, 17, &result); + dis_assemble_17 (result, &w1, &w2, &w); + INSERT_FIELD_AND_CONTINUE (opcode, + ((w2 << 2) | (w1 << 16) | w), 0); + } + else + { + the_insn.reloc = R_HPPA_PCREL_CALL; + the_insn.format = 17; + the_insn.arg_reloc = last_call_desc.arg_reloc; + bzero (&last_call_desc, sizeof (struct call_desc)); + continue; + } + + /* Handle an absolute 17 bit branch target. */ + case 'z': + the_insn.field_selector = pa_chk_field_selector (&s); + get_expression (s); + s = expr_end; + the_insn.pcrel = 0; + if (!the_insn.exp.X_add_symbol + || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), + "L$0\001")) + { + unsigned int w2, w1, w, result; + + num = evaluate_absolute (&the_insn); + if (num % 4) + { + as_bad ("Branch to unaligned address"); + break; + } + CHECK_FIELD (num, 262143, -262144, 0); + + if (the_insn.exp.X_add_symbol) + num -= 8; + + sign_unext (num >> 2, 17, &result); + dis_assemble_17 (result, &w1, &w2, &w); + INSERT_FIELD_AND_CONTINUE (opcode, + ((w2 << 2) | (w1 << 16) | w), 0); + } + else + { + the_insn.reloc = R_HPPA_ABS_CALL; + the_insn.format = 17; + the_insn.arg_reloc = last_call_desc.arg_reloc; + bzero (&last_call_desc, sizeof (struct call_desc)); + continue; + } + + /* Handle a 5 bit shift count at 26. */ + case 'p': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 31, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5); + + /* Handle a 5 bit bit position at 26. */ + case 'P': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 31, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 5); + + /* Handle a 5 bit immediate at 10. */ + case 'Q': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 31, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 21); + + /* Handle a 13 bit immediate at 18. */ + case 'A': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 8191, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 13); + + /* Handle a 26 bit immediate at 31. */ + case 'D': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 671108864, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + + /* Handle a 3 bit SFU identifier at 25. */ + case 'f': + if (*s++ != ',') + as_bad ("Invalid SFU identifier"); + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 7, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 6); + + /* Handle a 20 bit SOP field for spop0. */ + case 'O': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 1048575, 0, 0); + num = (num & 0x1f) | ((num & 0x000fffe0) << 6); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + + /* Handle a 15bit SOP field for spop1. */ + case 'o': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 32767, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 11); + + /* Handle a 10bit SOP field for spop3. */ + case '0': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 1023, 0, 0); + num = (num & 0x1f) | ((num & 0x000003e0) << 6); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + + /* Handle a 15 bit SOP field for spop2. */ + case '1': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 32767, 0, 0); + num = (num & 0x1f) | ((num & 0x00007fe0) << 6); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + + /* Handle a 3-bit co-processor ID field. */ + case 'u': + if (*s++ != ',') + as_bad ("Invalid COPR identifier"); + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 7, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 6); + + /* Handle a 22bit SOP field for copr. */ + case '2': + num = pa_get_absolute_expression (&the_insn, &s); + s = expr_end; + CHECK_FIELD (num, 4194303, 0, 0); + num = (num & 0x1f) | ((num & 0x003fffe0) << 4); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); + + /* Handle a source FP operand format completer. */ + case 'F': + flag = pa_parse_fp_format (&s); + the_insn.fpof1 = flag; + INSERT_FIELD_AND_CONTINUE (opcode, flag, 11); + + /* Handle a destination FP operand format completer. */ + case 'G': + /* pa_parse_format needs the ',' prefix. */ + s--; + flag = pa_parse_fp_format (&s); + the_insn.fpof2 = flag; + INSERT_FIELD_AND_CONTINUE (opcode, flag, 13); + + /* Handle FP compare conditions. */ + case 'M': + cond = pa_parse_fp_cmp_cond (&s); + INSERT_FIELD_AND_CONTINUE (opcode, cond, 0); + + /* Handle L/R register halves like 't'. */ + case 'v': + { + struct pa_11_fp_reg_struct result; + + pa_parse_number (&s, &result); + CHECK_FIELD (result.number_part, 31, 0, 0); + opcode |= result.number_part; + + /* 0x30 opcodes are FP arithmetic operation opcodes + and need to be turned into 0x38 opcodes. This + is not necessary for loads/stores. */ + if (need_pa11_opcode (&the_insn, &result) + && ((opcode & 0xfc000000) == 0x30000000)) + opcode |= 1 << 27; + + INSERT_FIELD_AND_CONTINUE (opcode, result.l_r_select & 1, 6); + } + + /* Handle L/R register halves like 'b'. */ + case 'E': + { + struct pa_11_fp_reg_struct result; + + pa_parse_number (&s, &result); + CHECK_FIELD (result.number_part, 31, 0, 0); + opcode |= result.number_part << 21; + if (need_pa11_opcode (&the_insn, &result)) + { + opcode |= (result.l_r_select & 1) << 7; + opcode |= 1 << 27; + } + continue; + } + + /* Handle L/R register halves like 'x'. */ + case 'X': + { + struct pa_11_fp_reg_struct result; + + pa_parse_number (&s, &result); + CHECK_FIELD (result.number_part, 31, 0, 0); + opcode |= (result.number_part & 0x1f) << 16; + if (need_pa11_opcode (&the_insn, &result)) + { + opcode |= (result.l_r_select & 1) << 12; + opcode |= 1 << 27; + } + continue; + } + + /* Handle a 5 bit register field at 10. */ + case '4': + { + struct pa_11_fp_reg_struct result; + + pa_parse_number (&s, &result); + CHECK_FIELD (result.number_part, 31, 0, 0); + if (the_insn.fpof1 == SGL) + { + if (result.number_part < 16) + { + as_bad ("Invalid register for single precision fmpyadd or fmpysub"); + break; + } + + result.number_part &= 0xF; + result.number_part |= (result.l_r_select & 1) << 4; + } + INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 21); + } + + /* Handle a 5 bit register field at 15. */ + case '6': + { + struct pa_11_fp_reg_struct result; + + pa_parse_number (&s, &result); + CHECK_FIELD (result.number_part, 31, 0, 0); + if (the_insn.fpof1 == SGL) + { + if (result.number_part < 16) + { + as_bad ("Invalid register for single precision fmpyadd or fmpysub"); + break; + } + result.number_part &= 0xF; + result.number_part |= (result.l_r_select & 1) << 4; + } + INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 16); + } + + /* Handle a 5 bit register field at 31. */ + case '7': + { + struct pa_11_fp_reg_struct result; + + pa_parse_number (&s, &result); + CHECK_FIELD (result.number_part, 31, 0, 0); + if (the_insn.fpof1 == SGL) + { + if (result.number_part < 16) + { + as_bad ("Invalid register for single precision fmpyadd or fmpysub"); + break; + } + result.number_part &= 0xF; + result.number_part |= (result.l_r_select & 1) << 4; + } + INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 0); + } + + /* Handle a 5 bit register field at 20. */ + case '8': + { + struct pa_11_fp_reg_struct result; + + pa_parse_number (&s, &result); + CHECK_FIELD (result.number_part, 31, 0, 0); + if (the_insn.fpof1 == SGL) + { + if (result.number_part < 16) + { + as_bad ("Invalid register for single precision fmpyadd or fmpysub"); + break; + } + result.number_part &= 0xF; + result.number_part |= (result.l_r_select & 1) << 4; + } + INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 11); + } + + /* Handle a 5 bit register field at 25. */ + case '9': + { + struct pa_11_fp_reg_struct result; + + pa_parse_number (&s, &result); + CHECK_FIELD (result.number_part, 31, 0, 0); + if (the_insn.fpof1 == SGL) + { + if (result.number_part < 16) + { + as_bad ("Invalid register for single precision fmpyadd or fmpysub"); + break; + } + result.number_part &= 0xF; + result.number_part |= (result.l_r_select & 1) << 4; + } + INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 6); + } + + /* Handle a floating point operand format at 26. + Only allows single and double precision. */ + case 'H': + flag = pa_parse_fp_format (&s); + switch (flag) + { + case SGL: + opcode |= 0x20; + case DBL: + the_insn.fpof1 = flag; + continue; + + case QUAD: + case ILLEGAL_FMT: + default: + as_bad ("Invalid Floating Point Operand Format."); + } + break; + + default: + abort (); + } + break; + } + + /* Check if the args matched. */ + if (match == FALSE) + { + if (&insn[1] - pa_opcodes < NUMOPCODES + && !strcmp (insn->name, insn[1].name)) + { + ++insn; + s = argstart; + continue; + } + else + { + as_bad ("Invalid operands %s", error_message); + return; + } + } + break; + } + + the_insn.opcode = opcode; +} + +/* Turn a string in input_line_pointer into a floating point constant of type + type, and store the appropriate bytes in *litP. The number of LITTLENUMS + emitted is stored in *sizeP . An error message or NULL is returned. */ + +#define MAX_LITTLENUMS 6 + +char * +md_atof (type, litP, sizeP) + char type; + char *litP; + int *sizeP; +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + + switch (type) + { + + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return "Bad call to MD_ATOF()"; + } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + *sizeP = prec * sizeof (LITTLENUM_TYPE); + for (wordP = words; prec--;) + { + md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + return NULL; +} + +/* Write out big-endian. */ + +void +md_number_to_chars (buf, val, n) + char *buf; + valueT val; + int n; +{ + number_to_chars_bigendian (buf, val, n); +} + +/* Translate internal representation of relocation info to BFD target + format. */ + +arelent ** +tc_gen_reloc (section, fixp) + asection *section; + fixS *fixp; +{ + arelent *reloc; + struct hppa_fix_struct *hppa_fixp; + bfd_reloc_code_real_type code; + static arelent *no_relocs = NULL; + arelent **relocs; + bfd_reloc_code_real_type **codes; + int n_relocs; + int i; + + hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data; + if (fixp->fx_addsy == 0) + return &no_relocs; + assert (hppa_fixp != 0); + assert (section != 0); + + reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent)); + assert (reloc != 0); + + reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; + codes = (bfd_reloc_code_real_type **) hppa_gen_reloc_type (stdoutput, + fixp->fx_r_type, + hppa_fixp->fx_r_format, + hppa_fixp->fx_r_field, + fixp->fx_subsy != NULL); + + for (n_relocs = 0; codes[n_relocs]; n_relocs++) + ; + + relocs = (arelent **) + bfd_alloc_by_size_t (stdoutput, sizeof (arelent *) * n_relocs + 1); + assert (relocs != 0); + + reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, + sizeof (arelent) * n_relocs); + if (n_relocs > 0) + assert (reloc != 0); + + for (i = 0; i < n_relocs; i++) + relocs[i] = &reloc[i]; + + relocs[n_relocs] = NULL; + +#ifdef OBJ_ELF + switch (fixp->fx_r_type) + { + default: + assert (n_relocs == 1); + + code = *codes[0]; + + reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + reloc->addend = 0; /* default */ + + assert (reloc->howto && code == reloc->howto->type); + + /* Now, do any processing that is dependent on the relocation type. */ + switch (code) + { + case R_PARISC_DLTREL21L: + case R_PARISC_DLTREL14R: + case R_PARISC_DLTREL14F: + case R_PARISC_PLABEL32: + case R_PARISC_PLABEL21L: + case R_PARISC_PLABEL14R: + /* For plabel relocations, the addend of the + relocation should be either 0 (no static link) or 2 + (static link required). + + FIXME: We always assume no static link! + + We also slam a zero addend into the DLT relative relocs; + it doesn't make a lot of sense to use any addend since + it gets you a different (eg unknown) DLT entry. */ + reloc->addend = 0; + break; + + case R_PARISC_PCREL21L: + case R_PARISC_PCREL17R: + case R_PARISC_PCREL17F: + case R_PARISC_PCREL17C: + case R_PARISC_PCREL14R: + case R_PARISC_PCREL14F: + /* The constant is stored in the instruction. */ + reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, 0); + break; + default: + reloc->addend = fixp->fx_offset; + break; + } + break; + } +#else /* OBJ_SOM */ + + /* Walk over reach relocation returned by the BFD backend. */ + for (i = 0; i < n_relocs; i++) + { + code = *codes[i]; + + relocs[i]->sym_ptr_ptr = &fixp->fx_addsy->bsym; + relocs[i]->howto = bfd_reloc_type_lookup (stdoutput, code); + relocs[i]->address = fixp->fx_frag->fr_address + fixp->fx_where; + + switch (code) + { + case R_COMP2: + /* The only time we ever use a R_COMP2 fixup is for the difference + of two symbols. With that in mind we fill in all four + relocs now and break out of the loop. */ + assert (i == 1); + relocs[0]->sym_ptr_ptr = &bfd_abs_symbol; + relocs[0]->howto = bfd_reloc_type_lookup (stdoutput, *codes[0]); + relocs[0]->address = fixp->fx_frag->fr_address + fixp->fx_where; + relocs[0]->addend = 0; + relocs[0]->sym_ptr_ptr = &fixp->fx_addsy->bsym; + relocs[1]->howto = bfd_reloc_type_lookup (stdoutput, *codes[1]); + relocs[1]->address = fixp->fx_frag->fr_address + fixp->fx_where; + relocs[1]->addend = 0; + relocs[2]->sym_ptr_ptr = &fixp->fx_subsy->bsym; + relocs[2]->howto = bfd_reloc_type_lookup (stdoutput, *codes[2]); + relocs[2]->address = fixp->fx_frag->fr_address + fixp->fx_where; + relocs[2]->addend = 0; + relocs[3]->sym_ptr_ptr = &bfd_abs_symbol; + relocs[3]->howto = bfd_reloc_type_lookup (stdoutput, *codes[3]); + relocs[3]->address = fixp->fx_frag->fr_address + fixp->fx_where; + relocs[3]->addend = 0; + relocs[4]->sym_ptr_ptr = &bfd_abs_symbol; + relocs[4]->howto = bfd_reloc_type_lookup (stdoutput, *codes[4]); + relocs[4]->address = fixp->fx_frag->fr_address + fixp->fx_where; + relocs[4]->addend = 0; + goto done; + case R_PCREL_CALL: + case R_ABS_CALL: + relocs[i]->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, 0); + break; + + case R_DLT_REL: + case R_DATA_PLABEL: + case R_CODE_PLABEL: + /* For plabel relocations, the addend of the + relocation should be either 0 (no static link) or 2 + (static link required). + + FIXME: We always assume no static link! + + We also slam a zero addend into the DLT relative relocs; + it doesn't make a lot of sense to use any addend since + it gets you a different (eg unknown) DLT entry. */ + relocs[i]->addend = 0; + break; + + 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_BEGIN_BRTAB: + case R_END_BRTAB: + /* There is no symbol or addend associated with these fixups. */ + relocs[i]->sym_ptr_ptr = &dummy_symbol->bsym; + relocs[i]->addend = 0; + break; + + case R_ENTRY: + case R_EXIT: + /* There is no symbol associated with these fixups. */ + relocs[i]->sym_ptr_ptr = &dummy_symbol->bsym; + relocs[i]->addend = fixp->fx_offset; + break; + + default: + relocs[i]->addend = fixp->fx_offset; + } + } +#endif + +done: + return relocs; +} + +/* Process any machine dependent frag types. */ + +void +md_convert_frag (abfd, sec, fragP) + register bfd *abfd; + register asection *sec; + register fragS *fragP; +{ + unsigned int address; + + if (fragP->fr_type == rs_machine_dependent) + { + switch ((int) fragP->fr_subtype) + { + case 0: + fragP->fr_type = rs_fill; + know (fragP->fr_var == 1); + know (fragP->fr_next); + address = fragP->fr_address + fragP->fr_fix; + if (address % fragP->fr_offset) + { + fragP->fr_offset = + fragP->fr_next->fr_address + - fragP->fr_address + - fragP->fr_fix; + } + else + fragP->fr_offset = 0; + break; + } + } +} + +/* Round up a section size to the appropriate boundary. */ + +valueT +md_section_align (segment, size) + asection *segment; + valueT size; +{ + int align = bfd_get_section_alignment (stdoutput, segment); + int align2 = (1 << align) - 1; + + return (size + align2) & ~align2; +} + +/* Create a short jump from FROM_ADDR to TO_ADDR. Not used on the PA. */ +void +md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + fprintf (stderr, "pa_create_short_jmp\n"); + abort (); +} + +/* Create a long jump from FROM_ADDR to TO_ADDR. Not used on the PA. */ +void +md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + fprintf (stderr, "pa_create_long_jump\n"); + abort (); +} + +/* Return the approximate size of a frag before relaxation has occurred. */ +int +md_estimate_size_before_relax (fragP, segment) + register fragS *fragP; + asection *segment; +{ + int size; + + size = 0; + + while ((fragP->fr_fix + size) % fragP->fr_offset) + size++; + + return size; +} + +CONST char *md_shortopts = ""; +struct option md_longopts[] = { + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof(md_longopts); + +int +md_parse_option (c, arg) + int c; + char *arg; +{ + return 0; +} + +void +md_show_usage (stream) + FILE *stream; +{ +} + +/* We have no need to default values of symbols. */ + +symbolS * +md_undefined_symbol (name) + char *name; +{ + return 0; +} + +/* Apply a fixup to an instruction. */ + +int +md_apply_fix (fixP, valp) + fixS *fixP; + valueT *valp; +{ + char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; + struct hppa_fix_struct *hppa_fixP; + long new_val, result; + unsigned int w1, w2, w; + + hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data; + /* SOM uses R_HPPA_ENTRY and R_HPPA_EXIT relocations which can + never be "applied" (they are just markers). Likewise for + R_HPPA_BEGIN_BRTAB and R_HPPA_END_BRTAB. */ +#ifdef OBJ_SOM + if (fixP->fx_r_type == R_HPPA_ENTRY + || fixP->fx_r_type == R_HPPA_EXIT + || fixP->fx_r_type == R_HPPA_BEGIN_BRTAB + || fixP->fx_r_type == R_HPPA_END_BRTAB) + return; +#endif + + /* There should have been an HPPA specific fixup associated + with the GAS fixup. */ + if (hppa_fixP) + { + unsigned long buf_wd = bfd_get_32 (stdoutput, buf); + unsigned char fmt = bfd_hppa_insn2fmt (buf_wd); + + /* If there is a symbol associated with this fixup, then it's something + which will need a SOM relocation (except for some PC-relative relocs). + In such cases we should treat the "val" or "addend" as zero since it + will be added in as needed from fx_offset in tc_gen_reloc. */ + if ((fixP->fx_addsy != NULL + || fixP->fx_r_type == R_HPPA_NONE) +#ifdef OBJ_SOM + && fmt != 32 + || hppa_fixP->fx_r_field == e_psel + || hppa_fixP->fx_r_field == e_rpsel + || hppa_fixP->fx_r_field == e_lpsel + || hppa_fixP->fx_r_field == e_tsel + || hppa_fixP->fx_r_field == e_rtsel + || hppa_fixP->fx_r_field == e_ltsel +#endif + ) + new_val = ((fmt == 12 || fmt == 17) ? 8 : 0); +#ifdef OBJ_SOM + /* This is truely disgusting. The machine independent code blindly + adds in the value of the symbol being relocated against. Damn! */ + else if (fmt == 32 + && fixP->fx_addsy != NULL + && S_GET_SEGMENT (fixP->fx_addsy) != bfd_com_section_ptr) + new_val = hppa_field_adjust (*valp - S_GET_VALUE (fixP->fx_addsy), + 0, hppa_fixP->fx_r_field); +#endif + else + new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field); + + /* Handle pc-relative exceptions from above. */ +#define arg_reloc_stub_needed(CALLER, CALLEE) \ + ((CALLEE) && (CALLER) && ((CALLEE) != (CALLER))) + if ((fmt == 12 || fmt == 17) + && fixP->fx_addsy + && fixP->fx_pcrel + && !arg_reloc_stub_needed (((obj_symbol_type *) + fixP->fx_addsy->bsym)->tc_data.hppa_arg_reloc, + hppa_fixP->fx_arg_reloc) + && ((int)(*valp) > -262144 && (int)(*valp) < 262143) + && S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment + && !(fixP->fx_subsy + && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment)) + + new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field); +#undef arg_reloc_stub_needed + + switch (fmt) + { + /* Handle all opcodes with the 'j' operand type. */ + case 14: + CHECK_FIELD (new_val, 8191, -8192, 0); + + /* Mask off 14 bits to be changed. */ + bfd_put_32 (stdoutput, + bfd_get_32 (stdoutput, buf) & 0xffffc000, + buf); + low_sign_unext (new_val, 14, &result); + break; + + /* Handle all opcodes with the 'k' operand type. */ + case 21: + CHECK_FIELD (new_val, 2097152, 0, 0); + + /* Mask off 21 bits to be changed. */ + bfd_put_32 (stdoutput, + bfd_get_32 (stdoutput, buf) & 0xffe00000, + buf); + dis_assemble_21 (new_val, &result); + break; + + /* Handle all the opcodes with the 'i' operand type. */ + case 11: + CHECK_FIELD (new_val, 1023, -1023, 0); + + /* Mask off 11 bits to be changed. */ + bfd_put_32 (stdoutput, + bfd_get_32 (stdoutput, buf) & 0xffff800, + buf); + low_sign_unext (new_val, 11, &result); + break; + + /* Handle all the opcodes with the 'w' operand type. */ + case 12: + CHECK_FIELD (new_val, 8199, -8184, 0) + + /* Mask off 11 bits to be changed. */ + sign_unext ((new_val - 8) >> 2, 12, &result); + bfd_put_32 (stdoutput, + bfd_get_32 (stdoutput, buf) & 0xffffe002, + buf); + + dis_assemble_12 (result, &w1, &w); + result = ((w1 << 2) | w); + break; + + /* Handle some of the opcodes with the 'W' operand type. */ + case 17: + CHECK_FIELD (new_val, 262143, -262144, 0); + + /* Mask off 17 bits to be changed. */ + bfd_put_32 (stdoutput, + bfd_get_32 (stdoutput, buf) & 0xffe0e002, + buf); + sign_unext ((new_val - 8) >> 2, 17, &result); + dis_assemble_17 (result, &w1, &w2, &w); + result = ((w2 << 2) | (w1 << 16) | w); + break; + + case 32: + result = 0; + bfd_put_32 (stdoutput, new_val, buf); + break; + + default: + as_bad ("Unknown relocation encountered in md_apply_fix."); + return; + } + + /* Insert the relocation. */ + bfd_put_32 (stdoutput, bfd_get_32 (stdoutput, buf) | result, buf); + return; + } + else + { + printf ("no hppa_fixup entry for this fixup (fixP = 0x%x, type = 0x%x)\n", + (unsigned int) fixP, fixP->fx_r_type); + return; + } +} + +/* Exactly what point is a PC-relative offset relative TO? + On the PA, they're relative to the address of the offset. */ + +long +md_pcrel_from (fixP) + fixS *fixP; +{ + return fixP->fx_where + fixP->fx_frag->fr_address; +} + +/* Return nonzero if the input line pointer is at the end of + a statement. */ + +static int +is_end_of_statement () +{ + return ((*input_line_pointer == '\n') + || (*input_line_pointer == ';') + || (*input_line_pointer == '!')); +} + +/* Read a number from S. The number might come in one of many forms, + the most common will be a hex or decimal constant, but it could be + a pre-defined register (Yuk!), or an absolute symbol. + + Return a number or -1 for failure. + + When parsing PA-89 FP register numbers RESULT will be + the address of a structure to return information about + L/R half of FP registers, store results there as appropriate. + + pa_parse_number can not handle negative constants and will fail + horribly if it is passed such a constant. */ + +static int +pa_parse_number (s, result) + char **s; + struct pa_11_fp_reg_struct *result; +{ + int num; + char *name; + char c; + symbolS *sym; + int status; + char *p = *s; + + /* Skip whitespace before the number. */ + while (*p == ' ' || *p == '\t') + p = p + 1; + + /* Store info in RESULT if requested by caller. */ + if (result) + { + result->number_part = -1; + result->l_r_select = -1; + } + num = -1; + + if (isdigit (*p)) + { + /* Looks like a number. */ + num = 0; + + if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X')) + { + /* The number is specified in hex. */ + p += 2; + while (isdigit (*p) || ((*p >= 'a') && (*p <= 'f')) + || ((*p >= 'A') && (*p <= 'F'))) + { + if (isdigit (*p)) + num = num * 16 + *p - '0'; + else if (*p >= 'a' && *p <= 'f') + num = num * 16 + *p - 'a' + 10; + else + num = num * 16 + *p - 'A' + 10; + ++p; + } + } + else + { + /* The number is specified in decimal. */ + while (isdigit (*p)) + { + num = num * 10 + *p - '0'; + ++p; + } + } + + /* Store info in RESULT if requested by the caller. */ + if (result) + { + result->number_part = num; + + if (IS_R_SELECT (p)) + { + result->l_r_select = 1; + ++p; + } + else if (IS_L_SELECT (p)) + { + result->l_r_select = 0; + ++p; + } + else + result->l_r_select = 0; + } + } + else if (*p == '%') + { + /* The number might be a predefined register. */ + num = 0; + name = p; + p++; + c = *p; + /* Tege hack: Special case for general registers as the general + code makes a binary search with case translation, and is VERY + slow. */ + if (c == 'r') + { + p++; + if (*p == 'e' && *(p + 1) == 't' + && (*(p + 2) == '0' || *(p + 2) == '1')) + { + p += 2; + num = *p - '0' + 28; + p++; + } + else if (*p == 'p') + { + num = 2; + p++; + } + else if (!isdigit (*p)) + { + if (print_errors) + as_bad ("Undefined register: '%s'.", name); + num = -1; + } + else + { + do + num = num * 10 + *p++ - '0'; + while (isdigit (*p)); + } + } + else + { + /* Do a normal register search. */ + while (is_part_of_name (c)) + { + p = p + 1; + c = *p; + } + *p = 0; + status = reg_name_search (name); + if (status >= 0) + num = status; + else + { + if (print_errors) + as_bad ("Undefined register: '%s'.", name); + num = -1; + } + *p = c; + } + + /* Store info in RESULT if requested by caller. */ + if (result) + { + result->number_part = num; + if (IS_R_SELECT (p - 1)) + result->l_r_select = 1; + else if (IS_L_SELECT (p - 1)) + result->l_r_select = 0; + else + result->l_r_select = 0; + } + } + else + { + /* And finally, it could be a symbol in the absolute section which + is effectively a constant. */ + num = 0; + name = p; + c = *p; + while (is_part_of_name (c)) + { + p = p + 1; + c = *p; + } + *p = 0; + if ((sym = symbol_find (name)) != NULL) + { + if (S_GET_SEGMENT (sym) == &bfd_abs_section) + num = S_GET_VALUE (sym); + else + { + if (print_errors) + as_bad ("Non-absolute symbol: '%s'.", name); + num = -1; + } + } + else + { + /* There is where we'd come for an undefined symbol + or for an empty string. For an empty string we + will return zero. That's a concession made for + compatability with the braindamaged HP assemblers. */ + if (*name == 0) + num = 0; + else + { + if (print_errors) + as_bad ("Undefined absolute constant: '%s'.", name); + num = -1; + } + } + *p = c; + + /* Store info in RESULT if requested by caller. */ + if (result) + { + result->number_part = num; + if (IS_R_SELECT (p - 1)) + result->l_r_select = 1; + else if (IS_L_SELECT (p - 1)) + result->l_r_select = 0; + else + result->l_r_select = 0; + } + } + + *s = p; + return num; +} + +#define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg)) + +/* Given NAME, find the register number associated with that name, return + the integer value associated with the given name or -1 on failure. */ + +static int +reg_name_search (name) + char *name; +{ + int middle, low, high; + int cmp; + + low = 0; + high = REG_NAME_CNT - 1; + + do + { + middle = (low + high) / 2; + cmp = strcasecmp (name, pre_defined_registers[middle].name); + if (cmp < 0) + high = middle - 1; + else if (cmp > 0) + low = middle + 1; + else + return pre_defined_registers[middle].value; + } + while (low <= high); + + return -1; +} + + +/* Return nonzero if the given INSN and L/R information will require + a new PA-1.1 opcode. */ + +static int +need_pa11_opcode (insn, result) + struct pa_it *insn; + struct pa_11_fp_reg_struct *result; +{ + if (result->l_r_select == 1 && !(insn->fpof1 == DBL && insn->fpof2 == DBL)) + { + /* If this instruction is specific to a particular architecture, + then set a new architecture. */ + if (bfd_get_mach (stdoutput) < pa11) + { + if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, pa11)) + as_warn ("could not update architecture and machine"); + } + return TRUE; + } + else + return FALSE; +} + +/* Parse a condition for a fcmp instruction. Return the numerical + code associated with the condition. */ + +static int +pa_parse_fp_cmp_cond (s) + char **s; +{ + int cond, i; + + cond = 0; + + for (i = 0; i < 32; i++) + { + if (strncasecmp (*s, fp_cond_map[i].string, + strlen (fp_cond_map[i].string)) == 0) + { + cond = fp_cond_map[i].cond; + *s += strlen (fp_cond_map[i].string); + /* If not a complete match, back up the input string and + report an error. */ + if (**s != ' ' && **s != '\t') + { + *s -= strlen (fp_cond_map[i].string); + break; + } + while (**s == ' ' || **s == '\t') + *s = *s + 1; + return cond; + } + } + + as_bad ("Invalid FP Compare Condition: %s", *s); + + /* Advance over the bogus completer. */ + while (**s != ',' && **s != ' ' && **s != '\t') + *s += 1; + + return 0; +} + +/* Parse an FP operand format completer returning the completer + type. */ + +static fp_operand_format +pa_parse_fp_format (s) + char **s; +{ + int format; + + format = SGL; + if (**s == ',') + { + *s += 1; + if (strncasecmp (*s, "sgl", 3) == 0) + { + format = SGL; + *s += 4; + } + else if (strncasecmp (*s, "dbl", 3) == 0) + { + format = DBL; + *s += 4; + } + else if (strncasecmp (*s, "quad", 4) == 0) + { + format = QUAD; + *s += 5; + } + else + { + format = ILLEGAL_FMT; + as_bad ("Invalid FP Operand Format: %3s", *s); + } + } + + return format; +} + +/* Convert from a selector string into a selector type. */ + +static int +pa_chk_field_selector (str) + char **str; +{ + int middle, low, high; + int cmp; + char name[3]; + + /* Read past any whitespace. */ + /* FIXME: should we read past newlines and formfeeds??? */ + while (**str == ' ' || **str == '\t' || **str == '\n' || **str == '\f') + *str = *str + 1; + + if ((*str)[1] == '\'' || (*str)[1] == '%') + name[0] = tolower ((*str)[0]), + name[1] = 0; + else if ((*str)[2] == '\'' || (*str)[2] == '%') + name[0] = tolower ((*str)[0]), + name[1] = tolower ((*str)[1]), + name[2] = 0; + else + return e_fsel; + + low = 0; + high = sizeof (selector_table) / sizeof (struct selector_entry) - 1; + + do + { + middle = (low + high) / 2; + cmp = strcmp (name, selector_table[middle].prefix); + if (cmp < 0) + high = middle - 1; + else if (cmp > 0) + low = middle + 1; + else + { + *str += strlen (name) + 1; + return selector_table[middle].field_selector; + } + } + while (low <= high); + + return e_fsel; +} + +/* Mark (via expr_end) the end of an expression (I think). FIXME. */ + +static int +get_expression (str) + char *str; +{ + char *save_in; + asection *seg; + + save_in = input_line_pointer; + input_line_pointer = str; + seg = expression (&the_insn.exp); + if (!(seg == absolute_section + || seg == undefined_section + || SEG_NORMAL (seg))) + { + as_warn ("Bad segment in expression."); + expr_end = input_line_pointer; + input_line_pointer = save_in; + return 1; + } + expr_end = input_line_pointer; + input_line_pointer = save_in; + return 0; +} + +/* Mark (via expr_end) the end of an absolute expression. FIXME. */ +static int +pa_get_absolute_expression (insn, strp) + struct pa_it *insn; + char **strp; +{ + char *save_in; + + insn->field_selector = pa_chk_field_selector (strp); + save_in = input_line_pointer; + input_line_pointer = *strp; + expression (&insn->exp); + if (insn->exp.X_op != O_constant) + { + as_bad ("Bad segment (should be absolute)."); + expr_end = input_line_pointer; + input_line_pointer = save_in; + return 0; + } + expr_end = input_line_pointer; + input_line_pointer = save_in; + return evaluate_absolute (insn); +} + +/* Evaluate an absolute expression EXP which may be modified by + the selector FIELD_SELECTOR. Return the value of the expression. */ +static int +evaluate_absolute (insn) + struct pa_it *insn; +{ + int value; + expressionS exp; + int field_selector = insn->field_selector; + + exp = insn->exp; + value = exp.X_add_number; + + switch (field_selector) + { + /* No change. */ + case e_fsel: + break; + + /* If bit 21 is on then add 0x800 and arithmetic shift right 11 bits. */ + case e_lssel: + if (value & 0x00000400) + value += 0x800; + value = (value & 0xfffff800) >> 11; + break; + + /* Sign extend from bit 21. */ + case e_rssel: + if (value & 0x00000400) + value |= 0xfffff800; + else + value &= 0x7ff; + break; + + /* Arithmetic shift right 11 bits. */ + case e_lsel: + value = (value & 0xfffff800) >> 11; + break; + + /* Set bits 0-20 to zero. */ + case e_rsel: + value = value & 0x7ff; + break; + + /* Add 0x800 and arithmetic shift right 11 bits. */ + case e_ldsel: + value += 0x800; + value = (value & 0xfffff800) >> 11; + break; + + /* Set bitgs 0-21 to one. */ + case e_rdsel: + value |= 0xfffff800; + break; + +#define RSEL_ROUND(c) (((c) + 0x1000) & ~0x1fff) + case e_rrsel: + value = (RSEL_ROUND (value) & 0x7ff) + (value - RSEL_ROUND (value)); + break; + + case e_lrsel: + value = (RSEL_ROUND (value) >> 11) & 0x1fffff; + break; +#undef RSEL_ROUND + + default: + BAD_CASE (field_selector); + break; + } + return value; +} + +/* Given an argument location specification return the associated + argument location number. */ + +static unsigned int +pa_build_arg_reloc (type_name) + char *type_name; +{ + + if (strncasecmp (type_name, "no", 2) == 0) + return 0; + if (strncasecmp (type_name, "gr", 2) == 0) + return 1; + else if (strncasecmp (type_name, "fr", 2) == 0) + return 2; + else if (strncasecmp (type_name, "fu", 2) == 0) + return 3; + else + as_bad ("Invalid argument location: %s\n", type_name); + + return 0; +} + +/* Encode and return an argument relocation specification for + the given register in the location specified by arg_reloc. */ + +static unsigned int +pa_align_arg_reloc (reg, arg_reloc) + unsigned int reg; + unsigned int arg_reloc; +{ + unsigned int new_reloc; + + new_reloc = arg_reloc; + switch (reg) + { + case 0: + new_reloc <<= 8; + break; + case 1: + new_reloc <<= 6; + break; + case 2: + new_reloc <<= 4; + break; + case 3: + new_reloc <<= 2; + break; + default: + as_bad ("Invalid argument description: %d", reg); + } + + return new_reloc; +} + +/* Parse a PA nullification completer (,n). Return nonzero if the + completer was found; return zero if no completer was found. */ + +static int +pa_parse_nullif (s) + char **s; +{ + int nullif; + + nullif = 0; + if (**s == ',') + { + *s = *s + 1; + if (strncasecmp (*s, "n", 1) == 0) + nullif = 1; + else + { + as_bad ("Invalid Nullification: (%c)", **s); + nullif = 0; + } + *s = *s + 1; + } + + return nullif; +} + +/* Parse a non-negated compare/subtract completer returning the + number (for encoding in instrutions) of the given completer. + + ISBRANCH specifies whether or not this is parsing a condition + completer for a branch (vs a nullification completer for a + computational instruction. */ + +static int +pa_parse_nonneg_cmpsub_cmpltr (s, isbranch) + char **s; + int isbranch; +{ + int cmpltr; + char *name = *s + 1; + char c; + char *save_s = *s; + + cmpltr = 0; + if (**s == ',') + { + *s += 1; + while (**s != ',' && **s != ' ' && **s != '\t') + *s += 1; + c = **s; + **s = 0x00; + if (strcmp (name, "=") == 0) + { + cmpltr = 1; + } + else if (strcmp (name, "<") == 0) + { + cmpltr = 2; + } + else if (strcmp (name, "<=") == 0) + { + cmpltr = 3; + } + else if (strcmp (name, "<<") == 0) + { + cmpltr = 4; + } + else if (strcmp (name, "<<=") == 0) + { + cmpltr = 5; + } + else if (strcasecmp (name, "sv") == 0) + { + cmpltr = 6; + } + else if (strcasecmp (name, "od") == 0) + { + cmpltr = 7; + } + /* If we have something like addb,n then there is no condition + completer. */ + else if (strcasecmp (name, "n") == 0 && isbranch) + { + cmpltr = 0; + } + else + { + cmpltr = -1; + } + **s = c; + } + + /* Reset pointers if this was really a ,n for a branch instruction. */ + if (cmpltr == 0 && *name == 'n' && isbranch) + *s = save_s; + + return cmpltr; +} + +/* Parse a negated compare/subtract completer returning the + number (for encoding in instrutions) of the given completer. + + ISBRANCH specifies whether or not this is parsing a condition + completer for a branch (vs a nullification completer for a + computational instruction. */ + +static int +pa_parse_neg_cmpsub_cmpltr (s, isbranch) + char **s; + int isbranch; +{ + int cmpltr; + char *name = *s + 1; + char c; + char *save_s = *s; + + cmpltr = 0; + if (**s == ',') + { + *s += 1; + while (**s != ',' && **s != ' ' && **s != '\t') + *s += 1; + c = **s; + **s = 0x00; + if (strcasecmp (name, "tr") == 0) + { + cmpltr = 0; + } + else if (strcmp (name, "<>") == 0) + { + cmpltr = 1; + } + else if (strcmp (name, ">=") == 0) + { + cmpltr = 2; + } + else if (strcmp (name, ">") == 0) + { + cmpltr = 3; + } + else if (strcmp (name, ">>=") == 0) + { + cmpltr = 4; + } + else if (strcmp (name, ">>") == 0) + { + cmpltr = 5; + } + else if (strcasecmp (name, "nsv") == 0) + { + cmpltr = 6; + } + else if (strcasecmp (name, "ev") == 0) + { + cmpltr = 7; + } + /* If we have something like addb,n then there is no condition + completer. */ + else if (strcasecmp (name, "n") == 0 && isbranch) + { + cmpltr = 0; + } + else + { + cmpltr = -1; + } + **s = c; + } + + /* Reset pointers if this was really a ,n for a branch instruction. */ + if (cmpltr == 0 && *name == 'n' && isbranch) + *s = save_s; + + return cmpltr; +} + +/* Parse a non-negated addition completer returning the number + (for encoding in instrutions) of the given completer. + + ISBRANCH specifies whether or not this is parsing a condition + completer for a branch (vs a nullification completer for a + computational instruction. */ + +static int +pa_parse_nonneg_add_cmpltr (s, isbranch) + char **s; + int isbranch; +{ + int cmpltr; + char *name = *s + 1; + char c; + char *save_s = *s; + + cmpltr = 0; + if (**s == ',') + { + *s += 1; + while (**s != ',' && **s != ' ' && **s != '\t') + *s += 1; + c = **s; + **s = 0x00; + if (strcmp (name, "=") == 0) + { + cmpltr = 1; + } + else if (strcmp (name, "<") == 0) + { + cmpltr = 2; + } + else if (strcmp (name, "<=") == 0) + { + cmpltr = 3; + } + else if (strcasecmp (name, "nuv") == 0) + { + cmpltr = 4; + } + else if (strcasecmp (name, "znv") == 0) + { + cmpltr = 5; + } + else if (strcasecmp (name, "sv") == 0) + { + cmpltr = 6; + } + else if (strcasecmp (name, "od") == 0) + { + cmpltr = 7; + } + /* If we have something like addb,n then there is no condition + completer. */ + else if (strcasecmp (name, "n") == 0 && isbranch) + { + cmpltr = 0; + } + else + { + cmpltr = -1; + } + **s = c; + } + + /* Reset pointers if this was really a ,n for a branch instruction. */ + if (cmpltr == 0 && *name == 'n' && isbranch) + *s = save_s; + + return cmpltr; +} + +/* Parse a negated addition completer returning the number + (for encoding in instrutions) of the given completer. + + ISBRANCH specifies whether or not this is parsing a condition + completer for a branch (vs a nullification completer for a + computational instruction. */ + +static int +pa_parse_neg_add_cmpltr (s, isbranch) + char **s; + int isbranch; +{ + int cmpltr; + char *name = *s + 1; + char c; + char *save_s = *s; + + cmpltr = 0; + if (**s == ',') + { + *s += 1; + while (**s != ',' && **s != ' ' && **s != '\t') + *s += 1; + c = **s; + **s = 0x00; + if (strcasecmp (name, "tr") == 0) + { + cmpltr = 0; + } + else if (strcmp (name, "<>") == 0) + { + cmpltr = 1; + } + else if (strcmp (name, ">=") == 0) + { + cmpltr = 2; + } + else if (strcmp (name, ">") == 0) + { + cmpltr = 3; + } + else if (strcasecmp (name, "uv") == 0) + { + cmpltr = 4; + } + else if (strcasecmp (name, "vnz") == 0) + { + cmpltr = 5; + } + else if (strcasecmp (name, "nsv") == 0) + { + cmpltr = 6; + } + else if (strcasecmp (name, "ev") == 0) + { + cmpltr = 7; + } + /* If we have something like addb,n then there is no condition + completer. */ + else if (strcasecmp (name, "n") == 0 && isbranch) + { + cmpltr = 0; + } + else + { + cmpltr = -1; + } + **s = c; + } + + /* Reset pointers if this was really a ,n for a branch instruction. */ + if (cmpltr == 0 && *name == 'n' && isbranch) + *s = save_s; + + return cmpltr; +} + +/* Handle an alignment directive. Special so that we can update the + alignment of the subspace if necessary. */ +static void +pa_align (bytes) +{ + /* We must have a valid space and subspace. */ + pa_check_current_space_and_subspace (); + + /* Let the generic gas code do most of the work. */ + s_align_bytes (bytes); + + /* If bytes is a power of 2, then update the current subspace's + alignment if necessary. */ + if (log2 (bytes) != -1) + record_alignment (current_subspace->ssd_seg, log2 (bytes)); +} + +/* Handle a .BLOCK type pseudo-op. */ + +static void +pa_block (z) + int z; +{ + char *p; + long int temp_fill; + unsigned int temp_size; + int i; + + /* We must have a valid space and subspace. */ + pa_check_current_space_and_subspace (); + + temp_size = get_absolute_expression (); + + /* Always fill with zeros, that's what the HP assembler does. */ + temp_fill = 0; + + p = frag_var (rs_fill, (int) temp_size, (int) temp_size, + (relax_substateT) 0, (symbolS *) 0, 1, NULL); + bzero (p, temp_size); + + /* Convert 2 bytes at a time. */ + + for (i = 0; i < temp_size; i += 2) + { + md_number_to_chars (p + i, + (valueT) temp_fill, + (int) ((temp_size - i) > 2 ? 2 : (temp_size - i))); + } + + pa_undefine_label (); + demand_empty_rest_of_line (); +} + +/* Handle a .begin_brtab and .end_brtab pseudo-op. */ + +static void +pa_brtab (begin) + int begin; +{ + +#ifdef OBJ_SOM + /* The BRTAB relocations are only availble in SOM (to denote + the beginning and end of branch tables). */ + char *where = frag_more (0); + + fix_new_hppa (frag_now, where - frag_now->fr_literal, 0, + NULL, (offsetT) 0, NULL, + 0, begin ? R_HPPA_BEGIN_BRTAB : R_HPPA_END_BRTAB, + e_fsel, 0, 0, NULL); +#endif + + demand_empty_rest_of_line (); +} + +/* Handle a .CALL pseudo-op. This involves storing away information + about where arguments are to be found so the linker can detect + (and correct) argument location mismatches between caller and callee. */ + +static void +pa_call (unused) + int unused; +{ + /* We must have a valid space and subspace. */ + pa_check_current_space_and_subspace (); + + pa_call_args (&last_call_desc); + demand_empty_rest_of_line (); +} + +/* Do the dirty work of building a call descriptor which describes + where the caller placed arguments to a function call. */ + +static void +pa_call_args (call_desc) + struct call_desc *call_desc; +{ + char *name, c, *p; + unsigned int temp, arg_reloc; + + while (!is_end_of_statement ()) + { + name = input_line_pointer; + c = get_symbol_end (); + /* Process a source argument. */ + if ((strncasecmp (name, "argw", 4) == 0)) + { + temp = atoi (name + 4); + p = input_line_pointer; + *p = c; + input_line_pointer++; + name = input_line_pointer; + c = get_symbol_end (); + arg_reloc = pa_build_arg_reloc (name); + call_desc->arg_reloc |= pa_align_arg_reloc (temp, arg_reloc); + } + /* Process a return value. */ + else if ((strncasecmp (name, "rtnval", 6) == 0)) + { + p = input_line_pointer; + *p = c; + input_line_pointer++; + name = input_line_pointer; + c = get_symbol_end (); + arg_reloc = pa_build_arg_reloc (name); + call_desc->arg_reloc |= (arg_reloc & 0x3); + } + else + { + as_bad ("Invalid .CALL argument: %s", name); + } + p = input_line_pointer; + *p = c; + if (!is_end_of_statement ()) + input_line_pointer++; + } +} + +/* Return TRUE if FRAG1 and FRAG2 are the same. */ + +static int +is_same_frag (frag1, frag2) + fragS *frag1; + fragS *frag2; +{ + + if (frag1 == NULL) + return (FALSE); + else if (frag2 == NULL) + return (FALSE); + else if (frag1 == frag2) + return (TRUE); + else if (frag2->fr_type == rs_fill && frag2->fr_fix == 0) + return (is_same_frag (frag1, frag2->fr_next)); + else + return (FALSE); +} + +#ifdef OBJ_ELF +/* Build an entry in the UNWIND subspace from the given function + attributes in CALL_INFO. This is not needed for SOM as using + R_ENTRY and R_EXIT relocations allow the linker to handle building + of the unwind spaces. */ + +static void +pa_build_unwind_subspace (call_info) + struct call_info *call_info; +{ + char *unwind; + asection *seg, *save_seg; + subsegT subseg, save_subseg; + int i; + char c, *p; + + /* Get into the right seg/subseg. This may involve creating + the seg the first time through. Make sure to have the + old seg/subseg so that we can reset things when we are done. */ + subseg = SUBSEG_UNWIND; + seg = bfd_get_section_by_name (stdoutput, UNWIND_SECTION_NAME); + if (seg == ASEC_NULL) + { + seg = bfd_make_section_old_way (stdoutput, UNWIND_SECTION_NAME); + bfd_set_section_flags (stdoutput, seg, + SEC_READONLY | SEC_HAS_CONTENTS + | SEC_LOAD | SEC_RELOC); + } + + save_seg = now_seg; + save_subseg = now_subseg; + subseg_set (seg, subseg); + + + /* Get some space to hold relocation information for the unwind + descriptor. */ + p = frag_more (4); + md_number_to_chars (p, 0, 4); + + /* Relocation info. for start offset of the function. */ + fix_new_hppa (frag_now, p - frag_now->fr_literal, 4, + call_info->start_symbol, (offsetT) 0, + (expressionS *) NULL, 0, R_PARISC_DIR32, e_fsel, 32, 0, NULL); + + p = frag_more (4); + md_number_to_chars (p, 0, 4); + + /* Relocation info. for end offset of the function. + + Because we allow reductions of 32bit relocations for ELF, this will be + reduced to section_sym + offset which avoids putting the temporary + symbol into the symbol table. It (should) end up giving the same + value as call_info->start_symbol + function size once the linker is + finished with its work. */ + + fix_new_hppa (frag_now, p - frag_now->fr_literal, 4, + call_info->end_symbol, (offsetT) 0, + (expressionS *) NULL, 0, R_PARISC_DIR32, e_fsel, 32, 0, NULL); + + /* Dump it. */ + unwind = (char *) &call_info->ci_unwind; + for (i = 8; i < sizeof (struct unwind_table); i++) + { + c = *(unwind + i); + { + FRAG_APPEND_1_CHAR (c); + } + } + + /* Return back to the original segment/subsegment. */ + subseg_set (save_seg, save_subseg); +} +#endif + +/* Process a .CALLINFO pseudo-op. This information is used later + to build unwind descriptors and maybe one day to support + .ENTER and .LEAVE. */ + +static void +pa_callinfo (unused) + int unused; +{ + char *name, c, *p; + int temp; + + /* We must have a valid space and subspace. */ + pa_check_current_space_and_subspace (); + + /* .CALLINFO must appear within a procedure definition. */ + if (!within_procedure) + as_bad (".callinfo is not within a procedure definition"); + + /* Mark the fact that we found the .CALLINFO for the + current procedure. */ + callinfo_found = TRUE; + + /* Iterate over the .CALLINFO arguments. */ + while (!is_end_of_statement ()) + { + name = input_line_pointer; + c = get_symbol_end (); + /* Frame size specification. */ + if ((strncasecmp (name, "frame", 5) == 0)) + { + p = input_line_pointer; + *p = c; + input_line_pointer++; + temp = get_absolute_expression (); + if ((temp & 0x3) != 0) + { + as_bad ("FRAME parameter must be a multiple of 8: %d\n", temp); + temp = 0; + } + + /* callinfo is in bytes and unwind_desc is in 8 byte units. */ + last_call_info->ci_unwind.descriptor.frame_size = temp / 8; + + } + /* Entry register (GR, GR and SR) specifications. */ + else if ((strncasecmp (name, "entry_gr", 8) == 0)) + { + p = input_line_pointer; + *p = c; + input_line_pointer++; + temp = get_absolute_expression (); + /* The HP assembler accepts 19 as the high bound for ENTRY_GR + even though %r19 is caller saved. I think this is a bug in + the HP assembler, and we are not going to emulate it. */ + if (temp < 3 || temp > 18) + as_bad ("Value for ENTRY_GR must be in the range 3..18\n"); + last_call_info->ci_unwind.descriptor.entry_gr = temp - 2; + } + else if ((strncasecmp (name, "entry_fr", 8) == 0)) + { + p = input_line_pointer; + *p = c; + input_line_pointer++; + temp = get_absolute_expression (); + /* Similarly the HP assembler takes 31 as the high bound even + though %fr21 is the last callee saved floating point register. */ + if (temp < 12 || temp > 21) + as_bad ("Value for ENTRY_FR must be in the range 12..21\n"); + last_call_info->ci_unwind.descriptor.entry_fr = temp - 11; + } + else if ((strncasecmp (name, "entry_sr", 8) == 0)) + { + p = input_line_pointer; + *p = c; + input_line_pointer++; + temp = get_absolute_expression (); + if (temp != 3) + as_bad ("Value for ENTRY_SR must be 3\n"); + } + /* Note whether or not this function performs any calls. */ + else if ((strncasecmp (name, "calls", 5) == 0) || + (strncasecmp (name, "caller", 6) == 0)) + { + p = input_line_pointer; + *p = c; + } + else if ((strncasecmp (name, "no_calls", 8) == 0)) + { + p = input_line_pointer; + *p = c; + } + /* Should RP be saved into the stack. */ + else if ((strncasecmp (name, "save_rp", 7) == 0)) + { + p = input_line_pointer; + *p = c; + last_call_info->ci_unwind.descriptor.save_rp = 1; + } + /* Likewise for SP. */ + else if ((strncasecmp (name, "save_sp", 7) == 0)) + { + p = input_line_pointer; + *p = c; + last_call_info->ci_unwind.descriptor.save_sp = 1; + } + /* Is this an unwindable procedure. If so mark it so + in the unwind descriptor. */ + else if ((strncasecmp (name, "no_unwind", 9) == 0)) + { + p = input_line_pointer; + *p = c; + last_call_info->ci_unwind.descriptor.cannot_unwind = 1; + } + /* Is this an interrupt routine. If so mark it in the + unwind descriptor. */ + else if ((strncasecmp (name, "hpux_int", 7) == 0)) + { + p = input_line_pointer; + *p = c; + last_call_info->ci_unwind.descriptor.hpux_interrupt_marker = 1; + } + /* Is this a millicode routine. "millicode" isn't in my + assembler manual, but my copy is old. The HP assembler + accepts it, and there's a place in the unwind descriptor + to drop the information, so we'll accept it too. */ + else if ((strncasecmp (name, "millicode", 9) == 0)) + { + p = input_line_pointer; + *p = c; + last_call_info->ci_unwind.descriptor.millicode = 1; + } + else + { + as_bad ("Invalid .CALLINFO argument: %s", name); + *input_line_pointer = c; + } + if (!is_end_of_statement ()) + input_line_pointer++; + } + + demand_empty_rest_of_line (); +} + +/* Switch into the code subspace. */ + +static void +pa_code (unused) + int unused; +{ + current_space = is_defined_space ("$TEXT$"); + current_subspace + = pa_subsegment_to_subspace (current_space->sd_seg, 0); + s_text (0); + pa_undefine_label (); +} + +/* This is different than the standard GAS s_comm(). On HP9000/800 machines, + the .comm pseudo-op has the following symtax: + +