From a45e437ef5e931d8ef44f91611c8fd2592ef68f9 Mon Sep 17 00:00:00 2001 From: eastb233 Date: Tue, 19 Aug 2025 15:12:57 +0800 Subject: [PATCH] [NFC] format patch names --- Sw64-revert-old-support-modified.patch | 2954 -- Sw64-revert-old-support-newfile.patch | 31574 --------------- ...tch => backport-CVE-2021-42574-part1.patch | 0 ...tch => backport-CVE-2021-42574-part2.patch | 0 ...tch => backport-CVE-2021-42574-part3.patch | 0 binutils.spec | 19 +- ...-support-not-upstream-modified-files.patch | 3328 -- sw_64-support-not-upstream-new-files.patch | 31730 ---------------- 8 files changed, 11 insertions(+), 69594 deletions(-) delete mode 100644 Sw64-revert-old-support-modified.patch delete mode 100644 Sw64-revert-old-support-newfile.patch rename backport-0001-CVE-2021-42574.patch => backport-CVE-2021-42574-part1.patch (100%) rename backport-0002-CVE-2021-42574.patch => backport-CVE-2021-42574-part2.patch (100%) rename backport-0003-CVE-2021-42574.patch => backport-CVE-2021-42574-part3.patch (100%) delete mode 100644 sw_64-support-not-upstream-modified-files.patch delete mode 100644 sw_64-support-not-upstream-new-files.patch diff --git a/Sw64-revert-old-support-modified.patch b/Sw64-revert-old-support-modified.patch deleted file mode 100644 index e629d79..0000000 --- a/Sw64-revert-old-support-modified.patch +++ /dev/null @@ -1,2954 +0,0 @@ ---- b/Makefile.in -+++ a/Makefile.in -@@ -619,7 +619,6 @@ - #### host and target specific makefile fragments come in here. - @target_makefile_frag@ - @alphaieee_frag@ --@sw_64ieee_frag@ - @ospace_frag@ - @host_makefile_frag@ - ### ---- b/Makefile.tpl -+++ a/Makefile.tpl -@@ -572,7 +572,6 @@ - #### host and target specific makefile fragments come in here. - @target_makefile_frag@ - @alphaieee_frag@ --@sw_64ieee_frag@ - @ospace_frag@ - @host_makefile_frag@ - ### ---- b/bfd/Makefile.am -+++ a/bfd/Makefile.am -@@ -92,7 +92,6 @@ - ALL_MACHINES = \ - cpu-aarch64.lo \ - cpu-alpha.lo \ -- cpu-sw_64.lo \ - cpu-arc.lo \ - cpu-arm.lo \ - cpu-avr.lo \ -@@ -177,7 +176,6 @@ - ALL_MACHINES_CFILES = \ - cpu-aarch64.c \ - cpu-alpha.c \ -- cpu-sw_64.c \ - cpu-arc.c \ - cpu-arm.c \ - cpu-avr.c \ -@@ -538,7 +536,6 @@ - aix5ppc-core.lo \ - aout64.lo \ - coff-alpha.lo \ -- coff-sw_64.lo \ - coff-x86_64.lo \ - coff64-rs6000.lo \ - elf32-ia64.lo \ -@@ -546,7 +543,6 @@ - elf32-score.lo \ - elf32-score7.lo \ - elf64-alpha.lo \ -- elf64-sw_64.lo \ - elf64-gen.lo \ - elf64-hppa.lo \ - elf64-ia64.lo \ -@@ -578,21 +574,18 @@ - pei-x86_64.lo \ - pepigen.lo \ - pex64igen.lo \ -+ vms-alpha.lo -- vms-alpha.lo \ -- vms-sw_64.lo - - BFD64_BACKENDS_CFILES = \ - aix5ppc-core.c \ - aout64.c \ - coff-alpha.c \ -- coff-sw_64.c \ - coff-x86_64.c \ - coff64-rs6000.c \ - elf32-mips.c \ - elf32-score.c \ - elf32-score7.c \ - elf64-alpha.c \ -- elf64-sw_64.c \ - elf64-gen.c \ - elf64-hppa.c \ - elf64-ia64-vms.c \ -@@ -619,8 +612,7 @@ - pei-aarch64.c \ - pei-ia64.c \ - pei-x86_64.c \ -+ vms-alpha.c -- vms-alpha.c \ -- vms-sw_64.c - - OPTIONAL_BACKENDS = \ - aix386-core.lo \ ---- b/bfd/Makefile.in -+++ a/bfd/Makefile.in -@@ -517,7 +517,6 @@ - ALL_MACHINES = \ - cpu-aarch64.lo \ - cpu-alpha.lo \ -- cpu-sw_64.lo \ - cpu-arc.lo \ - cpu-arm.lo \ - cpu-avr.lo \ -@@ -602,7 +601,6 @@ - ALL_MACHINES_CFILES = \ - cpu-aarch64.c \ - cpu-alpha.c \ -- cpu-sw_64.c \ - cpu-arc.c \ - cpu-arm.c \ - cpu-avr.c \ -@@ -965,7 +963,6 @@ - aix5ppc-core.lo \ - aout64.lo \ - coff-alpha.lo \ -- coff-sw_64.lo \ - coff-x86_64.lo \ - coff64-rs6000.lo \ - elf32-ia64.lo \ -@@ -973,7 +970,6 @@ - elf32-score.lo \ - elf32-score7.lo \ - elf64-alpha.lo \ -- elf64-sw_64.lo \ - elf64-gen.lo \ - elf64-hppa.lo \ - elf64-ia64.lo \ -@@ -1005,21 +1001,18 @@ - pei-x86_64.lo \ - pepigen.lo \ - pex64igen.lo \ -+ vms-alpha.lo -- vms-alpha.lo \ -- vms-sw_64.lo - - BFD64_BACKENDS_CFILES = \ - aix5ppc-core.c \ - aout64.c \ - coff-alpha.c \ -- coff-sw_64.c \ - coff-x86_64.c \ - coff64-rs6000.c \ - elf32-mips.c \ - elf32-score.c \ - elf32-score7.c \ - elf64-alpha.c \ -- elf64-sw_64.c \ - elf64-gen.c \ - elf64-hppa.c \ - elf64-ia64-vms.c \ -@@ -1046,8 +1039,7 @@ - pei-aarch64.c \ - pei-ia64.c \ - pei-x86_64.c \ -+ vms-alpha.c -- vms-alpha.c \ -- vms-sw_64.c - - OPTIONAL_BACKENDS = \ - aix386-core.lo \ -@@ -1314,7 +1306,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-i386lynx.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cisco-core.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-alpha.Plo@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-sw_64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-bfd.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-go32.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-i386.Plo@am__quote@ -@@ -1335,7 +1326,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/corefile.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-aarch64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-alpha.Plo@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-sw_64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-arc.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-arm.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-avr.Plo@am__quote@ -@@ -1500,7 +1490,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-aarch64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-alpha.Plo@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-sw_64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-bpf.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-gen.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-hppa.Plo@am__quote@ -@@ -1590,7 +1579,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vaxnetbsd.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verilog.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-alpha.Plo@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-sw_64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-lib.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-misc.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wasm-module.Plo@am__quote@ ---- b/bfd/archures.c -+++ a/bfd/archures.c -@@ -24,9 +24,6 @@ - #include "libbfd.h" - #include "safe-ctype.h" - --/* add sw_64 target -- * add cpu sw6a-1621, sw6b-3231. */ -- - /* - - SECTION -@@ -311,11 +308,6 @@ - .#define bfd_mach_alpha_ev4 0x10 - .#define bfd_mach_alpha_ev5 0x20 - .#define bfd_mach_alpha_ev6 0x30 --.#ifdef TARGET_SW_64 --. bfd_arch_sw_64, {* Sw_64 *} --.#define bfd_mach_sw_64_sw6a 4 --.#define bfd_mach_sw_64_sw6b 8 --.#endif - . bfd_arch_arm, {* Advanced Risc Machines ARM. *} - .#define bfd_mach_arm_unknown 0 - .#define bfd_mach_arm_2 1 -@@ -618,7 +610,6 @@ - - extern const bfd_arch_info_type bfd_aarch64_arch; - extern const bfd_arch_info_type bfd_alpha_arch; --extern const bfd_arch_info_type bfd_sw_64_arch; - extern const bfd_arch_info_type bfd_arc_arch; - extern const bfd_arch_info_type bfd_arm_arch; - extern const bfd_arch_info_type bfd_avr_arch; -@@ -708,9 +699,6 @@ - #else - &bfd_aarch64_arch, - &bfd_alpha_arch, --#ifdef TARGET_SW_64 -- &bfd_sw_64_arch, --#endif - &bfd_arc_arch, - &bfd_arm_arch, - &bfd_avr_arch, ---- b/bfd/bfd-in2.h -+++ a/bfd/bfd-in2.h -@@ -1680,11 +1680,6 @@ - #define bfd_mach_alpha_ev4 0x10 - #define bfd_mach_alpha_ev5 0x20 - #define bfd_mach_alpha_ev6 0x30 --#ifdef TARGET_SW_64 -- bfd_arch_sw_64, /* Sw_64 */ --#define bfd_mach_sw_64_sw6a 4 --#define bfd_mach_sw_64_sw6b 8 --#endif - bfd_arch_arm, /* Advanced Risc Machines ARM. */ - #define bfd_mach_arm_unknown 0 - #define bfd_mach_arm_2 1 -@@ -2523,110 +2518,6 @@ - BFD_RELOC_ALPHA_TPREL_LO16, - BFD_RELOC_ALPHA_TPREL16, - --#ifdef TARGET_SW_64 --/* Sw_64 ECOFF and ELF 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_SW_64_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_SW_64_GPDISP_LO16, -- --/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16 --relocation except that there is no accompanying GPDISP_LO16 --relocation. */ -- BFD_RELOC_SW_64_GPDISP, -- --/* The Sw_64 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 ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16. --It should refer to the symbol to be referenced, as with 16_GOTOFF, --but it generates output not based on the position within the .got --section, but relative to the GP value chosen for the file during the --final link stage. -- --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) */ -- BFD_RELOC_SW_64_LITERAL, -- BFD_RELOC_SW_64_ELF_LITERAL, -- BFD_RELOC_SW_64_ELF_LITERAL_GOT, -- BFD_RELOC_SW_64_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_SW_64_HINT, -- --/* The LINKAGE relocation outputs a linkage pair in the object file, --which is filled by the linker. */ -- BFD_RELOC_SW_64_LINKAGE, -- --/* The CODEADDR relocation outputs a STO_CA in the object file, --which is filled by the linker. */ -- BFD_RELOC_SW_64_CODEADDR, -- --/* The GPREL_HI/LO relocations together form a 32-bit offset from the --GP register. */ -- BFD_RELOC_SW_64_GPREL_HI16, -- BFD_RELOC_SW_64_GPREL_LO16, -- --/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must --share a common GP, and the target address is adjusted for --STO_SW_64_STD_GPLOAD. */ -- BFD_RELOC_SW_64_BRSGP, -- --/* The NOP relocation outputs a NOP if the longword displacement --between two procedure entry points is < 2^21. */ -- BFD_RELOC_SW_64_NOP, -- --/* The BSR relocation outputs a BSR if the longword displacement --between two procedure entry points is < 2^21. */ -- BFD_RELOC_SW_64_BSR, -- --/* The LDA relocation outputs a LDA if the longword displacement --between two procedure entry points is < 2^16. */ -- BFD_RELOC_SW_64_LDA, -- --/* The BOH relocation outputs a BSR if the longword displacement --between two procedure entry points is < 2^21, or else a hint. */ -- BFD_RELOC_SW_64_BOH, -- --/* Sw_64 thread-local storage relocations. */ -- BFD_RELOC_SW_64_TLSGD, -- BFD_RELOC_SW_64_TLSLDM, -- BFD_RELOC_SW_64_DTPMOD64, -- BFD_RELOC_SW_64_GOTDTPREL16, -- BFD_RELOC_SW_64_DTPREL64, -- BFD_RELOC_SW_64_DTPREL_HI16, -- BFD_RELOC_SW_64_DTPREL_LO16, -- BFD_RELOC_SW_64_DTPREL16, -- BFD_RELOC_SW_64_GOTTPREL16, -- BFD_RELOC_SW_64_TPREL64, -- BFD_RELOC_SW_64_TPREL_HI16, -- BFD_RELOC_SW_64_TPREL_LO16, -- BFD_RELOC_SW_64_TPREL16, -- BFD_RELOC_SW_64_BR26, --#endif -- - /* The MIPS jump instruction. */ - BFD_RELOC_MIPS_JMP, - BFD_RELOC_MICROMIPS_JMP, ---- b/bfd/config.bfd -+++ a/bfd/config.bfd -@@ -165,7 +165,6 @@ - case "${targ_cpu}" in - aarch64*) targ_archs="bfd_aarch64_arch bfd_arm_arch";; - alpha*) targ_archs=bfd_alpha_arch ;; --sw_64*) targ_archs=bfd_sw_64_arch ;; - am33_2.0*) targ_archs=bfd_mn10300_arch ;; - arc*) targ_archs=bfd_arc_arch ;; - arm*) targ_archs=bfd_arm_arch ;; -@@ -300,55 +299,6 @@ - targ_defvec=alpha_ecoff_le_vec - want64=true - ;; -- sw_64*-*-freebsd* | sw_64*-*-kfreebsd*-gnu) -- targ_defvec=sw_64_elf64_fbsd_vec -- targ_selvecs="sw_64_elf64_vec sw_64_ecoff_le_vec" -- want64=true -- # FreeBSD <= 4.0 supports only the old nonstandard way of ABI labelling. -- case "${targ}" in -- sw_64*-*-freebsd3* | sw_64*-*-freebsd4 | sw_64*-*-freebsd4.0*) -- targ_cflags=-DOLD_FREEBSD_ABI_LABEL ;; -- esac -- ;; -- sw_64*-*-netbsd* | sw_64*-*-openbsd*) -- targ_defvec=sw_64_elf64_vec -- targ_selvecs=sw_64_ecoff_le_vec -- want64=true -- ;; -- sw_64*-*-netware*) -- targ_defvec=sw_64_ecoff_le_vec -- targ_selvecs=sw_64_nlm32_vec -- want64=true -- ;; -- sw_64*-*-linux*ecoff*) -- targ_defvec=sw_64_ecoff_le_vec -- targ_selvecs=sw_64_elf64_vec -- want64=true -- ;; -- sw_64-*-linux-* | sw_64-*-elf*) -- targ_defvec=sw_64_elf64_vec -- targ_selvecs=sw_64_ecoff_le_vec -- want64=true -- ;; -- sw_64sw6a-*-linux-* | sw_64sw6a-*-elf*) -- targ_defvec=sw_64_elf64_vec -- targ_selvecs=sw_64_ecoff_le_vec -- want64=true -- ;; -- sw_64sw6b-*-linux-* | sw_64sw6b-*-elf*) -- targ_defvec=sw_64_elf64_vec -- targ_selvecs=sw_64_ecoff_le_vec -- want64=true -- ;; -- sw_64*-*-*vms*) -- targ_defvec=sw_64_vms_vec -- targ_selvecs=sw_64_vms_lib_txt_vec -- want64=true -- ;; -- sw_64*-*-*) -- targ_defvec=sw_64_ecoff_le_vec -- want64=true -- ;; - ia64*-*-freebsd* | ia64*-*-netbsd* | ia64*-*-linux-* | ia64*-*-elf* | ia64*-*-kfreebsd*-gnu) - targ_defvec=ia64_elf64_le_vec - targ_selvecs="ia64_elf64_be_vec ia64_pei_vec" ---- b/bfd/config.in -+++ a/bfd/config.in -@@ -341,5 +341,3 @@ - - /* Use structured /proc on Solaris. */ - #undef _STRUCTURED_PROC -- --#undef TARGET_SW_64 ---- b/bfd/configure -+++ a/bfd/configure -@@ -11907,11 +11907,6 @@ - ac_default_ld_z_separate_code=1 - fi - ;; --sw_64-*-linux-*) --cat >>confdefs.h <<_ACEOF --#define TARGET_SW_64 --_ACEOF -- ;; - esac - if test "${ac_default_ld_z_separate_code}" = unset; then - ac_default_ld_z_separate_code=0 -@@ -13292,12 +13287,6 @@ - alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; - alpha_vms_vec) tb="$tb vms-alpha.lo vms-misc.lo vms-lib.lo"; target_size=64 ;; - alpha_vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;; -- sw_64_ecoff_le_vec) tb="$tb coff-sw_64.lo ecoff.lo $ecoff"; target_size=64 ;; -- sw_64_elf64_vec) tb="$tb elf64-sw_64.lo elf64.lo $elf"; target_size=64 ;; -- sw_64_elf64_fbsd_vec) tb="$tb elf64-sw_64.lo elf64.lo $elf"; target_size=64 ;; -- sw_64_nlm32_vec) tb="$tb nlm32-sw_64.lo nlm32.lo nlm.lo"; target_size=64 ;; -- sw_64_vms_vec) tb="$tb vms-sw_64.lo vms-misc.lo vms-lib.lo"; target_size=64 ;; -- sw_64_vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;; - am33_elf32_linux_vec) tb="$tb elf32-am33lin.lo elf32.lo $elf" ;; - aout0_be_vec) tb="$tb aout0.lo aout32.lo" ;; - aout64_vec) tb="$tb demo64.lo aout64.lo"; target_size=64 ;; -@@ -13712,19 +13701,6 @@ - alpha*-*-*) - COREFILE=osf-core.lo - ;; -- sw_64*-*-freebsd* | sw_64*-*-kfreebsd*-gnu | sw_64*-*-*vms*) -- COREFILE='' -- ;; -- sw_64*-*-linux-*) -- COREFILE=trad-core.lo -- TRAD_HEADER='"hosts/sw_64linux.h"' -- ;; -- sw_64*-*-netbsd* | sw_64*-*-openbsd*) -- COREFILE=netbsd-core.lo -- ;; -- sw_64*-*-*) -- COREFILE=osf-core.lo -- ;; - arm-*-freebsd* | arm-*-kfreebsd*-gnu) - COREFILE='' ;; - arm*-*-netbsd* | arm-*-openbsd*) ---- b/bfd/configure.ac -+++ a/bfd/configure.ac -@@ -443,12 +443,6 @@ - alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; - alpha_vms_vec) tb="$tb vms-alpha.lo vms-misc.lo vms-lib.lo"; target_size=64 ;; - alpha_vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;; -- sw_64_ecoff_le_vec) tb="$tb coff-sw_64.lo ecoff.lo $ecoff"; target_size=64 ;; -- sw_64_elf64_vec) tb="$tb elf64-sw_64.lo elf64.lo $elf"; target_size=64 ;; -- sw_64_elf64_fbsd_vec) tb="$tb elf64-sw_64.lo elf64.lo $elf"; target_size=64 ;; -- sw_64_nlm32_vec) tb="$tb nlm32-sw_64.lo nlm32.lo nlm.lo"; target_size=64 ;; -- sw_64_vms_vec) tb="$tb vms-sw_64.lo vms-misc.lo vms-lib.lo"; target_size=64 ;; -- sw_64_vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;; - am33_elf32_linux_vec) tb="$tb elf32-am33lin.lo elf32.lo $elf" ;; - aout0_be_vec) tb="$tb aout0.lo aout32.lo" ;; - aout64_vec) tb="$tb demo64.lo aout64.lo"; target_size=64 ;; ---- b/bfd/configure.com -+++ a/bfd/configure.com -@@ -26,10 +26,9 @@ - $ arch=F$GETSYI("ARCH_NAME") - $ arch=F$EDIT(arch,"LOWERCASE") - $if arch .eqs. "alpha" then target = "alpha" --$if arch .eqs. "sw_64" then target = "sw_64" - $if arch .eqs. "ia64" then target = "ia64" - $! -+$if (arch .eqs. "alpha") .or. (arch .eqs. "ia64") --$if (arch .eqs. "alpha") .or. (arch .eqs. "ia64") .or. (arch .eqs. "sw_64") - $then - $! - $ write sys$output "Configuring BFD for ''target' target" -@@ -329,15 +328,6 @@ - $ FILES="cpu-alpha,vms,vms-hdr,vms-gsd,vms-tir,vms-misc," - $EOD - $ endif --$ if ARCH.eqs."sw_64" --$ then --$ create build.com --$DECK --$ DEFS="""SELECT_VECS=&sw_64_vms_vec"","+- -- """SELECT_ARCHITECTURES=&bfd_sw_64_arch""" --$ FILES="cpu-sw_64,vms,vms-hdr,vms-gsd,vms-tir,vms-misc," --$EOD --$ endif - $ if ARCH.eqs."ia64" - $ then - $ create build.com ---- b/bfd/ecoff.c -+++ a/bfd/ecoff.c -@@ -202,12 +202,6 @@ - mach = 0; - break; - --#ifdef TARGET_SW_64 -- case SW_64_MAGIC: -- arch = bfd_arch_sw_64; -- mach = 0; -- break; --#endif - default: - arch = bfd_arch_obscure; - mach = 0; -@@ -261,9 +255,6 @@ - case bfd_arch_alpha: - return ALPHA_MAGIC; - -- case bfd_arch_sw_64: -- return SW_64_MAGIC; -- - default: - abort (); - return 0; ---- b/bfd/elf-bfd.h -+++ a/bfd/elf-bfd.h -@@ -496,9 +496,6 @@ - { - AARCH64_ELF_DATA = 1, - ALPHA_ELF_DATA, --#ifdef TARGET_SW_64 -- SW_64_ELF_DATA, --#endif - ARC_ELF_DATA, - ARM_ELF_DATA, - AVR_ELF_DATA, ---- b/bfd/elf.c -+++ a/bfd/elf.c -@@ -11013,9 +11013,6 @@ - - case bfd_arch_aarch64: - case bfd_arch_alpha: --#ifdef TARGET_SW_64 -- case bfd_arch_sw_64: --#endif - case bfd_arch_sparc: - switch (note->type) - { ---- b/bfd/elflink.c -+++ a/bfd/elflink.c -@@ -4106,16 +4106,6 @@ - } - - ehdr = elf_elfheader (abfd); --#ifdef TARGET_SW_64 -- if(ehdr->e_machine != 0x9916) -- { -- char obj_elf_path[4096]={0}; -- char obj_buff[4094]; -- readlink("/proc/sel/exe",obj_elf_path,4096); -- sprintf(obj_buff,"fail to load_symbols %s,process_name %s\n",abfd->filename,obj_elf_path); -- //syslog(LOG_ALERT,obj_buff,strlen(obj_buff)); -- } --#endif - if (info->warn_alternate_em - && bed->elf_machine_code != ehdr->e_machine - && ((bed->elf_machine_alt1 != 0 -@@ -5932,19 +5922,6 @@ - if (!bfd_link_add_symbols (element, info)) - goto error_return; - --#ifdef TARGET_SW_64 -- Elf_Internal_Ehdr *archive_ehdrp; /* Elf file header, internal form. */ -- archive_ehdrp = elf_elfheader (element); -- if(archive_ehdrp->e_machine != 0x9916) -- { -- char archive_elf_path[4096]={0}; -- char archive_buff[4096]; -- readlink("/proc/sel/exe",archive_elf_path,4096); -- sprintf(archive_buff,"fail to load_symbols %s,process_name %s\n",element->filename,archive_elf_path); -- //syslog(LOG_ALERT,archive_buff,strlen(archive_buff)); -- } --#endif -- - /* 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 ---- b/bfd/libbfd-in.h -+++ a/bfd/libbfd-in.h -@@ -424,12 +424,8 @@ - (bfd *) ATTRIBUTE_HIDDEN; - extern bfd_cleanup _bfd_vms_lib_ia64_archive_p - (bfd *) ATTRIBUTE_HIDDEN; --extern const bfd_target *_bfd_vms_lib_sw_64_archive_p -- (bfd *) ATTRIBUTE_HIDDEN; - extern bool _bfd_vms_lib_alpha_mkarchive - (bfd *) ATTRIBUTE_HIDDEN; --extern bfd_boolean _bfd_vms_lib_sw_64_mkarchive -- (bfd *) ATTRIBUTE_HIDDEN; - extern bool _bfd_vms_lib_ia64_mkarchive - (bfd *) ATTRIBUTE_HIDDEN; - ---- b/bfd/libbfd.h -+++ a/bfd/libbfd.h -@@ -1214,34 +1214,6 @@ - "BFD_RELOC_ALPHA_TPREL_HI16", - "BFD_RELOC_ALPHA_TPREL_LO16", - "BFD_RELOC_ALPHA_TPREL16", --#ifdef TARGET_SW_64 -- "BFD_RELOC_SW_64_GPDISP_HI16", -- "BFD_RELOC_SW_64_GPDISP_LO16", -- "BFD_RELOC_SW_64_GPDISP", -- "BFD_RELOC_SW_64_LITERAL", -- "BFD_RELOC_SW_64_ELF_LITERAL", -- "BFD_RELOC_SW_64_LITUSE", -- "BFD_RELOC_SW_64_HINT", -- "BFD_RELOC_SW_64_LINKAGE", -- "BFD_RELOC_SW_64_CODEADDR", -- "BFD_RELOC_SW_64_GPREL_HI16", -- "BFD_RELOC_SW_64_GPREL_LO16", -- "BFD_RELOC_SW_64_BRSGP" -- "BFD_RELOC_SW_64_NOP", -- "BFD_RELOC_SW_64_BSR", -- "BFD_RELOC_SW_64_LDA", -- "BFD_RELOC_SW_64_BOH", -- "BFD_RELOC_SW_64_TLSGD", -- "BFD_RELOC_SW_64_TLSLDM", -- "BFD_RELOC_SW_64_DTPMOD64", -- "BFD_RELOC_SW_64_GOTDTPREL16", -- "BFD_RELOC_SW_64_DTPREL64", -- "BFD_RELOC_SW_64_DTPREL_HI16", -- "BFD_RELOC_SW_64_DTPREL_LO16", -- "BFD_RELOC_SW_64_DTPREL16", -- "BFD_RELOC_SW_64_GOTTPREL16", -- "BFD_RELOC_SW_64_TPREL64", --#endif - "BFD_RELOC_MIPS_JMP", - "BFD_RELOC_MICROMIPS_JMP", - "BFD_RELOC_MIPS16_JMP", ---- b/bfd/makefile.vms -+++ a/bfd/makefile.vms -@@ -36,13 +36,6 @@ - DEFS=SELECT_VECS="&alpha_vms_vec",SELECT_ARCHITECTURES="&bfd_alpha_arch" - endif - --ifeq ($(ARCH),SW_64) --HOSTFILE=sw_64vms.h --OBJS:=vms-sw_64.obj,vms-lib.obj,vms-misc.obj,cpu-sw_64.obj --DEFS=SELECT_VECS="&sw_64_vms_vec",SELECT_ARCHITECTURES="&bfd_sw_64_arch" --endif -- -- - OBJS:=$(OBJS),archive.obj,archive64.obj,archures.obj,bfd.obj,bfdio.obj,\ - binary.obj,cache.obj,coffgen.obj,compress.obj,corefile.obj,dwarf2.obj,\ - elf.obj,format.obj,hash.obj,ihex.obj,init.obj,libbfd.obj,linker.obj,\ ---- b/bfd/peicode.h -+++ a/bfd/peicode.h -@@ -1176,10 +1176,6 @@ - case IMAGE_FILE_MACHINE_UNKNOWN: - case IMAGE_FILE_MACHINE_ALPHA: - case IMAGE_FILE_MACHINE_ALPHA64: --#ifdef TARGET_SW_64 -- case IMAGE_FILE_MACHINE_SW_64: -- case IMAGE_FILE_MACHINE_SW_6464: --#endif - case IMAGE_FILE_MACHINE_IA64: - break; - ---- b/bfd/targets.c -+++ a/bfd/targets.c -@@ -685,14 +685,6 @@ - extern const bfd_target alpha_elf64_fbsd_vec; - extern const bfd_target alpha_vms_vec; - extern const bfd_target alpha_vms_lib_txt_vec; --#ifdef TARGET_SW_64 --extern const bfd_target sw_64_ecoff_le_vec; --extern const bfd_target sw_64_elf64_vec; --extern const bfd_target sw_64_elf64_fbsd_vec; --extern const bfd_target sw_64_nlm32_vec; --extern const bfd_target sw_64_vms_vec; --extern const bfd_target sw_64_vms_lib_txt_vec; --#endif - extern const bfd_target am33_elf32_linux_vec; - extern const bfd_target aout_vec; - extern const bfd_target arc_elf32_be_vec; -@@ -1011,15 +1003,6 @@ - #endif - &alpha_vms_lib_txt_vec, - --#ifdef BFD64 -- &sw_64_ecoff_le_vec, -- &sw_64_elf64_vec, -- &sw_64_elf64_fbsd_vec, -- &sw_64_nlm32_vec, -- &sw_64_vms_vec, --#endif -- &sw_64_vms_lib_txt_vec, -- - &am33_elf32_linux_vec, - - #if 0 ---- b/binutils/config.in -+++ a/binutils/config.in -@@ -260,5 +260,3 @@ - - /* Define to 1 if you need to in order for `stat' and other things to work. */ - #undef _POSIX_SOURCE -- --#undef TARGET_SW_64 ---- b/binutils/configure -+++ a/binutils/configure -@@ -14614,11 +14614,6 @@ - mep-*) - OBJDUMP_DEFS="-DSKIP_ZEROES=256 -DSKIP_ZEROES_AT_END=0" - ;; -- sw_64-*-*) --cat >>confdefs.h <<_ACEOF --#define TARGET_SW_64 --_ACEOF -- ;; - esac - - # Add objdump private vectors. ---- b/binutils/configure.com -+++ a/binutils/configure.com -@@ -84,7 +84,6 @@ - $! - $ if arch .eqs. "ia64" then target = "elf64-ia64-vms" - $ if arch .eqs. "alpha" then target = "vms-alpha" --$ if arch .eqs. "sw_64" then target = "vms-sw_64" - $ if arch .eqs. "vax" then target = "vms-vax" - $! - $ open/append tfile config.h ---- b/binutils/readelf.c -+++ a/binutils/readelf.c -@@ -91,9 +91,6 @@ - - #include "elf/aarch64.h" - #include "elf/alpha.h" --#ifdef TARGET_SW_64 --#include "elf/sw_64.h" --#endif - #include "elf/arc.h" - #include "elf/arm.h" - #include "elf/avr.h" -@@ -1024,9 +1021,6 @@ - case EM_AARCH64: - case EM_ADAPTEVA_EPIPHANY: - case EM_ALPHA: --#ifdef TARGET_SW_64 -- case EM_SW_64: --#endif - case EM_ALTERA_NIOS2: - case EM_ARC: - case EM_ARC_COMPACT: -@@ -1623,12 +1617,6 @@ - rtype = elf_alpha_reloc_type (type); - break; - --#ifdef TARGET_SW_64 -- case EM_SW_64: -- rtype = elf_sw_64_reloc_type (type); -- break; --#endif -- - case EM_ARM: - rtype = elf_arm_reloc_type (type); - break; -@@ -1845,35 +1833,6 @@ - res = false; - } - } --#ifdef TARGET_SW_64 -- else if (filedata->file_header.e_machine == EM_SW_64 -- && rtype != NULL -- && streq (rtype, "R_SW_64_LITUSE") -- ) -- //&& is_rela) -- { -- switch (rels[i].r_addend) -- { -- case LITUSE_SW_64_ADDR: rtype = "ADDR"; break; -- case LITUSE_SW_64_BASE: rtype = "BASE"; break; -- case LITUSE_SW_64_BYTOFF: rtype = "BYTOFF"; break; -- case LITUSE_SW_64_JSR: rtype = "JSR"; break; -- case LITUSE_SW_64_TLSGD: rtype = "TLSGD"; break; -- case LITUSE_SW_64_TLSLDM: rtype = "TLSLDM"; break; -- case LITUSE_SW_64_JSRDIRECT: rtype = "JSRDIRECT"; break; -- default: rtype = NULL; -- } -- if (rtype) -- printf (" (%s)", rtype); -- else -- { -- putchar (' '); -- printf (_(""), -- (unsigned long) rels[i].r_addend); -- res = false; -- } -- } --#endif - else if (symtab_index) - { - if (symtab == NULL || symtab_index >= nsyms) -@@ -2279,18 +2238,6 @@ - } - } - --#ifdef TARGET_SW_64 --static const char * --get_sw_64_dynamic_type (unsigned long type) --{ -- switch (type) -- { -- case DT_SW_64_PLTRO: return "SW_64_PLTRO"; -- default: return NULL; -- } --} --#endif -- - static const char * - get_score_dynamic_type (unsigned long type) - { -@@ -2481,11 +2428,6 @@ - case EM_ALPHA: - result = get_alpha_dynamic_type (type); - break; --#ifdef TARGET_SW_64 -- case EM_SW_64: -- result = get_sw_64_dynamic_type (type); -- break; --#endif - case EM_SCORE: - result = get_score_dynamic_type (type); - break; -@@ -2903,9 +2845,6 @@ - /* Large numbers... */ - case EM_MT: return "Morpho Techologies MT processor"; - case EM_ALPHA: return "Alpha"; --#ifdef TARGET_SW_64 -- case EM_SW_64: return "Sw_64"; --#endif - case EM_WEBASSEMBLY: return "Web Assembly"; - case EM_DLX: return "OpenDLX"; - case EM_XSTORMY16: return "Sanyo XStormy16 CPU core"; -@@ -12416,21 +12355,6 @@ - } - } - --#ifdef TARGET_SW_64 --static const char * --get_sw_64_symbol_other (unsigned int other) --{ -- switch (other) -- { -- case STO_SW_64_NOPV: return "NOPV"; -- case STO_SW_64_STD_GPLOAD: return "STD GPLOAD"; -- default: -- error (_("Unrecognized sw_64 specific other value: %u"), other); -- return _(""); -- } --} --#endif -- - static const char * - get_solaris_symbol_visibility (unsigned int visibility) - { -@@ -12573,11 +12497,6 @@ - case EM_ALPHA: - result = get_alpha_symbol_other (other); - break; --#ifdef TARGET_SW_64 -- case EM_SW_64: -- result = get_sw_64_symbol_other (other); -- break; --#endif - case EM_AARCH64: - result = get_aarch64_symbol_other (other); - break; -@@ -13871,10 +13790,6 @@ - return reloc_type == 3; - case EM_ALPHA: - return reloc_type == 1; /* R_ALPHA_REFLONG. */ --#ifdef TARGET_SW_64 -- case EM_SW_64: -- return reloc_type == 1; /* R_SW_64_REFLONG. */ --#endif - case EM_ARC: - return reloc_type == 1; /* R_ARC_32. */ - case EM_ARC_COMPACT: -@@ -14072,10 +13987,6 @@ - return reloc_type == 6; - case EM_ALPHA: - return reloc_type == 10; /* R_ALPHA_SREL32. */ --#ifdef TARGET_SW_64 -- case EM_SW_64: -- return reloc_type == 10; /* R_SW_64_SREL32. */ --#endif - case EM_ARC_COMPACT: - case EM_ARC_COMPACT2: - return reloc_type == 49; /* R_ARC_32_PCREL. */ -@@ -14144,10 +14055,6 @@ - return reloc_type == 257; /* R_AARCH64_ABS64. */ - case EM_ALPHA: - return reloc_type == 2; /* R_ALPHA_REFQUAD. */ --#ifdef TARGET_SW_64 -- case EM_SW_64: -- return reloc_type == 2; /* R_SW_64_REFQUAD. */ --#endif - case EM_IA_64: - return (reloc_type == 0x26 /* R_IA64_DIR64MSB. */ - || reloc_type == 0x27 /* R_IA64_DIR64LSB. */); -@@ -14190,10 +14097,6 @@ - return reloc_type == 260; /* R_AARCH64_PREL64. */ - case EM_ALPHA: - return reloc_type == 11; /* R_ALPHA_SREL64. */ --#ifdef TARGET_SW_64 -- case EM_SW_64: -- return reloc_type == 11; /* R_SW_64_SREL64. */ --#endif - case EM_IA_64: - return (reloc_type == 0x4e /* R_IA64_PCREL64MSB. */ - || reloc_type == 0x4f /* R_IA64_PCREL64LSB. */); -@@ -14499,9 +14402,6 @@ - case EM_68K: /* R_68K_NONE. */ - case EM_ADAPTEVA_EPIPHANY: - case EM_ALPHA: /* R_ALPHA_NONE. */ --#ifdef TARGET_SW_64 -- case EM_SW_64: /* R_SW_64_NONE. */ --#endif - case EM_ALTERA_NIOS2: /* R_NIOS2_NONE. */ - case EM_ARC: /* R_ARC_NONE. */ - case EM_ARC_COMPACT2: /* R_ARC_NONE. */ -@@ -20139,9 +20039,6 @@ - - case EM_OLD_ALPHA: - case EM_ALPHA: --#ifdef TARGET_SW_64 -- case EM_SW_64: --#endif - case EM_SPARC: - case EM_SPARC32PLUS: - case EM_SPARCV9: ---- b/binutils/testsuite/binutils-all/nm.exp -+++ a/binutils/testsuite/binutils-all/nm.exp -@@ -44,7 +44,7 @@ - - # 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*" -- setup_xfail "alpha*-*-osf*" "sw_64*-*-ecoff*" - setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" - setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" - -@@ -104,7 +104,7 @@ - - # 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*" -- setup_xfail "alpha*-*-osf*" "sw_64*-*-ecoff*" - setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" - setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" - -@@ -183,7 +183,7 @@ - - # 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*" -- setup_xfail "alpha*-*-osf*" "sw_64*-*-ecoff*" - setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" - setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" - -@@ -263,7 +263,7 @@ - setup_xfail "sh*-*-*" - # The pre-compiled dwarf info in dw4.s is not compatible with the - # ALPHA, HPPA, IA64 and MIPS targets. -+ setup_xfail "alpha*-*-*" "hppa*-*-*" "ia64*-*-*" "mips*-*-*" -- setup_xfail "alpha*-*-*" "sw_64*-*-*" "hppa*-*-*" "ia64*-*-*" "mips*-*-*" - # Assembling the source file triggers an ICE in the FT32 assembler. - # FIXME: Fix the ICE... - setup_xfail "ft32-*-*" -@@ -303,7 +303,7 @@ - # Test nm --ifunc-chars on a indirect symbols. - - # The following targets are known to not support ifuncs. -+ setup_xfail "alpha*-*-*" -- setup_xfail "alpha*-*-*" "sw_64*-*-*" - setup_xfail "arm*-elf" "arm*-*-nto*" "arm*-*-netbsdelf*" - setup_xfail "*-*-hpux*" - setup_xfail "mips*-*-*" "tx39*-*-*" ---- b/binutils/testsuite/binutils-all/objcopy.exp -+++ a/binutils/testsuite/binutils-all/objcopy.exp -@@ -120,7 +120,6 @@ - - # On OSF/1, this succeeds with gas and fails with /bin/as. - setup_xfail "alpha*-*-osf*" -- setup_xfail "sw_64*-*-osf*" - - fail "objcopy $type ($testname)" - } ---- b/binutils/testsuite/binutils-all/objdump.exp -+++ a/binutils/testsuite/binutils-all/objdump.exp -@@ -34,7 +34,7 @@ - set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"] - - set cpus_expected [list] -+lappend cpus_expected aarch64 alpha am33-2 arc ARC700 ARCv2 arm cris --lappend cpus_expected aarch64 alpha sw_64 am33-2 arc ARC700 ARCv2 arm cris - lappend cpus_expected d10v d30v fr30 fr500 fr550 h8 hppa i386 iamcu ip2022 - lappend cpus_expected m16c m32c m32r m68hc11 m68hc12 m68k MCore mep c5 h1 MicroBlaze - lappend cpus_expected mips mn10200 mn10300 ms1 msp MSP430 nds32 n1h_v3 ns32k ---- b/binutils/testsuite/lib/binutils-common.exp -+++ a/binutils/testsuite/lib/binutils-common.exp -@@ -1627,7 +1627,7 @@ - if [istarget "rx-*-elf"] { - return { "P" "D_1" "B_1" } - } -+ if { [istarget "alpha*-*-*vms*"] || [is_som_format] } { -- if { [istarget "alpha*-*-*vms*"] || [istarget "sw_64*-*-*vms*"] || [is_som_format] } { - return { {\$CODE\$} {\$DATA\$} {\$BSS\$} } - } - return ---- b/config.guess -+++ a/config.guess -@@ -355,36 +355,6 @@ - exitcode=$? - trap '' 0 - exit $exitcode ;; -- sw_64:OSF1:*:*) -- case $UNAME_RELEASE in -- *4.0) -- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` -- ;; -- *5.*) -- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` -- ;; -- esac -- # According to Compaq, /usr/sbin/psrinfo has been available on -- # OSF/1 and Tru64 systems produced since 1995. I hope that -- # covers most systems running today. This code pipes the CPU -- # types through head -n 1, so we only detect the type of CPU 0. -- SW_64_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The sw_64 \(.*\) processor.*$/\1/p' | head -n 1` -- case "$SW_64_CPU_TYPE" in -- "SW6A (21264)") -- UNAME_MACHINE="sw_64sw6a" ;; -- "SW6B (21264)") -- UNAME_MACHINE="sw_64sw6b" ;; -- "SW6 (21264A)") -- UNAME_MACHINE="sw_64sw6" ;; -- esac -- # A Pn.n version is a patched version. -- # A Vn.n version is a released version. -- # A Tn.n version is a released field test version. -- # A Xn.n version is an unreleased experimental baselevel. -- # 1.2 uses "1.2" for uname -r. -- OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` -- GUESS=$UNAME_MACHINE-dec-osf$OSF_REL -- ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; -@@ -983,16 +953,6 @@ - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; -- sw_64:Linux:*:*) -- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in -- SW6A) UNAME_MACHINE=sw_64sw6a ;; -- SW6B) UNAME_MACHINE=sw_64sw6b ;; -- SW6) UNAME_MACHINE=sw_64sw6 ;; -- esac -- objdump --private-headers /bin/sh | grep -q ld.so.1 -- if test "$?" = 0 ; then LIBC="gnulibc1" ; fi -- GUESS=$UNAME_MACHINE-unknown-linux-${LIBC} -- ;; - arc:Linux:*:* | arceb:Linux:*:* | arc64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; -@@ -1514,7 +1474,6 @@ - UNAME_MACHINE=$( (uname -p) 2>/dev/null) - case "$UNAME_MACHINE" in - A*) echo alpha-dec-vms ; exit ;; -- S*) echo sw_64-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; ---- b/config.sub -+++ a/config.sub -@@ -1163,7 +1163,6 @@ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ - | alphapca5[67] | alpha64pca5[67] \ -- | sw_64 | sw_64sw6a | sw_64sw6b \ - | am33_2.0 \ - | amdgcn \ - | arc | arceb | arc64 \ ---- b/config/elf.m4 -+++ a/config/elf.m4 -@@ -17,7 +17,7 @@ - case $target in - *-darwin* | *-aix* | *-cygwin* | *-mingw* | *-aout* | *-*coff* | \ - *-msdosdjgpp* | *-vms* | *-wince* | *-*-pe* | \ -+ alpha*-dec-osf* | *-interix* | hppa[[12]]*-*-hpux* | \ -- alpha*-dec-osf* | sw_64*-dec-osf* | *-interix* | hppa[[12]]*-*-hpux* | \ - nvptx-*-none) - target_elf=no - ;; ---- b/config/intdiv0.m4 -+++ a/config/intdiv0.m4 -@@ -56,7 +56,7 @@ - [ - # Guess based on the CPU. - case "$host_cpu" in -+ alpha* | i[34567]86 | m68k | s390*) -- alpha* | sw_64* | i[34567]86 | m68k | s390*) - gt_cv_int_divbyzero_sigfpe="guessing yes";; - *) - gt_cv_int_divbyzero_sigfpe="guessing no";; ---- b/config/picflag.m4 -+++ a/config/picflag.m4 -@@ -20,9 +20,6 @@ - alpha*-dec-osf5*) - # PIC is the default. - ;; -- sw_64*-dec-osf5*) -- # PIC is the default. -- ;; - hppa*64*-*-hpux*) - # PIC is the default for 64-bit PA HP-UX. - ;; ---- b/config/tcl.m4 -+++ a/config/tcl.m4 -@@ -1368,9 +1368,6 @@ - if test "`uname -m`" = "alpha" ; then - CFLAGS="$CFLAGS -mieee" - fi -- if test "`uname -m`" = "sw_64" ; then -- CFLAGS="$CFLAGS -mieee" -- fi - if test $do64bit = yes; then - AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ - hold_cflags=$CFLAGS -@@ -1421,9 +1418,6 @@ - if test "`uname -m`" = "alpha" ; then - CFLAGS="$CFLAGS -mieee" - fi -- if test "`uname -m`" = "sw_64" ; then -- CFLAGS="$CFLAGS -mieee" -- fi - ;; - Lynx*) - SHLIB_CFLAGS="-fPIC" ---- b/configure -+++ a/configure -@@ -778,7 +778,6 @@ - host_makefile_frag - target_makefile_frag - alphaieee_frag --sw_64ieee_frag - ospace_frag' - ac_user_opts=' - enable_option_checking -@@ -3014,7 +3013,7 @@ - *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \ - | *-*-linux* | *-*-gnu* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \ - | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* \ -+ | *-*-solaris2* | *-*-nto* | *-*-nacl*) -- | *-*-solaris2* | *-*-nto* | *-*-nacl* | sw_64-*-*-*) - case "${target}" in - *-*-linux*aout* | *-*-linux*oldld*) - ;; -@@ -3028,7 +3027,7 @@ - # Check for target supported by gold. - case "${target}" in - i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \ -+ | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*) -- | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | sw_64-*-*-*) - configdirs="$configdirs gold" - if test x${ENABLE_GOLD} = xdefault; then - default_ld=gold -@@ -3437,9 +3436,6 @@ - alpha*-*-*vms*) - noconfigdirs="$noconfigdirs target-libffi" - ;; -- sw_64*-*-*vms*) -- noconfigdirs="$noconfigdirs target-libffi" -- ;; - arm*-*-freebsd*) - noconfigdirs="$noconfigdirs target-libffi" - ;; -@@ -3574,9 +3570,6 @@ - alpha*-dec-osf*) - noconfigdirs="$noconfigdirs target-newlib target-libgloss" - ;; -- sw_64*-dec-osf*) -- noconfigdirs="$noconfigdirs target-newlib target-libgloss" -- ;; - i[3456789]86-*-linux*) - # This section makes it possible to build newlib natively on linux. - # If we are using a cross compiler then don't configure newlib. -@@ -3709,18 +3702,6 @@ - # newlib is not 64 bit ready - noconfigdirs="$noconfigdirs target-newlib target-libgloss" - ;; -- sw_64*-dec-osf*) -- # ld works, but does not support shared libraries. -- # gas doesn't generate exception information. -- noconfigdirs="$noconfigdirs gas ld" -- ;; -- sw_64*-*-*vms*) -- noconfigdirs="$noconfigdirs gdb target-newlib target-libgloss" -- ;; -- sw_64*-*-*) -- # newlib is not 64 bit ready -- noconfigdirs="$noconfigdirs target-newlib target-libgloss" -- ;; - sh*-*-pe|mips*-*-pe|*arm-wince-pe) - noconfigdirs="$noconfigdirs tcl tk itcl libgui sim" - ;; -@@ -3984,9 +3965,6 @@ - alpha*-linux*) - host_makefile_frag="config/mh-alpha-linux" - ;; -- sw_64*-linux*) -- host_makefile_frag="config/mh-sw_64-linux" -- ;; - hppa*-hp-hpux10*) - host_makefile_frag="config/mh-pa-hpux10" - ;; -@@ -6381,7 +6359,7 @@ - case $target in - *-darwin* | *-aix* | *-cygwin* | *-mingw* | *-aout* | *-*coff* | \ - *-msdosdjgpp* | *-vms* | *-wince* | *-*-pe* | \ -+ alpha*-dec-osf* | *-interix* | hppa[12]*-*-hpux* | \ -- alpha*-dec-osf* | sw_64*-dec-osf* | *-interix* | hppa[12]*-*-hpux* | \ - nvptx-*-none) - target_elf=no - ;; -@@ -7314,15 +7292,6 @@ - ;; - esac - --sw_64ieee_frag=/dev/null --case $target in -- sw_64*-*-*) -- # This just makes sure to use the -mieee option to build target libs. -- # This should probably be set individually by each library. -- sw_64ieee_frag="config/mt-sw_64ieee" -- ;; --esac -- - # If --enable-target-optspace always use -Os instead of -O2 to build - # the target libraries, similarly if it is not specified, use -Os - # on selected platforms. -@@ -8027,7 +7996,7 @@ - esac - - # Makefile fragments. -+for frag in host_makefile_frag target_makefile_frag alphaieee_frag ospace_frag; --for frag in host_makefile_frag target_makefile_frag alphaieee_frag sw_64ieee_frag ospace_frag; - do - eval fragval=\$$frag - if test $fragval != /dev/null; then ---- b/configure.ac -+++ a/configure.ac -@@ -336,7 +336,7 @@ - *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \ - | *-*-linux* | *-*-gnu* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \ - | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* \ -+ | *-*-solaris2* | *-*-nto* | *-*-nacl*) -- | *-*-solaris2* | *-*-nto* | *-*-nacl* | sw_64-*-*-*) - case "${target}" in - *-*-linux*aout* | *-*-linux*oldld*) - ;; -@@ -350,7 +350,7 @@ - # Check for target supported by gold. - case "${target}" in - i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \ -+ | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*) -- | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | sw_64-*-*-*) - configdirs="$configdirs gold" - if test x${ENABLE_GOLD} = xdefault; then - default_ld=gold -@@ -722,9 +722,6 @@ - alpha*-*-*vms*) - noconfigdirs="$noconfigdirs target-libffi" - ;; -- sw_64*-*-*vms*) -- noconfigdirs="$noconfigdirs target-libffi" -- ;; - arm*-*-freebsd*) - noconfigdirs="$noconfigdirs target-libffi" - ;; -@@ -856,9 +853,6 @@ - alpha*-dec-osf*) - noconfigdirs="$noconfigdirs target-newlib target-libgloss" - ;; -- sw_64*-dec-osf*) -- noconfigdirs="$noconfigdirs target-newlib target-libgloss" -- ;; - i[[3456789]]86-*-linux*) - # This section makes it possible to build newlib natively on linux. - # If we are using a cross compiler then don't configure newlib. -@@ -991,18 +985,6 @@ - # newlib is not 64 bit ready - noconfigdirs="$noconfigdirs target-newlib target-libgloss" - ;; -- sw_64*-dec-osf*) -- # ld works, but does not support shared libraries. -- # gas doesn't generate exception information. -- noconfigdirs="$noconfigdirs gas ld" -- ;; -- sw_64*-*-*vms*) -- noconfigdirs="$noconfigdirs gdb target-newlib target-libgloss" -- ;; -- sw_64*-*-*) -- # newlib is not 64 bit ready -- noconfigdirs="$noconfigdirs target-newlib target-libgloss" -- ;; - sh*-*-pe|mips*-*-pe|*arm-wince-pe) - noconfigdirs="$noconfigdirs tcl tk itcl libgui sim" - ;; -@@ -1247,9 +1229,6 @@ - alpha*-linux*) - host_makefile_frag="config/mh-alpha-linux" - ;; -- sw_64*-linux*) -- host_makefile_frag="config/mh-sw_64-linux" -- ;; - hppa*-hp-hpux10*) - host_makefile_frag="config/mh-pa-hpux10" - ;; -@@ -2629,15 +2608,6 @@ - ;; - esac - --sw_64ieee_frag=/dev/null --case $target in -- sw_64*-*-*) -- # This just makes sure to use the -mieee option to build target libs. -- # This should probably be set individually by each library. -- sw_64ieee_frag="config/mt-sw_64ieee" -- ;; --esac -- - # If --enable-target-optspace always use -Os instead of -O2 to build - # the target libraries, similarly if it is not specified, use -Os - # on selected platforms. -@@ -3337,7 +3307,7 @@ - esac - - # Makefile fragments. -+for frag in host_makefile_frag target_makefile_frag alphaieee_frag ospace_frag; --for frag in host_makefile_frag target_makefile_frag alphaieee_frag sw_64ieee_frag ospace_frag; - do - eval fragval=\$$frag - if test $fragval != /dev/null; then -@@ -3347,7 +3317,6 @@ - AC_SUBST_FILE(host_makefile_frag) - AC_SUBST_FILE(target_makefile_frag) - AC_SUBST_FILE(alphaieee_frag) --AC_SUBST_FILE(sw_64ieee_frag) - AC_SUBST_FILE(ospace_frag) - - # Miscellanea: directories, flags, etc. ---- b/elfcpp/elfcpp.h -+++ a/elfcpp/elfcpp.h -@@ -279,7 +279,6 @@ - EM_FRV = 0x5441, - // Infineon Technologies 16-bit microcontroller with C166-V2 core. - EM_X16X = 0x4688, -- EM_SW_64 = 0x9916, - // Xstorym16 - EM_XSTORMY16 = 0xad45, - // Renesas M32C -@@ -793,7 +792,6 @@ - // symbol in the symbol table. - DT_SPARC_REGISTER = 0x70000001, - -- DT_SW_64_PLTRO = 0x70000000, - // MIPS specific dynamic array tags. - // 32 bit version number for runtime linker interface. - DT_MIPS_RLD_VERSION = 0x70000001, ---- b/gas/Makefile.am -+++ a/gas/Makefile.am -@@ -132,7 +132,6 @@ - TARGET_CPU_CFILES = \ - config/tc-aarch64.c \ - config/tc-alpha.c \ -- config/tc-sw_64.c \ - config/tc-arc.c \ - config/tc-arm.c \ - config/tc-avr.c \ -@@ -208,7 +207,6 @@ - TARGET_CPU_HFILES = \ - config/tc-aarch64.h \ - config/tc-alpha.h \ -- config/tc-sw_64.h \ - config/tc-arc.h \ - config/tc-arm.h \ - config/tc-avr.h \ ---- b/gas/Makefile.in -+++ a/gas/Makefile.in -@@ -521,7 +521,6 @@ - TARGET_CPU_CFILES = \ - config/tc-aarch64.c \ - config/tc-alpha.c \ -- config/tc-sw_64.c \ - config/tc-arc.c \ - config/tc-arm.c \ - config/tc-avr.c \ -@@ -597,7 +596,6 @@ - TARGET_CPU_HFILES = \ - config/tc-aarch64.h \ - config/tc-alpha.h \ -- config/tc-sw_64.h \ - config/tc-arc.h \ - config/tc-arm.h \ - config/tc-avr.h \ -@@ -895,8 +893,6 @@ - config/$(DEPDIR)/$(am__dirstamp) - config/tc-alpha.$(OBJEXT): config/$(am__dirstamp) \ - config/$(DEPDIR)/$(am__dirstamp) --config/tc-sw_64.$(OBJEXT): config/$(am__dirstamp) \ -- config/$(DEPDIR)/$(am__dirstamp) - config/tc-arc.$(OBJEXT): config/$(am__dirstamp) \ - config/$(DEPDIR)/$(am__dirstamp) - config/tc-arm.$(OBJEXT): config/$(am__dirstamp) \ -@@ -1164,7 +1160,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/rx-parse.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-aarch64.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-alpha.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-sw_64.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-arc.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-arm.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-avr.Po@am__quote@ ---- b/gas/as.c -+++ a/gas/as.c -@@ -232,10 +232,9 @@ - if (printed) - return; - printed = 1; -- char *VERSION_SW="2.37-v1.0"; - - fprintf (stderr, _("GNU assembler version %s (%s) using BFD version %s\n"), -+ VERSION, TARGET_ALIAS, BFD_VERSION_STRING); -- VERSION_SW, TARGET_ALIAS, BFD_VERSION_STRING); - } - - #ifdef DEFAULT_FLAG_COMPRESS_DEBUG -@@ -504,8 +503,7 @@ - OPTION_WARN_FATAL, - OPTION_COMPRESS_DEBUG, - OPTION_NOCOMPRESS_DEBUG, -+ OPTION_NO_PAD_SECTIONS /* = STD_BASE + 40 */ -- OPTION_NO_PAD_SECTIONS, /* = STD_BASE + 40 */ -- OPTION_ORG_BACKWARDS - /* When you add options here, check that they do - not collide with OPTION_MD_BASE. See as.h. */ - }; -@@ -583,7 +581,6 @@ - ,{"target-help", no_argument, NULL, OPTION_TARGET_HELP} - ,{"traditional-format", no_argument, NULL, OPTION_TRADITIONAL_FORMAT} - ,{"warn", no_argument, NULL, OPTION_WARN} -- ,{"pal", no_argument, NULL, OPTION_ORG_BACKWARDS} - }; - - /* Construct the option lists from the standard list and the target -@@ -686,12 +683,6 @@ - flag_traditional_format = 1; - break; - --#ifdef TARGET_SW_64 -- case OPTION_ORG_BACKWARDS: -- pal_org_backwrards =1; -- break; --#endif -- - case OPTION_VERSION: - /* This output is intended to follow the GNU standards document. */ - printf (_("GNU assembler %s\n"), BFD_VERSION_STRING); ---- b/gas/as.h -+++ a/gas/as.h -@@ -344,12 +344,6 @@ - - COMMON int do_not_pad_sections_to_alignment; - --#ifdef TARGET_SW_64 --/* Support -pal for hmcode. */ --COMMON int pal_org_backwrards; --#endif -- -- - /* TRUE if we should produce a listing. */ - extern int listing; - ---- b/gas/config.in -+++ a/gas/config.in -@@ -325,12 +325,3 @@ - - /* Define to 1 if you need to in order for `stat' and other things to work. */ - #undef _POSIX_SOURCE -- --/* Default CPU for SW_64 targets. */ --#undef SW_CPU_STRING_DEFAULT -- --/*Define Git verion for elf flags*/ --#undef GIT_REVISION -- --#undef TARGET_SW_64 -- ---- b/gas/config/obj-ecoff.c -+++ a/gas/config/obj-ecoff.c -@@ -128,16 +128,6 @@ - fprmask = alpha_fprmask; - #endif - --#ifdef TC_SW_64 -- sw_64_frob_ecoff_data (); -- -- if (! bfd_ecoff_set_gp_value (stdoutput, sw_64_gp_value)) -- as_fatal (_("Can't set GP value")); -- -- gprmask = sw_64_gprmask; -- fprmask = sw_64_fprmask; --#endif -- - if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask)) - as_fatal (_("Can't set register masks")); - } ---- b/gas/config/obj-elf.c -+++ a/gas/config/obj-elf.c -@@ -40,12 +40,6 @@ - #include "elf/alpha.h" - #endif - --#ifdef TARGET_SW_64 --#ifdef TC_SW_64 --#include "elf/sw_64.h" --#endif --#endif -- - #ifdef TC_MIPS - #include "elf/mips.h" - #endif ---- b/gas/config/obj-elf.h -+++ a/gas/config/obj-elf.h -@@ -43,11 +43,6 @@ - extern int alpha_flag_mdebug; - #endif - --#ifdef TC_SW_64 --#define ECOFF_DEBUGGING (sw_64_flag_mdebug > 0) --extern int sw_64_flag_mdebug; --#endif -- - /* For now, always set ECOFF_DEBUGGING for a MIPS target. */ - #ifdef TC_MIPS - #define ECOFF_DEBUGGING mips_flag_mdebug ---- b/gas/configure -+++ a/gas/configure -@@ -12188,25 +12188,6 @@ - ;; - esac - -- case ${cpu_type} in -- sw_64 | sw_64sw*) -- # Set sw_cpu to the name of the default CPU. -- sw_cpu=$with_cpu -- cpu_types=${with_cpu:2:4} --cat >>confdefs.h <<_ACEOF --#define SW_CPU_STRING_DEFAULT "${with_cpu}" --_ACEOF -- --# Check for git version if there was a github --git_version=`git log -1 --format="%h"` --git_short=${git_version:0:5}${cpu_types}"9" --cat >> confdefs.h <<_ACEOF --#define GIT_REVISION 0x$git_short --#define TARGET_SW_64 --_ACEOF -- ;; -- esac -- - # Do we need the opcodes library? - case ${cpu_type} in - vax | tic30) ---- b/gas/configure.tgt -+++ a/gas/configure.tgt -@@ -49,7 +49,6 @@ - aarch64) cpu_type=aarch64 endian=little arch=aarch64;; - aarch64_be) cpu_type=aarch64 endian=big arch=aarch64;; - alpha*) cpu_type=alpha ;; -- sw_64*) cpu_type=sw_64 ;; - am33_2.0) cpu_type=mn10300 endian=little ;; - arc*eb) cpu_type=arc endian=big ;; - arm*be|arm*b) cpu_type=arm endian=big ;; -@@ -139,13 +138,6 @@ - alpha-*-linux-*) fmt=elf em=linux ;; - alpha-*-netbsd* | alpha-*-openbsd*) fmt=elf em=nbsd ;; - -- sw_64-*-*vms*) fmt=evax ;; -- sw_64-*-osf*) fmt=ecoff ;; -- sw_64-*-linux*ecoff*) fmt=ecoff ;; -- sw_64-*-linux-*) fmt=elf em=linux ;; -- sw_64-*-netbsd*) fmt=elf em=nbsd ;; -- sw_64-*-openbsd*) fmt=elf em=obsd ;; -- - arc-*-elf*) fmt=elf ;; - arc*-*-linux*) fmt=elf bfd_gas=yes ;; - -@@ -443,7 +435,7 @@ - - case ${cpu_type} in - aarch64 | alpha | arm | csky | i386 | ia64 | microblaze | mips | ns32k | \ -+ or1k | or1knd | pdp11 | ppc | riscv | sh | sparc | z80 | z8k) -- or1k | or1knd | pdp11 | ppc | riscv | sh | sparc | z80 | z8k | sw_64) - bfd_gas=yes - ;; - esac ---- b/gas/read.c -+++ a/gas/read.c -@@ -2520,7 +2520,7 @@ - subsegT current_subseg = now_subseg; - segT bss_seg = bss_section; - -+#if defined (TC_MIPS) || defined (TC_ALPHA) --#if defined (TC_MIPS) || defined (TC_ALPHA) || defined (TC_SW_64) - if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour - || OUTPUT_FLAVOR == bfd_target_elf_flavour) - { ---- b/gas/testsuite/gas/all/gas.exp -+++ a/gas/testsuite/gas/all/gas.exp -@@ -57,7 +57,6 @@ - # differences of two previously undefined symbols. Hence this test will - # not pass for these targets. - if { ![istarget alpha*-*-*vms*] -- && ![istarget sw_64*-*-*vms*] - && ![istarget am3*-*-*] - && ![istarget avr-*-*] - && ![istarget ft32-*-*] -@@ -121,8 +120,6 @@ - } - alpha-*-*linux*ecoff { } - alpha-*-osf* { } -- sw_64-*-*linux*ecoff { } -- sw_64-*-osf* { } - hppa*-*-hpux* { } - mep-*-* { } - mmix-*-* { } -@@ -142,7 +139,6 @@ - # pdp11 gets unexpected reloc types. - switch -glob $target_triplet { - alpha*-*-* { } -- sw_64*-*-* { } - am3*-*-* { } - cr16*-*-* { } - crx*-*-* { } -@@ -364,8 +360,6 @@ - switch -glob $target_triplet { - alpha-*-linux*ecoff { } - alpha-*-osf* { } -- sw_64-*-linux*ecoff { } -- sw_64-*-osf* { } - hppa*-*-* { } - *c4x*-*-* { } - *c54x*-*-* { } -@@ -437,7 +431,6 @@ - # .set works differently on some targets. - switch -glob $target_triplet { - alpha*-*-* { } -- sw_64*-*-* { } - mips*-*-* { } - *c54x*-*-* { } - z80-*-* { } ---- b/gas/testsuite/gas/all/weakref1.d -+++ a/gas/testsuite/gas/all/weakref1.d -@@ -4,8 +4,7 @@ - # pdp11 lacks .long - # darwin (mach-o) reverses the order of relocs. - # the following must be present in all weakref1*.d -+#notarget: alpha*-*-osf* *-*-ecoff pdp11-*-aout *-*-darwin* --#notarget: alpha*-*-osf* sw_64*-*-osf* *-*-ecoff pdp11-*-aout *-*-darwin* -- - #xfail: nds32*-*-* - - #... ---- b/gas/testsuite/gas/all/weakref1g.d -+++ a/gas/testsuite/gas/all/weakref1g.d -@@ -4,7 +4,7 @@ - # see weakref1.d for comments on the notargets - # ecoff (OSF/alpha) lacks .weak support - # pdp11 lacks .long -+#notarget: alpha*-*-osf* *-*-ecoff pdp11-*-aout --#notarget: alpha*-*-osf* sw_64*-*-osf* *-*-ecoff pdp11-*-aout - - # the rest of this file is generated with the following script: - # # script begin ---- b/gas/testsuite/gas/all/weakref1l.d -+++ a/gas/testsuite/gas/all/weakref1l.d -@@ -3,7 +3,7 @@ - #source: weakref1.s - # aix drops local symbols - # see weakref1.d for comments on the other notargets -+#notarget: [is_xcoff_format] alpha*-*-osf* *-*-ecoff pdp11-*-aout --#notarget: [is_xcoff_format] alpha*-*-osf* sw_64*-*-osf* *-*-ecoff pdp11-*-aout - - # the rest of this file is generated with the following script: - # # script begin ---- b/gas/testsuite/gas/all/weakref1u.d -+++ a/gas/testsuite/gas/all/weakref1u.d -@@ -3,7 +3,7 @@ - #source: weakref1.s - # aout turns undefined into *ABS* symbols. - # see weakref1.d for comments on the other notargets -+#notarget: *-*-*aout ns32k-*-* alpha*-*-osf* *-*-ecoff --#notarget: *-*-*aout ns32k-*-* alpha*-*-osf* sw_64*-*-osf* *-*-ecoff - - # the rest of this file is generated with the following script: - # # script begin ---- b/gas/testsuite/gas/all/weakref1w.d -+++ a/gas/testsuite/gas/all/weakref1w.d -@@ -2,7 +2,7 @@ - #name: weakref tests, weak undefined syms - #source: weakref1.s - # see weakref1.d for comments on the notargets -+#notarget: alpha*-*-osf* *-*-ecoff pdp11-*-aout --#notarget: alpha*-*-osf* sw_64*-*-osf* *-*-ecoff pdp11-*-aout - - # the rest of this file is generated with the following script: - # # script begin ---- b/gas/testsuite/gas/elf/common5a.d -+++ a/gas/testsuite/gas/elf/common5a.d -@@ -3,5 +3,3 @@ - #error_output: common5a.l - #notarget: alpha-*-* - # The Alpha target uses its own .set pseudo-insn. --#notarget: sw_64-*-* --# The sw_64 target uses its own .set pseudo-insn. ---- b/gas/testsuite/gas/elf/common5b.d -+++ a/gas/testsuite/gas/elf/common5b.d -@@ -3,5 +3,3 @@ - #error_output: common5b.l - #notarget: alpha-*-* - # The Alpha target uses its own .set pseudo-insn. --#notarget: sw_64-*-* --# The sw_64 target uses its own .set pseudo-insn. ---- b/gas/testsuite/gas/elf/common5c.d -+++ a/gas/testsuite/gas/elf/common5c.d -@@ -3,5 +3,3 @@ - #error_output: common5a.l - #notarget: alpha-*-* - # The Alpha target uses its own .set pseudo-insn. --#notarget: sw_64-*-* --# The sw_64 target uses its own .set pseudo-insn. ---- b/gas/testsuite/gas/elf/common5d.d -+++ a/gas/testsuite/gas/elf/common5d.d -@@ -3,5 +3,3 @@ - #error_output: common5b.l - #notarget: alpha-*-* - # The Alpha target uses its own .set pseudo-insn. --#notarget: sw_64-*-* --# The sw_64 target uses its own .set pseudo-insn. ---- b/gas/testsuite/gas/elf/elf.exp -+++ a/gas/testsuite/gas/elf/elf.exp -@@ -164,7 +164,6 @@ - } - switch -glob $target_triplet { - alpha*-*-* { } -- sw_64*-*-* { } - am3*-*-* { } - *c54x*-*-* { } - cr16*-*-* { } -@@ -217,7 +216,7 @@ - run_elf_list_test "section5" "" "-al -Z" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\"" - } - run_dump_test "struct" -+ if { ![istarget "alpha*-*-*"] } then { -- if {! [istarget "alpha*-*-*"] && ! [istarget "sw_64*-*-*"]} then { - # The alpha port uses .set for state, e.g. nomacro. - run_dump_test "symtab" - } -@@ -243,10 +242,7 @@ - run_elf_list_test "type-noifunc" "" "" "-s" "| grep \"1 *\\\[FONTC\\\]\"" - } - } else { -+ run_dump_test ifunc-1 -- #if {! [istarget "sw_64*-*-*"] } then { -- # run_dump_test ifunc-1 -- #} -- run_dump_test ifunc-1 - run_elf_list_test "type" "" "" "-s" "| grep \"1 *\\\[FIONTCU\\\]\"" - run_elf_list_test "type-2" "" "--warn" "-s" "| grep \"0 *\\\[FIONT\\\]\"" - } -@@ -312,9 +308,6 @@ - run_dump_test "bad-group" - run_dump_test "pr27355" - -- #if { ![istarget "sw_64*-*-*"]} then { -- # run_dump_test "syms" -- #} - run_dump_test "syms" - run_dump_test "startof" - -@@ -329,9 +322,6 @@ - run_dump_test "common3b" - run_dump_test "common4a" - run_dump_test "common4b" -- } -- -- if { ![istarget "*-*-hpux*"]} then { - run_dump_test "common5a" - run_dump_test "common5b" - run_dump_test "common5c" ---- b/gas/testsuite/gas/elf/ifunc-1.d -+++ a/gas/testsuite/gas/elf/ifunc-1.d -@@ -1,7 +1,6 @@ - #readelf: -s - #name: .set with IFUNC - #notarget: alpha* --#notarget: sw_64* - - #... - [ ]+[0-9]+:[ ]+[0-9a-f]+[ ]+[0-9]+[ ]+IFUNC[ ]+GLOBAL[ ]+DEFAULT[ ]+[1-9] __GI_foo ---- b/gas/testsuite/gas/elf/symtab.d -+++ a/gas/testsuite/gas/elf/symtab.d -@@ -1,7 +1,6 @@ - # The Alpha has its own version of .set. - # hppa SOM does not output non-global absolute symbols. - #xfail: alpha-*-* [is_som_format] --#xfail: sw_64-*-* [is_som_format] - #readelf: -s - #name: .set with expression - ---- b/gas/write.c -+++ a/gas/write.c -@@ -554,53 +554,6 @@ - info->changed = 1; - } - --#ifdef TARGET_SW_64 --static void --sort_frchain (frag_list) --fragS *frag_list; --{ -- fragS *fragp, *fragc, *fragi; -- long r; -- for (fragp = frag_list;fragp;) -- { -- fragc=fragp; -- if (fragp->fr_next) -- fragp = fragp->fr_next; -- else -- /* the end of the frag_list. */ -- break; -- r = ((long )fragp->fr_address - (long )fragc->fr_address - fragc->fr_fix) ; -- if ( r < 0 ) -- { -- /*adjust the last fill frag's address ,but don't insert back,changed by WCH20080921. */ -- if (fragp->fr_type == rs_fill && fragp->fr_next == 0) -- { -- fragp->fr_address=fragp->last_fr_address=fragc->fr_address+ -- fragc->fr_fix+fragc->fr_offset; -- continue; -- } -- -- fragc->fr_next = fragp->fr_next; -- for (fragi = frag_list; fragi != fragc; fragi=fragi->fr_next) -- { -- r = (fragi->fr_next->fr_address - fragp->fr_address - fragp->fr_fix) ; -- if (r >= 0) -- { -- fragp->fr_next = fragi->fr_next; -- fragi->fr_next = fragp; -- fragp = fragc; -- break; -- } -- } -- if (fragi == fragc) -- { -- as_bad_where (fragp->fr_file,fragp->fr_line,"ERR,can't insert the node!\n"); -- } -- } -- } --} --#endif -- - static void - size_seg (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *xxx ATTRIBUTE_UNUSED) - { -@@ -613,10 +566,6 @@ - subseg_change (sec, 0); - - seginfo = seg_info (sec); --#ifdef TARGET_SW_64 -- if (pal_org_backwrards) -- sort_frchain (seginfo->frchainP->frch_root); --#endif - if (seginfo && seginfo->frchainP) - { - for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next) -@@ -3046,12 +2995,7 @@ - /* Growth may be negative, but variable part of frag - cannot have fewer than 0 chars. That is, we can't - .org backwards. */ -+ if ((offsetT) (address + fragP->fr_fix) > target) -- --#ifdef TARGET_SW_64 -- if (((offsetT) (address + fragP->fr_fix) > target) && !pal_org_backwrards) --#else -- if ((offsetT) (address + fragP->fr_fix) > target) --#endif - { - growth = 0; - ---- b/gold/Makefile.am -+++ a/gold/Makefile.am -@@ -173,13 +173,13 @@ - - TARGETSOURCES = \ - i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc tilegx.cc \ -+ mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc -- mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc sw_64.cc - - ALL_TARGETOBJS = \ - i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \ - arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) \ - mips.$(OBJEXT) aarch64.$(OBJEXT) aarch64-reloc-property.$(OBJEXT) \ -+ s390.$(OBJEXT) -- s390.$(OBJEXT) sw_64.$(OBJEXT) - - libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES) - libgold_a_LIBADD = $(LIBOBJS) ---- b/gold/Makefile.in -+++ a/gold/Makefile.in -@@ -792,13 +792,13 @@ - EXTRA_DIST = yyscript.c yyscript.h - TARGETSOURCES = \ - i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc tilegx.cc \ -+ mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc -- mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc sw_64.cc - - ALL_TARGETOBJS = \ - i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \ - arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) \ - mips.$(OBJEXT) aarch64.$(OBJEXT) aarch64-reloc-property.$(OBJEXT) \ -+ s390.$(OBJEXT) -- s390.$(OBJEXT) sw_64.$(OBJEXT) - - libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES) - libgold_a_LIBADD = $(LIBOBJS) -@@ -1089,7 +1089,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapfile.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/merge.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mips.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sw_64.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nacl.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ ---- b/gold/configure -+++ a/gold/configure -@@ -731,8 +731,6 @@ - DEFAULT_TARGET_ARM_TRUE - DEFAULT_TARGET_AARCH64_FALSE - DEFAULT_TARGET_AARCH64_TRUE --DEFAULT_TARGET_SW_64_FALSE --DEFAULT_TARGET_SW_64_TRUE - PLUGINS_FALSE - PLUGINS_TRUE - installed_linker -@@ -5320,14 +5318,6 @@ - DEFAULT_TARGET_MIPS_FALSE= - fi - -- if test "$targ_obj" = "sw_64"; then -- DEFAULT_TARGET_SW_64_TRUE= -- DEFAULT_TARGET_SW_64_FALSE='#' --else -- DEFAULT_TARGET_SW_64_TRUE='#' -- DEFAULT_TARGET_SW_64_FALSE= --fi -- - DEFAULT_TARGET=${targ_obj} - - fi -@@ -10435,10 +10425,6 @@ - as_fn_error $? "conditional \"AMDEP\" was never defined. - Usually this means the macro was only invoked conditionally." "$LINENO" 5 - fi --if test -z "${DEFAULT_TARGET_SW_64_TRUE}" && test -z "${DEFAULT_TARGET_SW_64_FALSE}"; then -- as_fn_error $? "conditional \"DEFAULT_TARGET_SW_64\" was never defined. --Usually this means the macro was only invoked conditionally." "$LINENO" 5 --fi - if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. - Usually this means the macro was only invoked conditionally." "$LINENO" 5 ---- b/gold/configure.ac -+++ a/gold/configure.ac -@@ -239,7 +239,6 @@ - test "$target_x86_64" = "yes" -o "$target_x32" = "yes") - AM_CONDITIONAL(DEFAULT_TARGET_TILEGX, test "$targ_obj" = "tilegx") - AM_CONDITIONAL(DEFAULT_TARGET_MIPS, test "$targ_obj" = "mips") -- AM_CONDITIONAL(DEFAULT_TARGET_SW_64, test "$targ_obj" = "sw_64") - DEFAULT_TARGET=${targ_obj} - AC_SUBST(DEFAULT_TARGET) - fi ---- b/gold/configure.tgt -+++ a/gold/configure.tgt -@@ -181,12 +181,6 @@ - targ_big_endian=true - targ_extra_big_endian=false - ;; --sw_64*-*-*) -- targ_obj=sw_64 -- targ_machine=EM_SW_64 -- targ_size=64 -- targ_big_endian=false -- ;; - *) - targ_obj=UNKNOWN - ;; ---- b/gold/reloc.h -+++ a/gold/reloc.h -@@ -239,7 +239,6 @@ - RELOC_ADJUST_FOR_SECTION_RELA, - // Like RELOC_ADJUST_FOR_SECTION_RELA but the addend should not be - // adjusted. -- RELOC_ADJUST_FOR_SECTION_RELA_0, - RELOC_ADJUST_FOR_SECTION_0, - // Like RELOC_ADJUST_FOR_SECTION_RELA but the contents of the - // section need to be changed. The number indicates the number of ---- b/gold/target-reloc.h -+++ a/gold/target-reloc.h -@@ -845,7 +845,6 @@ - break; - - case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA: -- case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA_0: - case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0: - case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1: - case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2: -@@ -917,8 +916,7 @@ - - // Handle the reloc addend based on the strategy. - -+ if (strategy == Relocatable_relocs::RELOC_COPY) -- if (strategy == Relocatable_relocs::RELOC_COPY -- || Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA_0 == strategy) - { - if (Classify_reloc::sh_type == elfcpp::SHT_RELA) - Classify_reloc::put_r_addend(&reloc_write, ---- b/include/coff/ecoff.h -+++ a/include/coff/ecoff.h -@@ -47,20 +47,6 @@ - /* A compressed version of an ALPHA_MAGIC file created by DEC's tools. */ - #define ALPHA_MAGIC_COMPRESSED 0x188 - --#ifdef TARGET_SW_64 --/* Sw_64 magic numbers used in filehdr. */ --#define SW_64_MAGIC 0x184 --#define SW_64_MAGIC_BSD 0x187 --/* A compressed version of an SW_64_MAGIC file created by DEC's tools. */ --#define SW_64_MAGIC_COMPRESSED 0x189 --#endif -- --/* Alpha magic numbers used in filehdr. */ --#define SW_64_MAGIC 0x184 --#define SW_64_MAGIC_BSD 0x187 --/* A compressed version of an ALPHA_MAGIC file created by DEC's tools. */ --#define SW_64_MAGIC_COMPRESSED 0x189 -- - /* Magic numbers used in a.out header. */ - #define ECOFF_AOUT_OMAGIC 0407 /* not demand paged (ld -N). */ - #define ECOFF_AOUT_ZMAGIC 0413 /* demand load format, eg normal ld output */ ---- b/include/coff/pe.h -+++ a/include/coff/pe.h -@@ -134,10 +134,6 @@ - #define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 - #define IMAGE_FILE_MACHINE_ALPHA 0x0184 - #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 --#ifdef TARGET_SW_64 --#define IMAGE_FILE_MACHINE_SW_64 0x0184 --#define IMAGE_FILE_MACHINE_SW_6464 0x0284 --#endif - #define IMAGE_FILE_MACHINE_AM33 0x01d3 - #define IMAGE_FILE_MACHINE_AMD64 0x8664 - #define IMAGE_FILE_MACHINE_ARM 0x01c0 ---- b/include/elf/common.h -+++ a/include/elf/common.h -@@ -409,11 +409,6 @@ - /* Alpha backend magic number. Written in the absence of an ABI. */ - #define EM_ALPHA 0x9026 - --#ifdef TARGET_SW_64 --/* Sw_64 backend magic number. Written in the absence of an ABI. */ --#define EM_SW_64 0x9916 --#endif -- - /* Cygnus M32R ELF backend. Written in the absence of an ABI. */ - #define EM_CYGNUS_M32R 0x9041 - ---- b/include/longlong.h -+++ a/include/longlong.h -@@ -191,61 +191,6 @@ - #endif /* __alpha_cix__ */ - #endif /* __alpha */ - --//__sw_64_cix__ --#if defined (__sw_64) && W_TYPE_SIZE == 64 --/* There is a bug in g before version 5 that -- errors on __builtin_sw_64_umulh. */ --#if !defined(__cplusplus) || __GNUC__ >= 5 --#define umul_ppmm(ph, pl, m0, m1) \ -- do { \ -- UDItype __m0 = (m0), __m1 = (m1); \ -- (ph) = __builtin_sw_64_umulh (__m0, __m1); \ -- (pl) = __m0 * __m1; \ -- } while (0) --#define UMUL_TIME 46 --#endif /* !c */ --#ifndef LONGLONG_STANDALONE --#define udiv_qrnnd(q, r, n1, n0, d) \ -- do { UDItype __r; \ -- (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ -- (r) = __r; \ -- } while (0) --extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); --#define UDIV_TIME 220 --#endif /* LONGLONG_STANDALONE */ --#ifdef __sw_64_cix__ --#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clzl (X)) --#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctzl (X)) --#define COUNT_LEADING_ZEROS_0 64 --#else --#define count_leading_zeros(COUNT,X) \ -- do { \ -- UDItype __xr = (X), __t, __a; \ -- __t = __builtin_sw_64_cmpbge (0, __xr); \ -- __a = __clz_tab[__t ^ 0xff] - 1; \ -- __t = __builtin_sw_64_extbl (__xr, __a); \ -- (COUNT) = 64 - (__clz_tab[__t] __a*8); \ -- } while (0) --#define count_trailing_zeros(COUNT,X) \ -- do { \ -- UDItype __xr = (X), __t, __a; \ -- __t = __builtin_sw_64_cmpbge (0, __xr); \ -- __t = ~__t & -~__t; \ -- __a = ((__t & 0xCC) != 0) * 2; \ -- __a = ((__t & 0xF0) != 0) * 4; \ -- __a = ((__t & 0xAA) != 0); \ -- __t = __builtin_sw_64_extbl (__xr, __a); \ -- __a <<= 3; \ -- __t &= -__t; \ -- __a = ((__t & 0xCC) != 0) * 2; \ -- __a = ((__t & 0xF0) != 0) * 4; \ -- __a = ((__t & 0xAA) != 0); \ -- (COUNT) = __a; \ -- } while (0) --#endif /* __sw_64_cix__ */ --#endif /* __sw_64 */ --//sw_64 -- - #if defined (__arc__) && W_TYPE_SIZE == 32 - #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \ ---- b/ld/Makefile.am -+++ a/ld/Makefile.am -@@ -159,8 +159,6 @@ - eaixrs6.c \ - ealpha.c \ - ealphavms.c \ -- esw_64.c \ -- esw_64vms.c \ - earcv2elf.c \ - earcv2elfx.c \ - earcelf.c \ -@@ -431,9 +429,6 @@ - eelf64alpha.c \ - eelf64alpha_fbsd.c \ - eelf64alpha_nbsd.c \ -- eelf64sw_64.c \ -- eelf64sw_64_fbsd.c \ -- eelf64sw_64_nbsd.c \ - eelf64bmip.c \ - eelf64btsmip.c \ - eelf64btsmip_fbsd.c \ -@@ -654,8 +649,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixrs6.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealpha.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealphavms.Pc@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64.Pc@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64vms.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elf.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elfx.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcelf.Pc@am__quote@ -@@ -922,9 +915,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_fbsd.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_nbsd.Pc@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64.Pc@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_fbsd.Pc@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_nbsd.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bmip.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Pc@am__quote@ ---- b/ld/Makefile.in -+++ a/ld/Makefile.in -@@ -648,8 +648,6 @@ - eaixrs6.c \ - ealpha.c \ - ealphavms.c \ -- esw_64.c \ -- esw_64vms.c \ - earcv2elf.c \ - earcv2elfx.c \ - earcelf.c \ -@@ -919,9 +917,6 @@ - eelf64alpha.c \ - eelf64alpha_fbsd.c \ - eelf64alpha_nbsd.c \ -- eelf64sw_64.c \ -- eelf64sw_64_fbsd.c \ -- eelf64sw_64_nbsd.c \ - eelf64bmip.c \ - eelf64btsmip.c \ - eelf64btsmip_fbsd.c \ -@@ -1257,8 +1252,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixrs6.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealpha.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealphavms.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64vms.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcelf.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earclinux.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earclinux_nps.Po@am__quote@ -@@ -1416,9 +1409,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_fbsd.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_nbsd.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_fbsd.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_nbsd.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bmip.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bpf.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv.Po@am__quote@ -@@ -2316,8 +2306,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixrs6.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealpha.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealphavms.Pc@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64.Pc@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64vms.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elf.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elfx.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcelf.Pc@am__quote@ -@@ -2584,11 +2572,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_fbsd.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_nbsd.Pc@am__quote@ --#ifndef LIJM20201117 --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64.Pc@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_fbsd.Pc@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_nbsd.Pc@am__quote@ --#endif - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bmip.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Pc@am__quote@ ---- b/ld/config.in -+++ a/ld/config.in -@@ -241,5 +241,3 @@ - - /* Define to 1 if you need to in order for `stat' and other things to work. */ - #undef _POSIX_SOURCE -- --#undef TARGET_SW_64 ---- b/ld/configure -+++ a/ld/configure -@@ -15376,13 +15376,6 @@ - esac - fi - --case "${target}" in -- sw_64-*-*) --cat >>confdefs.h <<_ACEOF --#define TARGET_SW_64 --_ACEOF -- ;; -- esac - - case "${enable_default_hash_style}" in - sysv | both) ac_default_emit_sysv_hash=1 ;; ---- b/ld/configure.tgt -+++ a/ld/configure.tgt -@@ -102,19 +102,6 @@ - alpha*-*-*vms*) targ_emul=alphavms - targ_extra_ofiles= - ;; --sw_64*-*-linux-* | sw_64*-*-gnu*) -- case "${targ}" in -- sw_64sw6a*) -- targ_emul=elf64sw_64 targ_extra_emuls=sw_64 -- tdir_sw_64=`echo ${targ_alias} | sed -e 's/linux\(-gnu\)*/linux\1ecoff/'` ;; -- sw_64sw6b*) -- targ_emul=elf64sw_64 targ_extra_emuls=sw_64 -- tdir_sw_64=`echo ${targ_alias} | sed -e 's/linux\(-gnu\)*/linux\1ecoff/'` ;; -- *) -- targ_emul=elf64sw_64 targ_extra_emuls=sw_64 -- tdir_sw_64=`echo ${targ_alias} | sed -e 's/linux\(-gnu\)*/linux\1ecoff/'` ;; -- esac -- ;; - am33_2.0-*-linux*) targ_emul=elf32am33lin # mn10300 variant - ;; - arc*-*-elf*) targ_emul=arcelf -@@ -1098,9 +1085,6 @@ - NATIVE_LIB_DIRS='/usr/local/lib /usr/ccs/lib /lib /usr/lib' - ;; - --sw_64*-*-*) -- NATIVE_LIB_DIRS='/usr/local/lib /usr/ccs/lib /lib /usr/lib' -- ;; - esac - - case "${target}" in ---- b/ld/testsuite/config/default.exp -+++ a/ld/testsuite/config/default.exp -@@ -434,26 +434,6 @@ - unset f src - } - --# Provide dummy libraries that sw_64-vms-ld always loads --if { [istarget sw_64*-*-*vms*] } { -- set src tmpdir/empty.s -- set f [open $src "w"] -- close $f -- if { [ld_assemble $as $src tmpdir/empty.o] -- && ![ld_link $LD tmpdir/empty tmpdir/empty.o] -- && [regsub -all {[^\n]*: cannot find -l([^\n]*)} $exec_output {tmpdir/lib\1.a } missing_libs] } { -- regsub -all {\$} $missing_libs {\\\$} missing_libs -- for { set i 0 } { $i < [llength $missing_libs] } { incr i } { -- set f [lindex $missing_libs $i] -- verbose -log "creating dummy $f" -- ar_simple_create $ar {} $f tmpdir/empty.o -- } -- append LDFLAGS " -Ltmpdir" -- unset i missing_libs -- } -- unset f src --} -- - set plug_opt "" - if { [check_compiler_available] } { - set plugin_names { ---- b/ld/testsuite/ld-elf/binutils.exp -+++ a/ld/testsuite/ld-elf/binutils.exp -@@ -88,7 +88,6 @@ - # These targets do not set NO_SMALL_DATA or DATA_GOT and therefore - # have `.got' in (read-write) small data rather than regular data. - set relro_got [expr !([istarget "alpha*-*-*"] \ -- || [istarget "sw_64*-*-*"] \ - || [istarget "hppa*-*-linux-*"] \ - || [istarget "hppa*-*-netbsd*"] \ - || [istarget "hppa*-*-openbsd*"] \ ---- b/ld/testsuite/ld-elf/compress1a.d -+++ a/ld/testsuite/ld-elf/compress1a.d -@@ -2,7 +2,7 @@ - #as: --compress-debug-sections - #ld: -e func_cu2 - #readelf: -S --wide -+#xfail: alpha-*-*ecoff --#xfail: alpha-*-*ecoff sw_64-*-*ecoff - - #failif - #... ---- b/ld/testsuite/ld-elf/compressed1a.d -+++ a/ld/testsuite/ld-elf/compressed1a.d -@@ -2,7 +2,7 @@ - #as: --compress-debug-sections=zlib-gabi - #ld: -e func_cu2 - #readelf: -t -+#xfail: alpha-*-*ecoff --#xfail: alpha-*-*ecoff sw_64-*-*ecoff - - #failif - #... ---- b/ld/testsuite/ld-elf/eh5.d -+++ a/ld/testsuite/ld-elf/eh5.d -@@ -4,7 +4,7 @@ - #ld: - #readelf: -wf - #target: [check_as_cfi] -+#xfail: alpha-*-*ecoff hppa64-*-* tile*-*-* visium-*-* --#xfail: alpha-*-*ecoff sw_64-*-*ecoff hppa64-*-* tile*-*-* visium-*-* - - Contents of the .eh_frame section: - ---- b/ld/testsuite/ld-elf/elf.exp -+++ a/ld/testsuite/ld-elf/elf.exp -@@ -51,7 +51,7 @@ - set ASFLAGS "$ASFLAGS --defsym HPUX=1" - } - -+if { [istarget alpha*-*-* ] } { --+if { [istarget alpha*-*-* ] || [istarget sw_64*-*-*]} { - # The compress1 test is written expecting 32-bit addresses; force the - # executable down into the low address space to match. - # ??? How can we adjust just the one testcase? ---- b/ld/testsuite/ld-elf/pr17550a.d -+++ a/ld/testsuite/ld-elf/pr17550a.d -@@ -3,7 +3,7 @@ - #ld: -r - #readelf: -s --wide - # Disabled on alpha because alpha has a different .set directive. -+#xfail: alpha-*-* --#xfail: alpha-*-* sw_64-*-* - - #failif - #... ---- b/ld/testsuite/ld-elf/pr17550b.d -+++ a/ld/testsuite/ld-elf/pr17550b.d -@@ -3,7 +3,7 @@ - #ld: -r - #readelf: -s --wide - # Disabled on alpha because alpha has a different .set directive. -+#xfail: alpha-*-* --#xfail: alpha-*-* sw_64-*-* - - #failif - #... ---- b/ld/testsuite/ld-elf/pr17550c.d -+++ a/ld/testsuite/ld-elf/pr17550c.d -@@ -5,6 +5,3 @@ - #xfail: alpha-*-* [is_generic] - # Disabled on alpha because alpha has a different .set directive. - # Generic linker targets don't support comdat group sections. --#xfail: sw_64-*-* [is_generic] --# Disabled on sw_64 because sw_64 has a different .set directive. --# Generic linker targets don't support comdat group sections. ---- b/ld/testsuite/ld-elf/pr17550d.d -+++ a/ld/testsuite/ld-elf/pr17550d.d -@@ -5,9 +5,6 @@ - # Disabled on alpha because alpha has a different .set directive. - # Generic linker targets don't support comdat group sections. - #xfail: alpha-*-* [is_generic] --# Disabled on sw_64 because sw_64 has a different .set directive. --# Generic linker targets don't support comdat group sections. --#xfail: sw_64-*-* [is_generic] - - #... - +[0-9]+: +[0-9a-f]+ +0 +OBJECT +GLOBAL +DEFAULT +UND y ---- b/ld/testsuite/ld-elf/pr18720b.c -+++ a/ld/testsuite/ld-elf/pr18720b.c -@@ -9,8 +9,6 @@ - __asm__ (".symver foo,foo@FOO"); - #ifdef __alpha__ - __asm__ ("foo_alias = foo"); --#elif __sw_64__ --__asm__ ("foo_alias = foo"); - #else - __asm__ (".set foo_alias,foo"); - #endif ---- b/ld/testsuite/ld-elf/shared.exp -+++ a/ld/testsuite/ld-elf/shared.exp -@@ -346,7 +346,6 @@ - mips*-*-* { } - tic6x-*-* { } - xtensa-*-* { } -- sw_64-*-* { } - default { - run_ld_link_tests [list \ - [list \ -@@ -465,8 +464,7 @@ - ] - - # These targets don't copy dynamic variables into .bss. -+setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*" --# setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*" --setup_xfail "sw_64-*-*" "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*" - # or don't have .data.rel.ro - setup_xfail "hppa*64*-*-hpux*" "tic6x-*-*" - # or complain about relocs in read-only sections -@@ -486,8 +484,7 @@ - {pr20995c.s} {{readelf {-l --wide} pr20995-2so.r}} "pr20995-2.so"] \ - ] {![check_relro_support]} - -+setup_xfail alpha-*-* xtensa-*-* --# setup_xfail alpha-*-* xtensa-*-* --setup_xfail sw_64-*-* alpha-*-* xtensa-*-* - run_ld_link_tests [list \ - [list \ - "pr20995-2" \ -@@ -503,8 +500,7 @@ - # The next test checks that copy relocs are not used unnecessarily, - # but that is just an optimization so don't complain loudly. - setup_xfail *-*-* -+clear_xfail alpha-*-* bfin-*-linux* csky-*-* frv-*-* hppa*-*-* i?86-*-* --# clear_xfail alpha-*-* bfin-*-linux* csky-*-* frv-*-* hppa*-*-* i?86-*-* --clear_xfail sw_64-*-* alpha-*-* bfin-*-linux* csky-*-* frv-*-* hppa*-*-* i?86-*-* - clear_xfail ia64-*-* microblaze-*-* powerpc*-*-* x86_64-*-* xtensa-*-* - run_ld_link_tests { - {"pr22374 function pointer initialization" -@@ -875,8 +871,7 @@ - ] - - # pr19073.s uses .set, which has a different meaning on alpha. -+if { ![istarget alpha-*-*] } { --# if { ![istarget alpha-*-*] } { --if { ![istarget alpha-*-*] && ![istarget sw_64-*-*] } { - append build_tests { - {"Build pr19073a.o" - "-r -nostdlib" "" ---- b/ld/testsuite/ld-elf/stab.d -+++ a/ld/testsuite/ld-elf/stab.d -@@ -2,7 +2,7 @@ - #as: -gstabs - #readelf: -S --wide - #ld: -+#notarget: "ia64-*-*" "alpha*" --#notarget: "ia64-*-*" "alpha*" "sw_64*" - - # Disabled on alpha because the entry point may be above 4GB but the stabs - # value only 32 bits. ---- b/ld/testsuite/ld-elfvers/vers.exp -+++ a/ld/testsuite/ld-elfvers/vers.exp -@@ -51,7 +51,6 @@ - && ![istarget arm*-*-linux*] - && ![istarget mips*-*-linux*] - && ![istarget alpha*-*-linux*] -- && ![istarget sw_64*-*-linux*] - && ![istarget s390*-*-linux*] - && ![istarget sh\[34\]*-*-linux*] - && ![istarget x86_64-*-linux*] } { ---- b/ld/testsuite/ld-elfvsb/elfvsb.exp -+++ a/ld/testsuite/ld-elfvsb/elfvsb.exp -@@ -42,7 +42,6 @@ - && ![istarget powerpc*-*-linux*] \ - && ![istarget arm*-*-linux*] \ - && ![istarget alpha*-*-linux*] \ -- && ![istarget sw_64*-*-linux*] \ - && ![istarget sparc*-*-linux*] \ - && ![istarget s390*-*-linux*] \ - && ![istarget sh\[34\]*-*-linux*] \ -@@ -268,7 +267,6 @@ - && ![ string match $visibility "protected_undef" ] } { - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -- setup_xfail "sw_64*-*-linux*" - } - if { ![ string match $visibility "hidden" ] - && ![ string match $visibility "hidden_undef" ] -@@ -318,7 +316,6 @@ - && ![ string match $visibility "protected_undef" ] } { - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -- setup_xfail "sw_64*-*-linux*" - setup_xfail "mips*-*-linux*" - } - if { [is_elf64 $tmpdir/mainnp.o] } { -@@ -375,7 +372,6 @@ - && ![ string match $visibility "protected_undef" ] } { - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -- setup_xfail "sw_64*-*-linux*" - } - if { ![ string match $visibility "hidden" ] - && ![ string match $visibility "hidden_undef" ] ---- b/ld/testsuite/ld-elfweak/elfweak.exp -+++ a/ld/testsuite/ld-elfweak/elfweak.exp -@@ -31,7 +31,6 @@ - # Square bracket expressions seem to confuse istarget. - # This is similar to the test that is used in ld-shared, BTW. - if { ![istarget alpha*-*-linux*] -- && ![istarget sw_64*-*-linux*] - && ![istarget arm*-*-linux*] - && ![istarget hppa*64*-*-hpux*] - && ![istarget hppa*-*-linux*] ---- b/ld/testsuite/ld-ifunc/ifunc-26.d -+++ a/ld/testsuite/ld-ifunc/ifunc-26.d -@@ -1,6 +1,6 @@ - #ld: -shared - #readelf: -h -+#xfail: alpha-*-* --#xfail: alpha-*-* sw_64-*-* - - ELF Header: - #... ---- b/ld/testsuite/ld-ifunc/ifunc.exp -+++ a/ld/testsuite/ld-ifunc/ifunc.exp -@@ -25,7 +25,6 @@ - - if { ![is_elf_format] || ![supports_gnu_osabi] - || [istarget alpha-*-*] -- || [istarget sw_64*-*-*] - || [istarget arc*-*-*] - || [istarget am33*-*-*] - || [istarget bfin-*-*] ---- b/ld/testsuite/ld-misc/just-symbols.exp -+++ a/ld/testsuite/ld-misc/just-symbols.exp -@@ -26,8 +26,7 @@ - if { [istarget sh-*-pe] - || [istarget *-*-msdos] - || [istarget *c30-*-*] -+ || [istarget alpha-*-vms] } { -- || [istarget alpha-*-vms] -- || [istarget sw_64-*-vms] } { - return - } - ---- b/ld/testsuite/ld-plugin/plugin-14.d -+++ a/ld/testsuite/ld-plugin/plugin-14.d -@@ -29,6 +29,5 @@ - hook called: all symbols read. - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... ---- b/ld/testsuite/ld-plugin/plugin-15.d -+++ a/ld/testsuite/ld-plugin/plugin-15.d -@@ -30,6 +30,5 @@ - hook called: all symbols read. - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... ---- b/ld/testsuite/ld-plugin/plugin-16.d -+++ a/ld/testsuite/ld-plugin/plugin-16.d -@@ -34,6 +34,5 @@ - Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... ---- b/ld/testsuite/ld-plugin/plugin-20.d -+++ a/ld/testsuite/ld-plugin/plugin-20.d -@@ -4,5 +4,4 @@ - Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. ---- b/ld/testsuite/ld-plugin/plugin-21.d -+++ a/ld/testsuite/ld-plugin/plugin-21.d -@@ -4,5 +4,4 @@ - Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. ---- b/ld/testsuite/ld-plugin/plugin-22.d -+++ a/ld/testsuite/ld-plugin/plugin-22.d -@@ -4,5 +4,4 @@ - Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. ---- b/ld/testsuite/ld-plugin/plugin-23.d -+++ a/ld/testsuite/ld-plugin/plugin-23.d -@@ -4,5 +4,4 @@ - Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. ---- b/ld/testsuite/ld-plugin/plugin-6.d -+++ a/ld/testsuite/ld-plugin/plugin-6.d -@@ -29,6 +29,5 @@ - hook called: all symbols read. - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... ---- b/ld/testsuite/ld-plugin/plugin-7.d -+++ a/ld/testsuite/ld-plugin/plugin-7.d -@@ -30,6 +30,5 @@ - hook called: all symbols read. - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... ---- b/ld/testsuite/ld-plugin/plugin-8.d -+++ a/ld/testsuite/ld-plugin/plugin-8.d -@@ -34,6 +34,5 @@ - Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' --.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... ---- b/ld/testsuite/ld-scripts/fill.d -+++ a/ld/testsuite/ld-scripts/fill.d -@@ -7,7 +7,7 @@ - #skip: ia64-*-* mips*-*-freebsd* mips*-*-gnu* mips*-*-irix* mips*-*-kfreebsd* - #skip: mips*-*-linux* mips*-*-netbsd* mips*-*-openbsd* mips*-*-sysv4* sh-*-pe - #skip: tilegx*-*-* tilepro-*-* x86_64-*-cygwin x86_64-*-mingw* x86_64-*-pe* -+#xfail: alpha*-*-*ecoff sparc*-*-coff --#xfail: alpha*-*-*ecoff sw_64*-*-*ecoff sparc*-*-coff - #xfail: tic30-*-coff tic4x-*-* tic54x-*-* z8k-*-* - # - # See also fill16.d. We use `skip' for configurations unsupported -@@ -16,7 +16,6 @@ - # configurations are listed above. - # - # alpha-linuxecoff pads out code to 16 bytes. --# sw_64-linuxecoff pads out code to 16 bytes. - # ia64 aligns code to minimum 16 bytes. - # mips aligns to minimum 16 bytes (except for bare-metal ELF and VxWorks). - # sh-pe pads out code sections to 16 bytes ---- b/ld/testsuite/ld-scripts/fill16.d -+++ a/ld/testsuite/ld-scripts/fill16.d -@@ -5,7 +5,7 @@ - #objdump: -s -j .text - #notarget: [is_aout_format] - #skip: arm-*-coff i[3-7]86-*-coff [is_xcoff_format] -+#xfail: alpha*-*-*ecoff sparc*-*-coff --#xfail: alpha*-*-*ecoff sw_64*-*-*ecoff sparc*-*-coff - #xfail: tic30-*-coff tic4x-*-* tic54x-*-* z8k-*-* - #xfail: z80-*-coff - # -@@ -15,7 +15,6 @@ - # configurations are listed above. - # - # alpha-linuxecoff pads out code to 16 bytes. --# sw_64-linuxecoff pads out code to 16 bytes. - # arm-coff always aligns code to 4 bytes. - # i386-coff always aligns code to 4 bytes. - # sh-pe pads out code sections to 16 bytes ---- b/ld/testsuite/ld-scripts/pr27100.d -+++ a/ld/testsuite/ld-scripts/pr27100.d -@@ -1,7 +1,7 @@ - #ld: -r -T pr27100.t - #objdump: -h - #notarget: [is_aout_format] -+#xfail: alpha*-*-*vms* mmix-*-* *c54x-*-* [is_xcoff_format] --#xfail: alpha*-*-*vms* sw_64*-*-*vms* mmix-*-* *c54x-*-* [is_xcoff_format] - - #... - .* \.data +0+60 .* ---- b/ld/testsuite/ld-shared/shared.exp -+++ a/ld/testsuite/ld-shared/shared.exp -@@ -53,7 +53,6 @@ - && ![istarget sparc*-*-linux*] \ - && ![istarget arm*-*-linux*] \ - && ![istarget alpha*-*-linux*] \ -- && ![istarget sw_64*-*-linux*] \ - && ![istarget rs6000*-*-aix*] \ - && ![istarget powerpc*-*-aix*] \ - && ![istarget s390*-*-linux*] \ -@@ -234,7 +233,6 @@ - setup_xfail "*-*-solaris2*" - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -- setup_xfail "sw_64*-*-linux*" - setup_xfail "powerpc64*-*-*" - if { ![istarget hppa*64*-*-linux*] } { - setup_xfail "hppa*-*-linux*" -@@ -261,7 +259,6 @@ - setup_xfail "powerpc*-*-linux*" - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -- setup_xfail "sw_64*-*-linux*" - setup_xfail "mips*-*-linux*" - if { ![istarget hppa*64*-*-linux*] } { - setup_xfail "hppa*-*-linux*" -@@ -317,7 +314,6 @@ - setup_xfail "*-*-solaris2*" - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -- setup_xfail "sw_64*-*-linux*" - setup_xfail "powerpc64*-*-*" - if { ![istarget hppa*64*-*-linux*] } { - setup_xfail "hppa*-*-linux*" ---- b/ld/testsuite/ld-srec/srec.exp -+++ a/ld/testsuite/ld-srec/srec.exp -@@ -408,9 +408,6 @@ - # The S-record linker doesn't handle Alpha Elf relaxation. - setup_xfail "alpha*-*-elf*" "alpha*-*-linux-*" "alpha*-*-gnu*" - setup_xfail "alpha*-*-netbsd*" --#setup_xfail "sw_64*-*-*" --setup_xfail "sw_64*-*-elf*" "sw_64*-*-linux-*" "sw_64*-*-gnu*" --setup_xfail "sw_64*-*-netbsd*" - - # The S-record linker hasn't any hope of coping with HPPA relocs. - # Or MeP complex relocs. -@@ -474,9 +471,6 @@ - setup_xfail "v850*-*-elf" - setup_xfail "alpha*-*-elf*" "alpha*-*-linux-*" "alpha*-*-gnu*" - setup_xfail "alpha*-*-netbsd*" --#setup_xfail "sw_64*-*-*" --setup_xfail "sw_64*-*-elf*" "sw_64*-*-linux-*" "sw_64*-*-gnu*" --setup_xfail "sw_64*-*-netbsd*" - setup_xfail "hppa*-*-*" "mep-*-*" - setup_xfail "ia64-*-*" - setup_xfail "*-*-cygwin*" "*-*-mingw*" "*-*-pe*" "*-*-winnt*" ---- b/makefile.vms -+++ a/makefile.vms -@@ -15,14 +15,6 @@ - GASCC = gcc - endif - --ifeq ($(ARCH),SW_64) --CC = gcc --GASCC = $(CC) --else --CC = cc --GASCC = gcc --endif -- - ifeq ($(CC),cc) - CHECK-COMPILER = check_compiler - else ---- b/opcodes/Makefile.am -+++ a/opcodes/Makefile.am -@@ -97,8 +97,6 @@ - aarch64-opc-2.c \ - alpha-dis.c \ - alpha-opc.c \ -- sw_64-dis.c \ -- sw_64-opc.c \ - arc-dis.c \ - arc-ext.c \ - arc-opc.c \ ---- b/opcodes/Makefile.in -+++ a/opcodes/Makefile.in -@@ -488,8 +488,6 @@ - aarch64-opc-2.c \ - alpha-dis.c \ - alpha-opc.c \ -- sw_64-dis.c \ -- sw_64-opc.c \ - arc-dis.c \ - arc-ext.c \ - arc-opc.c \ -@@ -905,8 +903,6 @@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aarch64-opc.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alpha-dis.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alpha-opc.Plo@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sw_64-opc.Plo@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sw_64-dis.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-dis.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-ext.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-opc.Plo@am__quote@ ---- b/opcodes/config.in -+++ a/opcodes/config.in -@@ -117,5 +117,3 @@ - - /* Define to 1 if you need to in order for `stat' and other things to work. */ - #undef _POSIX_SOURCE -- --#undef TARGET_SW_64 ---- b/opcodes/configure -+++ a/opcodes/configure -@@ -12235,13 +12235,6 @@ - case "$arch" in - bfd_aarch64_arch) ta="$ta aarch64-asm.lo aarch64-dis.lo aarch64-opc.lo aarch64-asm-2.lo aarch64-dis-2.lo aarch64-opc-2.lo" ;; - bfd_alpha_arch) ta="$ta alpha-dis.lo alpha-opc.lo" ;; --# ifdef TARGET_SW_64 -- bfd_sw_64_arch) ta="$ta sw_64-dis.lo sw_64-opc.lo" --cat >>confdefs.h <<_ACEOF --#define TARGET_SW_64 --_ACEOF --# endif -- ;; - bfd_arc_arch) ta="$ta arc-dis.lo arc-opc.lo arc-ext.lo" ;; - bfd_arm_arch) ta="$ta arm-dis.lo" ;; - bfd_avr_arch) ta="$ta avr-dis.lo" ;; ---- b/opcodes/configure.ac -+++ a/opcodes/configure.ac -@@ -272,7 +272,6 @@ - case "$arch" in - bfd_aarch64_arch) ta="$ta aarch64-asm.lo aarch64-dis.lo aarch64-opc.lo aarch64-asm-2.lo aarch64-dis-2.lo aarch64-opc-2.lo" ;; - bfd_alpha_arch) ta="$ta alpha-dis.lo alpha-opc.lo" ;; -- bfd_sw_64_arch) ta="$ta sw_64-dis.lo sw_64-opc.lo" ;; - bfd_arc_arch) ta="$ta arc-dis.lo arc-opc.lo arc-ext.lo" ;; - bfd_arm_arch) ta="$ta arm-dis.lo" ;; - bfd_avr_arch) ta="$ta avr-dis.lo" ;; ---- b/opcodes/configure.com -+++ a/opcodes/configure.com -@@ -44,14 +44,6 @@ - $ DEFS="""ARCH_alpha""" - $EOD - $ endif --$ if arch.eqs."sw_64" --$ then --$ create build.com --$DECK --$ FILES="sw_64-dis,sw_64-opc" --$ DEFS="""ARCH_sw_64""" --$EOD --$ endif - $! - $ append sys$input build.com - $DECK ---- b/opcodes/disassemble.c -+++ a/opcodes/disassemble.c -@@ -26,9 +26,6 @@ - #ifdef ARCH_all - #define ARCH_aarch64 - #define ARCH_alpha --#ifdef TARGET_SW_64 --#define ARCH_sw_64 --#endif - #define ARCH_arc - #define ARCH_arm - #define ARCH_avr -@@ -148,13 +145,6 @@ - disassemble = print_insn_alpha; - break; - #endif --#ifdef TARGET_SW_64 --#ifdef ARCH_sw_64 -- case bfd_arch_sw_64: -- disassemble = print_insn_sw_64; -- break; --#endif --#endif - #ifdef ARCH_arc - case bfd_arch_arc: - disassemble = arc_get_disassembler (abfd); ---- b/opcodes/disassemble.h -+++ a/opcodes/disassemble.h -@@ -23,9 +23,6 @@ - - extern int print_insn_aarch64 (bfd_vma, disassemble_info *); - extern int print_insn_alpha (bfd_vma, disassemble_info *); --#ifdef TARGET_SW_64 --extern int print_insn_sw_64 (bfd_vma, disassemble_info *); --#endif - extern int print_insn_avr (bfd_vma, disassemble_info *); - extern int print_insn_bfin (bfd_vma, disassemble_info *); - extern int print_insn_big_arm (bfd_vma, disassemble_info *); diff --git a/Sw64-revert-old-support-newfile.patch b/Sw64-revert-old-support-newfile.patch deleted file mode 100644 index c87ee32..0000000 --- a/Sw64-revert-old-support-newfile.patch +++ /dev/null @@ -1,31574 +0,0 @@ ---- b/bfd/coff-sw_64.c -+++ /dev/null -@@ -1,2470 +0,0 @@ --/* BFD back-end for SW_64 Extended-Coff files. -- Copyright (C) 1993-2021 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 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. */ -- --#include "sysdep.h" --#include "bfd.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/sw_64.h" --#include "aout/ar.h" --#include "libcoff.h" --#include "libecoff.h" -- --/* Prototypes for static functions. */ -- -- -- --/* 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 H_GET_64 --#define PUT_FILEHDR_SYMPTR H_PUT_64 --#define GET_AOUTHDR_TSIZE H_GET_64 --#define PUT_AOUTHDR_TSIZE H_PUT_64 --#define GET_AOUTHDR_DSIZE H_GET_64 --#define PUT_AOUTHDR_DSIZE H_PUT_64 --#define GET_AOUTHDR_BSIZE H_GET_64 --#define PUT_AOUTHDR_BSIZE H_PUT_64 --#define GET_AOUTHDR_ENTRY H_GET_64 --#define PUT_AOUTHDR_ENTRY H_PUT_64 --#define GET_AOUTHDR_TEXT_START H_GET_64 --#define PUT_AOUTHDR_TEXT_START H_PUT_64 --#define GET_AOUTHDR_DATA_START H_GET_64 --#define PUT_AOUTHDR_DATA_START H_PUT_64 --#define GET_SCNHDR_PADDR H_GET_64 --#define PUT_SCNHDR_PADDR H_PUT_64 --#define GET_SCNHDR_VADDR H_GET_64 --#define PUT_SCNHDR_VADDR H_PUT_64 --#define GET_SCNHDR_SIZE H_GET_64 --#define PUT_SCNHDR_SIZE H_PUT_64 --#define GET_SCNHDR_SCNPTR H_GET_64 --#define PUT_SCNHDR_SCNPTR H_PUT_64 --#define GET_SCNHDR_RELPTR H_GET_64 --#define PUT_SCNHDR_RELPTR H_PUT_64 --#define GET_SCNHDR_LNNOPTR H_GET_64 --#define PUT_SCNHDR_LNNOPTR H_PUT_64 -- --#define SW_64ECOFF -- --#define NO_COFF_RELOCS --#define NO_COFF_SYMBOLS --#define NO_COFF_LINENOS --#define coff_swap_filehdr_in sw_64_ecoff_swap_filehdr_in --#define coff_swap_filehdr_out sw_64_ecoff_swap_filehdr_out --#define coff_swap_aouthdr_in sw_64_ecoff_swap_aouthdr_in --#define coff_swap_aouthdr_out sw_64_ecoff_swap_aouthdr_out --#define coff_swap_scnhdr_in sw_64_ecoff_swap_scnhdr_in --#define coff_swap_scnhdr_out sw_64_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 (bfd *abfd ATTRIBUTE_UNUSED, -- arelent *reloc ATTRIBUTE_UNUSED, -- asymbol *sym ATTRIBUTE_UNUSED, -- void * data ATTRIBUTE_UNUSED, -- asection *sec ATTRIBUTE_UNUSED, -- bfd *output_bfd ATTRIBUTE_UNUSED, -- char **error_message ATTRIBUTE_UNUSED) --{ -- 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 sw_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 bfd_cleanup --sw_64_ecoff_object_p (bfd *abfd) --{ -- bfd_cleanup 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 = (bfd_size_type) sec->line_filepos * 8; -- BFD_ASSERT (size == sec->size -- || size + 8 == sec->size); -- if (!bfd_set_section_size (sec, size)) -- return NULL; -- } -- } -- -- return ret; --} -- --/* See whether the magic number matches. */ -- --static bool --sw_64_ecoff_bad_format_hook (bfd *abfd ATTRIBUTE_UNUSED, -- void * filehdr) --{ -- struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; -- -- if (! SW_64_ECOFF_BADMAG (*internal_f)) -- return true; -- -- if (SW_64_ECOFF_COMPRESSEDMAG (*internal_f)) -- _bfd_error_handler -- (_("%pB: cannot handle compressed Alpha binaries; " -- "use compiler flags, or objZ, to generate uncompressed binaries"), -- abfd); -- -- return false; --} -- --/* This is a hook called by coff_real_object_p to create any backend -- specific information. */ -- --static void * --sw_64_ecoff_mkobject_hook (bfd *abfd, void * filehdr, void * aouthdr) --{ -- void * 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_SW_64_OBJECT_TYPE_MASK) -- { -- case F_SW_64_SHARABLE: -- abfd->flags |= DYNAMIC; -- break; -- case F_SW_64_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 --sw_64_ecoff_swap_reloc_in (bfd *abfd, -- void * ext_ptr, -- struct internal_reloc *intern) --{ -- const RELOC *ext = (RELOC *) ext_ptr; -- -- intern->r_vaddr = H_GET_64 (abfd, ext->r_vaddr); -- intern->r_symndx = H_GET_32 (abfd, ext->r_symndx); -- -- BFD_ASSERT (bfd_header_little_endian (abfd)); -- -- intern->r_type = ((ext->r_bits[0] & RELOC_BITS0_TYPE_LITTLE) -- >> RELOC_BITS0_TYPE_SH_LITTLE); -- intern->r_extern = (ext->r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0; -- intern->r_offset = ((ext->r_bits[1] & RELOC_BITS1_OFFSET_LITTLE) -- >> RELOC_BITS1_OFFSET_SH_LITTLE); -- /* Ignored the reserved bits. */ -- intern->r_size = ((ext->r_bits[3] & RELOC_BITS3_SIZE_LITTLE) -- >> RELOC_BITS3_SIZE_SH_LITTLE); -- -- if (intern->r_type == SW_64_R_LITUSE -- || intern->r_type == SW_64_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 == SW_64_R_IGNORE) -- { -- /* The IGNORE reloc generally follows a GPDISP reloc, and is -- against the .lita section. The section is irrelevant. */ -- if (! intern->r_extern && -- intern->r_symndx == RELOC_SECTION_ABS) -- abort (); -- if (! intern->r_extern && intern->r_symndx == RELOC_SECTION_LITA) -- intern->r_symndx = RELOC_SECTION_ABS; -- } --} -- --/* Swap a reloc out. */ -- --static void --sw_64_ecoff_swap_reloc_out (bfd *abfd, -- const struct internal_reloc *intern, -- void * dst) --{ -- RELOC *ext = (RELOC *) dst; -- long symndx; -- unsigned char size; -- -- /* Undo the hackery done in swap_reloc_in. */ -- if (intern->r_type == SW_64_R_LITUSE -- || intern->r_type == SW_64_R_GPDISP) -- { -- symndx = intern->r_size; -- size = 0; -- } -- else if (intern->r_type == SW_64_R_IGNORE -- && ! intern->r_extern -- && intern->r_symndx == RELOC_SECTION_ABS) -- { -- symndx = RELOC_SECTION_LITA; -- size = intern->r_size; -- } -- else -- { -- symndx = intern->r_symndx; -- size = intern->r_size; -- } -- -- /* XXX FIXME: The maximum symndx value used to be 14 but this -- fails with object files produced by DEC's C++ compiler. -- Where does the value 14 (or 15) come from anyway ? */ -- BFD_ASSERT (intern->r_extern -- || (intern->r_symndx >= 0 && intern->r_symndx <= 15)); -- -- H_PUT_64 (abfd, intern->r_vaddr, ext->r_vaddr); -- H_PUT_32 (abfd, symndx, ext->r_symndx); -- -- BFD_ASSERT (bfd_header_little_endian (abfd)); -- -- ext->r_bits[0] = ((intern->r_type << RELOC_BITS0_TYPE_SH_LITTLE) -- & RELOC_BITS0_TYPE_LITTLE); -- ext->r_bits[1] = ((intern->r_extern ? RELOC_BITS1_EXTERN_LITTLE : 0) -- | ((intern->r_offset << RELOC_BITS1_OFFSET_SH_LITTLE) -- & RELOC_BITS1_OFFSET_LITTLE)); -- ext->r_bits[2] = 0; -- ext->r_bits[3] = ((size << RELOC_BITS3_SIZE_SH_LITTLE) -- & RELOC_BITS3_SIZE_LITTLE); --} -- --/* Finish canonicalizing a reloc. Part of this is generic to all -- ECOFF targets, and that part is in ecoff.c. The rest is done in -- this backend routine. It must fill in the howto field. */ -- --static void --sw_64_adjust_reloc_in (bfd *abfd, -- const struct internal_reloc *intern, -- arelent *rptr) --{ -- if (intern->r_type > SW_64_R_GPVALUE) -- { -- /* xgettext:c-format */ -- _bfd_error_handler (_("%pB: unsupported relocation type %#x"), -- abfd, intern->r_type); -- bfd_set_error (bfd_error_bad_value); -- rptr->addend = 0; -- rptr->howto = NULL; -- return; -- } -- -- switch (intern->r_type) -- { -- case SW_64_R_BRADDR: -- case SW_64_R_SREL16: -- case SW_64_R_SREL32: -- case SW_64_R_SREL64: -- /* This relocs appear to be fully resolved when they are against -- internal symbols. Against external symbols, BRADDR at least -- appears to be resolved against the next instruction. */ -- if (! intern->r_extern) -- rptr->addend = 0; -- else -- rptr->addend = - (intern->r_vaddr + 4); -- break; -- -- case SW_64_R_GPREL32: -- case SW_64_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 SW_64_R_LITUSE: -- case SW_64_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 SW_64_R_OP_STORE: -- /* The STORE reloc needs the size and offset fields. We store -- them in the addend. */ -- BFD_ASSERT (intern->r_offset <= 256); -- rptr->addend = (intern->r_offset << 8) + intern->r_size; -- break; -- -- case SW_64_R_OP_PUSH: -- case SW_64_R_OP_PSUB: -- case SW_64_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 SW_64_R_GPVALUE: -- /* Set the addend field to the new GP value. */ -- rptr->addend = intern->r_symndx + ecoff_data (abfd)->gp; -- break; -- -- case SW_64_R_IGNORE: -- /* If the type is SW_64_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 = &sw_64_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 -- sw_64_adjust_reloc_in, except that there are several changes we do -- not need to undo. */ -- --static void --sw_64_adjust_reloc_out (bfd *abfd ATTRIBUTE_UNUSED, -- const arelent *rel, -- struct internal_reloc *intern) --{ -- switch (intern->r_type) -- { -- case SW_64_R_LITUSE: -- case SW_64_R_GPDISP: -- intern->r_size = rel->addend; -- break; -- -- case SW_64_R_OP_STORE: -- intern->r_size = rel->addend & 0xff; -- intern->r_offset = (rel->addend >> 8) & 0xff; -- break; -- -- case SW_64_R_OP_PUSH: -- case SW_64_R_OP_PSUB: -- case SW_64_R_OP_PRSHIFT: -- intern->r_vaddr = rel->addend; -- break; -- -- case SW_64_R_IGNORE: -- intern->r_vaddr = rel->address; -- break; -- -- default: -- break; -- } --} -- --/* The size of the stack for the relocation evaluator. */ --#define RELOC_STACKSIZE (10) -- --/* Alpha ECOFF relocs have a built in expression evaluator as well as -- other interdependencies. Rather than use a bunch of special -- functions and global variables, we use a single routine to do all -- the relocation for a section. I haven't yet worked out how the -- assembler is going to handle this. */ -- --static bfd_byte * --sw_64_ecoff_get_relocated_section_contents (bfd *abfd, -- struct bfd_link_info *link_info, -- struct bfd_link_order *link_order, -- bfd_byte *data, -- bool relocatable, -- 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 = relocatable ? abfd : (bfd *) NULL; -- bfd_vma gp; -- bfd_size_type sz; -- bool gp_undefined; -- bfd_vma stack[RELOC_STACKSIZE]; -- int tos = 0; -- -- if (reloc_size < 0) -- goto error_return; -- reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); -- if (reloc_vector == NULL && reloc_size != 0) -- goto error_return; -- -- sz = input_section->rawsize ? input_section->rawsize : input_section->size; -- if (! bfd_get_section_contents (input_bfd, input_section, data, 0, sz)) -- goto error_return; -- -- reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, -- reloc_vector, symbols); -- if (reloc_count < 0) -- goto error_return; -- if (reloc_count == 0) -- goto successful_return; -- -- /* Get the GP value for the output BFD. */ -- gp_undefined = false; -- gp = _bfd_get_gp_value (abfd); -- if (gp == 0) -- { -- if (relocatable) -- { -- asection *sec; -- bfd_vma lo; -- -- /* Make up a value. */ -- lo = (bfd_vma) -1; -- for (sec = abfd->sections; sec != NULL; sec = sec->next) -- { -- if (sec->vma < lo -- && (strcmp (sec->name, ".sbss") == 0 -- || strcmp (sec->name, ".sdata") == 0 -- || strcmp (sec->name, ".lit4") == 0 -- || strcmp (sec->name, ".lit8") == 0 -- || strcmp (sec->name, ".lita") == 0)) -- lo = sec->vma; -- } -- gp = lo + 0x8000; -- _bfd_set_gp_value (abfd, gp); -- } -- else -- { -- struct bfd_link_hash_entry *h; -- -- h = bfd_link_hash_lookup (link_info->hash, "_gp", false, false, -- true); -- if (h == (struct bfd_link_hash_entry *) NULL -- || h->type != bfd_link_hash_defined) -- gp_undefined = true; -- else -- { -- gp = (h->u.def.value -- + h->u.def.section->output_section->vma -- + h->u.def.section->output_offset); -- _bfd_set_gp_value (abfd, gp); -- } -- } -- } -- -- for (; *reloc_vector != (arelent *) NULL; reloc_vector++) -- { -- arelent *rel; -- bfd_reloc_status_type r; -- char *err; -- -- rel = *reloc_vector; -- r = bfd_reloc_ok; -- switch (rel->howto->type) -- { -- case SW_64_R_IGNORE: -- rel->address += input_section->output_offset; -- break; -- -- case SW_64_R_REFLONG: -- case SW_64_R_REFQUAD: -- case SW_64_R_BRADDR: -- case SW_64_R_HINT: -- case SW_64_R_SREL16: -- case SW_64_R_SREL32: -- case SW_64_R_SREL64: -- if (relocatable -- && ((*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 SW_64_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 SW_64_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 SW_64_R_LITUSE: -- /* See SW_64_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 SW_64_R_GPDISP: -- /* This marks the ldah of an ldah/lda pair which loads the -- gp register with the difference of the gp value and the -- current location. The second of the pair is r_size bytes -- ahead; it used to be marked with an SW_64_R_IGNORE reloc, -- but that no longer happens in OSF/1 3.2. */ -- { -- unsigned long insn1, insn2; -- bfd_vma addend; -- -- /* Get the two instructions. */ -- insn1 = bfd_get_32 (input_bfd, data + rel->address); -- insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend); -- -- BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ -- BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ -- -- /* Get the existing addend. We must account for the sign -- extension done by lda and ldah. */ -- addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); -- if (insn1 & 0x8000) -- { -- addend -= 0x80000000; -- addend -= 0x80000000; -- } -- if (insn2 & 0x8000) -- addend -= 0x10000; -- -- /* The existing addend includes the different between the -- gp of the input BFD and the address in the input BFD. -- Subtract this out. */ -- addend -= (ecoff_data (input_bfd)->gp -- - (input_section->vma + rel->address)); -- -- /* Now add in the final gp value, and subtract out the -- final address. */ -- addend += (gp -- - (input_section->output_section->vma -- + input_section->output_offset -- + rel->address)); -- -- /* Change the instructions, accounting for the sign -- extension, and write them out. */ -- if (addend & 0x8000) -- addend += 0x10000; -- insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff); -- insn2 = (insn2 & 0xffff0000) | (addend & 0xffff); -- -- bfd_put_32 (input_bfd, (bfd_vma) insn1, data + rel->address); -- bfd_put_32 (input_bfd, (bfd_vma) insn2, -- data + rel->address + rel->addend); -- -- rel->address += input_section->output_offset; -- } -- break; -- -- case SW_64_R_OP_PUSH: -- /* Push a value on the reloc evaluation stack. */ -- { -- asymbol *symbol; -- bfd_vma relocation; -- -- if (relocatable) -- { -- 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 SW_64_R_OP_STORE: -- /* Store a value from the reloc stack into a bitfield. */ -- { -- bfd_vma val; -- int offset, size; -- -- if (relocatable) -- { -- 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 sw_64_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 SW_64_R_OP_PSUB: -- /* Subtract a value from the top of the stack. */ -- { -- asymbol *symbol; -- bfd_vma relocation; -- -- if (relocatable) -- { -- 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 SW_64_R_OP_PRSHIFT: -- /* Shift the value on the top of the stack. */ -- { -- asymbol *symbol; -- bfd_vma relocation; -- -- if (relocatable) -- { -- 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 SW_64_R_GPVALUE: -- /* I really don't know if this does the right thing. */ -- gp = rel->addend; -- gp_undefined = false; -- break; -- -- default: -- abort (); -- } -- -- if (relocatable) -- { -- 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: -- (*link_info->callbacks->undefined_symbol) -- (link_info, bfd_asymbol_name (*rel->sym_ptr_ptr), -- input_bfd, input_section, rel->address, true); -- break; -- case bfd_reloc_dangerous: -- (*link_info->callbacks->reloc_dangerous) -- (link_info, err, input_bfd, input_section, rel->address); -- break; -- case bfd_reloc_overflow: -- (*link_info->callbacks->reloc_overflow) -- (link_info, NULL, bfd_asymbol_name (*rel->sym_ptr_ptr), -- rel->howto->name, rel->addend, input_bfd, -- input_section, rel->address); -- break; -- case bfd_reloc_outofrange: -- default: -- abort (); -- break; -- } -- } -- } -- -- if (tos != 0) -- abort (); -- -- successful_return: -- free (reloc_vector); -- return data; -- -- error_return: -- free (reloc_vector); -- return NULL; --} -- --/* Get the howto structure for a generic reloc type. */ -- --static reloc_howto_type * --sw_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, -- bfd_reloc_code_real_type code) --{ -- int sw_64_type; -- -- switch (code) -- { -- case BFD_RELOC_32: -- sw_64_type = SW_64_R_REFLONG; -- break; -- case BFD_RELOC_64: -- case BFD_RELOC_CTOR: -- sw_64_type = SW_64_R_REFQUAD; -- break; -- case BFD_RELOC_GPREL32: -- sw_64_type = SW_64_R_GPREL32; -- break; -- case BFD_RELOC_SW_64_LITERAL: -- sw_64_type = SW_64_R_LITERAL; -- break; -- case BFD_RELOC_SW_64_LITUSE: -- sw_64_type = SW_64_R_LITUSE; -- break; -- case BFD_RELOC_SW_64_GPDISP_HI16: -- sw_64_type = SW_64_R_GPDISP; -- break; -- case BFD_RELOC_SW_64_GPDISP_LO16: -- sw_64_type = SW_64_R_IGNORE; -- break; -- case BFD_RELOC_23_PCREL_S2: -- sw_64_type = SW_64_R_BRADDR; -- break; -- case BFD_RELOC_SW_64_HINT: -- sw_64_type = SW_64_R_HINT; -- break; -- case BFD_RELOC_16_PCREL: -- sw_64_type = SW_64_R_SREL16; -- break; -- case BFD_RELOC_32_PCREL: -- sw_64_type = SW_64_R_SREL32; -- break; -- case BFD_RELOC_64_PCREL: -- sw_64_type = SW_64_R_SREL64; -- break; -- default: -- return (reloc_howto_type *) NULL; -- } -- -- return &sw_64_howto_table[sw_64_type]; --} -- --static reloc_howto_type * --sw_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, -- const char *r_name) --{ -- unsigned int i; -- -- for (i = 0; -- i < sizeof (sw_64_howto_table) / sizeof (sw_64_howto_table[0]); -- i++) -- if (sw_64_howto_table[i].name != NULL -- && strcasecmp (sw_64_howto_table[i].name, r_name) == 0) -- return &sw_64_howto_table[i]; -- -- return NULL; --} -- --/* A helper routine for sw_64_relocate_section which converts an -- external reloc when generating relocatable output. Returns the -- relocation amount. */ -- --static bfd_vma --sw_64_convert_external_reloc (bfd *output_bfd ATTRIBUTE_UNUSED, -- 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 (bfd_link_relocatable (info)); -- -- 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_section_name (hsec->output_section); -- -- r_symndx = (unsigned long) -1; -- switch (name[1]) -- { -- case 'A': -- if (strcmp (name, "*ABS*") == 0) -- r_symndx = RELOC_SECTION_ABS; -- break; -- case 'b': -- if (strcmp (name, ".bss") == 0) -- r_symndx = RELOC_SECTION_BSS; -- break; -- case 'd': -- if (strcmp (name, ".data") == 0) -- r_symndx = RELOC_SECTION_DATA; -- break; -- case 'f': -- if (strcmp (name, ".fini") == 0) -- r_symndx = RELOC_SECTION_FINI; -- break; -- case 'i': -- if (strcmp (name, ".init") == 0) -- r_symndx = RELOC_SECTION_INIT; -- break; -- case 'l': -- if (strcmp (name, ".lita") == 0) -- r_symndx = RELOC_SECTION_LITA; -- else if (strcmp (name, ".lit8") == 0) -- r_symndx = RELOC_SECTION_LIT8; -- else if (strcmp (name, ".lit4") == 0) -- r_symndx = RELOC_SECTION_LIT4; -- break; -- case 'p': -- if (strcmp (name, ".pdata") == 0) -- r_symndx = RELOC_SECTION_PDATA; -- break; -- case 'r': -- if (strcmp (name, ".rdata") == 0) -- r_symndx = RELOC_SECTION_RDATA; -- else if (strcmp (name, ".rconst") == 0) -- r_symndx = RELOC_SECTION_RCONST; -- break; -- case 's': -- if (strcmp (name, ".sdata") == 0) -- r_symndx = RELOC_SECTION_SDATA; -- else if (strcmp (name, ".sbss") == 0) -- r_symndx = RELOC_SECTION_SBSS; -- break; -- case 't': -- if (strcmp (name, ".text") == 0) -- r_symndx = RELOC_SECTION_TEXT; -- break; -- case 'x': -- if (strcmp (name, ".xdata") == 0) -- r_symndx = RELOC_SECTION_XDATA; -- break; -- } -- -- if (r_symndx == (unsigned long) -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 == (unsigned long) -1) -- { -- /* Caller must give an error. */ -- r_symndx = 0; -- } -- relocation = 0; -- } -- -- /* Write out the new r_symndx value. */ -- H_PUT_32 (input_bfd, r_symndx, 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 bool --sw_64_relocate_section (bfd *output_bfd, -- struct bfd_link_info *info, -- bfd *input_bfd, -- asection *input_section, -- bfd_byte *contents, -- void * external_relocs) --{ -- asection **symndx_to_section, *lita_sec; -- struct ecoff_link_hash_entry **sym_hashes; -- bfd_vma gp; -- bool gp_undefined; -- bfd_vma stack[RELOC_STACKSIZE]; -- int tos = 0; -- struct external_reloc *ext_rel; -- struct external_reloc *ext_rel_end; -- bfd_size_type amt; -- -- /* 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) -- { -- amt = NUM_RELOC_SECTIONS * sizeof (asection *); -- symndx_to_section = (asection **) bfd_alloc (input_bfd, amt); -- if (!symndx_to_section) -- return false; -- -- symndx_to_section[RELOC_SECTION_NONE] = NULL; -- symndx_to_section[RELOC_SECTION_TEXT] = -- bfd_get_section_by_name (input_bfd, ".text"); -- symndx_to_section[RELOC_SECTION_RDATA] = -- bfd_get_section_by_name (input_bfd, ".rdata"); -- symndx_to_section[RELOC_SECTION_DATA] = -- bfd_get_section_by_name (input_bfd, ".data"); -- symndx_to_section[RELOC_SECTION_SDATA] = -- bfd_get_section_by_name (input_bfd, ".sdata"); -- symndx_to_section[RELOC_SECTION_SBSS] = -- bfd_get_section_by_name (input_bfd, ".sbss"); -- symndx_to_section[RELOC_SECTION_BSS] = -- bfd_get_section_by_name (input_bfd, ".bss"); -- symndx_to_section[RELOC_SECTION_INIT] = -- bfd_get_section_by_name (input_bfd, ".init"); -- symndx_to_section[RELOC_SECTION_LIT8] = -- bfd_get_section_by_name (input_bfd, ".lit8"); -- symndx_to_section[RELOC_SECTION_LIT4] = -- bfd_get_section_by_name (input_bfd, ".lit4"); -- symndx_to_section[RELOC_SECTION_XDATA] = -- bfd_get_section_by_name (input_bfd, ".xdata"); -- symndx_to_section[RELOC_SECTION_PDATA] = -- bfd_get_section_by_name (input_bfd, ".pdata"); -- symndx_to_section[RELOC_SECTION_FINI] = -- bfd_get_section_by_name (input_bfd, ".fini"); -- symndx_to_section[RELOC_SECTION_LITA] = -- bfd_get_section_by_name (input_bfd, ".lita"); -- symndx_to_section[RELOC_SECTION_ABS] = bfd_abs_section_ptr; -- symndx_to_section[RELOC_SECTION_RCONST] = -- bfd_get_section_by_name (input_bfd, ".rconst"); -- -- ecoff_data (input_bfd)->symndx_to_section = symndx_to_section; -- } -- -- sym_hashes = ecoff_data (input_bfd)->sym_hashes; -- -- /* On the Alpha, the .lita section must be addressable by the global -- pointer. To support large programs, we need to allow multiple -- global pointers. This works as long as each input .lita section -- is <64KB big. This implies that when producing relocatable -- output, the .lita section is limited to 64KB. . */ -- -- lita_sec = symndx_to_section[RELOC_SECTION_LITA]; -- gp = _bfd_get_gp_value (output_bfd); -- if (! bfd_link_relocatable (info) && lita_sec != NULL) -- { -- struct ecoff_section_tdata *lita_sec_data; -- -- /* Make sure we have a section data structure to which we can -- hang on to the gp value we pick for the section. */ -- lita_sec_data = ecoff_section_data (input_bfd, lita_sec); -- if (lita_sec_data == NULL) -- { -- amt = sizeof (struct ecoff_section_tdata); -- lita_sec_data = ((struct ecoff_section_tdata *) -- bfd_zalloc (input_bfd, amt)); -- lita_sec->used_by_bfd = lita_sec_data; -- } -- -- if (lita_sec_data->gp != 0) -- { -- /* If we already assigned a gp to this section, we better -- stick with that value. */ -- gp = lita_sec_data->gp; -- } -- else -- { -- bfd_vma lita_vma; -- bfd_size_type lita_size; -- -- lita_vma = lita_sec->output_offset + lita_sec->output_section->vma; -- lita_size = lita_sec->size; -- -- if (gp == 0 -- || lita_vma < gp - 0x8000 -- || lita_vma + lita_size >= gp + 0x8000) -- { -- /* Either gp hasn't been set at all or the current gp -- cannot address this .lita section. In both cases we -- reset the gp to point into the "middle" of the -- current input .lita section. */ -- if (gp && !ecoff_data (output_bfd)->issued_multiple_gp_warning) -- { -- (*info->callbacks->warning) (info, -- _("using multiple gp values"), -- (char *) NULL, output_bfd, -- (asection *) NULL, (bfd_vma) 0); -- ecoff_data (output_bfd)->issued_multiple_gp_warning = true; -- } -- if (lita_vma < gp - 0x8000) -- gp = lita_vma + lita_size - 0x8000; -- else -- gp = lita_vma + 0x8000; -- -- } -- -- lita_sec_data->gp = gp; -- } -- -- _bfd_set_gp_value (output_bfd, gp); -- } -- -- gp_undefined = (gp == 0); -- -- BFD_ASSERT (bfd_header_little_endian (output_bfd)); -- BFD_ASSERT (bfd_header_little_endian (input_bfd)); -- -- ext_rel = (struct external_reloc *) external_relocs; -- ext_rel_end = ext_rel + input_section->reloc_count; -- for (; ext_rel < ext_rel_end; ext_rel++) -- { -- bfd_vma r_vaddr; -- unsigned long r_symndx; -- int r_type; -- int r_extern; -- int r_offset; -- int r_size; -- bool relocatep; -- bool adjust_addrp; -- bool gp_usedp; -- bfd_vma addend; -- -- r_vaddr = H_GET_64 (input_bfd, ext_rel->r_vaddr); -- r_symndx = H_GET_32 (input_bfd, 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) -- { -- case SW_64_R_GPRELHIGH: -- _bfd_error_handler (_("%pB: %s unsupported"), -- input_bfd, "SW_64_R_GPRELHIGH"); -- bfd_set_error (bfd_error_bad_value); -- continue; -- -- case SW_64_R_GPRELLOW: -- _bfd_error_handler (_("%pB: %s unsupported"), -- input_bfd, "SW_64_R_GPRELLOW"); -- bfd_set_error (bfd_error_bad_value); -- continue; -- -- default: -- /* xgettext:c-format */ -- _bfd_error_handler (_("%pB: unsupported relocation type %#x"), -- input_bfd, (int) r_type); -- bfd_set_error (bfd_error_bad_value); -- continue; -- -- case SW_64_R_IGNORE: -- /* This reloc appears after a GPDISP reloc. On earlier -- versions of OSF/1, It marked the position of the second -- instruction to be altered by the GPDISP reloc, but it is -- not otherwise used for anything. For some reason, the -- address of the relocation does not appear to include the -- section VMA, unlike the other relocation types. */ -- if (bfd_link_relocatable (info)) -- H_PUT_64 (input_bfd, input_section->output_offset + r_vaddr, -- ext_rel->r_vaddr); -- adjust_addrp = false; -- break; -- -- case SW_64_R_REFLONG: -- case SW_64_R_REFQUAD: -- case SW_64_R_HINT: -- relocatep = true; -- break; -- -- case SW_64_R_BRADDR: -- case SW_64_R_SREL16: -- case SW_64_R_SREL32: -- case SW_64_R_SREL64: -- if (r_extern) -- addend += - (r_vaddr + 4); -- relocatep = true; -- break; -- -- case SW_64_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 SW_64_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 SW_64_R_LITUSE: -- /* See SW_64_R_LITERAL above for the uses of this reloc. It -- does not cause anything to happen, itself. */ -- break; -- -- case SW_64_R_GPDISP: -- /* This marks the ldah of an ldah/lda pair which loads the -- gp register with the difference of the gp value and the -- current location. The second of the pair is r_symndx -- bytes ahead. It used to be marked with an SW_64_R_IGNORE -- reloc, but OSF/1 3.2 no longer does that. */ -- { -- unsigned long insn1, insn2; -- -- /* Get the two instructions. */ -- insn1 = bfd_get_32 (input_bfd, -- contents + r_vaddr - input_section->vma); -- insn2 = bfd_get_32 (input_bfd, -- (contents -- + r_vaddr -- - input_section->vma -- + r_symndx)); -- -- BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ -- BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ -- -- /* Get the existing addend. We must account for the sign -- extension done by lda and ldah. */ -- addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); -- if (insn1 & 0x8000) -- { -- /* This is addend -= 0x100000000 without causing an -- integer overflow on a 32 bit host. */ -- addend -= 0x80000000; -- addend -= 0x80000000; -- } -- if (insn2 & 0x8000) -- addend -= 0x10000; -- -- /* The existing addend includes the difference between the -- gp of the input BFD and the address in the input BFD. -- We want to change this to the difference between the -- final GP and the final address. */ -- addend += (gp -- - ecoff_data (input_bfd)->gp -- + input_section->vma -- - (input_section->output_section->vma -- + input_section->output_offset)); -- -- /* Change the instructions, accounting for the sign -- extension, and write them out. */ -- if (addend & 0x8000) -- addend += 0x10000; -- insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff); -- insn2 = (insn2 & 0xffff0000) | (addend & 0xffff); -- -- bfd_put_32 (input_bfd, (bfd_vma) insn1, -- contents + r_vaddr - input_section->vma); -- bfd_put_32 (input_bfd, (bfd_vma) insn2, -- contents + r_vaddr - input_section->vma + r_symndx); -- -- gp_usedp = true; -- } -- break; -- -- case SW_64_R_OP_PUSH: -- case SW_64_R_OP_PSUB: -- case SW_64_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 (! bfd_link_relocatable (info)) -- { -- 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. */ -- (*info->callbacks->undefined_symbol) -- (info, h->root.root.string, input_bfd, -- input_section, (bfd_vma) 0, true); -- 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. */ -- (*info->callbacks->unattached_reloc) -- (info, h->root.root.string, -- input_bfd, input_section, (bfd_vma) 0); -- } -- -- addend = sw_64_convert_external_reloc (output_bfd, info, -- input_bfd, -- ext_rel, h); -- } -- } -- -- addend += r_vaddr; -- -- if (bfd_link_relocatable (info)) -- { -- /* Adjust r_vaddr by the addend. */ -- H_PUT_64 (input_bfd, addend, ext_rel->r_vaddr); -- } -- else -- { -- switch (r_type) -- { -- case SW_64_R_OP_PUSH: -- if (tos >= RELOC_STACKSIZE) -- abort (); -- stack[tos++] = addend; -- break; -- -- case SW_64_R_OP_PSUB: -- if (tos == 0) -- abort (); -- stack[tos - 1] -= addend; -- break; -- -- case SW_64_R_OP_PRSHIFT: -- if (tos == 0) -- abort (); -- stack[tos - 1] >>= addend; -- break; -- } -- } -- -- adjust_addrp = false; -- break; -- -- case SW_64_R_OP_STORE: -- /* Store a value from the reloc stack into a bitfield. If -- we are generating relocatable output, all we do is -- adjust the address of the reloc. */ -- if (! bfd_link_relocatable (info)) -- { -- 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 SW_64_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 = &sw_64_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 (bfd_link_relocatable (info)) -- { -- /* We are generating relocatable 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. */ -- (*info->callbacks->unattached_reloc) -- (info, h->root.root.string, input_bfd, -- input_section, r_vaddr - input_section->vma); -- } -- -- relocation = sw_64_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 -- { -- (*info->callbacks->undefined_symbol) -- (info, h->root.root.string, input_bfd, input_section, -- r_vaddr - input_section->vma, true); -- 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 (symndx_to_section[r_symndx]); -- (*info->callbacks->reloc_overflow) -- (info, NULL, name, sw_64_howto_table[r_type].name, -- (bfd_vma) 0, input_bfd, input_section, -- r_vaddr - input_section->vma); -- } -- break; -- } -- } -- } -- -- if (bfd_link_relocatable (info) && adjust_addrp) -- { -- /* Change the address of the relocation. */ -- H_PUT_64 (input_bfd, -- (input_section->output_section->vma -- + input_section->output_offset -- - input_section->vma -- + r_vaddr), -- ext_rel->r_vaddr); -- } -- -- if (gp_usedp && gp_undefined) -- { -- (*info->callbacks->reloc_dangerous) -- (info, _("GP relative relocation used when GP not defined"), -- input_bfd, input_section, r_vaddr - input_section->vma); -- /* Only give the error once per link. */ -- gp = 4; -- _bfd_set_gp_value (output_bfd, gp); -- gp_undefined = false; -- } -- } -- -- if (tos != 0) -- abort (); -- -- return true; --} -- --/* Do final adjustments to the filehdr and the aouthdr. This routine -- sets the dynamic bits in the file header. */ -- --static bool --sw_64_adjust_headers (bfd *abfd, -- struct internal_filehdr *fhdr, -- struct internal_aouthdr *ahdr ATTRIBUTE_UNUSED) --{ -- if ((abfd->flags & (DYNAMIC | EXEC_P)) == (DYNAMIC | EXEC_P)) -- fhdr->f_flags |= F_SW_64_CALL_SHARED; -- else if ((abfd->flags & DYNAMIC) != 0) -- fhdr->f_flags |= F_SW_64_SHARABLE; -- return true; --} -- --/* Archive handling. In OSF/1 (or Digital Unix) v3.2, Digital -- introduced archive packing, in which the elements in an archive are -- optionally compressed using a simple dictionary scheme. We know -- how to read such archives, but we don't write them. */ -- --#define sw_64_ecoff_slurp_armap _bfd_ecoff_slurp_armap --#define sw_64_ecoff_slurp_extended_name_table \ -- _bfd_ecoff_slurp_extended_name_table --#define sw_64_ecoff_construct_extended_name_table \ -- _bfd_ecoff_construct_extended_name_table --#define sw_64_ecoff_truncate_arname _bfd_ecoff_truncate_arname --#define sw_64_ecoff_write_armap _bfd_ecoff_write_armap --#define sw_64_ecoff_write_ar_hdr _bfd_generic_write_ar_hdr --#define sw_64_ecoff_generic_stat_arch_elt _bfd_ecoff_generic_stat_arch_elt --#define sw_64_ecoff_update_armap_timestamp _bfd_ecoff_update_armap_timestamp -- --/* A compressed file uses this instead of ARFMAG. */ -- --#define ARFZMAG "Z\012" -- --/* Read an archive header. This is like the standard routine, but it -- also accepts ARFZMAG. */ -- --static void * --sw_64_ecoff_read_ar_hdr (bfd *abfd) --{ -- struct areltdata *ret; -- struct ar_hdr *h; -- -- ret = (struct areltdata *) _bfd_generic_read_ar_hdr_mag (abfd, ARFZMAG); -- if (ret == NULL) -- return NULL; -- -- h = (struct ar_hdr *) ret->arch_header; -- if (strncmp (h->ar_fmag, ARFZMAG, 2) == 0) -- { -- bfd_byte ab[8]; -- -- /* This is a compressed file. We must set the size correctly. -- The size is the eight bytes after the dummy file header. */ -- if (bfd_seek (abfd, (file_ptr) FILHSZ, SEEK_CUR) != 0 -- || bfd_bread (ab, (bfd_size_type) 8, abfd) != 8 -- || bfd_seek (abfd, (file_ptr) (- (FILHSZ + 8)), SEEK_CUR) != 0) -- { -- free (ret); -- return NULL; -- } -- -- ret->parsed_size = H_GET_64 (abfd, ab); -- } -- -- return ret; --} -- --/* Get an archive element at a specified file position. This is where -- we uncompress the archive element if necessary. */ -- --static bfd * --sw_64_ecoff_get_elt_at_filepos (bfd *archive, file_ptr filepos) --{ -- bfd *nbfd = NULL; -- struct areltdata *tdata; -- struct ar_hdr *hdr; -- bfd_byte ab[8]; -- bfd_size_type size; -- bfd_byte *buf, *p; -- struct bfd_in_memory *bim; -- ufile_ptr filesize; -- -- buf = NULL; -- nbfd = _bfd_get_elt_at_filepos (archive, filepos); -- if (nbfd == NULL) -- goto error_return; -- -- if ((nbfd->flags & BFD_IN_MEMORY) != 0) -- { -- /* We have already expanded this BFD. */ -- return nbfd; -- } -- -- tdata = (struct areltdata *) nbfd->arelt_data; -- hdr = (struct ar_hdr *) tdata->arch_header; -- if (strncmp (hdr->ar_fmag, ARFZMAG, 2) != 0) -- return nbfd; -- -- /* We must uncompress this element. We do this by copying it into a -- memory buffer, and making bfd_bread and bfd_seek use that buffer. -- This can use a lot of memory, but it's simpler than getting a -- temporary file, making that work with the file descriptor caching -- code, and making sure that it is deleted at all appropriate -- times. It can be changed if it ever becomes important. */ -- -- /* The compressed file starts with a dummy ECOFF file header. */ -- if (bfd_seek (nbfd, (file_ptr) FILHSZ, SEEK_SET) != 0) -- goto error_return; -- -- /* The next eight bytes are the real file size. */ -- if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8) -- goto error_return; -- size = H_GET_64 (nbfd, ab); -- -- /* The decompression algorithm will at most expand by eight times. */ -- filesize = bfd_get_file_size (archive); -- if (filesize != 0 && size / 8 > filesize) -- { -- bfd_set_error (bfd_error_malformed_archive); -- goto error_return; -- } -- -- if (size != 0) -- { -- bfd_size_type left; -- bfd_byte dict[4096]; -- unsigned int h; -- bfd_byte b; -- -- buf = (bfd_byte *) bfd_malloc (size); -- if (buf == NULL) -- goto error_return; -- p = buf; -- -- left = size; -- -- /* I don't know what the next eight bytes are for. */ -- if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8) -- goto error_return; -- -- /* This is the uncompression algorithm. It's a simple -- dictionary based scheme in which each character is predicted -- by a hash of the previous three characters. A control byte -- indicates whether the character is predicted or whether it -- appears in the input stream; each control byte manages the -- next eight bytes in the output stream. */ -- memset (dict, 0, sizeof dict); -- h = 0; -- while (bfd_bread (&b, (bfd_size_type) 1, nbfd) == 1) -- { -- unsigned int i; -- -- for (i = 0; i < 8; i++, b >>= 1) -- { -- bfd_byte n; -- -- if ((b & 1) == 0) -- n = dict[h]; -- else -- { -- if (bfd_bread (&n, 1, nbfd) != 1) -- goto error_return; -- dict[h] = n; -- } -- -- *p++ = n; -- -- --left; -- if (left == 0) -- break; -- -- h <<= 4; -- h ^= n; -- h &= sizeof dict - 1; -- } -- -- if (left == 0) -- break; -- } -- } -- -- /* Now the uncompressed file contents are in buf. */ -- bim = ((struct bfd_in_memory *) -- bfd_malloc ((bfd_size_type) sizeof (struct bfd_in_memory))); -- if (bim == NULL) -- goto error_return; -- bim->size = size; -- bim->buffer = buf; -- -- nbfd->mtime_set = true; -- nbfd->mtime = strtol (hdr->ar_date, (char **) NULL, 10); -- -- nbfd->flags |= BFD_IN_MEMORY; -- nbfd->iostream = bim; -- nbfd->iovec = &_bfd_memory_iovec; -- nbfd->origin = 0; -- BFD_ASSERT (! nbfd->cacheable); -- -- return nbfd; -- -- error_return: -- free (buf); -- if (nbfd != NULL) -- bfd_close (nbfd); -- return NULL; --} -- --/* Open the next archived file. */ -- --static bfd * --sw_64_ecoff_openr_next_archived_file (bfd *archive, bfd *last_file) --{ -- ufile_ptr filestart; -- -- if (last_file == NULL) -- filestart = bfd_ardata (archive)->first_file_filepos; -- else -- { -- struct areltdata *t; -- struct ar_hdr *h; -- bfd_size_type size; -- -- /* We can't use arelt_size here, because that uses parsed_size, -- which is the uncompressed size. We need the compressed size. */ -- t = (struct areltdata *) last_file->arelt_data; -- h = (struct ar_hdr *) t->arch_header; -- size = strtol (h->ar_size, (char **) NULL, 10); -- -- /* Pad to an even boundary... -- Note that last_file->origin can be odd in the case of -- BSD-4.4-style element with a long odd size. */ -- filestart = last_file->proxy_origin + size; -- filestart += filestart % 2; -- if (filestart < last_file->proxy_origin) -- { -- /* Prevent looping. See PR19256. */ -- bfd_set_error (bfd_error_malformed_archive); -- return NULL; -- } -- } -- -- return sw_64_ecoff_get_elt_at_filepos (archive, filestart); --} -- --/* Open the archive file given an index into the armap. */ -- --static bfd * --sw_64_ecoff_get_elt_at_index (bfd *abfd, symindex sym_index) --{ -- carsym *entry; -- -- entry = bfd_ardata (abfd)->symdefs + sym_index; -- return sw_64_ecoff_get_elt_at_filepos (abfd, entry->file_offset); --} -- --static void --sw_64_ecoff_swap_coff_aux_in (bfd *abfd ATTRIBUTE_UNUSED, -- void *ext1 ATTRIBUTE_UNUSED, -- int type ATTRIBUTE_UNUSED, -- int in_class ATTRIBUTE_UNUSED, -- int indx ATTRIBUTE_UNUSED, -- int numaux ATTRIBUTE_UNUSED, -- void *in1 ATTRIBUTE_UNUSED) --{ --} -- --static void --sw_64_ecoff_swap_coff_sym_in (bfd *abfd ATTRIBUTE_UNUSED, -- void *ext1 ATTRIBUTE_UNUSED, -- void *in1 ATTRIBUTE_UNUSED) --{ --} -- --static void --sw_64_ecoff_swap_coff_lineno_in (bfd *abfd ATTRIBUTE_UNUSED, -- void *ext1 ATTRIBUTE_UNUSED, -- void *in1 ATTRIBUTE_UNUSED) --{ --} -- --static unsigned int --sw_64_ecoff_swap_coff_aux_out (bfd *abfd ATTRIBUTE_UNUSED, -- void *inp ATTRIBUTE_UNUSED, -- int type ATTRIBUTE_UNUSED, -- int in_class ATTRIBUTE_UNUSED, -- int indx ATTRIBUTE_UNUSED, -- int numaux ATTRIBUTE_UNUSED, -- void *extp ATTRIBUTE_UNUSED) --{ -- return 0; --} -- --static unsigned int --sw_64_ecoff_swap_coff_sym_out (bfd *abfd ATTRIBUTE_UNUSED, -- void *inp ATTRIBUTE_UNUSED, -- void *extp ATTRIBUTE_UNUSED) --{ -- return 0; --} -- --static unsigned int --sw_64_ecoff_swap_coff_lineno_out (bfd *abfd ATTRIBUTE_UNUSED, -- void *inp ATTRIBUTE_UNUSED, -- void *extp ATTRIBUTE_UNUSED) --{ -- return 0; --} -- --static unsigned int --sw_64_ecoff_swap_coff_reloc_out (bfd *abfd ATTRIBUTE_UNUSED, -- void *inp ATTRIBUTE_UNUSED, -- void *extp ATTRIBUTE_UNUSED) --{ -- return 0; --} -- --/* This is the ECOFF backend structure. The backend field of the -- target vector points to this. */ -- --static const struct ecoff_backend_data sw_64_ecoff_backend_data = --{ -- /* COFF backend structure. */ -- { -- sw_64_ecoff_swap_coff_aux_in, sw_64_ecoff_swap_coff_sym_in, -- sw_64_ecoff_swap_coff_lineno_in, sw_64_ecoff_swap_coff_aux_out, -- sw_64_ecoff_swap_coff_sym_out, sw_64_ecoff_swap_coff_lineno_out, -- sw_64_ecoff_swap_coff_reloc_out, -- sw_64_ecoff_swap_filehdr_out, sw_64_ecoff_swap_aouthdr_out, -- sw_64_ecoff_swap_scnhdr_out, -- FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, true, -- ECOFF_NO_LONG_SECTION_NAMES, 4, false, 2, 32768, -- sw_64_ecoff_swap_filehdr_in, sw_64_ecoff_swap_aouthdr_in, -- sw_64_ecoff_swap_scnhdr_in, NULL, -- sw_64_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, -- sw_64_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags, -- _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table, -- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -- NULL, NULL, NULL, NULL -- }, -- /* Supported architecture. */ -- bfd_arch_sw_64, -- /* 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. */ -- &sw_64_howto_table[SW_64_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. */ -- sw_64_ecoff_swap_reloc_in, -- sw_64_ecoff_swap_reloc_out, -- /* Backend reloc tweaking. */ -- sw_64_adjust_reloc_in, -- sw_64_adjust_reloc_out, -- /* Relocate section contents while linking. */ -- sw_64_relocate_section, -- /* Do final adjustments to filehdr and aouthdr. */ -- sw_64_adjust_headers, -- /* Read an element from an archive at a given file position. */ -- sw_64_ecoff_get_elt_at_filepos --}; -- --/* Looking up a reloc type is Alpha specific. */ --#define _bfd_ecoff_bfd_reloc_type_lookup sw_64_bfd_reloc_type_lookup --#define _bfd_ecoff_bfd_reloc_name_lookup \ -- sw_64_bfd_reloc_name_lookup -- --/* So is getting relocated section contents. */ --#define _bfd_ecoff_bfd_get_relocated_section_contents \ -- sw_64_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 -- --/* Input section flag lookup is generic. */ --#define _bfd_ecoff_bfd_lookup_section_flags bfd_generic_lookup_section_flags -- --/* Relaxing sections is generic. */ --#define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section --#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections --#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections --#define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section --#define _bfd_ecoff_bfd_group_name bfd_generic_group_name --#define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group --#define _bfd_ecoff_section_already_linked \ -- _bfd_coff_section_already_linked --#define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol --#define _bfd_ecoff_bfd_link_hide_symbol _bfd_generic_link_hide_symbol --#define _bfd_ecoff_bfd_define_start_stop bfd_generic_define_start_stop --#define _bfd_ecoff_bfd_link_check_relocs _bfd_generic_link_check_relocs -- --/* Installing internal relocations in a section is also generic. */ --#define _bfd_ecoff_set_reloc _bfd_generic_set_reloc -- --const bfd_target sw_64_ecoff_le_vec = --{ -- "ecoff-littlesw_64", /* name */ -- bfd_target_ecoff_flavour, -- BFD_ENDIAN_LITTLE, /* data byte order is little */ -- BFD_ENDIAN_LITTLE, /* header byte order is little */ -- -- (HAS_RELOC | EXEC_P /* object flags */ -- | HAS_LINENO | HAS_DEBUG -- | HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), -- -- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE -- | SEC_DATA | SEC_SMALL_DATA), -- 0, /* leading underscore */ -- ' ', /* ar_pad_char */ -- 15, /* ar_max_namelen */ -- 0, /* match priority. */ -- TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ -- 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_check_format */ -- _bfd_dummy_target, -- sw_64_ecoff_object_p, -- bfd_generic_archive_p, -- _bfd_dummy_target -- }, -- { /* bfd_set_format */ -- _bfd_bool_bfd_false_error, -- _bfd_ecoff_mkobject, -- _bfd_generic_mkarchive, -- _bfd_bool_bfd_false_error -- }, -- { /* bfd_write_contents */ -- _bfd_bool_bfd_false_error, -- _bfd_ecoff_write_object_contents, -- _bfd_write_archive_contents, -- _bfd_bool_bfd_false_error -- }, -- -- BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), -- BFD_JUMP_TABLE_COPY (_bfd_ecoff), -- BFD_JUMP_TABLE_CORE (_bfd_nocore), -- BFD_JUMP_TABLE_ARCHIVE (sw_64_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), -- -- NULL, -- -- &sw_64_ecoff_backend_data --}; ---- b/bfd/cpu-sw_64.c -+++ /dev/null -@@ -1,59 +0,0 @@ --/* BFD support for the Sw_64 architecture. -- Copyright (C) 1992-2018 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 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. */ -- --#include "sysdep.h" --#include "bfd.h" --#include "libbfd.h" -- --#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \ -- { \ -- BITS_WORD, /* Bits in a word. */ \ -- BITS_ADDR, /* Bits in an address. */ \ -- 8, /* Bits in a byte. */ \ -- bfd_arch_sw_64, \ -- NUMBER, \ -- "sw_64", \ -- PRINT, \ -- 3, /* Section alignment power. */ \ -- DEFAULT, \ -- bfd_default_compatible, \ -- bfd_default_scan, \ -- bfd_arch_default_fill, \ -- NEXT, \ -- 0 /* Maximum offset of a reloc from the start of an insn. */ \ -- } -- --enum --{ -- I_sw6a, -- I_sw6b --}; -- --#define NN(index) (&arch_info_struct[(index) + 1]) --static const bfd_arch_info_type arch_info_struct[] = --{ -- N (64, 64, bfd_mach_sw_64_sw6a, "sw_64:4", false, NN(I_sw6a)), -- N (64, 64, bfd_mach_sw_64_sw6a, "sw_64:4", false, NN(I_sw6b)), -- /* The next element of the last one should be NULL. */ -- N (64, 64, bfd_mach_sw_64_sw6b, "sw_64:8", false, NULL), --}; -- --const bfd_arch_info_type bfd_sw_64_arch = -- N (64, 64, 0, "sw_64", false, &arch_info_struct[0]); ---- b/bfd/elf64-sw_64.c -+++ /dev/null -@@ -1,5718 +0,0 @@ --/* Sw_64 specific support for 64-bit ELF -- Copyright (C) 1996-2021 Free Software Foundation, Inc. -- Contributed by Richard Henderson . -- -- This file is part of BFD, the Binary File Descriptor library. -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. */ -- -- --/* We need a published ABI spec for this. Until one comes out, don't -- assume this'll remain unchanged forever. */ -- --#include "sysdep.h" --#include "bfd.h" --#include "libbfd.h" --#include "elf-bfd.h" --#include "ecoff-bfd.h" -- --#include "elf/sw_64.h" -- --#define SW_64ECOFF -- --#define NO_COFF_RELOCS --#define NO_COFF_SYMBOLS --#define NO_COFF_LINENOS -- --/* Get the ECOFF swapping routines. Needed for the debug information. */ --#include "coff/internal.h" --#include "coff/sym.h" --#include "coff/symconst.h" --#include "coff/ecoff.h" --#include "coff/sw_64.h" --#include "aout/ar.h" --#include "libcoff.h" --#include "libecoff.h" --#define ECOFF_64 --#include "ecoffswap.h" -- -- --/* Instruction data for plt generation and relaxation. */ -- --#define OP_LDI 0x3eU --#define OP_LDIH 0x3fU --#define OP_LDL 0x23U --#define OP_BR 0x04U --#define OP_BSR 0x05U -- --#define INSN_LDI (OP_LDI << 26) --#define INSN_LDIH (OP_LDIH << 26) --#define INSN_LDL (OP_LDL << 26) --#define INSN_BR (OP_BR << 26) -- --#define INSN_ADDL 0x40000100 --#define INSN_RDUNIQ 0x0000009e --#define INSN_SUBL 0x40000120 --#define INSN_S4SUBL 0x40000160 --#define INSN_UNOP 0x43ff075f -- --#define INSN_JSR 0x04000000 --#define INSN_JMP 0x0c000000 --#define INSN_JSR_MASK 0xfc000000 --#define INSN_LDL_MASK 0xfc000000 -- --#define INSN_A(I,A) (I | ((unsigned) A << 21)) --#define INSN_AB(I,A,B) (INSN_A (I, A) | (B << 16)) --#define INSN_ABC(I,A,B,C) (INSN_A (I, A) | (B << 16) | C) --#define INSN_ABO(I,A,B,O) (INSN_A (I, A) | (B << 16) | ((O) & 0xffff)) --#define INSN_AD(I,A,D) (INSN_A (I, A) | (((D) >> 2) & 0x1fffff)) -- --/* PLT/GOT Stuff */ -- --/* Set by ld emulation. Putting this into the link_info or hash structure -- is simply working too hard. */ --#ifdef USE_SECUREPLT --bool elf64_sw_64_use_secureplt = true; --#else --bool elf64_sw_64_use_secureplt = false; --#endif -- --#define OLD_PLT_HEADER_SIZE 32 --#define OLD_PLT_ENTRY_SIZE 12 --#define NEW_PLT_HEADER_SIZE 36 --#define NEW_PLT_ENTRY_SIZE 4 -- --#define PLT_HEADER_SIZE \ -- (elf64_sw_64_use_secureplt ? NEW_PLT_HEADER_SIZE : OLD_PLT_HEADER_SIZE) --#define PLT_ENTRY_SIZE \ -- (elf64_sw_64_use_secureplt ? NEW_PLT_ENTRY_SIZE : OLD_PLT_ENTRY_SIZE) -- --#define MAX_GOT_SIZE_NEW (1024*1024*2048-1) -- --#define MAX_GOT_SIZE (64*1024) -- --#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so" -- -- --/* Used to implement multiple .got subsections. */ --struct sw_64_elf_got_entry --{ -- struct sw_64_elf_got_entry *next; -- -- /* Which .got subsection? */ -- bfd *gotobj; -- -- /* The addend in effect for this entry. */ -- bfd_vma addend; -- -- /* The .got offset for this entry. */ -- int got_offset; -- -- /* The .plt offset for this entry. */ -- int plt_offset; -- -- /* How many references to this entry? */ -- int use_count; -- -- /* The relocation type of this entry. */ -- unsigned char reloc_type; -- -- /* How a LITERAL is used. */ -- unsigned char flags; -- -- /* Have we initialized the dynamic relocation for this entry? */ -- unsigned char reloc_done; -- -- /* Have we adjusted this entry for SEC_MERGE? */ -- unsigned char reloc_xlated; --}; -- --struct sw_64_elf_reloc_entry --{ -- struct sw_64_elf_reloc_entry *next; -- -- /* Which .reloc section? */ -- asection *srel; -- -- /* Which section this relocation is against? */ -- asection *sec; -- -- /* How many did we find? */ -- unsigned long count; -- -- /* What kind of relocation? */ -- unsigned int rtype; --}; -- --struct sw_64_elf_link_hash_entry --{ -- struct elf_link_hash_entry root; -- -- /* External symbol information. */ -- EXTR esym; -- -- /* Cumulative flags for all the .got entries. */ -- int flags; -- -- /* Contexts in which a literal was referenced. */ --#define SW_64_ELF_LINK_HASH_LU_ADDR 0x01 --#define SW_64_ELF_LINK_HASH_LU_MEM 0x02 --#define SW_64_ELF_LINK_HASH_LU_BYTE 0x04 --#define SW_64_ELF_LINK_HASH_LU_JSR 0x08 --#define SW_64_ELF_LINK_HASH_LU_TLSGD 0x10 --#define SW_64_ELF_LINK_HASH_LU_TLSLDM 0x20 --#define SW_64_ELF_LINK_HASH_LU_JSRDIRECT 0x40 --#define SW_64_ELF_LINK_HASH_LU_PLT 0x38 --#define SW_64_ELF_LINK_HASH_TLS_IE 0x80 -- -- /* Used to implement multiple .got subsections. */ -- struct sw_64_elf_got_entry *got_entries; -- -- /* Used to count non-got, non-plt relocations for delayed sizing -- of relocation sections. */ -- struct sw_64_elf_reloc_entry *reloc_entries; --}; -- --/* Sw_64 ELF linker hash table. */ -- --struct sw_64_elf_link_hash_table --{ -- struct elf_link_hash_table root; -- -- /* The head of a list of .got subsections linked through -- sw_64_elf_tdata(abfd)->got_link_next. */ -- bfd *got_list; -- -- /* The most recent relax pass that we've seen. The GOTs -- should be regenerated if this doesn't match. */ -- int relax_trip; --}; -- --/* Look up an entry in a Sw_64 ELF linker hash table. */ -- --#define sw_64_elf_link_hash_lookup(table, string, create, copy, follow) \ -- ((struct sw_64_elf_link_hash_entry *) \ -- elf_link_hash_lookup (&(table)->root, (string), (create), \ -- (copy), (follow))) -- --/* Traverse a Sw_64 ELF linker hash table. */ -- --#define sw_64_elf_link_hash_traverse(table, func, info) \ -- (elf_link_hash_traverse \ -- (&(table)->root, \ -- (bool (*) (struct elf_link_hash_entry *, void *)) (func), \ -- (info))) -- --/* Get the Sw_64 ELF linker hash table from a link_info structure. */ -- --#define sw_64_elf_hash_table(p) \ -- ((is_elf_hash_table ((p)->hash) \ -- && elf_hash_table_id (elf_hash_table (p)) == SW_64_ELF_DATA) \ -- ? (struct sw_64_elf_link_hash_table *) (p)->hash : NULL) -- --/* Get the object's symbols as our own entry type. */ -- --#define sw_64_elf_sym_hashes(abfd) \ -- ((struct sw_64_elf_link_hash_entry **)elf_sym_hashes(abfd)) -- --/* Should we do dynamic things to this symbol? This differs from the -- generic version in that we never need to consider function pointer -- equality wrt PLT entries -- we don't create a PLT entry if a symbol's -- address is ever taken. */ -- -- static inline bool --sw_64_elf_dynamic_symbol_p (struct elf_link_hash_entry *h, -- struct bfd_link_info *info) --{ -- return _bfd_elf_dynamic_symbol_p (h, info, 0); --} -- --/* Create an entry in a Sw_64 ELF linker hash table. */ -- -- static struct bfd_hash_entry * --elf64_sw_64_link_hash_newfunc (struct bfd_hash_entry *entry, -- struct bfd_hash_table *table, -- const char *string) --{ -- struct sw_64_elf_link_hash_entry *ret = -- (struct sw_64_elf_link_hash_entry *) entry; -- -- /* Allocate the structure if it has not already been allocated by a -- subclass. */ -- if (ret == (struct sw_64_elf_link_hash_entry *) NULL) -- ret = ((struct sw_64_elf_link_hash_entry *) -- bfd_hash_allocate (table, -- sizeof (struct sw_64_elf_link_hash_entry))); -- if (ret == (struct sw_64_elf_link_hash_entry *) NULL) -- return (struct bfd_hash_entry *) ret; -- -- /* Call the allocation method of the superclass. */ -- ret = ((struct sw_64_elf_link_hash_entry *) -- _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, -- table, string)); -- if (ret != (struct sw_64_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; -- ret->flags = 0; -- ret->got_entries = NULL; -- ret->reloc_entries = NULL; -- } -- -- return (struct bfd_hash_entry *) ret; --} -- --/* Create a Sw_64 ELF linker hash table. */ -- -- static struct bfd_link_hash_table * --elf64_sw_64_bfd_link_hash_table_create (bfd *abfd) --{ -- struct sw_64_elf_link_hash_table *ret; -- size_t amt = sizeof (struct sw_64_elf_link_hash_table); -- -- ret = (struct sw_64_elf_link_hash_table *) bfd_zmalloc (amt); -- if (ret == (struct sw_64_elf_link_hash_table *) NULL) -- return NULL; -- -- if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, -- elf64_sw_64_link_hash_newfunc, -- sizeof (struct sw_64_elf_link_hash_entry), -- SW_64_ELF_DATA)) -- { -- free (ret); -- return NULL; -- } -- -- return &ret->root.root; --} -- --/* Sw_64 ELF follows MIPS ELF in using a special find_nearest_line -- routine in order to handle the ECOFF debugging information. */ -- --struct sw_64_elf_find_line --{ -- struct ecoff_debug_info d; -- struct ecoff_find_line i; --}; -- --/* We have some private fields hanging off of the elf_tdata structure. */ -- --struct sw_64_elf_obj_tdata --{ -- struct elf_obj_tdata root; -- -- /* For every input file, these are the got entries for that object's -- local symbols. */ -- struct sw_64_elf_got_entry ** local_got_entries; -- -- /* For every input file, this is the object that owns the got that -- this input file uses. */ -- bfd *gotobj; -- -- /* For every got, this is a linked list through the objects using this got */ -- bfd *in_got_link_next; -- -- /* For every got, this is a link to the next got subsegment. */ -- bfd *got_link_next; -- -- /* For every got, this is the section. */ -- asection *got; -- -- /* For every got, this is it's total number of words. */ -- int total_got_size; -- -- /* For every got, this is the sum of the number of words required -- to hold all of the member object's local got. */ -- int local_got_size; -- -- /* Used by elf64_sw_64_find_nearest_line entry point. */ -- struct sw_64_elf_find_line *find_line_info; -- --}; -- --#define sw_64_elf_tdata(abfd) \ -- ((struct sw_64_elf_obj_tdata *) (abfd)->tdata.any) -- --#define is_sw_64_elf(bfd) \ -- (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ -- && elf_tdata (bfd) != NULL \ -- && elf_object_id (bfd) == SW_64_ELF_DATA) -- -- static bool --elf64_sw_64_mkobject (bfd *abfd) --{ -- return bfd_elf_allocate_object (abfd, sizeof (struct sw_64_elf_obj_tdata), -- SW_64_ELF_DATA); --} -- --/* Return the MACH for a sw_64 e_flags value. */ -- unsigned long --bfd_elf_sw_64_mach (flagword flags) --{ -- switch (flags) -- { -- case E_SW_64_MACH_SW6A: -- return bfd_mach_sw_64_sw6a; -- case E_SW_64_MACH_SW6B: -- return bfd_mach_sw_64_sw6b; -- default: -- return 0; -- } -- return 0; --} -- -- static bool --elf64_sw_64_object_p (bfd *abfd) --{ -- /* Set the right machine number for an Sw_64 ELF file. */ -- unsigned long mach; -- -- mach = bfd_elf_sw_64_mach (elf_elfheader (abfd)->e_flags); -- return bfd_default_set_arch_mach (abfd, bfd_arch_sw_64, mach); --} -- --/* A relocation function which doesn't do anything. */ -- -- static bfd_reloc_status_type --elf64_sw_64_reloc_nil (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc, -- asymbol *sym ATTRIBUTE_UNUSED, -- void * data ATTRIBUTE_UNUSED, asection *sec, -- bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) --{ -- if (output_bfd) -- reloc->address += sec->output_offset; -- return bfd_reloc_ok; --} -- --/* A relocation function used for an unsupported reloc. */ -- -- static bfd_reloc_status_type --elf64_sw_64_reloc_bad (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc, -- asymbol *sym ATTRIBUTE_UNUSED, -- void * data ATTRIBUTE_UNUSED, asection *sec, -- bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) --{ -- if (output_bfd) -- reloc->address += sec->output_offset; -- return bfd_reloc_notsupported; --} -- --/* Do the work of the GPDISP relocation. */ -- -- static bfd_reloc_status_type --elf64_sw_64_do_reloc_gpdisp (bfd *abfd, bfd_vma gpdisp, bfd_byte *p_ldih, -- bfd_byte *p_ldi) --{ -- bfd_reloc_status_type ret = bfd_reloc_ok; -- bfd_vma addend; -- unsigned long i_ldih, i_ldi; -- -- i_ldih = bfd_get_32 (abfd, p_ldih); -- i_ldi = bfd_get_32 (abfd, p_ldi); -- -- /* Complain if the instructions are not correct. */ -- if (((i_ldih >> 26) & 0x3f) != 0x3f -- || ((i_ldi >> 26) & 0x3f) != 0x3e) -- ret = bfd_reloc_dangerous; -- -- /* Extract the user-supplied offset, mirroring the sign extensions -- that the instructions perform. */ -- addend = ((i_ldih & 0xffff) << 16) | (i_ldi & 0xffff); -- addend = (addend ^ 0x80008000) - 0x80008000; -- -- gpdisp += addend; -- -- if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000 -- || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000) -- ret = bfd_reloc_overflow; -- -- /* compensate for the sign extension again. */ -- i_ldih = ((i_ldih & 0xffff0000) -- | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff)); -- i_ldi = (i_ldi & 0xffff0000) | (gpdisp & 0xffff); -- -- bfd_put_32 (abfd, (bfd_vma) i_ldih, p_ldih); -- bfd_put_32 (abfd, (bfd_vma) i_ldi, p_ldi); -- -- return ret; --} -- --/* The special function for the GPDISP reloc. */ -- -- static bfd_reloc_status_type --elf64_sw_64_reloc_gpdisp (bfd *abfd, arelent *reloc_entry, -- asymbol *sym ATTRIBUTE_UNUSED, void * data, -- asection *input_section, bfd *output_bfd, -- char **err_msg) --{ -- bfd_reloc_status_type ret; -- bfd_vma gp, relocation; -- bfd_vma high_address; -- bfd_byte *p_ldih, *p_ldi; -- -- /* Don't do anything if we're not doing a final link. */ -- if (output_bfd) -- { -- reloc_entry->address += input_section->output_offset; -- return bfd_reloc_ok; -- } -- -- high_address = bfd_get_section_limit (abfd, input_section); -- if (reloc_entry->address > high_address -- || reloc_entry->address + reloc_entry->addend > high_address) -- return bfd_reloc_outofrange; -- -- /* The gp used in the portion of the output object to which this -- input object belongs is cached on the input bfd. */ -- gp = _bfd_get_gp_value (abfd); -- -- relocation = (input_section->output_section->vma -- + input_section->output_offset -- + reloc_entry->address); -- -- p_ldih = (bfd_byte *) data + reloc_entry->address; -- p_ldi = p_ldih + reloc_entry->addend; -- -- ret = elf64_sw_64_do_reloc_gpdisp (abfd, gp - relocation, p_ldih, p_ldi); -- -- /* Complain if the instructions are not correct. */ -- if (ret == bfd_reloc_dangerous) -- *err_msg = _("GPDISP relocation did not find ldih and ldi instructions"); -- -- return ret; --} -- --/* 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) -- -- --#define SKIP_HOWTO(N) \ -- HOWTO(N, 0, 0, 0, 0, 0, complain_overflow_dont, elf64_sw_64_reloc_bad, 0, 0, 0, 0, 0) -- --static reloc_howto_type elf64_sw_64_howto_table[] = --{ -- HOWTO (R_SW_64_NONE, /* type */ -- 0, /* rightshift */ -- 3, /* size (0 = byte, 1 = short, 2 = long) */ -- 0, /* bitsize */ -- true, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- elf64_sw_64_reloc_nil, /* special_function */ -- "NONE", /* name */ -- false, /* partial_inplace */ -- 0, /* src_mask */ -- 0, /* dst_mask */ -- true), /* pcrel_offset */ -- -- /* A 32 bit reference to a symbol. */ -- HOWTO (R_SW_64_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 */ -- bfd_elf_generic_reloc, /* special_function */ -- "REFLONG", /* name */ -- false, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* A 64 bit reference to a symbol. */ -- HOWTO (R_SW_64_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 */ -- bfd_elf_generic_reloc, /* special_function */ -- "REFQUAD", /* name */ -- false, /* 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 (R_SW_64_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 */ -- "GPREL32", /* name */ -- false, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* Used for an instruction that refers to memory off the GP register. */ -- HOWTO (R_SW_64_LITERAL, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "ELF_LITERAL", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* This reloc only appears immediately following an ELF_LITERAL reloc. -- It identifies a use of the literal. 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 (R_SW_64_LITUSE, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- elf64_sw_64_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 ldih instruction -- which loads the upper 16 bits of the gp register. The symbol -- index of the GPDISP instruction is an offset in bytes to the ldi -- instruction that loads the lower 16 bits. 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. -- -- NOTE: Unlike ECOFF, partial in-place relocation is not done. If -- any offset is present in the instructions, it is an offset from -- the register to the ldih instruction. This lets us avoid any -- stupid hackery like inventing a gp value to do partial relocation -- against. Also unlike ECOFF, we do the whole relocation off of -- the GPDISP rather than a GPDISP_HI16/GPDISP_LO16 pair. An odd, -- space consuming bit, that, since all the information was present -- in the GPDISP_HI16 reloc. */ -- HOWTO (R_SW_64_GPDISP, /* type */ -- 16, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- elf64_sw_64_reloc_gpdisp, /* special_function */ -- "GPDISP", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- true), /* pcrel_offset */ -- -- /* A 21 bit branch. */ -- HOWTO (R_SW_64_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 */ -- bfd_elf_generic_reloc, /* special_function */ -- "BRADDR", /* name */ -- false, /* partial_inplace */ -- 0x1fffff, /* src_mask */ -- 0x1fffff, /* dst_mask */ -- true), /* pcrel_offset */ -- -- /* A hint for a jump to a register. */ -- HOWTO (R_SW_64_HINT, /* type */ -- 2, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- true, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "HINT", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- true), /* pcrel_offset */ -- -- /* 16 bit PC relative offset. */ -- HOWTO (R_SW_64_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 */ -- bfd_elf_generic_reloc, /* special_function */ -- "SREL16", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- true), /* pcrel_offset */ -- -- /* 32 bit PC relative offset. */ -- HOWTO (R_SW_64_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 */ -- bfd_elf_generic_reloc, /* special_function */ -- "SREL32", /* name */ -- false, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- true), /* pcrel_offset */ -- -- /* A 64 bit PC relative offset. */ -- HOWTO (R_SW_64_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 */ -- bfd_elf_generic_reloc, /* special_function */ -- "SREL64", /* name */ -- false, /* partial_inplace */ -- MINUS_ONE, /* src_mask */ -- MINUS_ONE, /* dst_mask */ -- true), /* pcrel_offset */ -- -- /* Skip 12 - 16; deprecated ECOFF relocs. */ -- SKIP_HOWTO (12), -- SKIP_HOWTO (13), -- SKIP_HOWTO (14), -- SKIP_HOWTO (15), -- SKIP_HOWTO (16), -- -- /* The high 16 bits of the displacement from GP to the target. */ -- HOWTO (R_SW_64_GPRELHIGH, -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "GPRELHIGH", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* The low 16 bits of the displacement from GP to the target. */ -- HOWTO (R_SW_64_GPRELLOW, -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "GPRELLOW", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* A 16-bit displacement from the GP to the target. */ -- HOWTO (R_SW_64_GPREL16, -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "GPREL16", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* Skip 20 - 23; deprecated ECOFF relocs. */ -- SKIP_HOWTO (20), -- SKIP_HOWTO (21), -- SKIP_HOWTO (22), -- SKIP_HOWTO (23), -- -- /* Misc ELF relocations. */ -- -- /* A dynamic relocation to copy the target into our .dynbss section. */ -- /* Not generated, as all Sw_64 objects use PIC, so it is not needed. It -- is present because every other ELF has one, but should not be used -- because .dynbss is an ugly thing. */ -- HOWTO (R_SW_64_COPY, -- 0, -- 0, -- 0, -- false, -- 0, -- complain_overflow_dont, -- bfd_elf_generic_reloc, -- "COPY", -- false, -- 0, -- 0, -- true), -- -- /* A dynamic relocation for a .got entry. */ -- HOWTO (R_SW_64_GLOB_DAT, -- 0, -- 0, -- 0, -- false, -- 0, -- complain_overflow_dont, -- bfd_elf_generic_reloc, -- "GLOB_DAT", -- false, -- 0, -- 0, -- true), -- -- /* A dynamic relocation for a .plt entry. */ -- HOWTO (R_SW_64_JMP_SLOT, -- 0, -- 0, -- 0, -- false, -- 0, -- complain_overflow_dont, -- bfd_elf_generic_reloc, -- "JMP_SLOT", -- false, -- 0, -- 0, -- true), -- -- /* A dynamic relocation to add the base of the DSO to a 64-bit field. */ -- HOWTO (R_SW_64_RELATIVE, -- 0, -- 0, -- 0, -- false, -- 0, -- complain_overflow_dont, -- bfd_elf_generic_reloc, -- "RELATIVE", -- false, -- 0, -- 0, -- true), -- -- /* A 21 bit branch that adjusts for gp loads. */ -- HOWTO (R_SW_64_BRSGP, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 21, /* bitsize */ -- true, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "BRSGP", /* name */ -- false, /* partial_inplace */ -- 0x1fffff, /* src_mask */ -- 0x1fffff, /* dst_mask */ -- true), /* pcrel_offset */ -- -- /* Creates a tls_index for the symbol in the got. */ -- HOWTO (R_SW_64_TLSGD, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "TLSGD", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* Creates a tls_index for the (current) module in the got. */ -- HOWTO (R_SW_64_TLSLDM, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "TLSLDM", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* A dynamic relocation for a DTP module entry. */ -- HOWTO (R_SW_64_DTPMOD64, /* type */ -- 0, /* rightshift */ -- 4, /* size (0 = byte, 1 = short, 2 = long) */ -- 64, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "DTPMOD64", /* name */ -- false, /* partial_inplace */ -- MINUS_ONE, /* src_mask */ -- MINUS_ONE, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* Creates a 64-bit offset in the got for the displacement -- from DTP to the target. */ -- HOWTO (R_SW_64_GOTDTPREL, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "GOTDTPREL", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* A dynamic relocation for a displacement from DTP to the target. */ -- HOWTO (R_SW_64_DTPREL64, /* type */ -- 0, /* rightshift */ -- 4, /* size (0 = byte, 1 = short, 2 = long) */ -- 64, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "DTPREL64", /* name */ -- false, /* partial_inplace */ -- MINUS_ONE, /* src_mask */ -- MINUS_ONE, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* The high 16 bits of the displacement from DTP to the target. */ -- HOWTO (R_SW_64_DTPRELHI, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "DTPRELHI", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* The low 16 bits of the displacement from DTP to the target. */ -- HOWTO (R_SW_64_DTPRELLO, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "DTPRELLO", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* A 16-bit displacement from DTP to the target. */ -- HOWTO (R_SW_64_DTPREL16, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "DTPREL16", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* Creates a 64-bit offset in the got for the displacement -- from TP to the target. */ -- HOWTO (R_SW_64_GOTTPREL, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "GOTTPREL", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* A dynamic relocation for a displacement from TP to the target. */ -- HOWTO (R_SW_64_TPREL64, /* type */ -- 0, /* rightshift */ -- 4, /* size (0 = byte, 1 = short, 2 = long) */ -- 64, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "TPREL64", /* name */ -- false, /* partial_inplace */ -- MINUS_ONE, /* src_mask */ -- MINUS_ONE, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* The high 16 bits of the displacement from TP to the target. */ -- HOWTO (R_SW_64_TPRELHI, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "TPRELHI", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* The low 16 bits of the displacement from TP to the target. */ -- HOWTO (R_SW_64_TPRELLO, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "TPRELLO", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- -- /* A 16-bit displacement from TP to the target. */ -- HOWTO (R_SW_64_TPREL16, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "TPREL16", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ -- /* A 26 bit branch. */ -- HOWTO (R_SW_64_BR26ADDR, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 26, /* bitsize */ -- true, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "BR26ADDR", /* name */ -- false, /* partial_inplace */ -- 0x3ffffff, /* src_mask */ -- 0x3ffffff, /* dst_mask */ -- true), /* pcrel_offset */ -- HOWTO (R_SW_64_LITERAL_GOT, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- false, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "ELF_LITERAL_GOT", /* name */ -- false, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- false), /* pcrel_offset */ --}; -- --/* A mapping from BFD reloc types to Sw_64 ELF reloc types. */ -- --struct elf_reloc_map --{ -- bfd_reloc_code_real_type bfd_reloc_val; -- int elf_reloc_val; --}; -- --static const struct elf_reloc_map elf64_sw_64_reloc_map[] = --{ -- {BFD_RELOC_NONE, R_SW_64_NONE}, -- {BFD_RELOC_32, R_SW_64_REFLONG}, -- {BFD_RELOC_64, R_SW_64_REFQUAD}, -- {BFD_RELOC_CTOR, R_SW_64_REFQUAD}, -- {BFD_RELOC_GPREL32, R_SW_64_GPREL32}, -- {BFD_RELOC_SW_64_ELF_LITERAL, R_SW_64_LITERAL}, -- {BFD_RELOC_SW_64_LITUSE, R_SW_64_LITUSE}, -- {BFD_RELOC_SW_64_GPDISP, R_SW_64_GPDISP}, -- {BFD_RELOC_23_PCREL_S2, R_SW_64_BRADDR}, -- {BFD_RELOC_SW_64_HINT, R_SW_64_HINT}, -- {BFD_RELOC_16_PCREL, R_SW_64_SREL16}, -- {BFD_RELOC_32_PCREL, R_SW_64_SREL32}, -- {BFD_RELOC_64_PCREL, R_SW_64_SREL64}, -- {BFD_RELOC_SW_64_GPREL_HI16, R_SW_64_GPRELHIGH}, -- {BFD_RELOC_SW_64_GPREL_LO16, R_SW_64_GPRELLOW}, -- {BFD_RELOC_GPREL16, R_SW_64_GPREL16}, -- {BFD_RELOC_SW_64_BRSGP, R_SW_64_BRSGP}, -- {BFD_RELOC_SW_64_TLSGD, R_SW_64_TLSGD}, -- {BFD_RELOC_SW_64_TLSLDM, R_SW_64_TLSLDM}, -- {BFD_RELOC_SW_64_DTPMOD64, R_SW_64_DTPMOD64}, -- {BFD_RELOC_SW_64_GOTDTPREL16, R_SW_64_GOTDTPREL}, -- {BFD_RELOC_SW_64_DTPREL64, R_SW_64_DTPREL64}, -- {BFD_RELOC_SW_64_DTPREL_HI16, R_SW_64_DTPRELHI}, -- {BFD_RELOC_SW_64_DTPREL_LO16, R_SW_64_DTPRELLO}, -- {BFD_RELOC_SW_64_DTPREL16, R_SW_64_DTPREL16}, -- {BFD_RELOC_SW_64_GOTTPREL16, R_SW_64_GOTTPREL}, -- {BFD_RELOC_SW_64_TPREL64, R_SW_64_TPREL64}, -- {BFD_RELOC_SW_64_TPREL_HI16, R_SW_64_TPRELHI}, -- {BFD_RELOC_SW_64_TPREL_LO16, R_SW_64_TPRELLO}, -- {BFD_RELOC_SW_64_TPREL16, R_SW_64_TPREL16}, -- {BFD_RELOC_SW_64_BR26, R_SW_64_BR26ADDR}, -- {BFD_RELOC_SW_64_ELF_LITERAL_GOT, R_SW_64_LITERAL_GOT}, --}; -- --/* Given a BFD reloc type, return a HOWTO structure. */ -- -- static reloc_howto_type * --elf64_sw_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, -- bfd_reloc_code_real_type code) --{ -- const struct elf_reloc_map *i, *e; -- i = e = elf64_sw_64_reloc_map; -- e += sizeof (elf64_sw_64_reloc_map) / sizeof (struct elf_reloc_map); -- for (; i != e; ++i) -- { -- if (i->bfd_reloc_val == code) -- return &elf64_sw_64_howto_table[i->elf_reloc_val]; -- } -- return 0; --} -- -- static reloc_howto_type * --elf64_sw_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, -- const char *r_name) --{ -- unsigned int i; -- -- for (i = 0; -- i < (sizeof (elf64_sw_64_howto_table) -- / sizeof (elf64_sw_64_howto_table[0])); -- i++) -- if (elf64_sw_64_howto_table[i].name != NULL -- && strcasecmp (elf64_sw_64_howto_table[i].name, r_name) == 0) -- return &elf64_sw_64_howto_table[i]; -- -- return NULL; --} -- --/* Given an Sw_64 ELF reloc type, fill in an arelent structure. */ -- -- static bool --elf64_sw_64_info_to_howto (bfd *abfd, arelent *cache_ptr, -- Elf_Internal_Rela *dst) --{ -- unsigned r_type = ELF64_R_TYPE(dst->r_info); -- -- if (r_type >= R_SW_64_max) -- { -- /* xgettext:c-format */ -- _bfd_error_handler (_("%pB: unsupported relocation type %#x"), -- abfd, r_type); -- bfd_set_error (bfd_error_bad_value); -- return false; -- } -- cache_ptr->howto = &elf64_sw_64_howto_table[r_type]; -- return true; --} -- --/* These two relocations create a two-word entry in the got. */ --#define sw_64_got_entry_size(r_type) \ -- (r_type == R_SW_64_TLSGD || r_type == R_SW_64_TLSLDM ? 16 : 8) -- --/* This is PT_TLS segment p_vaddr. */ --#define sw_64_get_dtprel_base(info) \ -- (elf_hash_table (info)->tls_sec->vma) -- --/* Main program TLS (whose template starts at PT_TLS p_vaddr) -- is assigned offset round(16, PT_TLS p_align). */ --#define sw_64_get_tprel_base(info) \ -- (elf_hash_table (info)->tls_sec->vma \ -- - align_power ((bfd_vma) 16, \ -- elf_hash_table (info)->tls_sec->alignment_power)) -- --/* Handle an Sw_64 specific section when reading an object file. This -- is called when bfd_section_from_shdr finds a section with an unknown -- type. */ -- -- static bool --elf64_sw_64_section_from_shdr (bfd *abfd, -- Elf_Internal_Shdr *hdr, -- const char *name, -- int shindex) --{ -- 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_SW_64_DEBUG: -- if (strcmp (name, ".mdebug") != 0) -- return false; -- break; -- default: -- return false; -- } -- -- if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) -- return false; -- newsect = hdr->bfd_section; -- -- if (hdr->sh_type == SHT_SW_64_DEBUG) -- { -- if (!bfd_set_section_flags (newsect, -- bfd_section_flags (newsect) | SEC_DEBUGGING)) -- return false; -- } -- -- return true; --} -- --/* Convert Sw_64 specific section flags to bfd internal section flags. */ -- -- static bool --elf64_sw_64_section_flags (const Elf_Internal_Shdr *hdr) --{ -- if (hdr->sh_flags & SHF_SW_64_GPREL) -- hdr->bfd_section->flags |= SEC_SMALL_DATA; -- -- return true; --} -- --/* Set the correct type for an Sw_64 ELF section. We do this by the -- section name, which is a hack, but ought to work. */ -- -- static bool --elf64_sw_64_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) --{ -- register const char *name; -- -- name = bfd_section_name (sec); -- -- if (strcmp (name, ".mdebug") == 0) -- { -- hdr->sh_type = SHT_SW_64_DEBUG; -- /* In a shared object on Irix 5.3, the .mdebug section has an -- entsize of 0. FIXME: Does this matter? */ -- if ((abfd->flags & DYNAMIC) != 0 ) -- hdr->sh_entsize = 0; -- else -- hdr->sh_entsize = 1; -- } -- else if ((sec->flags & SEC_SMALL_DATA) -- || strcmp (name, ".sdata") == 0 -- || strcmp (name, ".sbss") == 0 -- || strcmp (name, ".lit4") == 0 -- || strcmp (name, ".lit8") == 0) -- hdr->sh_flags |= SHF_SW_64_GPREL; -- -- return true; --} -- --/* Hook called by the linker routine which adds symbols from an object -- file. We use it to put .comm items in .sbss, and not .bss. */ -- -- static bool --elf64_sw_64_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, -- Elf_Internal_Sym *sym, -- const char **namep ATTRIBUTE_UNUSED, -- flagword *flagsp ATTRIBUTE_UNUSED, -- asection **secp, bfd_vma *valp) --{ -- if (sym->st_shndx == SHN_COMMON -- && !bfd_link_relocatable (info) -- && sym->st_size <= elf_gp_size (abfd)) -- { -- /* Common symbols less than or equal to -G nn bytes are -- automatically put into .sbss. */ -- -- asection *scomm = bfd_get_section_by_name (abfd, ".scommon"); -- -- if (scomm == NULL) -- { -- scomm = bfd_make_section_with_flags (abfd, ".scommon", -- (SEC_ALLOC -- | SEC_IS_COMMON -- | SEC_SMALL_DATA -- | SEC_LINKER_CREATED)); -- if (scomm == NULL) -- return false; -- } -- -- *secp = scomm; -- *valp = sym->st_size; -- } -- -- return true; --} -- --/* Create the .got section. */ -- -- static bool --elf64_sw_64_create_got_section (bfd *abfd, -- struct bfd_link_info *info ATTRIBUTE_UNUSED) --{ -- flagword flags; -- asection *s; -- -- if (! is_sw_64_elf (abfd)) -- return false; -- -- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY -- | SEC_LINKER_CREATED); -- s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); -- if (s == NULL -- || !bfd_set_section_alignment (s, 3)) -- return false; -- -- sw_64_elf_tdata (abfd)->got = s; -- -- /* Make sure the object's gotobj is set to itself so that we default -- to every object with its own .got. We'll merge .gots later once -- we've collected each object's info. */ -- sw_64_elf_tdata (abfd)->gotobj = abfd; -- -- return true; --} -- --/* Create all the dynamic sections. */ -- -- static bool --elf64_sw_64_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) --{ -- asection *s; -- flagword flags; -- struct elf_link_hash_entry *h; -- -- if (! is_sw_64_elf (abfd)) -- return false; -- -- /* We need to create .plt, .rela.plt, .got, and .rela.got sections. */ -- -- flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY -- | SEC_LINKER_CREATED -- | (elf64_sw_64_use_secureplt ? SEC_READONLY : 0)); -- s = bfd_make_section_anyway_with_flags (abfd, ".plt", flags); -- elf_hash_table (info)->splt = s; -- if (s == NULL || ! bfd_set_section_alignment (s, 4)) -- return false; -- -- /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the -- .plt section. */ -- h = _bfd_elf_define_linkage_sym (abfd, info, s, -- "_PROCEDURE_LINKAGE_TABLE_"); -- elf_hash_table (info)->hplt = h; -- if (h == NULL) -- return false; -- -- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY -- | SEC_LINKER_CREATED | SEC_READONLY); -- s = bfd_make_section_anyway_with_flags (abfd, ".rela.plt", flags); -- elf_hash_table (info)->srelplt = s; -- if (s == NULL || ! bfd_set_section_alignment (s, 3)) -- return false; -- -- if (elf64_sw_64_use_secureplt) -- { -- flags = SEC_ALLOC | SEC_LINKER_CREATED; -- s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags); -- elf_hash_table (info)->sgotplt = s; -- if (s == NULL || ! bfd_set_section_alignment ( s, 3)) -- return false; -- } -- -- /* We may or may not have created a .got section for this object, but -- we definitely havn't done the rest of the work. */ -- -- if (sw_64_elf_tdata(abfd)->gotobj == NULL) -- { -- if (!elf64_sw_64_create_got_section (abfd, info)) -- return false; -- } -- -- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY -- | SEC_LINKER_CREATED | SEC_READONLY); -- s = bfd_make_section_anyway_with_flags (abfd, ".rela.got", flags); -- elf_hash_table (info)->srelgot = s; -- if (s == NULL -- || !bfd_set_section_alignment (s, 3)) -- return false; -- -- /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the -- dynobj's .got 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 = _bfd_elf_define_linkage_sym (abfd, info, sw_64_elf_tdata(abfd)->got, -- "_GLOBAL_OFFSET_TABLE_"); -- elf_hash_table (info)->hgot = h; -- if (h == NULL) -- return false; -- -- return true; --} -- --/* Read ECOFF debugging information from a .mdebug section into a -- ecoff_debug_info structure. */ -- -- static bool --elf64_sw_64_read_ecoff_info (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; -- memset (debug, 0, sizeof (*debug)); -- -- ext_hdr = (char *) bfd_malloc (swap->external_hdr_size); -- if (ext_hdr == NULL && swap->external_hdr_size != 0) -- goto error_return; -- -- if (! bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0, -- swap->external_hdr_size)) -- 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. */ --#ifdef ZZH20210707_SWGNU --#define READ(ptr, offset, count, size, type) \ -- do \ -- { \ -- size_t amt; \ -- debug->ptr = NULL; \ -- if (symhdr->count == 0) \ -- break; \ -- if (_bfd_mul_overflow (size, symhdr->count, &amt)) \ -- { \ -- bfd_set_error (bfd_error_file_too_big); \ -- goto error_return; \ -- } \ -- if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0) \ -- goto error_return; \ -- debug->ptr = (type) _bfd_malloc_and_read (abfd, amt, amt); \ -- if (debug->ptr == NULL) \ -- goto error_return; \ -- } while (0) --#else --#define READ(ptr, offset, count, size, type) \ -- if (symhdr->count == 0) \ -- debug->ptr = NULL; \ -- else \ -- { \ -- bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ -- debug->ptr = (type) bfd_malloc (amt); \ -- if (debug->ptr == NULL) \ -- goto error_return; \ -- if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ -- || bfd_bread (debug->ptr, amt, abfd) != amt) \ -- goto error_return; \ -- } --#endif -- -- READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); -- READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *); -- READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *); -- READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *); -- READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *); -- 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, void *); -- READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *); -- READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *); --#undef READ -- -- debug->fdr = NULL; -- -- return true; -- --error_return: -- free (ext_hdr); -- free (debug->line); -- free (debug->external_dnr); -- free (debug->external_pdr); -- free (debug->external_sym); -- free (debug->external_opt); -- free (debug->external_aux); -- free (debug->ss); -- free (debug->ssext); -- free (debug->external_fdr); -- free (debug->external_rfd); -- free (debug->external_ext); -- return false; --} -- --/* Sw_64 ELF local labels start with '$'. */ -- -- static bool --elf64_sw_64_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name) --{ -- return name[0] == '$'; --} -- -- static bool --elf64_sw_64_find_nearest_line (bfd *abfd, asymbol **symbols, -- asection *section, bfd_vma offset, -- const char **filename_ptr, -- const char **functionname_ptr, -- unsigned int *line_ptr, -- unsigned int *discriminator_ptr) --{ -- asection *msec; -- -- if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, -- filename_ptr, functionname_ptr, -- line_ptr, discriminator_ptr, -- dwarf_debug_sections, -- &elf_tdata (abfd)->dwarf2_find_line_info) -- == 1) -- return true; -- -- msec = bfd_get_section_by_name (abfd, ".mdebug"); -- if (msec != NULL) -- { -- flagword origflags; -- struct sw_64_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, sw_64_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 = sw_64_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; -- bfd_size_type amt = sizeof (struct sw_64_elf_find_line); -- -- fi = (struct sw_64_elf_find_line *) bfd_zalloc (abfd, amt); -- if (fi == NULL) -- { -- msec->flags = origflags; -- return false; -- } -- -- if (!elf64_sw_64_read_ecoff_info (abfd, msec, &fi->d)) -- { -- msec->flags = origflags; -- return false; -- } -- -- /* Swap in the FDR information. */ -- amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr); -- fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt); -- if (fi->d.fdr == NULL) -- { -- msec->flags = origflags; -- return false; -- } -- external_fdr_size = swap->external_fdr_size; -- fdr_ptr = fi->d.fdr; -- fraw_src = (char *) fi->d.external_fdr; -- fraw_end = (fraw_src -- + fi->d.symbolic_header.ifdMax * external_fdr_size); -- for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) -- (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr); -- -- sw_64_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, symbols, section, offset, -- filename_ptr, functionname_ptr, -- line_ptr, discriminator_ptr); --} -- --/* Structure used to pass information to sw_64_elf_output_extsym. */ -- --struct extsym_info --{ -- bfd *abfd; -- struct bfd_link_info *info; -- struct ecoff_debug_info *debug; -- const struct ecoff_debug_swap *swap; -- bool failed; --}; -- -- static bool --elf64_sw_64_output_extsym (struct sw_64_elf_link_hash_entry *h, void * data) --{ -- struct extsym_info *einfo = (struct extsym_info *) data; -- bool strip; -- asection *sec, *output_section; -- -- if (h->root.indx == -2) -- strip = false; -- else if ((h->root.def_dynamic -- || h->root.ref_dynamic -- || h->root.root.type == bfd_link_hash_new) -- && !h->root.def_regular -- && !h->root.ref_regular) -- 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 -- { -- const char *name; -- -- sec = h->root.root.u.def.section; -- output_section = sec->output_section; -- -- /* When making a shared library and symbol h is the one from -- the another shared library, OUTPUT_SECTION may be null. */ -- if (output_section == NULL) -- h->esym.asym.sc = scUndefined; -- else -- { -- name = bfd_section_name (output_section); -- -- if (strcmp (name, ".text") == 0) -- h->esym.asym.sc = scText; -- else if (strcmp (name, ".data") == 0) -- h->esym.asym.sc = scData; -- else if (strcmp (name, ".sdata") == 0) -- h->esym.asym.sc = scSData; -- else if (strcmp (name, ".rodata") == 0 -- || strcmp (name, ".rdata") == 0) -- h->esym.asym.sc = scRData; -- else if (strcmp (name, ".bss") == 0) -- h->esym.asym.sc = scBss; -- else if (strcmp (name, ".sbss") == 0) -- h->esym.asym.sc = scSBss; -- else if (strcmp (name, ".init") == 0) -- h->esym.asym.sc = scInit; -- else if (strcmp (name, ".fini") == 0) -- h->esym.asym.sc = scFini; -- else -- h->esym.asym.sc = scAbs; -- } -- } -- -- h->esym.asym.reserved = 0; -- h->esym.asym.index = indexNil; -- } -- -- if (h->root.root.type == bfd_link_hash_common) -- h->esym.asym.value = h->root.root.u.c.size; -- else if (h->root.root.type == bfd_link_hash_defined -- || h->root.root.type == bfd_link_hash_defweak) -- { -- if (h->esym.asym.sc == scCommon) -- h->esym.asym.sc = scBss; -- else if (h->esym.asym.sc == scSCommon) -- h->esym.asym.sc = scSBss; -- -- sec = h->root.root.u.def.section; -- output_section = sec->output_section; -- if (output_section != NULL) -- h->esym.asym.value = (h->root.root.u.def.value -- + sec->output_offset -- + output_section->vma); -- else -- h->esym.asym.value = 0; -- } -- -- 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; --} -- --/* Search for and possibly create a got entry. */ -- -- static struct sw_64_elf_got_entry * --get_got_entry (bfd *abfd, struct sw_64_elf_link_hash_entry *h, -- unsigned long r_type, unsigned long r_symndx, -- bfd_vma r_addend) --{ -- struct sw_64_elf_got_entry *gotent; -- struct sw_64_elf_got_entry **slot; -- -- if (h) -- slot = &h->got_entries; -- else -- { -- /* This is a local .got entry -- record for merge. */ -- -- struct sw_64_elf_got_entry **local_got_entries; -- -- local_got_entries = sw_64_elf_tdata(abfd)->local_got_entries; -- if (!local_got_entries) -- { -- bfd_size_type size; -- Elf_Internal_Shdr *symtab_hdr; -- -- symtab_hdr = &elf_tdata(abfd)->symtab_hdr; -- size = symtab_hdr->sh_info; -- size *= sizeof (struct sw_64_elf_got_entry *); -- -- local_got_entries -- = (struct sw_64_elf_got_entry **) bfd_zalloc (abfd, size); -- if (!local_got_entries) -- return NULL; -- -- sw_64_elf_tdata (abfd)->local_got_entries = local_got_entries; -- } -- -- slot = &local_got_entries[r_symndx]; -- } -- -- for (gotent = *slot; gotent ; gotent = gotent->next) -- if (gotent->gotobj == abfd -- && gotent->reloc_type == r_type -- && gotent->addend == r_addend) -- break; -- -- if (!gotent) -- { -- int entry_size; -- size_t amt; -- -- amt = sizeof (struct sw_64_elf_got_entry); -- gotent = (struct sw_64_elf_got_entry *) bfd_alloc (abfd, amt); -- if (!gotent) -- return NULL; -- -- gotent->gotobj = abfd; -- gotent->addend = r_addend; -- gotent->got_offset = -1; -- gotent->plt_offset = -1; -- gotent->use_count = 1; -- gotent->reloc_type = r_type; -- gotent->reloc_done = 0; -- gotent->reloc_xlated = 0; -- -- gotent->next = *slot; -- *slot = gotent; -- -- entry_size = sw_64_got_entry_size (r_type); -- sw_64_elf_tdata (abfd)->total_got_size += entry_size; -- if (!h) -- sw_64_elf_tdata(abfd)->local_got_size += entry_size; -- } -- else -- gotent->use_count += 1; -- -- return gotent; --} -- -- static bool --elf64_sw_64_want_plt (struct sw_64_elf_link_hash_entry *ah) --{ -- return ((ah->root.type == STT_FUNC -- || ah->root.root.type == bfd_link_hash_undefweak -- || ah->root.root.type == bfd_link_hash_undefined) -- && (ah->flags & SW_64_ELF_LINK_HASH_LU_PLT) != 0 -- && (ah->flags & ~SW_64_ELF_LINK_HASH_LU_PLT) == 0); --} -- --/* Whether to sort relocs output by ld -r or ld --emit-relocs, by r_offset. -- Don't do so for code sections. We want to keep ordering of LITERAL/LITUSE -- as is. On the other hand, elf-eh-frame.c processing requires .eh_frame -- relocs to be sorted. */ -- -- static bool --elf64_sw_64_sort_relocs_p (asection *sec) --{ -- return (sec->flags & SEC_CODE) == 0; --} -- -- --/* Handle dynamic relocations when doing an Sw_64 ELF link. */ -- -- static bool --elf64_sw_64_check_relocs (bfd *abfd, struct bfd_link_info *info, -- asection *sec, const Elf_Internal_Rela *relocs) --{ -- bfd *dynobj; -- asection *sreloc; -- Elf_Internal_Shdr *symtab_hdr; -- struct sw_64_elf_link_hash_entry **sym_hashes; -- const Elf_Internal_Rela *rel, *relend; -- -- if (bfd_link_relocatable (info)) -- return true; -- -- /* Don't do anything special with non-loaded, non-alloced sections. -- In particular, any relocs in such sections should not affect GOT -- and PLT reference counting (ie. we don't allow them to create GOT -- or PLT entries), there's no possibility or desire to optimize TLS -- relocs, and there's not much point in propagating relocs to shared -- libs that the dynamic linker won't relocate. */ -- if ((sec->flags & SEC_ALLOC) == 0) -- return true; -- -- BFD_ASSERT (is_sw_64_elf (abfd)); -- -- dynobj = elf_hash_table (info)->dynobj; -- if (dynobj == NULL) -- elf_hash_table (info)->dynobj = dynobj = abfd; -- -- sreloc = NULL; -- symtab_hdr = &elf_symtab_hdr (abfd); -- sym_hashes = sw_64_elf_sym_hashes (abfd); -- -- relend = relocs + sec->reloc_count; -- for (rel = relocs; rel < relend; ++rel) -- { -- enum { -- NEED_GOT = 1, -- NEED_GOT_ENTRY = 2, -- NEED_DYNREL = 4 -- }; -- -- unsigned long r_symndx, r_type; -- struct sw_64_elf_link_hash_entry *h; -- unsigned int gotent_flags; -- bool maybe_dynamic; -- unsigned int need; -- bfd_vma addend; -- -- r_symndx = ELF64_R_SYM (rel->r_info); -- if (r_symndx < symtab_hdr->sh_info) -- h = NULL; -- else -- { -- h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -- -- while (h->root.root.type == bfd_link_hash_indirect -- || h->root.root.type == bfd_link_hash_warning) -- h = (struct sw_64_elf_link_hash_entry *)h->root.root.u.i.link; -- -- /* PR15323, ref flags aren't set for references in the same -- object. */ -- h->root.ref_regular = 1; -- } -- -- /* We can only get preliminary data on whether a symbol is -- locally or externally defined, as not all of the input files -- have yet been processed. Do something with what we know, as -- this may help reduce memory usage and processing time later. */ -- maybe_dynamic = false; -- if (h && ((bfd_link_pic (info) -- && (!info->symbolic -- || info->unresolved_syms_in_shared_libs == RM_IGNORE)) -- || !h->root.def_regular -- || h->root.root.type == bfd_link_hash_defweak)) -- maybe_dynamic = true; -- -- need = 0; -- gotent_flags = 0; -- r_type = ELF64_R_TYPE (rel->r_info); -- addend = rel->r_addend; -- -- switch (r_type) -- { -- case R_SW_64_LITERAL: -- need = NEED_GOT | NEED_GOT_ENTRY; -- -- /* Remember how this literal is used from its LITUSEs. -- This will be important when it comes to decide if we can -- create a .plt entry for a function symbol. */ -- while (++rel < relend && ELF64_R_TYPE (rel->r_info) == R_SW_64_LITUSE) -- if (rel->r_addend >= 1 && rel->r_addend <= 6) -- gotent_flags |= 1 << rel->r_addend; -- --rel; -- -- /* No LITUSEs -- presumably the address is used somehow. */ -- if (gotent_flags == 0) -- gotent_flags = SW_64_ELF_LINK_HASH_LU_ADDR; -- break; -- -- case R_SW_64_GPDISP: -- case R_SW_64_GPREL16: -- case R_SW_64_GPREL32: -- case R_SW_64_GPRELHIGH: -- case R_SW_64_GPRELLOW: -- case R_SW_64_BRSGP: -- need = NEED_GOT; -- break; -- -- case R_SW_64_REFLONG: -- case R_SW_64_REFQUAD: -- if (bfd_link_pic (info) || maybe_dynamic) -- need = NEED_DYNREL; -- break; -- -- case R_SW_64_TLSLDM: -- /* The symbol for a TLSLDM reloc is ignored. Collapse the -- reloc to the STN_UNDEF (0) symbol so that they all match. */ -- r_symndx = STN_UNDEF; -- h = 0; -- maybe_dynamic = false; -- /* FALLTHRU */ -- -- case R_SW_64_TLSGD: -- case R_SW_64_GOTDTPREL: -- need = NEED_GOT | NEED_GOT_ENTRY; -- break; -- -- case R_SW_64_GOTTPREL: -- need = NEED_GOT | NEED_GOT_ENTRY; -- gotent_flags = SW_64_ELF_LINK_HASH_TLS_IE; -- if (bfd_link_pic (info)) -- info->flags |= DF_STATIC_TLS; -- break; -- -- case R_SW_64_TPREL64: -- if (bfd_link_dll (info)) -- { -- info->flags |= DF_STATIC_TLS; -- need = NEED_DYNREL; -- } -- else if (maybe_dynamic) -- need = NEED_DYNREL; -- break; -- } -- -- if (need & NEED_GOT) -- { -- if (sw_64_elf_tdata(abfd)->gotobj == NULL) -- { -- if (!elf64_sw_64_create_got_section (abfd, info)) -- return false; -- } -- } -- -- if (need & NEED_GOT_ENTRY) -- { -- struct sw_64_elf_got_entry *gotent; -- -- gotent = get_got_entry (abfd, h, r_type, r_symndx, addend); -- if (!gotent) -- return false; -- -- if (gotent_flags) -- { -- gotent->flags |= gotent_flags; -- if (h) -- { -- gotent_flags |= h->flags; -- h->flags = gotent_flags; -- -- /* Make a guess as to whether a .plt entry is needed. */ -- /* ??? It appears that we won't make it into -- adjust_dynamic_symbol for symbols that remain -- totally undefined. Copying this check here means -- we can create a plt entry for them too. */ -- h->root.needs_plt -- = (maybe_dynamic && elf64_sw_64_want_plt (h)); -- } -- } -- } -- -- if (need & NEED_DYNREL) -- { -- /* We need to create the section here now whether we eventually -- use it or not so that it gets mapped to an output section by -- the linker. If not used, we'll kill it in size_dynamic_sections. */ -- if (sreloc == NULL) -- { -- sreloc = _bfd_elf_make_dynamic_reloc_section -- (sec, dynobj, 3, abfd, /*rela?*/ true); -- -- if (sreloc == NULL) -- return false; -- } -- -- if (h) -- { -- /* Since we havn't seen all of the input symbols yet, we -- don't know whether we'll actually need a dynamic relocation -- entry for this reloc. So make a record of it. Once we -- find out if this thing needs dynamic relocation we'll -- expand the relocation sections by the appropriate amount. */ -- -- struct sw_64_elf_reloc_entry *rent; -- -- for (rent = h->reloc_entries; rent; rent = rent->next) -- if (rent->rtype == r_type && rent->srel == sreloc) -- break; -- -- if (!rent) -- { -- size_t amt = sizeof (struct sw_64_elf_reloc_entry); -- rent = (struct sw_64_elf_reloc_entry *) bfd_alloc (abfd, amt); -- if (!rent) -- return false; -- -- rent->srel = sreloc; -- rent->sec = sec; -- rent->rtype = r_type; -- rent->count = 1; -- -- rent->next = h->reloc_entries; -- h->reloc_entries = rent; -- } -- else -- rent->count++; -- } -- else if (bfd_link_pic (info)) -- { -- /* If this is a shared library, and the section is to be -- loaded into memory, we need a RELATIVE reloc. */ -- sreloc->size += sizeof (Elf64_External_Rela); -- if (sec->flags & SEC_READONLY) -- { -- info->flags |= DF_TEXTREL; -- info->callbacks->minfo -- (_("%pB: dynamic relocation against `T' in " -- "read-only section `%pA'\n"), -- sec->owner, sec); -- } -- } -- } -- } -- -- return true; --} -- --/* Return the section that should be marked against GC for a given -- relocation. */ -- -- static asection * --elf64_sw_64_gc_mark_hook (asection *sec, struct bfd_link_info *info, -- Elf_Internal_Rela *rel, -- struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) --{ -- /* These relocations don't really reference a symbol. Instead we store -- extra data in their addend slot. Ignore the symbol. */ -- switch (ELF64_R_TYPE (rel->r_info)) -- { -- case R_SW_64_LITUSE: -- case R_SW_64_GPDISP: -- case R_SW_64_HINT: -- return NULL; -- } -- -- return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); --} -- --/* 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 bool --elf64_sw_64_adjust_dynamic_symbol (struct bfd_link_info *info, -- struct elf_link_hash_entry *h) --{ -- bfd *dynobj; -- asection *s; -- struct sw_64_elf_link_hash_entry *ah; -- -- dynobj = elf_hash_table(info)->dynobj; -- ah = (struct sw_64_elf_link_hash_entry *)h; -- -- /* Now that we've seen all of the input symbols, finalize our decision -- about whether this symbol should get a .plt entry. Irritatingly, it -- is common for folk to leave undefined symbols in shared libraries, -- and they still expect lazy binding; accept undefined symbols in lieu -- of STT_FUNC. */ -- if (sw_64_elf_dynamic_symbol_p (h, info) && elf64_sw_64_want_plt (ah)) -- { -- h->needs_plt = true; -- -- s = elf_hash_table(info)->splt; -- if (!s && !elf64_sw_64_create_dynamic_sections (dynobj, info)) -- return false; -- -- /* We need one plt entry per got subsection. Delay allocation of -- the actual plt entries until size_plt_section, called from -- size_dynamic_sections or during relaxation. */ -- -- return true; -- } -- else -- h->needs_plt = false; -- -- /* 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->is_weakalias) -- { -- struct elf_link_hash_entry *def = weakdef (h); -- BFD_ASSERT (def->root.type == bfd_link_hash_defined); -- h->root.u.def.section = def->root.u.def.section; -- h->root.u.def.value = def->root.u.def.value; -- return true; -- } -- -- /* This is a reference to a symbol defined by a dynamic object which -- is not a function. The Sw_64, since it uses .got entries for all -- symbols even in regular objects, does not need the hackery of a -- .dynbss section and COPY dynamic relocations. */ -- -- return true; --} -- --/* Record STO_SW_64_NOPV and STO_SW_64_STD_GPLOAD. */ -- -- static void --elf64_sw_64_merge_symbol_attribute (struct elf_link_hash_entry *h, -- unsigned int st_other, -- bool definition, -- bool dynamic) --{ -- if (!dynamic && definition) -- h->other = ((h->other & ELF_ST_VISIBILITY (-1)) -- | (st_other & ~ELF_ST_VISIBILITY (-1))); --} -- --/* Symbol versioning can create new symbols, and make our old symbols -- indirect to the new ones. Consolidate the got and reloc information -- in these situations. */ -- -- static void --elf64_sw_64_copy_indirect_symbol (struct bfd_link_info *info, -- struct elf_link_hash_entry *dir, -- struct elf_link_hash_entry *ind) --{ -- struct sw_64_elf_link_hash_entry *hi -- = (struct sw_64_elf_link_hash_entry *) ind; -- struct sw_64_elf_link_hash_entry *hs -- = (struct sw_64_elf_link_hash_entry *) dir; -- -- /* Do the merging in the superclass. */ -- _bfd_elf_link_hash_copy_indirect(info, dir, ind); -- -- /* Merge the flags. Whee. */ -- hs->flags |= hi->flags; -- -- /* ??? It's unclear to me what's really supposed to happen when -- "merging" defweak and defined symbols, given that we don't -- actually throw away the defweak. This more-or-less copies -- the logic related to got and plt entries in the superclass. */ -- if (ind->root.type != bfd_link_hash_indirect) -- return; -- -- /* Merge the .got entries. Cannibalize the old symbol's list in -- doing so, since we don't need it anymore. */ -- -- if (hs->got_entries == NULL) -- hs->got_entries = hi->got_entries; -- else -- { -- struct sw_64_elf_got_entry *gi, *gs, *gin, *gsh; -- -- gsh = hs->got_entries; -- for (gi = hi->got_entries; gi ; gi = gin) -- { -- gin = gi->next; -- for (gs = gsh; gs ; gs = gs->next) -- if (gi->gotobj == gs->gotobj -- && gi->reloc_type == gs->reloc_type -- && gi->addend == gs->addend) -- { -- gs->use_count += gi->use_count; -- goto got_found; -- } -- gi->next = hs->got_entries; -- hs->got_entries = gi; --got_found:; -- } -- } -- hi->got_entries = NULL; -- -- /* And similar for the reloc entries. */ -- -- if (hs->reloc_entries == NULL) -- hs->reloc_entries = hi->reloc_entries; -- else -- { -- struct sw_64_elf_reloc_entry *ri, *rs, *rin, *rsh; -- -- rsh = hs->reloc_entries; -- for (ri = hi->reloc_entries; ri ; ri = rin) -- { -- rin = ri->next; -- for (rs = rsh; rs ; rs = rs->next) -- if (ri->rtype == rs->rtype && ri->srel == rs->srel) -- { -- rs->count += ri->count; -- goto found_reloc; -- } -- ri->next = hs->reloc_entries; -- hs->reloc_entries = ri; --found_reloc:; -- } -- } -- hi->reloc_entries = NULL; --} -- --/* Is it possible to merge two object file's .got tables? */ -- -- static bool --elf64_sw_64_can_merge_gots (bfd *a, bfd *b) --{ -- int total = sw_64_elf_tdata (a)->total_got_size; -- bfd *bsub; -- -- /* Trivial quick fallout test. */ -- if (total + sw_64_elf_tdata (b)->total_got_size <= MAX_GOT_SIZE) -- return true; -- -- /* By their nature, local .got entries cannot be merged. */ -- if ((total += sw_64_elf_tdata (b)->local_got_size) > MAX_GOT_SIZE) -- return false; -- -- /* Failing the common trivial comparison, we must effectively -- perform the merge. Not actually performing the merge means that -- we don't have to store undo information in case we fail. */ -- for (bsub = b; bsub ; bsub = sw_64_elf_tdata (bsub)->in_got_link_next) -- { -- struct sw_64_elf_link_hash_entry **hashes = sw_64_elf_sym_hashes (bsub); -- Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr; -- int i, n; -- -- n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; -- for (i = 0; i < n; ++i) -- { -- struct sw_64_elf_got_entry *ae, *be; -- struct sw_64_elf_link_hash_entry *h; -- -- h = hashes[i]; -- while (h->root.root.type == bfd_link_hash_indirect -- || h->root.root.type == bfd_link_hash_warning) -- h = (struct sw_64_elf_link_hash_entry *)h->root.root.u.i.link; -- -- for (be = h->got_entries; be ; be = be->next) -- { -- if (be->use_count == 0) -- continue; -- if (be->gotobj != b) -- continue; -- -- for (ae = h->got_entries; ae ; ae = ae->next) -- if (ae->gotobj == a -- && ae->reloc_type == be->reloc_type -- && ae->addend == be->addend) -- goto global_found; -- -- total += sw_64_got_entry_size (be->reloc_type); -- if (total > MAX_GOT_SIZE) -- return false; --global_found:; -- } -- } -- } -- -- return true; --} -- --/* Actually merge two .got tables. */ -- -- static void --elf64_sw_64_merge_gots (bfd *a, bfd *b) --{ -- int total = sw_64_elf_tdata (a)->total_got_size; -- bfd *bsub; -- -- /* Remember local expansion. */ -- { -- int e = sw_64_elf_tdata (b)->local_got_size; -- total += e; -- sw_64_elf_tdata (a)->local_got_size += e; -- } -- -- for (bsub = b; bsub ; bsub = sw_64_elf_tdata (bsub)->in_got_link_next) -- { -- struct sw_64_elf_got_entry **local_got_entries; -- struct sw_64_elf_link_hash_entry **hashes; -- Elf_Internal_Shdr *symtab_hdr; -- int i, n; -- -- /* Let the local .got entries know they are part of a new subsegment. */ -- local_got_entries = sw_64_elf_tdata (bsub)->local_got_entries; -- if (local_got_entries) -- { -- n = elf_tdata (bsub)->symtab_hdr.sh_info; -- for (i = 0; i < n; ++i) -- { -- struct sw_64_elf_got_entry *ent; -- for (ent = local_got_entries[i]; ent; ent = ent->next) -- ent->gotobj = a; -- } -- } -- -- /* Merge the global .got entries. */ -- hashes = sw_64_elf_sym_hashes (bsub); -- symtab_hdr = &elf_tdata (bsub)->symtab_hdr; -- -- n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; -- for (i = 0; i < n; ++i) -- { -- struct sw_64_elf_got_entry *ae, *be, **pbe, **start; -- struct sw_64_elf_link_hash_entry *h; -- -- h = hashes[i]; -- while (h->root.root.type == bfd_link_hash_indirect -- || h->root.root.type == bfd_link_hash_warning) -- h = (struct sw_64_elf_link_hash_entry *)h->root.root.u.i.link; -- -- pbe = start = &h->got_entries; -- while ((be = *pbe) != NULL) -- { -- if (be->use_count == 0) -- { -- *pbe = be->next; -- memset (be, 0xa5, sizeof (*be)); -- goto kill; -- } -- if (be->gotobj != b) -- goto next; -- -- for (ae = *start; ae ; ae = ae->next) -- if (ae->gotobj == a -- && ae->reloc_type == be->reloc_type -- && ae->addend == be->addend) -- { -- ae->flags |= be->flags; -- ae->use_count += be->use_count; -- *pbe = be->next; -- memset (be, 0xa5, sizeof (*be)); -- goto kill; -- } -- be->gotobj = a; -- total += sw_64_got_entry_size (be->reloc_type); -- --next:; -- pbe = &be->next; --kill:; -- } -- } -- -- sw_64_elf_tdata (bsub)->gotobj = a; -- } -- sw_64_elf_tdata (a)->total_got_size = total; -- -- /* Merge the two in_got chains. */ -- { -- bfd *next; -- -- bsub = a; -- while ((next = sw_64_elf_tdata (bsub)->in_got_link_next) != NULL) -- bsub = next; -- -- sw_64_elf_tdata (bsub)->in_got_link_next = b; -- } --} -- --/* Calculate the offsets for the got entries. */ -- -- static bool --elf64_sw_64_calc_got_offsets_for_symbol (struct sw_64_elf_link_hash_entry *h, -- void * arg ATTRIBUTE_UNUSED) --{ -- struct sw_64_elf_got_entry *gotent; -- -- for (gotent = h->got_entries; gotent; gotent = gotent->next) -- if (gotent->use_count > 0) -- { -- struct sw_64_elf_obj_tdata *td; -- bfd_size_type *plge; -- -- td = sw_64_elf_tdata (gotent->gotobj); -- plge = &td->got->size; -- gotent->got_offset = *plge; -- *plge += sw_64_got_entry_size (gotent->reloc_type); -- } -- -- return true; --} -- -- static void --elf64_sw_64_calc_got_offsets (struct bfd_link_info *info) --{ -- bfd *i, *got_list; -- struct sw_64_elf_link_hash_table * htab; -- -- htab = sw_64_elf_hash_table (info); -- if (htab == NULL) -- return; -- got_list = htab->got_list; -- -- /* First, zero out the .got sizes, as we may be recalculating the -- .got after optimizing it. */ -- for (i = got_list; i ; i = sw_64_elf_tdata(i)->got_link_next) -- sw_64_elf_tdata(i)->got->size = 0; -- -- /* Next, fill in the offsets for all the global entries. */ -- sw_64_elf_link_hash_traverse (htab, -- elf64_sw_64_calc_got_offsets_for_symbol, -- NULL); -- -- /* Finally, fill in the offsets for the local entries. */ -- for (i = got_list; i ; i = sw_64_elf_tdata(i)->got_link_next) -- { -- bfd_size_type got_offset = sw_64_elf_tdata(i)->got->size; -- bfd *j; -- -- for (j = i; j ; j = sw_64_elf_tdata(j)->in_got_link_next) -- { -- struct sw_64_elf_got_entry **local_got_entries, *gotent; -- int k, n; -- -- local_got_entries = sw_64_elf_tdata(j)->local_got_entries; -- if (!local_got_entries) -- continue; -- -- for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k) -- for (gotent = local_got_entries[k]; gotent; gotent = gotent->next) -- if (gotent->use_count > 0) -- { -- gotent->got_offset = got_offset; -- got_offset += sw_64_got_entry_size (gotent->reloc_type); -- } -- } -- -- sw_64_elf_tdata(i)->got->size = got_offset; -- } --} -- --/* Constructs the gots. */ -- -- static bool --elf64_sw_64_size_got_sections (struct bfd_link_info *info, -- bool may_merge) --{ -- bfd *i, *got_list, *cur_got_obj = NULL; -- struct sw_64_elf_link_hash_table * htab; -- -- htab = sw_64_elf_hash_table (info); -- if (htab == NULL) -- return false; -- got_list = htab->got_list; -- -- /* On the first time through, pretend we have an existing got list -- consisting of all of the input files. */ -- if (got_list == NULL) -- { -- for (i = info->input_bfds; i ; i = i->link.next) -- { -- bfd *this_got; -- -- if (! is_sw_64_elf (i)) -- continue; -- -- this_got = sw_64_elf_tdata (i)->gotobj; -- if (this_got == NULL) -- continue; -- -- /* We are assuming no merging has yet occurred. */ -- BFD_ASSERT (this_got == i); -- -- if (sw_64_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE_NEW) -- { -- /* Yikes! A single object file has too many entries. */ -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: .got subsegment exceeds 2G (size %d)"), -- i, sw_64_elf_tdata (this_got)->total_got_size); -- return false; -- } -- -- if (got_list == NULL) -- got_list = this_got; -- else -- sw_64_elf_tdata(cur_got_obj)->got_link_next = this_got; -- cur_got_obj = this_got; -- } -- -- /* Strange degenerate case of no got references. */ -- if (got_list == NULL) -- return true; -- -- htab->got_list = got_list; -- } -- -- cur_got_obj = got_list; -- if (cur_got_obj == NULL) -- return false; -- -- if (may_merge) -- { -- i = sw_64_elf_tdata(cur_got_obj)->got_link_next; -- while (i != NULL) -- { -- if (elf64_sw_64_can_merge_gots (cur_got_obj, i)) -- { -- elf64_sw_64_merge_gots (cur_got_obj, i); -- -- sw_64_elf_tdata(i)->got->size = 0; -- i = sw_64_elf_tdata(i)->got_link_next; -- sw_64_elf_tdata(cur_got_obj)->got_link_next = i; -- } -- else -- { -- cur_got_obj = i; -- i = sw_64_elf_tdata(i)->got_link_next; -- } -- } -- } -- -- /* Once the gots have been merged, fill in the got offsets for -- everything therein. */ -- elf64_sw_64_calc_got_offsets (info); -- -- return true; --} -- -- static bool --elf64_sw_64_size_plt_section_1 (struct sw_64_elf_link_hash_entry *h, -- void * data) --{ -- asection *splt = (asection *) data; -- struct sw_64_elf_got_entry *gotent; -- bool saw_one = false; -- -- /* If we didn't need an entry before, we still don't. */ -- if (!h->root.needs_plt) -- return true; -- -- /* For each LITERAL got entry still in use, allocate a plt entry. */ -- for (gotent = h->got_entries; gotent ; gotent = gotent->next) -- if (gotent->reloc_type == R_SW_64_LITERAL -- && gotent->use_count > 0) -- { -- if (splt->size == 0) -- splt->size = PLT_HEADER_SIZE; -- gotent->plt_offset = splt->size; -- splt->size += PLT_ENTRY_SIZE; -- saw_one = true; -- } -- -- /* If there weren't any, there's no longer a need for the PLT entry. */ -- if (!saw_one) -- h->root.needs_plt = false; -- -- return true; --} -- --/* Called from relax_section to rebuild the PLT in light of potential changes -- in the function's status. */ -- -- static void --elf64_sw_64_size_plt_section (struct bfd_link_info *info) --{ -- asection *splt, *spltrel, *sgotplt; -- unsigned long entries; -- struct sw_64_elf_link_hash_table * htab; -- -- htab = sw_64_elf_hash_table (info); -- if (htab == NULL) -- return; -- -- splt = elf_hash_table(info)->splt; -- if (splt == NULL) -- return; -- -- splt->size = 0; -- -- sw_64_elf_link_hash_traverse (htab, -- elf64_sw_64_size_plt_section_1, splt); -- -- /* Every plt entry requires a JMP_SLOT relocation. */ -- spltrel = elf_hash_table(info)->srelplt; -- entries = 0; -- if (splt->size) -- { -- if (elf64_sw_64_use_secureplt) -- entries = (splt->size - NEW_PLT_HEADER_SIZE) / NEW_PLT_ENTRY_SIZE; -- else -- entries = (splt->size - OLD_PLT_HEADER_SIZE) / OLD_PLT_ENTRY_SIZE; -- } -- spltrel->size = entries * sizeof (Elf64_External_Rela); -- -- /* When using the secureplt, we need two words somewhere in the data -- segment for the dynamic linker to tell us where to go. This is the -- entire contents of the .got.plt section. */ -- if (elf64_sw_64_use_secureplt) -- { -- sgotplt = elf_hash_table(info)->sgotplt; -- sgotplt->size = entries ? 16 : 0; -- } --} -- -- static bool --elf64_sw_64_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, -- struct bfd_link_info *info) --{ -- bfd *i; -- struct sw_64_elf_link_hash_table * htab; -- -- if (bfd_link_relocatable (info)) -- return true; -- -- htab = sw_64_elf_hash_table (info); -- if (htab == NULL) -- return false; -- -- if (!elf64_sw_64_size_got_sections (info, true)) -- return false; -- -- /* Allocate space for all of the .got subsections. */ -- i = htab->got_list; -- for ( ; i ; i = sw_64_elf_tdata(i)->got_link_next) -- { -- asection *s = sw_64_elf_tdata(i)->got; -- if (s->size > 0) -- { -- s->contents = (bfd_byte *) bfd_zalloc (i, s->size); -- if (s->contents == NULL) -- return false; -- } -- } -- -- return true; --} -- --/* The number of dynamic relocations required by a static relocation. */ -- -- static int --sw_64_dynamic_entries_for_reloc (int r_type, int dynamic, int shared, int pie) --{ -- switch (r_type) -- { -- /* May appear in GOT entries. */ -- case R_SW_64_TLSGD: -- return (dynamic ? 2 : shared ? 1 : 0); -- case R_SW_64_TLSLDM: -- return shared; -- case R_SW_64_LITERAL: -- return dynamic || shared; -- case R_SW_64_GOTTPREL: -- return dynamic || (shared && !pie); -- case R_SW_64_GOTDTPREL: -- return dynamic; -- -- /* May appear in data sections. */ -- case R_SW_64_REFLONG: -- case R_SW_64_REFQUAD: -- return dynamic || shared; -- case R_SW_64_TPREL64: -- return dynamic || (shared && !pie); -- -- /* Everything else is illegal. We'll issue an error during -- relocate_section. */ -- default: -- return 0; -- } --} -- --/* Work out the sizes of the dynamic relocation entries. */ -- -- static bool --elf64_sw_64_calc_dynrel_sizes (struct sw_64_elf_link_hash_entry *h, -- struct bfd_link_info *info) --{ -- bool dynamic; -- struct sw_64_elf_reloc_entry *relent; -- unsigned long entries; -- -- /* If the symbol was defined as a common symbol in a regular object -- file, and there was no definition in any dynamic object, then the -- linker will have allocated space for the symbol in a common -- section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been -- set. This is done for dynamic symbols in -- elf_adjust_dynamic_symbol but this is not done for non-dynamic -- symbols, somehow. */ -- if (!h->root.def_regular -- && h->root.ref_regular -- && !h->root.def_dynamic -- && (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)) -- h->root.def_regular = 1; -- -- /* If the symbol is dynamic, we'll need all the relocations in their -- natural form. If this is a shared object, and it has been forced -- local, we'll need the same number of RELATIVE relocations. */ -- dynamic = sw_64_elf_dynamic_symbol_p (&h->root, info); -- -- /* If the symbol is a hidden undefined weak, then we never have any -- relocations. Avoid the loop which may want to add RELATIVE relocs -- based on bfd_link_pic (info). */ -- if (h->root.root.type == bfd_link_hash_undefweak && !dynamic) -- return true; -- -- for (relent = h->reloc_entries; relent; relent = relent->next) -- { -- entries = sw_64_dynamic_entries_for_reloc (relent->rtype, dynamic, -- bfd_link_pic (info), -- bfd_link_pie (info)); -- if (entries) -- { -- asection *sec = relent->sec; -- relent->srel->size += -- entries * sizeof (Elf64_External_Rela) * relent->count; -- if ((sec->flags & SEC_READONLY) != 0) -- { -- info->flags |= DT_TEXTREL; -- info->callbacks->minfo -- (_("%pB: dynamic relocation against `T' in " -- "read-only section `%pA'\n"), -- sec->owner, sec); -- } -- } -- } -- -- return true; --} -- --/* Subroutine of elf64_sw_64_size_rela_got_section for doing the -- global symbols. */ -- -- static bool --elf64_sw_64_size_rela_got_1 (struct sw_64_elf_link_hash_entry *h, -- struct bfd_link_info *info) --{ -- bool dynamic; -- struct sw_64_elf_got_entry *gotent; -- unsigned long entries; -- -- /* If we're using a plt for this symbol, then all of its relocations -- for its got entries go into .rela.plt. */ -- if (h->root.needs_plt) -- return true; -- -- /* If the symbol is dynamic, we'll need all the relocations in their -- natural form. If this is a shared object, and it has been forced -- local, we'll need the same number of RELATIVE relocations. */ -- dynamic = sw_64_elf_dynamic_symbol_p (&h->root, info); -- -- /* If the symbol is a hidden undefined weak, then we never have any -- relocations. Avoid the loop which may want to add RELATIVE relocs -- based on bfd_link_pic (info). */ -- if (h->root.root.type == bfd_link_hash_undefweak && !dynamic) -- return true; -- -- entries = 0; -- for (gotent = h->got_entries; gotent ; gotent = gotent->next) -- if (gotent->use_count > 0) -- entries += sw_64_dynamic_entries_for_reloc (gotent->reloc_type, dynamic, -- bfd_link_pic (info), -- bfd_link_pie (info)); -- -- if (entries > 0) -- { -- asection *srel = elf_hash_table(info)->srelgot; -- BFD_ASSERT (srel != NULL); -- srel->size += sizeof (Elf64_External_Rela) * entries; -- } -- -- return true; --} -- --/* Set the sizes of the dynamic relocation sections. */ -- -- static void --elf64_sw_64_size_rela_got_section (struct bfd_link_info *info) --{ -- unsigned long entries; -- bfd *i; -- asection *srel; -- struct sw_64_elf_link_hash_table * htab; -- -- htab = sw_64_elf_hash_table (info); -- if (htab == NULL) -- return; -- -- /* Shared libraries often require RELATIVE relocs, and some relocs -- require attention for the main application as well. */ -- -- entries = 0; -- for (i = htab->got_list; -- i ; i = sw_64_elf_tdata(i)->got_link_next) -- { -- bfd *j; -- -- for (j = i; j ; j = sw_64_elf_tdata(j)->in_got_link_next) -- { -- struct sw_64_elf_got_entry **local_got_entries, *gotent; -- int k, n; -- -- local_got_entries = sw_64_elf_tdata(j)->local_got_entries; -- if (!local_got_entries) -- continue; -- -- for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k) -- for (gotent = local_got_entries[k]; -- gotent ; gotent = gotent->next) -- if (gotent->use_count > 0) -- entries += (sw_64_dynamic_entries_for_reloc -- (gotent->reloc_type, 0, bfd_link_pic (info), -- bfd_link_pie (info))); -- } -- } -- -- srel = elf_hash_table(info)->srelgot; -- if (!srel) -- { -- BFD_ASSERT (entries == 0); -- return; -- } -- srel->size = sizeof (Elf64_External_Rela) * entries; -- -- /* Now do the non-local symbols. */ -- sw_64_elf_link_hash_traverse (htab, -- elf64_sw_64_size_rela_got_1, info); --} -- --/* Set the sizes of the dynamic sections. */ -- -- static bool --elf64_sw_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, -- struct bfd_link_info *info) --{ -- bfd *dynobj; -- asection *s; -- bool relplt, relocs; -- struct sw_64_elf_link_hash_table * htab; -- -- htab = sw_64_elf_hash_table (info); -- if (htab == NULL) -- return false; -- -- 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 (bfd_link_executable (info) && !info->nointerp) -- { -- s = bfd_get_linker_section (dynobj, ".interp"); -- BFD_ASSERT (s != NULL); -- s->size = sizeof ELF_DYNAMIC_INTERPRETER; -- s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; -- } -- -- /* Now that we've seen all of the input files, we can decide which -- symbols need dynamic relocation entries and which don't. We've -- collected information in check_relocs that we can now apply to -- size the dynamic relocation sections. */ -- sw_64_elf_link_hash_traverse (htab, -- elf64_sw_64_calc_dynrel_sizes, info); -- -- elf64_sw_64_size_rela_got_section (info); -- elf64_sw_64_size_plt_section (info); -- } -- /* else we're not dynamic and by definition we don't need such things. */ -- -- /* The check_relocs and adjust_dynamic_symbol entry points have -- determined the sizes of the various dynamic sections. Allocate -- memory for them. */ -- relplt = false; -- relocs = false; -- for (s = dynobj->sections; s != NULL; s = s->next) -- { -- const char *name; -- -- if (!(s->flags & SEC_LINKER_CREATED)) -- 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_section_name (s); -- -- if (startswith (name, ".rela")) -- { -- if (s->size != 0) -- { -- if (strcmp (name, ".rela.plt") == 0) -- relplt = true; -- else -- relocs = 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 (! startswith (name, ".got") -- && strcmp (name, ".plt") != 0 -- && strcmp (name, ".dynbss") != 0) -- { -- /* It's not one of our dynamic sections, so don't allocate space. */ -- continue; -- } -- -- if (s->size == 0) -- { -- /* If we don't need this section, strip it from the output file. -- This is to handle .rela.bss and .rela.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. */ -- if (!startswith (name, ".got")) -- s->flags |= SEC_EXCLUDE; -- } -- else if ((s->flags & SEC_HAS_CONTENTS) != 0) -- { -- /* Allocate memory for the section contents. */ -- s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); -- if (s->contents == NULL) -- return false; -- } -- } -- -- if (elf_hash_table (info)->dynamic_sections_created) -- { -- /* Add some entries to the .dynamic section. We fill in the -- values later, in elf64_sw_64_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. */ --#define add_dynamic_entry(TAG, VAL) \ -- _bfd_elf_add_dynamic_entry (info, TAG, VAL) -- --#ifdef ZZH20210707_SWGNU -- if (!_bfd_elf_add_dynamic_tags (output_bfd, info, -- relocs || relplt)) -- return false; -- -- if (relplt -- && elf64_sw_64_use_secureplt -- && !add_dynamic_entry (DT_SW_64_PLTRO, 1)) -- return false; --#else -- if (bfd_link_executable (info)) -- { -- if (!add_dynamic_entry (DT_DEBUG, 0)) -- return false; -- } -- -- if (relplt) -- { -- if (!add_dynamic_entry (DT_PLTGOT, 0) -- || !add_dynamic_entry (DT_PLTRELSZ, 0) -- || !add_dynamic_entry (DT_PLTREL, DT_RELA) -- || !add_dynamic_entry (DT_JMPREL, 0)) -- return false; -- -- if (elf64_sw_64_use_secureplt -- && !add_dynamic_entry (DT_SW_64_PLTRO, 1)) -- return false; -- } -- -- if (relocs) -- { -- if (!add_dynamic_entry (DT_RELA, 0) -- || !add_dynamic_entry (DT_RELASZ, 0) -- || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) -- return false; -- -- if (info->flags & DF_TEXTREL) -- { -- if (!add_dynamic_entry (DT_TEXTREL, 0)) -- return false; -- } -- } --#endif -- } --#undef add_dynamic_entry -- -- return true; --} -- --/* These functions do relaxation for Sw_64 ELF. -- -- Currently I'm only handling what I can do with existing compiler -- and assembler support, which means no instructions are removed, -- though some may be nopped. At this time GCC does not emit enough -- information to do all of the relaxing that is possible. It will -- take some not small amount of work for that to happen. -- -- There are a couple of interesting papers that I once read on this -- subject, that I cannot find references to at the moment, that -- related to Sw_64 in particular. They are by David Wall, then of -- DEC WRL. */ -- --struct sw_64_relax_info --{ -- bfd *abfd; -- asection *sec; -- bfd_byte *contents; -- Elf_Internal_Shdr *symtab_hdr; -- Elf_Internal_Rela *relocs, *relend; -- struct bfd_link_info *link_info; -- bfd_vma gp; -- bfd *gotobj; -- asection *tsec; -- struct sw_64_elf_link_hash_entry *h; -- struct sw_64_elf_got_entry **first_gotent; -- struct sw_64_elf_got_entry *gotent; -- bool changed_contents; -- bool changed_relocs; -- unsigned char other; --}; -- -- static Elf_Internal_Rela * --elf64_sw_64_find_reloc_at_ofs (Elf_Internal_Rela *rel, -- Elf_Internal_Rela *relend, -- bfd_vma offset, int type) --{ -- while (rel < relend) -- { -- if (rel->r_offset == offset -- && ELF64_R_TYPE (rel->r_info) == (unsigned int) type) -- return rel; -- ++rel; -- } -- return NULL; --} -- -- static bool --elf64_sw_64_relax_got_load (struct sw_64_relax_info *info, bfd_vma symval, -- Elf_Internal_Rela *irel, unsigned long r_type) --{ -- unsigned int insn; -- bfd_signed_vma disp; -- -- /* Get the instruction. */ -- insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); -- -- if (insn >> 26 != OP_LDL) -- { -- reloc_howto_type *howto = elf64_sw_64_howto_table + r_type; -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: %pA+%#" PRIx64 ": warning: " -- "%s relocation against unexpected insn"), -- info->abfd, info->sec, (uint64_t) irel->r_offset, howto->name); -- return true; -- } -- -- /* Can't relax dynamic symbols. */ -- if (info->h != NULL -- && sw_64_elf_dynamic_symbol_p (&info->h->root, info->link_info)) -- return true; -- -- /* Can't use local-exec relocations in shared libraries. */ -- if (r_type == R_SW_64_GOTTPREL -- && bfd_link_dll (info->link_info)) -- return true; -- -- if (r_type == R_SW_64_LITERAL) -- { -- /* Look for nice constant addresses. This includes the not-uncommon -- special case of 0 for undefweak symbols. */ -- if ((info->h && info->h->root.root.type == bfd_link_hash_undefweak) -- || (!bfd_link_pic (info->link_info) -- && (symval >= (bfd_vma)-0x8000 || symval < 0x8000))) -- { -- disp = 0; -- insn = (OP_LDI << 26) | (insn & (31 << 21)) | (31 << 16); -- insn |= (symval & 0xffff); -- r_type = R_SW_64_NONE; -- } -- else -- { -- /* We may only create GPREL relocs during the second pass. */ -- if (info->link_info->relax_pass == 0) -- return true; -- -- disp = symval - info->gp; -- insn = (OP_LDI << 26) | (insn & 0x03ff0000); -- r_type = R_SW_64_GPREL16; -- } -- } -- else -- { -- bfd_vma dtp_base, tp_base; -- -- BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL); -- dtp_base = sw_64_get_dtprel_base (info->link_info); -- tp_base = sw_64_get_tprel_base (info->link_info); -- disp = symval - (r_type == R_SW_64_GOTDTPREL ? dtp_base : tp_base); -- -- insn = (OP_LDI << 26) | (insn & (31 << 21)) | (31 << 16); -- -- switch (r_type) -- { -- case R_SW_64_GOTDTPREL: -- r_type = R_SW_64_DTPREL16; -- break; -- case R_SW_64_GOTTPREL: -- r_type = R_SW_64_TPREL16; -- break; -- default: -- BFD_ASSERT (0); -- return false; -- } -- } -- -- if (disp < -0x8000 || disp >= 0x8000) -- return true; -- -- bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset); -- info->changed_contents = true; -- -- /* Reduce the use count on this got entry by one, possibly -- eliminating it. */ -- if (--info->gotent->use_count == 0) -- { -- int sz = sw_64_got_entry_size (r_type); -- sw_64_elf_tdata (info->gotobj)->total_got_size -= sz; -- if (!info->h) -- sw_64_elf_tdata (info->gotobj)->local_got_size -= sz; -- } -- -- /* Smash the existing GOT relocation for its 16-bit immediate pair. */ -- irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type); -- info->changed_relocs = true; -- -- /* ??? Search forward through this basic block looking for insns -- that use the target register. Stop after an insn modifying the -- register is seen, or after a branch or call. -- -- Any such memory load insn may be substituted by a load directly -- off the GP. This allows the memory load insn to be issued before -- the calculated GP register would otherwise be ready. -- -- Any such jsr insn can be replaced by a bsr if it is in range. -- -- This would mean that we'd have to _add_ relocations, the pain of -- which gives one pause. */ -- -- return true; --} -- -- static bfd_vma --elf64_sw_64_relax_opt_call (struct sw_64_relax_info *info, bfd_vma symval) --{ -- /* If the function has the same gp, and we can identify that the -- function does not use its function pointer, we can eliminate the -- address load. */ -- -- /* If the symbol is marked NOPV, we are being told the function never -- needs its procedure value. */ -- if ((info->other & STO_SW_64_STD_GPLOAD) == STO_SW_64_NOPV) -- return symval; -- -- /* If the symbol is marked STD_GP, we are being told the function does -- a normal ldgp in the first two words. */ -- else if ((info->other & STO_SW_64_STD_GPLOAD) == STO_SW_64_STD_GPLOAD) -- ; -- -- /* Otherwise, we may be able to identify a GP load in the first two -- words, which we can then skip. */ -- else -- { -- Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp; -- bfd_vma ofs; -- -- /* Load the relocations from the section that the target symbol is in. */ -- if (info->sec == info->tsec) -- { -- tsec_relocs = info->relocs; -- tsec_relend = info->relend; -- tsec_free = NULL; -- } -- else -- { -- tsec_relocs = (_bfd_elf_link_read_relocs -- (info->abfd, info->tsec, NULL, -- (Elf_Internal_Rela *) NULL, -- info->link_info->keep_memory)); -- if (tsec_relocs == NULL) -- return 0; -- tsec_relend = tsec_relocs + info->tsec->reloc_count; -- tsec_free = (elf_section_data (info->tsec)->relocs == tsec_relocs -- ? NULL -- : tsec_relocs); -- } -- -- /* Recover the symbol's offset within the section. */ -- ofs = (symval - info->tsec->output_section->vma -- - info->tsec->output_offset); -- -- /* Look for a GPDISP reloc. */ -- gpdisp = (elf64_sw_64_find_reloc_at_ofs -- (tsec_relocs, tsec_relend, ofs, R_SW_64_GPDISP)); -- -- if (!gpdisp || gpdisp->r_addend != 4) -- { -- free (tsec_free); -- return 0; -- } -- free (tsec_free); -- } -- -- /* We've now determined that we can skip an initial gp load. Verify -- that the call and the target use the same gp. */ -- if (info->link_info->output_bfd->xvec != info->tsec->owner->xvec -- || info->gotobj != sw_64_elf_tdata (info->tsec->owner)->gotobj) -- return 0; -- -- return symval + 8; --} -- -- static bool --elf64_sw_64_relax_with_lituse (struct sw_64_relax_info *info, -- bfd_vma symval, Elf_Internal_Rela *irel) --{ -- Elf_Internal_Rela *urel, *erel, *irelend = info->relend; -- int flags; -- bfd_signed_vma disp; -- bool fits16; -- bool fits32; -- bool lit_reused = false; -- bool all_optimized = true; -- bool changed_contents; -- bool changed_relocs; -- bfd_byte *contents = info->contents; -- bfd *abfd = info->abfd; -- bfd_vma sec_output_vma; -- unsigned int lit_insn; -- int relax_pass; -- -- lit_insn = bfd_get_32 (abfd, contents + irel->r_offset); -- if (lit_insn >> 26 != OP_LDL) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: %pA+%#" PRIx64 ": warning: " -- "%s relocation against unexpected insn"), -- abfd, info->sec, (uint64_t) irel->r_offset, "LITERAL"); -- return true; -- } -- -- /* Can't relax dynamic symbols. */ -- if (info->h != NULL && sw_64_elf_dynamic_symbol_p (&info->h->root, info->link_info)) -- return true; -- -- changed_contents = info->changed_contents; -- changed_relocs = info->changed_relocs; -- sec_output_vma = info->sec->output_section->vma + info->sec->output_offset; -- relax_pass = info->link_info->relax_pass; -- -- /* Summarize how this particular LITERAL is used. */ -- for (erel = irel+1, flags = 0; erel < irelend; ++erel) -- { -- if (ELF64_R_TYPE (erel->r_info) != R_SW_64_LITUSE) -- break; -- if (erel->r_addend <= 6) -- flags |= 1 << erel->r_addend; -- } -- -- /* A little preparation for the loop... */ -- disp = symval - info->gp; -- -- for (urel = irel+1; urel < erel; ++urel) -- { -- bfd_vma urel_r_offset = urel->r_offset; -- unsigned int insn; -- int insn_disp; -- bfd_signed_vma xdisp; -- Elf_Internal_Rela nrel; -- -- insn = bfd_get_32 (abfd, contents + urel_r_offset); -- -- switch (urel->r_addend) -- { -- case LITUSE_SW_64_ADDR: -- default: -- /* This type is really just a placeholder to note that all -- uses cannot be optimized, but to still allow some. */ -- all_optimized = false; -- break; -- -- case LITUSE_SW_64_BASE: -- /* We may only create GPREL relocs during the second pass. */ -- if (relax_pass == 0) -- { -- all_optimized = false; -- break; -- } -- -- /* We can always optimize 16-bit displacements. */ -- -- /* Extract the displacement from the instruction, sign-extending -- it if necessary, then test whether it is within 16 or 32 bits -- displacement from GP. */ -- insn_disp = ((insn & 0xffff) ^ 0x8000) - 0x8000; -- -- xdisp = disp + insn_disp; -- fits16 = (xdisp >= - (bfd_signed_vma) 0x8000 && xdisp < 0x8000); -- fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000 -- && xdisp < 0x7fff8000); -- -- if (fits16) -- { -- /* Take the op code and dest from this insn, take the base -- register from the literal insn. Leave the offset alone. */ -- insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000); -- bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); -- changed_contents = true; -- -- nrel = *urel; -- nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), -- R_SW_64_GPREL16); -- nrel.r_addend = irel->r_addend; -- -- /* As we adjust, move the reloc to the end so that we don't -- break the LITERAL+LITUSE chain. */ -- if (urel < --erel) -- *urel-- = *erel; -- *erel = nrel; -- changed_relocs = true; -- } -- -- /* If all mem+byte, we can optimize 32-bit mem displacements. */ -- else if (fits32 && !(flags & ~6)) -- { -- /* FIXME: sanity check that lit insn Ra is mem insn Rb. */ -- -- irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), -- R_SW_64_GPRELHIGH); -- lit_insn = (OP_LDIH << 26) | (lit_insn & 0x03ff0000); -- bfd_put_32 (abfd, (bfd_vma) lit_insn, contents + irel->r_offset); -- lit_reused = true; -- changed_contents = true; -- -- /* Since all relocs must be optimized, don't bother swapping -- this relocation to the end. */ -- urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), -- R_SW_64_GPRELLOW); -- urel->r_addend = irel->r_addend; -- changed_relocs = true; -- } -- else -- all_optimized = false; -- break; -- -- case LITUSE_SW_64_BYTOFF: -- /* We can always optimize byte instructions. */ -- -- /* FIXME: sanity check the insn for byte op. Check that the -- literal dest reg is indeed Rb in the byte insn. */ -- -- insn &= ~ (unsigned) 0x001ff000; -- insn |= ((symval & 7) << 13) | 0x1000; -- bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); -- changed_contents = true; -- -- nrel = *urel; -- nrel.r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- nrel.r_addend = 0; -- -- /* As we adjust, move the reloc to the end so that we don't -- break the LITERAL+LITUSE chain. */ -- if (urel < --erel) -- *urel-- = *erel; -- *erel = nrel; -- changed_relocs = true; -- break; -- -- case LITUSE_SW_64_JSR: -- case LITUSE_SW_64_TLSGD: -- case LITUSE_SW_64_TLSLDM: -- case LITUSE_SW_64_JSRDIRECT: -- { -- bfd_vma optdest, org; -- bfd_signed_vma odisp; -- -- /* For undefined weak symbols, we're mostly interested in getting -- rid of the got entry whenever possible, so optimize this to a -- use of the zero register. */ -- if (info->h && info->h->root.root.type == bfd_link_hash_undefweak) -- { -- insn |= 31 << 16; -- bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); -- -- changed_contents = true; -- break; -- } -- -- /* If not zero, place to jump without needing pv. */ -- optdest = elf64_sw_64_relax_opt_call (info, symval); -- org = sec_output_vma + urel_r_offset + 4; -- odisp = (optdest ? optdest : symval) - org; -- -- if (odisp >= -0x400000 && odisp < 0x400000) -- { -- Elf_Internal_Rela *xrel; -- -- /* Preserve branch prediction call stack when possible. */ -- if ((insn & INSN_JSR_MASK) == INSN_JSR) -- insn = (OP_BSR << 26) | (insn & 0x03e00000); -- else -- insn = (OP_BR << 26) | (insn & 0x03e00000); -- bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); -- changed_contents = true; -- -- nrel = *urel; -- nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), -- R_SW_64_BRADDR); -- nrel.r_addend = irel->r_addend; -- -- if (optdest) -- nrel.r_addend += optdest - symval; -- else -- all_optimized = false; -- -- /* Kill any HINT reloc that might exist for this insn. */ -- xrel = (elf64_sw_64_find_reloc_at_ofs -- (info->relocs, info->relend, urel_r_offset, -- R_SW_64_HINT)); -- if (xrel) -- xrel->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- -- /* As we adjust, move the reloc to the end so that we don't -- break the LITERAL+LITUSE chain. */ -- if (urel < --erel) -- *urel-- = *erel; -- *erel = nrel; -- -- info->changed_relocs = true; -- } -- else -- all_optimized = false; -- -- /* Even if the target is not in range for a direct branch, -- if we share a GP, we can eliminate the gp reload. */ -- if (optdest) -- { -- Elf_Internal_Rela *gpdisp -- = (elf64_sw_64_find_reloc_at_ofs -- (info->relocs, irelend, urel_r_offset + 4, -- R_SW_64_GPDISP)); -- if (gpdisp) -- { -- bfd_byte *p_ldih = contents + gpdisp->r_offset; -- bfd_byte *p_ldi = p_ldih + gpdisp->r_addend; -- unsigned int ldih = bfd_get_32 (abfd, p_ldih); -- unsigned int ldi = bfd_get_32 (abfd, p_ldi); -- -- /* Verify that the instruction is "ldih $29,0($26)". -- Consider a function that ends in a noreturn call, -- and that the next function begins with an ldgp, -- and that by accident there is no padding between. -- In that case the insn would use $27 as the base. */ -- -- if (ldih == 0xffba0000 && ldi == 0xfbba0000) -- { -- bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_ldih); -- bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_ldi); -- -- gpdisp->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- changed_contents = true; -- changed_relocs = true; -- } -- } -- } -- } -- break; -- } -- } -- -- /* If we reused the literal instruction, we must have optimized all. */ -- BFD_ASSERT(!lit_reused || all_optimized); -- -- /* If all cases were optimized, we can reduce the use count on this -- got entry by one, possibly eliminating it. */ -- if (all_optimized) -- { -- if (--info->gotent->use_count == 0) -- { -- int sz = sw_64_got_entry_size (R_SW_64_LITERAL); -- sw_64_elf_tdata (info->gotobj)->total_got_size -= sz; -- if (!info->h) -- sw_64_elf_tdata (info->gotobj)->local_got_size -= sz; -- } -- -- /* If the literal instruction is no longer needed (it may have been -- reused. We can eliminate it. */ -- /* ??? For now, I don't want to deal with compacting the section, -- so just nop it out. */ -- if (!lit_reused) -- { -- /* this will cause sw_64/brk.S err. */ -- if (ELF64_R_TYPE ((irel-1)->r_info) == R_SW_64_LITERAL_GOT) -- { -- (irel-1)->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- changed_relocs = true; -- -- bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, contents + (irel-1)->r_offset); -- } -- irel->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- changed_relocs = true; -- -- bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, contents + irel->r_offset); -- changed_contents = true; -- } -- } -- -- info->changed_contents = changed_contents; -- info->changed_relocs = changed_relocs; -- -- if (all_optimized || relax_pass == 0) -- return true; -- return elf64_sw_64_relax_got_load (info, symval, irel, R_SW_64_LITERAL); --} -- -- static bool --elf64_sw_64_relax_tls_get_addr (struct sw_64_relax_info *info, bfd_vma symval, -- Elf_Internal_Rela *irel, bool is_gd) --{ -- bfd_byte *pos[5]; -- unsigned int insn, tlsgd_reg; -- Elf_Internal_Rela *gpdisp, *hint; -- bool dynamic, use_gottprel; -- unsigned long new_symndx; -- -- dynamic = (info->h != NULL -- && sw_64_elf_dynamic_symbol_p (&info->h->root, info->link_info)); -- -- /* If a TLS symbol is accessed using IE at least once, there is no point -- to use dynamic model for it. */ -- if (is_gd && info->h && (info->h->flags & SW_64_ELF_LINK_HASH_TLS_IE)) -- ; -- -- /* If the symbol is local, and we've already committed to DF_STATIC_TLS, -- then we might as well relax to IE. */ -- else if (bfd_link_pic (info->link_info) && !dynamic -- && (info->link_info->flags & DF_STATIC_TLS)) -- ; -- -- /* Otherwise we must be building an executable to do anything. */ -- else if (bfd_link_pic (info->link_info)) -- return true; -- -- /* The TLSGD/TLSLDM relocation must be followed by a LITERAL and -- the matching LITUSE_TLS relocations. */ -- if (irel + 2 >= info->relend) -- return true; -- if (ELF64_R_TYPE (irel[1].r_info) != R_SW_64_LITERAL -- || ELF64_R_TYPE (irel[2].r_info) != R_SW_64_LITUSE -- || irel[2].r_addend != (is_gd ? LITUSE_SW_64_TLSGD : LITUSE_SW_64_TLSLDM)) -- return true; -- -- /* There must be a GPDISP relocation positioned immediately after the -- LITUSE relocation. */ -- gpdisp = elf64_sw_64_find_reloc_at_ofs (info->relocs, info->relend, -- irel[2].r_offset + 4, R_SW_64_GPDISP); -- if (!gpdisp) -- return true; -- -- pos[0] = info->contents + irel[0].r_offset; -- pos[1] = info->contents + irel[1].r_offset; -- pos[2] = info->contents + irel[2].r_offset; -- pos[3] = info->contents + gpdisp->r_offset; -- pos[4] = pos[3] + gpdisp->r_addend; -- -- /* Beware of the compiler hoisting part of the sequence out a loop -- and adjusting the destination register for the TLSGD insn. If this -- happens, there will be a move into $16 before the JSR insn, so only -- transformations of the first insn pair should use this register. */ -- tlsgd_reg = bfd_get_32 (info->abfd, pos[0]); -- tlsgd_reg = (tlsgd_reg >> 21) & 31; -- -- /* Generally, the positions are not allowed to be out of order, lest the -- modified insn sequence have different register lifetimes. We can make -- an exception when pos 1 is adjacent to pos 0. */ -- if (pos[1] + 4 == pos[0]) -- { -- bfd_byte *tmp = pos[0]; -- pos[0] = pos[1]; -- pos[1] = tmp; -- } -- if (pos[1] >= pos[2] || pos[2] >= pos[3]) -- return true; -- -- /* Reduce the use count on the LITERAL relocation. Do this before we -- smash the symndx when we adjust the relocations below. */ -- { -- struct sw_64_elf_got_entry *lit_gotent; -- struct sw_64_elf_link_hash_entry *lit_h; -- unsigned long indx; -- -- BFD_ASSERT (ELF64_R_SYM (irel[1].r_info) >= info->symtab_hdr->sh_info); -- indx = ELF64_R_SYM (irel[1].r_info) - info->symtab_hdr->sh_info; -- lit_h = sw_64_elf_sym_hashes (info->abfd)[indx]; -- -- while (lit_h->root.root.type == bfd_link_hash_indirect -- || lit_h->root.root.type == bfd_link_hash_warning) -- lit_h = (struct sw_64_elf_link_hash_entry *) lit_h->root.root.u.i.link; -- -- for (lit_gotent = lit_h->got_entries; lit_gotent ; -- lit_gotent = lit_gotent->next) -- if (lit_gotent->gotobj == info->gotobj -- && lit_gotent->reloc_type == R_SW_64_LITERAL -- && lit_gotent->addend == irel[1].r_addend) -- break; -- BFD_ASSERT (lit_gotent); -- -- if (--lit_gotent->use_count == 0) -- { -- int sz = sw_64_got_entry_size (R_SW_64_LITERAL); -- sw_64_elf_tdata (info->gotobj)->total_got_size -= sz; -- } -- } -- -- /* Change -- -- ldi $16,x($gp) !tlsgd!1 -- ldl $27,__tls_get_addr($gp) !literal!1 -- jsr $26,($27),__tls_get_addr !lituse_tlsgd!1 -- ldih $29,0($26) !gpdisp!2 -- ldi $29,0($29) !gpdisp!2 -- to -- ldl $16,x($gp) !gottprel -- unop -- call_pal rduniq -- addl $16,$0,$0 -- unop -- or the first pair to -- ldi $16,x($gp) !tprel -- unop -- or -- ldih $16,x($gp) !tprelhi -- ldi $16,x($16) !tprello -- -- as appropriate. */ -- -- use_gottprel = false; -- new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : STN_UNDEF; -- -- /* Some compilers warn about a Boolean-looking expression being -- used in a switch. The explicit cast silences them. */ -- switch ((int) (!dynamic && !bfd_link_pic (info->link_info))) -- { -- case 1: -- { -- bfd_vma tp_base; -- bfd_signed_vma disp; -- -- BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL); -- tp_base = sw_64_get_tprel_base (info->link_info); -- disp = symval - tp_base; -- -- if (disp >= -0x8000 && disp < 0x8000) -- { -- insn = (OP_LDI << 26) | (tlsgd_reg << 21) | (31 << 16); -- bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); -- bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]); -- -- irel[0].r_offset = pos[0] - info->contents; -- irel[0].r_info = ELF64_R_INFO (new_symndx, R_SW_64_TPREL16); -- irel[1].r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- break; -- } -- else if (disp >= -(bfd_signed_vma) 0x80000000 -- && disp < (bfd_signed_vma) 0x7fff8000 -- && pos[0] + 4 == pos[1]) -- { -- insn = (OP_LDIH << 26) | (tlsgd_reg << 21) | (31 << 16); -- bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); -- insn = (OP_LDI << 26) | (tlsgd_reg << 21) | (tlsgd_reg << 16); -- bfd_put_32 (info->abfd, (bfd_vma) insn, pos[1]); -- -- irel[0].r_offset = pos[0] - info->contents; -- irel[0].r_info = ELF64_R_INFO (new_symndx, R_SW_64_TPRELHI); -- irel[1].r_offset = pos[1] - info->contents; -- irel[1].r_info = ELF64_R_INFO (new_symndx, R_SW_64_TPRELLO); -- break; -- } -- } -- /* FALLTHRU */ -- -- default: -- use_gottprel = true; -- -- insn = (OP_LDL << 26) | (tlsgd_reg << 21) | (29 << 16); -- bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); -- bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]); -- -- irel[0].r_offset = pos[0] - info->contents; -- irel[0].r_info = ELF64_R_INFO (new_symndx, R_SW_64_GOTTPREL); -- irel[1].r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- break; -- } -- -- bfd_put_32 (info->abfd, (bfd_vma) INSN_RDUNIQ, pos[2]); -- -- insn = INSN_ADDL | (16 << 21) | (0 << 16) | (0 << 0); -- bfd_put_32 (info->abfd, (bfd_vma) insn, pos[3]); -- -- bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[4]); -- -- irel[2].r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- gpdisp->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- -- hint = elf64_sw_64_find_reloc_at_ofs (info->relocs, info->relend, -- irel[2].r_offset, R_SW_64_HINT); -- if (hint) -- hint->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -- -- info->changed_contents = true; -- info->changed_relocs = true; -- -- /* Reduce the use count on the TLSGD/TLSLDM relocation. */ -- if (--info->gotent->use_count == 0) -- { -- int sz = sw_64_got_entry_size (info->gotent->reloc_type); -- sw_64_elf_tdata (info->gotobj)->total_got_size -= sz; -- if (!info->h) -- sw_64_elf_tdata (info->gotobj)->local_got_size -= sz; -- } -- -- /* If we've switched to a GOTTPREL relocation, increment the reference -- count on that got entry. */ -- if (use_gottprel) -- { -- struct sw_64_elf_got_entry *tprel_gotent; -- -- for (tprel_gotent = *info->first_gotent; tprel_gotent ; -- tprel_gotent = tprel_gotent->next) -- if (tprel_gotent->gotobj == info->gotobj -- && tprel_gotent->reloc_type == R_SW_64_GOTTPREL -- && tprel_gotent->addend == irel->r_addend) -- break; -- if (tprel_gotent) -- tprel_gotent->use_count++; -- else -- { -- if (info->gotent->use_count == 0) -- tprel_gotent = info->gotent; -- else -- { -- tprel_gotent = (struct sw_64_elf_got_entry *) -- bfd_alloc (info->abfd, sizeof (struct sw_64_elf_got_entry)); -- if (!tprel_gotent) -- return false; -- -- tprel_gotent->next = *info->first_gotent; -- *info->first_gotent = tprel_gotent; -- -- tprel_gotent->gotobj = info->gotobj; -- tprel_gotent->addend = irel->r_addend; -- tprel_gotent->got_offset = -1; -- tprel_gotent->reloc_done = 0; -- tprel_gotent->reloc_xlated = 0; -- } -- -- tprel_gotent->use_count = 1; -- tprel_gotent->reloc_type = R_SW_64_GOTTPREL; -- } -- } -- -- return true; --} -- -- static bool --elf64_sw_64_relax_section (bfd *abfd, asection *sec, -- struct bfd_link_info *link_info, bool *again) --{ -- Elf_Internal_Shdr *symtab_hdr; -- Elf_Internal_Rela *internal_relocs; -- Elf_Internal_Rela *irel, *irelend; -- Elf_Internal_Sym *isymbuf = NULL; -- struct sw_64_elf_got_entry **local_got_entries; -- struct sw_64_relax_info info; -- struct sw_64_elf_link_hash_table * htab; -- int relax_pass; -- -- htab = sw_64_elf_hash_table (link_info); -- if (htab == NULL) -- return false; -- -- /* There's nothing to change, yet. */ -- *again = false; -- -- if (bfd_link_relocatable (link_info) -- || ((sec->flags & (SEC_CODE | SEC_RELOC | SEC_ALLOC)) -- != (SEC_CODE | SEC_RELOC | SEC_ALLOC)) -- || sec->reloc_count == 0) -- return true; -- -- BFD_ASSERT (is_sw_64_elf (abfd)); -- relax_pass = link_info->relax_pass; -- -- /* Make sure our GOT and PLT tables are up-to-date. */ -- if (htab->relax_trip != link_info->relax_trip) -- { -- htab->relax_trip = link_info->relax_trip; -- -- /* This should never fail after the initial round, since the only error -- is GOT overflow, and relaxation only shrinks the table. However, we -- may only merge got sections during the first pass. If we merge -- sections after we've created GPREL relocs, the GP for the merged -- section backs up which may put the relocs out of range. */ -- if (!elf64_sw_64_size_got_sections (link_info, relax_pass == 0)) -- abort (); -- if (elf_hash_table (link_info)->dynamic_sections_created) -- { -- elf64_sw_64_size_plt_section (link_info); -- elf64_sw_64_size_rela_got_section (link_info); -- } -- } -- -- symtab_hdr = &elf_symtab_hdr (abfd); -- local_got_entries = sw_64_elf_tdata(abfd)->local_got_entries; -- -- /* Load the relocations for this section. */ -- internal_relocs = (_bfd_elf_link_read_relocs -- (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, -- link_info->keep_memory)); -- if (internal_relocs == NULL) -- return false; -- -- memset(&info, 0, sizeof (info)); -- info.abfd = abfd; -- info.sec = sec; -- info.link_info = link_info; -- info.symtab_hdr = symtab_hdr; -- info.relocs = internal_relocs; -- info.relend = irelend = internal_relocs + sec->reloc_count; -- -- /* Find the GP for this object. Do not store the result back via -- _bfd_set_gp_value, since this could change again before final. */ -- info.gotobj = sw_64_elf_tdata (abfd)->gotobj; -- if (info.gotobj) -- { -- asection *sgot = sw_64_elf_tdata (info.gotobj)->got; -- info.gp = (sgot->output_section->vma -- + sgot->output_offset -- + 0x8000); -- } -- -- /* Get the section contents. */ -- if (elf_section_data (sec)->this_hdr.contents != NULL) -- info.contents = elf_section_data (sec)->this_hdr.contents; -- else -- { -- if (!bfd_malloc_and_get_section (abfd, sec, &info.contents)) -- goto error_return; -- } -- -- for (irel = internal_relocs; irel < irelend; irel++) -- { -- bfd_vma symval; -- struct sw_64_elf_got_entry *gotent; -- unsigned long r_type = ELF64_R_TYPE (irel->r_info); -- unsigned long r_symndx = ELF64_R_SYM (irel->r_info); -- -- /* Early exit for unhandled or unrelaxable relocations. */ -- if (r_type != R_SW_64_LITERAL) -- { -- /* We complete everything except LITERAL in the first pass. */ -- if (relax_pass != 0) -- continue; -- if (r_type == R_SW_64_TLSLDM) -- { -- /* The symbol for a TLSLDM reloc is ignored. Collapse the -- reloc to the STN_UNDEF (0) symbol so that they all match. */ -- r_symndx = STN_UNDEF; -- } -- else if (r_type != R_SW_64_GOTDTPREL -- && r_type != R_SW_64_GOTTPREL -- && r_type != R_SW_64_TLSGD) -- continue; -- } -- -- /* Get the value of the symbol referred to by the reloc. */ -- if (r_symndx < symtab_hdr->sh_info) -- { -- /* A local symbol. */ -- Elf_Internal_Sym *isym; -- -- /* Read this BFD's local symbols. */ -- if (isymbuf == NULL) -- { -- isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; -- if (isymbuf == NULL) -- isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, -- symtab_hdr->sh_info, 0, -- NULL, NULL, NULL); -- if (isymbuf == NULL) -- goto error_return; -- } -- -- isym = isymbuf + r_symndx; -- -- /* Given the symbol for a TLSLDM reloc is ignored, this also -- means forcing the symbol value to the tp base. */ -- if (r_type == R_SW_64_TLSLDM) -- { -- info.tsec = bfd_abs_section_ptr; -- symval = sw_64_get_tprel_base (info.link_info); -- } -- else -- { -- symval = isym->st_value; -- if (isym->st_shndx == SHN_UNDEF) -- continue; -- else if (isym->st_shndx == SHN_ABS) -- info.tsec = bfd_abs_section_ptr; -- else if (isym->st_shndx == SHN_COMMON) -- info.tsec = bfd_com_section_ptr; -- else -- info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); -- } -- -- info.h = NULL; -- info.other = isym->st_other; -- if (local_got_entries) -- info.first_gotent = &local_got_entries[r_symndx]; -- else -- { -- info.first_gotent = &info.gotent; -- info.gotent = NULL; -- } -- } -- else -- { -- unsigned long indx; -- struct sw_64_elf_link_hash_entry *h; -- -- indx = r_symndx - symtab_hdr->sh_info; -- h = sw_64_elf_sym_hashes (abfd)[indx]; -- BFD_ASSERT (h != NULL); -- -- while (h->root.root.type == bfd_link_hash_indirect -- || h->root.root.type == bfd_link_hash_warning) -- h = (struct sw_64_elf_link_hash_entry *)h->root.root.u.i.link; -- -- /* If the symbol is undefined, we can't do anything with it. */ -- if (h->root.root.type == bfd_link_hash_undefined) -- continue; -- -- /* If the symbol isn't defined in the current module, -- again we can't do anything. */ -- if (h->root.root.type == bfd_link_hash_undefweak) -- { -- info.tsec = bfd_abs_section_ptr; -- symval = 0; -- } -- else if (!h->root.def_regular) -- { -- /* Except for TLSGD relocs, which can sometimes be -- relaxed to GOTTPREL relocs. */ -- if (r_type != R_SW_64_TLSGD) -- continue; -- info.tsec = bfd_abs_section_ptr; -- symval = 0; -- } -- else -- { -- info.tsec = h->root.root.u.def.section; -- symval = h->root.root.u.def.value; -- } -- -- info.h = h; -- info.other = h->root.other; -- info.first_gotent = &h->got_entries; -- } -- -- /* Search for the got entry to be used by this relocation. */ -- for (gotent = *info.first_gotent; gotent ; gotent = gotent->next) -- if (gotent->gotobj == info.gotobj -- && gotent->reloc_type == r_type -- && gotent->addend == irel->r_addend) -- break; -- info.gotent = gotent; -- -- symval += info.tsec->output_section->vma + info.tsec->output_offset; -- symval += irel->r_addend; -- -- switch (r_type) -- { -- case R_SW_64_LITERAL: -- BFD_ASSERT(info.gotent != NULL); -- -- /* If there exist LITUSE relocations immediately following, this -- opens up all sorts of interesting optimizations, because we -- now know every location that this address load is used. */ -- if (irel+1 < irelend -- && ELF64_R_TYPE (irel[1].r_info) == R_SW_64_LITUSE) -- { -- if (!elf64_sw_64_relax_with_lituse (&info, symval, irel)) -- goto error_return; -- } -- else -- { -- if (!elf64_sw_64_relax_got_load (&info, symval, irel, r_type)) -- goto error_return; -- } -- break; -- -- case R_SW_64_GOTDTPREL: -- case R_SW_64_GOTTPREL: -- BFD_ASSERT(info.gotent != NULL); -- if (!elf64_sw_64_relax_got_load (&info, symval, irel, r_type)) -- goto error_return; -- break; -- -- case R_SW_64_TLSGD: -- case R_SW_64_TLSLDM: -- BFD_ASSERT(info.gotent != NULL); -- if (!elf64_sw_64_relax_tls_get_addr (&info, symval, irel, -- r_type == R_SW_64_TLSGD)) -- goto error_return; -- break; -- } -- } -- -- if (isymbuf != NULL -- && symtab_hdr->contents != (unsigned char *) isymbuf) -- { -- if (!link_info->keep_memory) -- free (isymbuf); -- else -- { -- /* Cache the symbols for elf_link_input_bfd. */ -- symtab_hdr->contents = (unsigned char *) isymbuf; -- } -- } -- -- if (info.contents != NULL -- && elf_section_data (sec)->this_hdr.contents != info.contents) -- { -- if (!info.changed_contents && !link_info->keep_memory) -- free (info.contents); -- else -- { -- /* Cache the section contents for elf_link_input_bfd. */ -- elf_section_data (sec)->this_hdr.contents = info.contents; -- } -- } -- -- if (elf_section_data (sec)->relocs != internal_relocs) -- { -- if (!info.changed_relocs) -- free (internal_relocs); -- else -- elf_section_data (sec)->relocs = internal_relocs; -- } -- -- *again = info.changed_contents || info.changed_relocs; -- -- return true; -- --error_return: -- if (symtab_hdr->contents != (unsigned char *) isymbuf) -- free (isymbuf); -- if (elf_section_data (sec)->this_hdr.contents != info.contents) -- free (info.contents); -- if (elf_section_data (sec)->relocs != internal_relocs) -- free (internal_relocs); -- return false; --} -- --/* Emit a dynamic relocation for (DYNINDX, RTYPE, ADDEND) at (SEC, OFFSET) -- into the next available slot in SREL. */ -- -- static void --elf64_sw_64_emit_dynrel (bfd *abfd, struct bfd_link_info *info, -- asection *sec, asection *srel, bfd_vma offset, -- long dynindx, long rtype, bfd_vma addend) --{ -- Elf_Internal_Rela outrel; -- bfd_byte *loc; -- -- BFD_ASSERT (srel != NULL); -- -- outrel.r_info = ELF64_R_INFO (dynindx, rtype); -- outrel.r_addend = addend; -- -- offset = _bfd_elf_section_offset (abfd, info, sec, offset); -- if ((offset | 1) != (bfd_vma) -1) -- outrel.r_offset = sec->output_section->vma + sec->output_offset + offset; -- else -- memset (&outrel, 0, sizeof (outrel)); -- -- loc = srel->contents; -- loc += srel->reloc_count++ * sizeof (Elf64_External_Rela); -- bfd_elf64_swap_reloca_out (abfd, &outrel, loc); -- BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count <= srel->size); --} -- --/* Relocate an Sw_64 ELF section for a relocatable 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. */ -- -- static bool --elf64_sw_64_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED, -- struct bfd_link_info *info ATTRIBUTE_UNUSED, -- bfd *input_bfd, asection *input_section, -- bfd_byte *contents ATTRIBUTE_UNUSED, -- Elf_Internal_Rela *relocs, -- Elf_Internal_Sym *local_syms, -- asection **local_sections) --{ -- unsigned long symtab_hdr_sh_info; -- Elf_Internal_Rela *rel; -- Elf_Internal_Rela *relend; -- struct elf_link_hash_entry **sym_hashes; -- bool ret_val = true; -- -- symtab_hdr_sh_info = elf_symtab_hdr (input_bfd).sh_info; -- sym_hashes = elf_sym_hashes (input_bfd); -- -- relend = relocs + input_section->reloc_count; -- for (rel = relocs; rel < relend; rel++) -- { -- unsigned long r_symndx; -- Elf_Internal_Sym *sym; -- asection *sec; -- unsigned long r_type; -- -- r_type = ELF64_R_TYPE (rel->r_info); -- if (r_type >= R_SW_64_max) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: unsupported relocation type %#x"), -- input_bfd, (int) r_type); -- bfd_set_error (bfd_error_bad_value); -- ret_val = false; -- continue; -- } -- -- /* The symbol associated with GPDISP and LITUSE is -- immaterial. Only the addend is significant. */ -- if (r_type == R_SW_64_GPDISP || r_type == R_SW_64_LITUSE) -- continue; -- -- r_symndx = ELF64_R_SYM (rel->r_info); -- if (r_symndx < symtab_hdr_sh_info) -- { -- sym = local_syms + r_symndx; -- sec = local_sections[r_symndx]; -- } -- else -- { -- struct elf_link_hash_entry *h; -- -- h = sym_hashes[r_symndx - symtab_hdr_sh_info]; -- -- while (h->root.type == bfd_link_hash_indirect -- || h->root.type == bfd_link_hash_warning) -- h = (struct elf_link_hash_entry *) h->root.u.i.link; -- -- if (h->root.type != bfd_link_hash_defined -- && h->root.type != bfd_link_hash_defweak) -- continue; -- -- sym = NULL; -- sec = h->root.u.def.section; -- } -- -- if (sec != NULL && discarded_section (sec)) -- RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, -- rel, 1, relend, -- elf64_sw_64_howto_table + r_type, 0, -- contents); -- -- if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) -- rel->r_addend += sec->output_offset; -- } -- -- return ret_val; --} -- --/* Relocate an Sw_64 ELF section. */ -- -- static bool --elf64_sw_64_relocate_section (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; -- asection *sgot, *srel, *srelgot; -- bfd *dynobj, *gotobj; -- bfd_vma gp, tp_base, dtp_base; -- struct sw_64_elf_got_entry **local_got_entries; -- bool ret_val; -- -- BFD_ASSERT (is_sw_64_elf (input_bfd)); -- -- /* Handle relocatable links with a smaller loop. */ -- if (bfd_link_relocatable (info)) -- return elf64_sw_64_relocate_section_r (output_bfd, info, input_bfd, -- input_section, contents, relocs, -- local_syms, local_sections); -- -- /* This is a final link. */ -- -- ret_val = true; -- -- symtab_hdr = &elf_symtab_hdr (input_bfd); -- -- dynobj = elf_hash_table (info)->dynobj; -- srelgot = elf_hash_table (info)->srelgot; -- -- if (input_section->flags & SEC_ALLOC) -- { -- const char *section_name; -- section_name = (bfd_elf_string_from_elf_section -- (input_bfd, elf_elfheader(input_bfd)->e_shstrndx, -- _bfd_elf_single_rel_hdr (input_section)->sh_name)); -- BFD_ASSERT(section_name != NULL); -- srel = bfd_get_linker_section (dynobj, section_name); -- } -- else -- srel = NULL; -- -- /* Find the gp value for this input bfd. */ -- gotobj = sw_64_elf_tdata (input_bfd)->gotobj; -- if (gotobj) -- { -- sgot = sw_64_elf_tdata (gotobj)->got; -- gp = _bfd_get_gp_value (gotobj); -- if (gp == 0) -- { -- gp = (sgot->output_section->vma -- + sgot->output_offset -- + 0x8000); -- _bfd_set_gp_value (gotobj, gp); -- } -- } -- else -- { -- sgot = NULL; -- gp = 0; -- } -- -- local_got_entries = sw_64_elf_tdata(input_bfd)->local_got_entries; -- -- if (elf_hash_table (info)->tls_sec != NULL) -- { -- dtp_base = sw_64_get_dtprel_base (info); -- tp_base = sw_64_get_tprel_base (info); -- } -- else -- dtp_base = tp_base = 0; -- -- relend = relocs + input_section->reloc_count; -- for (rel = relocs; rel < relend; rel++) -- { -- struct sw_64_elf_link_hash_entry *h = NULL; -- struct sw_64_elf_got_entry *gotent; -- bfd_reloc_status_type r; -- reloc_howto_type *howto; -- unsigned long r_symndx; -- Elf_Internal_Sym *sym = NULL; -- asection *sec = NULL; -- bfd_vma value; -- bfd_vma addend; -- bool dynamic_symbol_p; -- bool unresolved_reloc = false; -- bool undef_weak_ref = false; -- unsigned long r_type; -- -- r_type = ELF64_R_TYPE(rel->r_info); -- if (r_type >= R_SW_64_max) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: unsupported relocation type %#x"), -- input_bfd, (int) r_type); -- bfd_set_error (bfd_error_bad_value); -- ret_val = false; -- continue; -- } -- -- howto = elf64_sw_64_howto_table + r_type; -- r_symndx = ELF64_R_SYM(rel->r_info); -- -- /* The symbol for a TLSLDM reloc is ignored. Collapse the -- reloc to the STN_UNDEF (0) symbol so that they all match. */ -- if (r_type == R_SW_64_TLSLDM) -- r_symndx = STN_UNDEF; -- -- if (r_symndx < symtab_hdr->sh_info) -- { -- asection *msec; -- sym = local_syms + r_symndx; -- sec = local_sections[r_symndx]; -- msec = sec; -- value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel); -- -- /* If this is a tp-relative relocation against sym STN_UNDEF (0), -- this is hackery from relax_section. Force the value to -- be the tls module base. */ -- if (r_symndx == STN_UNDEF -- && (r_type == R_SW_64_TLSLDM -- || r_type == R_SW_64_GOTTPREL -- || r_type == R_SW_64_TPREL64 -- || r_type == R_SW_64_TPRELHI -- || r_type == R_SW_64_TPRELLO -- || r_type == R_SW_64_TPREL16)) -- value = dtp_base; -- -- if (local_got_entries) -- gotent = local_got_entries[r_symndx]; -- else -- gotent = NULL; -- -- /* Need to adjust local GOT entries' addends for SEC_MERGE -- unless it has been done already. */ -- if ((sec->flags & SEC_MERGE) -- && ELF_ST_TYPE (sym->st_info) == STT_SECTION -- && sec->sec_info_type == SEC_INFO_TYPE_MERGE -- && gotent -- && !gotent->reloc_xlated) -- { -- struct sw_64_elf_got_entry *ent; -- -- for (ent = gotent; ent; ent = ent->next) -- { -- ent->reloc_xlated = 1; -- if (ent->use_count == 0) -- continue; -- msec = sec; -- ent->addend = -- _bfd_merged_section_offset (output_bfd, &msec, -- elf_section_data (sec)-> -- sec_info, -- sym->st_value + ent->addend); -- ent->addend -= sym->st_value; -- ent->addend += msec->output_section->vma -- + msec->output_offset -- - sec->output_section->vma -- - sec->output_offset; -- } -- } -- -- dynamic_symbol_p = false; -- } -- else -- { -- bool warned, ignored; -- struct elf_link_hash_entry *hh; -- struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd); -- -- RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, -- r_symndx, symtab_hdr, sym_hashes, -- hh, sec, value, -- unresolved_reloc, warned, ignored); -- -- if (warned) -- continue; -- -- if (value == 0 -- && ! unresolved_reloc -- && hh->root.type == bfd_link_hash_undefweak) -- undef_weak_ref = true; -- -- h = (struct sw_64_elf_link_hash_entry *) hh; -- dynamic_symbol_p = sw_64_elf_dynamic_symbol_p (&h->root, info); -- gotent = h->got_entries; -- } -- -- if (sec != NULL && discarded_section (sec)) -- RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, -- rel, 1, relend, howto, 0, contents); -- -- addend = rel->r_addend; -- value += addend; -- -- /* Search for the proper got entry. */ -- for (; gotent ; gotent = gotent->next) -- if (gotent->gotobj == gotobj -- && gotent->reloc_type == r_type -- && gotent->addend == addend) -- break; -- -- switch (r_type) -- { -- case R_SW_64_GPDISP: -- { -- bfd_byte *p_ldih, *p_ldi; -- -- BFD_ASSERT(gp != 0); -- -- value = (input_section->output_section->vma -- + input_section->output_offset -- + rel->r_offset); -- -- p_ldih = contents + rel->r_offset; -- p_ldi = p_ldih + rel->r_addend; -- -- r = elf64_sw_64_do_reloc_gpdisp (input_bfd, gp - value, -- p_ldih, p_ldi); -- } -- break; -- -- case R_SW_64_LITERAL: -- BFD_ASSERT(sgot != NULL); -- BFD_ASSERT(gp != 0); -- BFD_ASSERT(gotent != NULL); -- BFD_ASSERT(gotent->use_count >= 1); -- -- if (!gotent->reloc_done) -- { -- gotent->reloc_done = 1; -- -- bfd_put_64 (output_bfd, value, -- sgot->contents + gotent->got_offset); -- -- /* If the symbol has been forced local, output a -- RELATIVE reloc, otherwise it will be handled in -- finish_dynamic_symbol. */ -- if (bfd_link_pic (info) -- && !dynamic_symbol_p -- && !undef_weak_ref) -- elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srelgot, -- gotent->got_offset, 0, -- R_SW_64_RELATIVE, value); -- } -- -- value = (sgot->output_section->vma -- + sgot->output_offset -- + gotent->got_offset); -- Elf_Internal_Rela *rel_got; -- rel_got = rel-1; -- //printf("ELF64_R_TYPE((rel_got)->r_info)=%d\n\n",ELF64_R_TYPE((rel-1)->r_info)); -- //printf("ELF64_R_TYPE((rel)->r_info)=%d\n\n",ELF64_R_TYPE((rel)->r_info)); -- if((ELF64_R_TYPE(rel_got->r_info) == R_SW_64_LITERAL_GOT)) -- { -- -- value -= gp; -- -- /* ldl $27, disp($29)->ldl $27, disp($27). */ -- unsigned int insn; -- unsigned int operand_1; -- unsigned long p_ldl; -- p_ldl = contents + rel->r_offset; -- insn = bfd_get_32 (input_bfd, p_ldl); -- operand_1 = insn & 0x03e00000; -- if ((insn & INSN_LDL_MASK) == INSN_LDL) -- insn = (insn & 0xffe0ffff) | (operand_1 >> 5); -- bfd_put_32 (input_bfd, (bfd_vma) insn, contents + rel->r_offset); -- -- /* emit the ldih $29, got_disp($29). */ -- bfd_byte *p_ldih; -- p_ldih = contents + rel_got->r_offset; -- bfd_vma got_disp; -- bfd_vma got_low; -- bfd_vma got_tmp; -- unsigned long i_ldih; -- i_ldih = bfd_get_32 (input_bfd, p_ldih); -- got_disp = ((i_ldih & 0xffff) << 16); -- got_disp = (got_disp ^ 0x80008000) - 0x80008000; -- -- //disp = value - got_disp*65536; -- // low = sign_extend_16 (addend); -- // tmp = addend - low; -- // value = sign_extend_16 (tmp >> 16); -- if((int)value >= 0x8000 || (int)value<-0x8000) -- { -- // printf("hit got\n"); -- got_low =(short)value; -- got_tmp = value - got_low; -- got_disp = got_disp + got_tmp; -- //printf("int(value)=%x got_disp=%x got_low=%x got_tmp=%x\n",(int)value,got_disp,got_low,got_tmp); -- value = (bfd_vma)got_low; -- } -- i_ldih = ((i_ldih & 0xffff0000) -- | (((got_disp >> 16) + ((got_disp >> 15) & 1)) & 0xffff)); -- bfd_put_32 (input_bfd, (bfd_vma) i_ldih, p_ldih); -- -- //emit ldl $27,disp($27) -- goto default_reloc; -- } -- else{ -- value -= gp; -- goto default_reloc; -- } -- -- case R_SW_64_GPREL32: -- case R_SW_64_GPREL16: -- case R_SW_64_GPRELLOW: -- if (dynamic_symbol_p) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: gp-relative relocation against dynamic symbol %s"), -- input_bfd, h->root.root.root.string); -- ret_val = false; -- } -- BFD_ASSERT(gp != 0); -- value -= gp; -- goto default_reloc; -- -- case R_SW_64_GPRELHIGH: -- if (dynamic_symbol_p) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: gp-relative relocation against dynamic symbol %s"), -- input_bfd, h->root.root.root.string); -- ret_val = false; -- } -- BFD_ASSERT(gp != 0); -- value -= gp; -- value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1); -- goto default_reloc; -- -- case R_SW_64_HINT: -- /* A call to a dynamic symbol is definitely out of range of -- the 16-bit displacement. Don't bother writing anything. */ -- if (dynamic_symbol_p) -- { -- r = bfd_reloc_ok; -- break; -- } -- /* The regular PC-relative stuff measures from the start of -- the instruction rather than the end. */ -- value -= 4; -- goto default_reloc; -- -- case R_SW_64_BRADDR: -- if (dynamic_symbol_p) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: pc-relative relocation against dynamic symbol %s"), -- input_bfd, h->root.root.root.string); -- ret_val = false; -- } -- /* The regular PC-relative stuff measures from the start of -- the instruction rather than the end. */ -- value -= 4; -- goto default_reloc; -- -- case R_SW_64_BRSGP: -- { -- int other; -- const char *name; -- -- /* The regular PC-relative stuff measures from the start of -- the instruction rather than the end. */ -- value -= 4; -- -- /* The source and destination gp must be the same. Note that -- the source will always have an assigned gp, since we forced -- one in check_relocs, but that the destination may not, as -- it might not have had any relocations at all. Also take -- care not to crash if H is an undefined symbol. */ -- if (h != NULL && sec != NULL -- && sw_64_elf_tdata (sec->owner)->gotobj -- && gotobj != sw_64_elf_tdata (sec->owner)->gotobj) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: change in gp: BRSGP %s"), -- input_bfd, h->root.root.root.string); -- ret_val = false; -- } -- -- /* The symbol should be marked either NOPV or STD_GPLOAD. */ -- if (h != NULL) -- other = h->root.other; -- else -- other = sym->st_other; -- switch (other & STO_SW_64_STD_GPLOAD) -- { -- case STO_SW_64_NOPV: -- break; -- case STO_SW_64_STD_GPLOAD: -- value += 8; -- break; -- default: -- if (h != NULL) -- name = h->root.root.root.string; -- else -- { -- name = (bfd_elf_string_from_elf_section -- (input_bfd, symtab_hdr->sh_link, sym->st_name)); -- if (name == NULL) -- name = _(""); -- else if (name[0] == 0) -- name = bfd_section_name (sec); -- } -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: !samegp reloc against symbol without .prologue: %s"), -- input_bfd, name); -- ret_val = false; -- break; -- } -- -- goto default_reloc; -- } -- -- case R_SW_64_REFLONG: -- case R_SW_64_REFQUAD: -- case R_SW_64_DTPREL64: -- case R_SW_64_TPREL64: -- { -- long dynindx, dyntype = r_type; -- bfd_vma dynaddend; -- -- /* Careful here to remember RELATIVE relocations for global -- variables for symbolic shared objects. */ -- -- if (dynamic_symbol_p) -- { -- BFD_ASSERT(h->root.dynindx != -1); -- dynindx = h->root.dynindx; -- dynaddend = addend; -- addend = 0, value = 0; -- } -- else if (r_type == R_SW_64_DTPREL64) -- { -- BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -- value -= dtp_base; -- goto default_reloc; -- } -- else if (r_type == R_SW_64_TPREL64) -- { -- BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -- if (!bfd_link_dll (info)) -- { -- value -= tp_base; -- goto default_reloc; -- } -- dynindx = 0; -- dynaddend = value - dtp_base; -- } -- else if (bfd_link_pic (info) -- && r_symndx != STN_UNDEF -- && (input_section->flags & SEC_ALLOC) -- && !undef_weak_ref -- && !(unresolved_reloc -- && (_bfd_elf_section_offset (output_bfd, info, -- input_section, -- rel->r_offset) -- == (bfd_vma) -1))) -- { -- if (r_type == R_SW_64_REFLONG) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: unhandled dynamic relocation against %s"), -- input_bfd, -- h->root.root.root.string); -- ret_val = false; -- } -- dynindx = 0; -- dyntype = R_SW_64_RELATIVE; -- dynaddend = value; -- } -- else -- goto default_reloc; -- -- if (input_section->flags & SEC_ALLOC) -- elf64_sw_64_emit_dynrel (output_bfd, info, input_section, -- srel, rel->r_offset, dynindx, -- dyntype, dynaddend); -- } -- goto default_reloc; -- -- case R_SW_64_SREL16: -- case R_SW_64_SREL32: -- case R_SW_64_SREL64: -- if (dynamic_symbol_p) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: pc-relative relocation against dynamic symbol %s"), -- input_bfd, h->root.root.root.string); -- ret_val = false; -- } -- else if (bfd_link_pic (info) -- && undef_weak_ref) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: pc-relative relocation against undefined weak symbol %s"), -- input_bfd, h->root.root.root.string); -- ret_val = false; -- } -- -- -- /* ??? .eh_frame references to discarded sections will be smashed -- to relocations against SHN_UNDEF. The .eh_frame format allows -- NULL to be encoded as 0 in any format, so this works here. */ -- if (r_symndx == STN_UNDEF -- || (unresolved_reloc -- && _bfd_elf_section_offset (output_bfd, info, -- input_section, -- rel->r_offset) == (bfd_vma) -1)) -- howto = (elf64_sw_64_howto_table -- + (r_type - R_SW_64_SREL32 + R_SW_64_REFLONG)); -- goto default_reloc; -- -- case R_SW_64_TLSLDM: -- /* Ignore the symbol for the relocation. The result is always -- the current module. */ -- dynamic_symbol_p = 0; -- /* FALLTHRU */ -- -- case R_SW_64_TLSGD: -- if (!gotent->reloc_done) -- { -- gotent->reloc_done = 1; -- -- /* Note that the module index for the main program is 1. */ -- bfd_put_64 (output_bfd, -- !bfd_link_pic (info) && !dynamic_symbol_p, -- sgot->contents + gotent->got_offset); -- -- /* If the symbol has been forced local, output a -- DTPMOD64 reloc, otherwise it will be handled in -- finish_dynamic_symbol. */ -- if (bfd_link_pic (info) && !dynamic_symbol_p) -- elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srelgot, -- gotent->got_offset, 0, -- R_SW_64_DTPMOD64, 0); -- -- if (dynamic_symbol_p || r_type == R_SW_64_TLSLDM) -- value = 0; -- else -- { -- BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -- value -= dtp_base; -- } -- bfd_put_64 (output_bfd, value, -- sgot->contents + gotent->got_offset + 8); -- } -- -- value = (sgot->output_section->vma -- + sgot->output_offset -- + gotent->got_offset); -- value -= gp; -- goto default_reloc; -- -- case R_SW_64_DTPRELHI: -- case R_SW_64_DTPRELLO: -- case R_SW_64_DTPREL16: -- if (dynamic_symbol_p) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: dtp-relative relocation against dynamic symbol %s"), -- input_bfd, h->root.root.root.string); -- ret_val = false; -- } -- BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -- value -= dtp_base; -- if (r_type == R_SW_64_DTPRELHI) -- value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1); -- goto default_reloc; -- -- case R_SW_64_TPRELHI: -- case R_SW_64_TPRELLO: -- case R_SW_64_TPREL16: -- if (bfd_link_dll (info)) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: TLS local exec code cannot be linked into shared objects"), -- input_bfd); -- ret_val = false; -- } -- else if (dynamic_symbol_p) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%pB: tp-relative relocation against dynamic symbol %s"), -- input_bfd, h->root.root.root.string); -- ret_val = false; -- } -- BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -- value -= tp_base; -- if (r_type == R_SW_64_TPRELHI) -- value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1); -- goto default_reloc; -- -- case R_SW_64_GOTDTPREL: -- case R_SW_64_GOTTPREL: -- BFD_ASSERT(sgot != NULL); -- BFD_ASSERT(gp != 0); -- BFD_ASSERT(gotent != NULL); -- BFD_ASSERT(gotent->use_count >= 1); -- -- if (!gotent->reloc_done) -- { -- gotent->reloc_done = 1; -- -- if (dynamic_symbol_p) -- value = 0; -- else -- { -- BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -- if (r_type == R_SW_64_GOTDTPREL) -- value -= dtp_base; -- else if (bfd_link_executable (info)) -- value -= tp_base; -- else -- { -- elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srelgot, -- gotent->got_offset, 0, -- R_SW_64_TPREL64, -- value - dtp_base); -- value = 0; -- } -- } -- bfd_put_64 (output_bfd, value, -- sgot->contents + gotent->got_offset); -- } -- -- value = (sgot->output_section->vma -- + sgot->output_offset -- + gotent->got_offset); -- value -= gp; -- goto default_reloc; -- -- default: --default_reloc: -- r = _bfd_final_link_relocate (howto, input_bfd, input_section, -- contents, rel->r_offset, value, 0); -- break; -- } -- -- switch (r) -- { -- case bfd_reloc_ok: -- break; -- -- case bfd_reloc_overflow: -- { -- const char *name; -- -- /* Don't warn if the overflow is due to pc relative reloc -- against discarded section. Section optimization code should -- handle it. */ -- -- if (r_symndx < symtab_hdr->sh_info -- && sec != NULL && howto->pc_relative -- && discarded_section (sec)) -- break; -- -- if (h != NULL) -- name = NULL; -- 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 (sec); -- } -- (*info->callbacks->reloc_overflow) -- (info, (h ? &h->root.root : NULL), name, howto->name, -- (bfd_vma) 0, input_bfd, input_section, rel->r_offset); -- } -- break; -- -- default: -- case bfd_reloc_outofrange: -- abort (); -- } -- } -- -- return ret_val; --} -- --/* Finish up dynamic symbol handling. We set the contents of various -- dynamic sections here. */ -- -- static bool --elf64_sw_64_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, -- struct elf_link_hash_entry *h, -- Elf_Internal_Sym *sym) --{ -- struct sw_64_elf_link_hash_entry *ah = (struct sw_64_elf_link_hash_entry *)h; -- -- if (h->needs_plt) -- { -- /* Fill in the .plt entry for this symbol. */ -- asection *splt, *sgot, *srel; -- Elf_Internal_Rela outrel; -- bfd_byte *loc; -- bfd_vma got_addr, plt_addr; -- bfd_vma plt_index; -- struct sw_64_elf_got_entry *gotent; -- -- BFD_ASSERT (h->dynindx != -1); -- -- splt = elf_hash_table (info)->splt; -- BFD_ASSERT (splt != NULL); -- srel = elf_hash_table (info)->srelplt; -- BFD_ASSERT (srel != NULL); -- -- for (gotent = ah->got_entries; gotent ; gotent = gotent->next) -- if (gotent->reloc_type == R_SW_64_LITERAL -- && gotent->use_count > 0) -- { -- unsigned int insn; -- int disp; -- -- sgot = sw_64_elf_tdata (gotent->gotobj)->got; -- BFD_ASSERT (sgot != NULL); -- -- BFD_ASSERT (gotent->got_offset != -1); -- BFD_ASSERT (gotent->plt_offset != -1); -- -- got_addr = (sgot->output_section->vma -- + sgot->output_offset -- + gotent->got_offset); -- plt_addr = (splt->output_section->vma -- + splt->output_offset -- + gotent->plt_offset); -- -- plt_index = (gotent->plt_offset-PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; -- -- /* Fill in the entry in the procedure linkage table. */ -- if (elf64_sw_64_use_secureplt) -- { -- disp = (PLT_HEADER_SIZE - 4) - (gotent->plt_offset + 4); -- insn = INSN_AD (INSN_BR, 31, disp); -- bfd_put_32 (output_bfd, insn, -- splt->contents + gotent->plt_offset); -- -- plt_index = ((gotent->plt_offset - NEW_PLT_HEADER_SIZE) -- / NEW_PLT_ENTRY_SIZE); -- } -- else -- { -- disp = -(gotent->plt_offset + 4); -- insn = INSN_AD (INSN_BR, 28, disp); -- bfd_put_32 (output_bfd, insn, -- splt->contents + gotent->plt_offset); -- bfd_put_32 (output_bfd, INSN_UNOP, -- splt->contents + gotent->plt_offset + 4); -- bfd_put_32 (output_bfd, INSN_UNOP, -- splt->contents + gotent->plt_offset + 8); -- -- plt_index = ((gotent->plt_offset - OLD_PLT_HEADER_SIZE) -- / OLD_PLT_ENTRY_SIZE); -- } -- -- /* Fill in the entry in the .rela.plt section. */ -- outrel.r_offset = got_addr; -- outrel.r_info = ELF64_R_INFO(h->dynindx, R_SW_64_JMP_SLOT); -- outrel.r_addend = 0; -- -- loc = srel->contents + plt_index * sizeof (Elf64_External_Rela); -- bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); -- -- /* Fill in the entry in the .got. */ -- bfd_put_64 (output_bfd, plt_addr, -- sgot->contents + gotent->got_offset); -- } -- } -- else if (sw_64_elf_dynamic_symbol_p (h, info)) -- { -- /* Fill in the dynamic relocations for this symbol's .got entries. */ -- asection *srel; -- struct sw_64_elf_got_entry *gotent; -- -- srel = elf_hash_table (info)->srelgot; -- BFD_ASSERT (srel != NULL); -- -- for (gotent = ((struct sw_64_elf_link_hash_entry *) h)->got_entries; -- gotent != NULL; -- gotent = gotent->next) -- { -- asection *sgot; -- long r_type; -- -- if (gotent->use_count == 0) -- continue; -- -- sgot = sw_64_elf_tdata (gotent->gotobj)->got; -- -- r_type = gotent->reloc_type; -- switch (r_type) -- { -- case R_SW_64_LITERAL: -- r_type = R_SW_64_GLOB_DAT; -- break; -- case R_SW_64_TLSGD: -- r_type = R_SW_64_DTPMOD64; -- break; -- case R_SW_64_GOTDTPREL: -- r_type = R_SW_64_DTPREL64; -- break; -- case R_SW_64_GOTTPREL: -- r_type = R_SW_64_TPREL64; -- break; -- case R_SW_64_TLSLDM: -- default: -- abort (); -- } -- -- elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srel, -- gotent->got_offset, h->dynindx, -- r_type, gotent->addend); -- -- if (gotent->reloc_type == R_SW_64_TLSGD) -- elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srel, -- gotent->got_offset + 8, h->dynindx, -- R_SW_64_DTPREL64, gotent->addend); -- } -- } -- -- /* Mark some specially defined symbols as absolute. */ -- if (h == elf_hash_table (info)->hdynamic -- || h == elf_hash_table (info)->hgot -- || h == elf_hash_table (info)->hplt) -- sym->st_shndx = SHN_ABS; -- -- return true; --} -- --/* Finish up the dynamic sections. */ -- -- static bool --elf64_sw_64_finish_dynamic_sections (bfd *output_bfd, -- struct bfd_link_info *info) --{ -- bfd *dynobj; -- asection *sdyn; -- -- dynobj = elf_hash_table (info)->dynobj; -- sdyn = bfd_get_linker_section (dynobj, ".dynamic"); -- -- if (elf_hash_table (info)->dynamic_sections_created) -- { -- asection *splt, *sgotplt, *srelaplt; -- Elf64_External_Dyn *dyncon, *dynconend; -- bfd_vma plt_vma, gotplt_vma; -- -- splt = elf_hash_table (info)->splt; -- srelaplt = elf_hash_table (info)->srelplt; -- BFD_ASSERT (splt != NULL && sdyn != NULL); -- -- plt_vma = splt->output_section->vma + splt->output_offset; -- -- gotplt_vma = 0; -- if (elf64_sw_64_use_secureplt) -- { -- sgotplt = elf_hash_table (info)->sgotplt; -- BFD_ASSERT (sgotplt != NULL); -- if (sgotplt->size > 0) -- gotplt_vma = sgotplt->output_section->vma + sgotplt->output_offset; -- } -- -- dyncon = (Elf64_External_Dyn *) sdyn->contents; -- dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size); -- for (; dyncon < dynconend; dyncon++) -- { -- Elf_Internal_Dyn dyn; -- -- bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); -- -- switch (dyn.d_tag) -- { -- case DT_PLTGOT: -- dyn.d_un.d_ptr -- = elf64_sw_64_use_secureplt ? gotplt_vma : plt_vma; -- break; -- case DT_PLTRELSZ: -- dyn.d_un.d_val = srelaplt ? srelaplt->size : 0; -- break; -- case DT_JMPREL: -- dyn.d_un.d_ptr = srelaplt ? (srelaplt->output_section->vma -- + srelaplt->output_offset) : 0; -- break; -- } -- -- bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); -- } -- -- /* Initialize the plt header. */ -- if (splt->size > 0) -- { -- unsigned int insn; -- int ofs; -- -- if (elf64_sw_64_use_secureplt) -- { -- ofs = gotplt_vma - (plt_vma + PLT_HEADER_SIZE); -- -- insn = INSN_ABC (INSN_SUBL, 27, 28, 25); -- bfd_put_32 (output_bfd, insn, splt->contents); -- -- insn = INSN_ABO (INSN_LDIH, 28, 28, (ofs + 0x8000) >> 16); -- bfd_put_32 (output_bfd, insn, splt->contents + 4); -- -- insn = INSN_ABC (INSN_S4SUBL, 25, 25, 25); -- bfd_put_32 (output_bfd, insn, splt->contents + 8); -- -- insn = INSN_ABO (INSN_LDI, 28, 28, ofs); -- bfd_put_32 (output_bfd, insn, splt->contents + 12); -- -- insn = INSN_ABO (INSN_LDL, 27, 28, 0); -- bfd_put_32 (output_bfd, insn, splt->contents + 16); -- -- insn = INSN_ABC (INSN_ADDL, 25, 25, 25); -- bfd_put_32 (output_bfd, insn, splt->contents + 20); -- -- insn = INSN_ABO (INSN_LDL, 28, 28, 8); -- bfd_put_32 (output_bfd, insn, splt->contents + 24); -- -- insn = INSN_AB (INSN_JMP, 31, 27); -- bfd_put_32 (output_bfd, insn, splt->contents + 28); -- -- insn = INSN_AD (INSN_BR, 28, -PLT_HEADER_SIZE); -- bfd_put_32 (output_bfd, insn, splt->contents + 32); -- } -- else -- { -- insn = INSN_AD (INSN_BR, 27, 0); /* br $27, .+4 */ -- bfd_put_32 (output_bfd, insn, splt->contents); -- -- insn = INSN_ABO (INSN_LDL, 27, 27, 12); -- bfd_put_32 (output_bfd, insn, splt->contents + 4); -- -- insn = INSN_UNOP; -- bfd_put_32 (output_bfd, insn, splt->contents + 8); -- -- insn = INSN_AB (INSN_JMP, 27, 27); -- bfd_put_32 (output_bfd, insn, splt->contents + 12); -- -- /* The next two words will be filled in by ld.so. */ -- bfd_put_64 (output_bfd, 0, splt->contents + 16); -- bfd_put_64 (output_bfd, 0, splt->contents + 24); -- } -- -- elf_section_data (splt->output_section)->this_hdr.sh_entsize = 0; -- } -- } -- -- return true; --} -- --/* We need to use a special link routine to handle the .mdebug section. -- We need to merge all instances of these sections together, not write -- them all out sequentially. */ -- -- static bool --elf64_sw_64_final_link (bfd *abfd, struct bfd_link_info *info) --{ -- asection *o; -- struct bfd_link_order *p; -- asection *mdebug_sec; -- 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; -- void * mdebug_handle = NULL; -- struct sw_64_elf_link_hash_table * htab; -- -- htab = sw_64_elf_hash_table (info); -- if (htab == NULL) -- return false; -- -- /* Go through the sections and collect the mdebug information. */ -- mdebug_sec = NULL; -- for (o = abfd->sections; o != (asection *) NULL; o = o->next) -- { -- 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 == NULL) -- return false; -- -- if (1) -- { -- asection *s; -- EXTR esym; -- bfd_vma last = 0; -- unsigned int i; -- static const char * const name[] = -- { -- ".text", ".init", ".fini", ".data", -- ".rodata", ".sdata", ".sbss", ".bss" -- }; -- static const int sc[] = { scText, scInit, scFini, scData, -- scRData, scSData, scSBss, scBss }; -- -- esym.jmptbl = 0; -- esym.cobol_main = 0; -- esym.weakext = 0; -- esym.reserved = 0; -- esym.ifd = ifdNil; -- esym.asym.iss = issNil; -- esym.asym.st = stLocal; -- esym.asym.reserved = 0; -- esym.asym.index = indexNil; -- for (i = 0; i < 8; i++) -- { -- esym.asym.sc = sc[i]; -- s = bfd_get_section_by_name (abfd, name[i]); -- if (s != NULL) -- { -- esym.asym.value = s->vma; -- last = s->vma + s->size; -- } -- else -- esym.asym.value = last; -- -- if (! bfd_ecoff_debug_one_external (abfd, &debug, swap, -- name[i], &esym)) -- return false; -- } -- } -- -- for (p = o->map_head.link_order; -- 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_data_link_order) -- continue; -- abort (); -- } -- -- input_section = p->u.indirect.section; -- input_bfd = input_section->owner; -- -- if (! is_sw_64_elf (input_bfd)) -- /* I don't know what a non SW_64 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->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 (!elf64_sw_64_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 = (char *) 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 sw_64_elf_link_hash_entry *h; -- -- (*input_swap->swap_ext_in) (input_bfd, 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 = sw_64_elf_link_hash_lookup (htab, 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; -- elf_link_hash_traverse (elf_hash_table (info), -- elf64_sw_64_output_extsym, -- &einfo); -- if (einfo.failed) -- return false; -- -- /* Set the size of the .mdebug section. */ -- o->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->map_head.link_order = (struct bfd_link_order *) NULL; -- -- mdebug_sec = o; -- } -- } -- -- /* Invoke the regular ELF backend linker to do all the work. */ -- if (! bfd_elf_final_link (abfd, info)) -- return false; -- -- /* Now write out the computed sections. */ -- -- /* The .got subsections... */ -- { -- bfd *i, *dynobj = elf_hash_table(info)->dynobj; -- for (i = htab->got_list; -- i != NULL; -- i = sw_64_elf_tdata(i)->got_link_next) -- { -- asection *sgot; -- -- /* elf_bfd_final_link already did everything in dynobj. */ -- if (i == dynobj) -- continue; -- -- sgot = sw_64_elf_tdata(i)->got; -- if (! bfd_set_section_contents (abfd, sgot->output_section, -- sgot->contents, -- (file_ptr) sgot->output_offset, -- sgot->size)) -- 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); -- } -- -- return true; --} -- -- static enum elf_reloc_type_class --elf64_sw_64_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, -- const asection *rel_sec ATTRIBUTE_UNUSED, -- const Elf_Internal_Rela *rela) --{ -- switch ((int) ELF64_R_TYPE (rela->r_info)) -- { -- case R_SW_64_RELATIVE: -- return reloc_class_relative; -- case R_SW_64_JMP_SLOT: -- return reloc_class_plt; -- case R_SW_64_COPY: -- return reloc_class_copy; -- default: -- return reloc_class_normal; -- } --} -- --static const struct bfd_elf_special_section elf64_sw_64_special_sections[] = --{ -- { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_SW_64_GPREL }, -- { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_SW_64_GPREL }, -- { NULL, 0, 0, 0, 0 } --}; -- --/* ECOFF swapping routines. These are used when dealing with the -- .mdebug section, which is in the ECOFF debugging format. Copied -- from elf32-mips.c. */ --static const struct ecoff_debug_swap --elf64_sw_64_ecoff_debug_swap = --{ -- /* 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. */ -- elf64_sw_64_read_ecoff_info --}; -- --/* Use a non-standard hash bucket size of 8. */ -- --static const struct elf_size_info sw_64_elf_size_info = --{ -- sizeof (Elf64_External_Ehdr), -- sizeof (Elf64_External_Phdr), -- sizeof (Elf64_External_Shdr), -- sizeof (Elf64_External_Rel), -- sizeof (Elf64_External_Rela), -- sizeof (Elf64_External_Sym), -- sizeof (Elf64_External_Dyn), -- sizeof (Elf_External_Note), -- 8, -- 1, -- 64, 3, -- ELFCLASS64, EV_CURRENT, -- bfd_elf64_write_out_phdrs, -- bfd_elf64_write_shdrs_and_ehdr, -- bfd_elf64_checksum_contents, -- bfd_elf64_write_relocs, -- bfd_elf64_swap_symbol_in, -- bfd_elf64_swap_symbol_out, -- bfd_elf64_slurp_reloc_table, -- bfd_elf64_slurp_symbol_table, -- bfd_elf64_swap_dyn_in, -- bfd_elf64_swap_dyn_out, -- bfd_elf64_swap_reloc_in, -- bfd_elf64_swap_reloc_out, -- bfd_elf64_swap_reloca_in, -- bfd_elf64_swap_reloca_out --}; -- --#define TARGET_LITTLE_SYM sw_64_elf64_vec --#define TARGET_LITTLE_NAME "elf64-sw_64" --#define ELF_ARCH bfd_arch_sw_64 --#define ELF_TARGET_ID SW_64_ELF_DATA --#define ELF_MACHINE_CODE EM_SW_64 --#define ELF_MAXPAGESIZE 0x10000 --#define ELF_COMMONPAGESIZE 0x2000 -- --#define bfd_elf64_bfd_link_hash_table_create \ -- elf64_sw_64_bfd_link_hash_table_create -- --#define bfd_elf64_bfd_reloc_type_lookup \ -- elf64_sw_64_bfd_reloc_type_lookup --#define bfd_elf64_bfd_reloc_name_lookup \ -- elf64_sw_64_bfd_reloc_name_lookup --#define elf_info_to_howto \ -- elf64_sw_64_info_to_howto -- --#define bfd_elf64_mkobject \ -- elf64_sw_64_mkobject --#define elf_backend_object_p \ -- elf64_sw_64_object_p -- --#define elf_backend_section_from_shdr \ -- elf64_sw_64_section_from_shdr --#define elf_backend_section_flags \ -- elf64_sw_64_section_flags --#define elf_backend_fake_sections \ -- elf64_sw_64_fake_sections -- --#define bfd_elf64_bfd_is_local_label_name \ -- elf64_sw_64_is_local_label_name --#define bfd_elf64_find_nearest_line \ -- elf64_sw_64_find_nearest_line --#define bfd_elf64_bfd_relax_section \ -- elf64_sw_64_relax_section -- --#define elf_backend_add_symbol_hook \ -- elf64_sw_64_add_symbol_hook --#define elf_backend_relocs_compatible \ -- _bfd_elf_relocs_compatible --#define elf_backend_sort_relocs_p \ -- elf64_sw_64_sort_relocs_p --#define elf_backend_check_relocs \ -- elf64_sw_64_check_relocs --#define elf_backend_create_dynamic_sections \ -- elf64_sw_64_create_dynamic_sections --#define elf_backend_adjust_dynamic_symbol \ -- elf64_sw_64_adjust_dynamic_symbol --#define elf_backend_merge_symbol_attribute \ -- elf64_sw_64_merge_symbol_attribute --#define elf_backend_copy_indirect_symbol \ -- elf64_sw_64_copy_indirect_symbol --#define elf_backend_always_size_sections \ -- elf64_sw_64_always_size_sections --#define elf_backend_size_dynamic_sections \ -- elf64_sw_64_size_dynamic_sections --#define elf_backend_omit_section_dynsym \ -- _bfd_elf_omit_section_dynsym_all --#define elf_backend_relocate_section \ -- elf64_sw_64_relocate_section --#define elf_backend_finish_dynamic_symbol \ -- elf64_sw_64_finish_dynamic_symbol --#define elf_backend_finish_dynamic_sections \ -- elf64_sw_64_finish_dynamic_sections --#define bfd_elf64_bfd_final_link \ -- elf64_sw_64_final_link --#define elf_backend_reloc_type_class \ -- elf64_sw_64_reloc_type_class -- --#define elf_backend_can_gc_sections 1 --#define elf_backend_gc_mark_hook elf64_sw_64_gc_mark_hook -- --#define elf_backend_ecoff_debug_swap \ -- &elf64_sw_64_ecoff_debug_swap -- --#define elf_backend_size_info \ -- sw_64_elf_size_info -- --#define elf_backend_special_sections \ -- elf64_sw_64_special_sections -- --#define elf_backend_strip_zero_sized_dynamic_sections \ -- _bfd_elf_strip_zero_sized_dynamic_sections -- --/* A few constants that determine how the .plt section is set up. */ --#define elf_backend_want_got_plt 0 --#define elf_backend_plt_readonly 0 --#define elf_backend_want_plt_sym 1 --#define elf_backend_got_header_size 0 --#define elf_backend_dtrel_excludes_plt 1 -- --#include "elf64-target.h" -- --/* FreeBSD support. */ -- --#undef TARGET_LITTLE_SYM --#define TARGET_LITTLE_SYM sw_64_elf64_fbsd_vec --#undef TARGET_LITTLE_NAME --#define TARGET_LITTLE_NAME "elf64-sw_64-freebsd" --#undef ELF_OSABI --#define ELF_OSABI ELFOSABI_FREEBSD -- --/* The kernel recognizes executables as valid only if they carry a -- "FreeBSD" label in the ELF header. So we put this label on all -- executables and (for simplicity) also all other object files. */ -- -- static bool --elf64_sw_64_fbsd_init_file_header (bfd *abfd, struct bfd_link_info *info) --{ -- Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */ -- -- if (!_bfd_elf_init_file_header (abfd, info)) -- return false; -- -- i_ehdrp = elf_elfheader (abfd); -- -- /* Put an ABI label supported by FreeBSD >= 4.1. */ -- i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi; --#ifdef OLD_FREEBSD_ABI_LABEL -- /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ -- memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); --#endif -- return true; --} --#undef elf_backend_init_file_header --#define elf_backend_init_file_header \ -- elf64_sw_64_fbsd_init_file_header -- --#undef elf64_bed --#define elf64_bed elf64_sw_64_fbsd_bed -- --#include "elf64-target.h" ---- b/bfd/hosts/sw_64linux.h -+++ /dev/null -@@ -1,25 +0,0 @@ --/* Copyright (C) 2007-2018 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 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. */ -- --/* Linux dumps "struct task_struct" at the end of the core-file. This -- structure is currently 1080 bytes long, but we allow up to 4096 -- bytes to allow for some future growth. */ --#define TRAD_CORE_EXTRA_SIZE_ALLOWED 4096 --#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(abfd) \ -- ((abfd)->tdata.trad_core_data->u.signal) ---- b/bfd/hosts/sw_64vms.h -+++ /dev/null -@@ -1,68 +0,0 @@ --/* alphavms.h -- BFD definitions for an openVMS host -- Copyright (C) 1996-2018 Free Software Foundation, Inc. -- Written by Klaus Kämpf (kkaempf@progis.de) -- of proGIS Softwareentwicklung, Aachen, Germany -- -- This file is part of BFD, the Binary File Descriptor library. -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. */ -- --#ifdef PACKAGE --#error sysdep.h must be included in lieu of config.h --#endif -- --#include "config.h" --#include "ansidecl.h" -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "filenames.h" --#include "fopen-vms.h" -- --#define NO_FCNTL 1 -- --#ifndef O_ACCMODE --#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) --#endif -- --extern int getpagesize (void); --extern char *stpcpy (char *, const char *); -- --/* No intl. */ --#define gettext(Msgid) (Msgid) --#define dgettext(Domainname, Msgid) (Msgid) --#define dcgettext(Domainname, Msgid, Category) (Msgid) --#define ngettext(Msgid1, Msgid2, n) \ -- (n == 1 ? Msgid1 : Msgid2) --#define dngettext(Domainname, Msgid1, Msgid2, n) \ -- (n == 1 ? Msgid1 : Msgid2) --#define dcngettext(Domainname, Msgid1, Msgid2, n, Category) \ -- (n == 1 ? Msgid1 : Msgid2) --#define textdomain(Domainname) do {} while (0) --#define bindtextdomain(Domainname, Dirname) do {} while (0) --#define _(String) (String) --#define N_(String) (String) ---- b/bfd/vms-sw_64.c -+++ /dev/null -@@ -1,10248 +0,0 @@ --/* vms.c -- BFD back-end for EVAX (openVMS/Sw_64) files. -- Copyright (C) 1996-2020 Free Software Foundation, Inc. -- -- Initial version written by Klaus Kaempf (kkaempf@rmi.de) -- Major rewrite by Adacore. -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. */ -- --/* TODO: -- o overlayed sections -- o PIC -- o Generation of shared image -- o Relocation optimizations -- o EISD for the stack -- o Vectors isect -- o 64 bits sections -- o Entry point -- o LIB$INITIALIZE -- o protected sections (for messages) -- ... --*/ -- --#include "sysdep.h" --#include "bfd.h" --#include "bfdlink.h" --#include "libbfd.h" --#include "bfdver.h" -- --#include "vms.h" --#include "vms/eihd.h" --#include "vms/eiha.h" --#include "vms/eihi.h" --#include "vms/eihs.h" --#include "vms/eisd.h" --#include "vms/dmt.h" --#include "vms/dst.h" --#include "vms/eihvn.h" --#include "vms/eobjrec.h" --#include "vms/egsd.h" --#include "vms/egps.h" --#include "vms/esgps.h" --#include "vms/eeom.h" --#include "vms/emh.h" --#include "vms/eiaf.h" --#include "vms/shl.h" --#include "vms/eicp.h" --#include "vms/etir.h" --#include "vms/egsy.h" --#include "vms/esdf.h" --#include "vms/esdfm.h" --#include "vms/esdfv.h" --#include "vms/esrf.h" --#include "vms/egst.h" --#include "vms/eidc.h" --#include "vms/dsc.h" --#include "vms/prt.h" --#include "vms/internal.h" -- -- --#define MIN(a,b) ((a) < (b) ? (a) : (b)) -- --/* The r_type field in a reloc is one of the following values. */ --#define SW_64_R_IGNORE 0 --#define SW_64_R_REFQUAD 1 --#define SW_64_R_BRADDR 2 --#define SW_64_R_HINT 3 --#define SW_64_R_SREL16 4 --#define SW_64_R_SREL32 5 --#define SW_64_R_SREL64 6 --#define SW_64_R_OP_PUSH 7 --#define SW_64_R_OP_STORE 8 --#define SW_64_R_OP_PSUB 9 --#define SW_64_R_OP_PRSHIFT 10 --#define SW_64_R_LINKAGE 11 --#define SW_64_R_REFLONG 12 --#define SW_64_R_CODEADDR 13 --#define SW_64_R_NOP 14 --#define SW_64_R_BSR 15 --#define SW_64_R_LDA 16 --#define SW_64_R_BOH 17 -- --/* These are used with DST_S_C_LINE_NUM. */ --#define DST_S_C_LINE_NUM_HEADER_SIZE 4 -- --/* These are used with DST_S_C_SOURCE */ -- --#define DST_S_B_PCLINE_UNSBYTE 1 --#define DST_S_W_PCLINE_UNSWORD 1 --#define DST_S_L_PCLINE_UNSLONG 1 -- --#define DST_S_B_MODBEG_NAME 14 --#define DST_S_L_RTNBEG_ADDRESS 5 --#define DST_S_B_RTNBEG_NAME 13 --#define DST_S_L_RTNEND_SIZE 5 -- --/* These are used with DST_S_C_SOURCE. */ --#define DST_S_C_SOURCE_HEADER_SIZE 4 -- --#define DST_S_B_SRC_DF_LENGTH 1 --#define DST_S_W_SRC_DF_FILEID 3 --#define DST_S_B_SRC_DF_FILENAME 20 --#define DST_S_B_SRC_UNSBYTE 1 --#define DST_S_W_SRC_UNSWORD 1 --#define DST_S_L_SRC_UNSLONG 1 -- --/* Debugger symbol definitions. */ -- --#define DBG_S_L_DMT_MODBEG 0 --#define DBG_S_L_DST_SIZE 4 --#define DBG_S_W_DMT_PSECT_COUNT 8 --#define DBG_S_C_DMT_HEADER_SIZE 12 -- --#define DBG_S_L_DMT_PSECT_START 0 --#define DBG_S_L_DMT_PSECT_LENGTH 4 --#define DBG_S_C_DMT_PSECT_SIZE 8 -- --/* VMS module header. */ -- --struct hdr_struct --{ -- char hdr_b_strlvl; -- int hdr_l_arch1; -- int hdr_l_arch2; -- int hdr_l_recsiz; -- char *hdr_t_name; -- char *hdr_t_version; -- char *hdr_t_date; -- char *hdr_c_lnm; -- char *hdr_c_src; -- char *hdr_c_ttl; --}; -- --#define EMH_DATE_LENGTH 17 -- --/* VMS End-Of-Module records (EOM/EEOM). */ -- --struct eom_struct --{ -- unsigned int eom_l_total_lps; -- unsigned short eom_w_comcod; -- bfd_boolean eom_has_transfer; -- unsigned char eom_b_tfrflg; -- unsigned int eom_l_psindx; -- unsigned int eom_l_tfradr; --}; -- --struct vms_symbol_entry --{ -- bfd *owner; -- -- /* Common fields. */ -- unsigned char typ; -- unsigned char data_type; -- unsigned short flags; -- -- /* Section and offset/value of the symbol. */ -- unsigned int value; -- asection *section; -- -- /* Section and offset/value for the entry point (only for subprg). */ -- asection *code_section; -- unsigned int code_value; -- -- /* Symbol vector offset. */ -- unsigned int symbol_vector; -- -- /* Length of the name. */ -- unsigned char namelen; -- -- char name[1]; --}; -- --/* Stack value for push/pop commands. */ -- --struct stack_struct --{ -- bfd_vma value; -- unsigned int reloc; --}; -- --#define STACKSIZE 128 -- --/* A minimal decoding of DST compilation units. We only decode -- what's needed to get to the line number information. */ -- --struct fileinfo --{ -- char *name; -- unsigned int srec; --}; -- --struct srecinfo --{ -- struct srecinfo *next; -- unsigned int line; -- unsigned int sfile; -- unsigned int srec; --}; -- --struct lineinfo --{ -- struct lineinfo *next; -- bfd_vma address; -- unsigned int line; --}; -- --struct funcinfo --{ -- struct funcinfo *next; -- char *name; -- bfd_vma low; -- bfd_vma high; --}; -- --struct module --{ -- /* Chain the previously read compilation unit. */ -- struct module *next; -- -- /* The module name. */ -- char *name; -- -- /* The start offset and size of debug info in the DST section. */ -- unsigned int modbeg; -- unsigned int size; -- -- /* The lowest and highest addresses contained in this compilation -- unit as specified in the compilation unit header. */ -- bfd_vma low; -- bfd_vma high; -- -- /* The listing line table. */ -- struct lineinfo *line_table; -- -- /* The source record table. */ -- struct srecinfo *srec_table; -- -- /* A list of the functions found in this module. */ -- struct funcinfo *func_table; -- -- /* Current allocation of file_table. */ -- unsigned int file_table_count; -- -- /* An array of the files making up this module. */ -- struct fileinfo *file_table; --}; -- --/* BFD private data for sw_64-vms. */ -- --struct vms_private_data_struct --{ -- /* If true, relocs have been read. */ -- bfd_boolean reloc_done; -- -- /* Record input buffer. */ -- struct vms_rec_rd recrd; -- struct vms_rec_wr recwr; -- -- struct hdr_struct hdr_data; /* data from HDR/EMH record */ -- struct eom_struct eom_data; /* data from EOM/EEOM record */ -- -- /* Transfer addresses (entry points). */ -- bfd_vma transfer_address[4]; -- -- /* Array of GSD sections to get the correspond BFD one. */ -- unsigned int section_max; /* Size of the sections array. */ -- unsigned int section_count; /* Number of GSD sections. */ -- asection **sections; -- -- /* Array of raw symbols. */ -- struct vms_symbol_entry **syms; -- -- /* Canonicalized symbols. */ -- asymbol **csymbols; -- -- /* Number of symbols. */ -- unsigned int gsd_sym_count; -- /* Size of the syms array. */ -- unsigned int max_sym_count; -- /* Number of procedure symbols. */ -- unsigned int norm_sym_count; -- -- /* Stack used to evaluate TIR/ETIR commands. */ -- struct stack_struct *stack; -- int stackptr; -- -- /* Content reading. */ -- asection *image_section; /* section for image_ptr */ -- file_ptr image_offset; /* Offset for image_ptr. */ -- -- struct module *modules; /* list of all compilation units */ -- -- /* The DST section. */ -- asection *dst_section; -- -- unsigned int dst_ptr_offsets_count; /* # of offsets in following array */ -- unsigned int *dst_ptr_offsets; /* array of saved image_ptr offsets */ -- -- /* Shared library support */ -- bfd_vma symvva; /* relative virtual address of symbol vector */ -- unsigned int ident; -- unsigned char matchctl; -- -- /* Shared library index. This is used for input bfd while linking. */ -- unsigned int shr_index; -- -- /* Used to place structures in the file. */ -- file_ptr file_pos; -- -- /* Simply linked list of eisd. */ -- struct vms_internal_eisd_map *eisd_head; -- struct vms_internal_eisd_map *eisd_tail; -- -- /* Simply linked list of eisd for shared libraries. */ -- struct vms_internal_eisd_map *gbl_eisd_head; -- struct vms_internal_eisd_map *gbl_eisd_tail; -- -- /* linkage index counter used by conditional store commands */ -- unsigned int vms_linkage_index; --}; -- --#define PRIV2(abfd, name) \ -- (((struct vms_private_data_struct *)(abfd)->tdata.any)->name) --#define PRIV(name) PRIV2(abfd,name) -- -- --/* Used to keep extra VMS 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 VMS relocations -- are variable length. -- -- reloc_stream is the actual stream of relocation entries. */ -- --struct vms_section_data_struct --{ -- /* Maximnum number of entries in sec->relocation. */ -- unsigned reloc_max; -- -- /* Corresponding eisd. Used only while generating executables. */ -- struct vms_internal_eisd_map *eisd; -- -- /* PSC flags to be clear. */ -- flagword no_flags; -- -- /* PSC flags to be set. */ -- flagword flags; --}; -- --#define vms_section_data(sec) \ -- ((struct vms_section_data_struct *)sec->used_by_bfd) -- --/* To be called from the debugger. */ --struct vms_private_data_struct *bfd_vms_get_data (bfd *); -- --static int vms_get_remaining_object_record (bfd *, unsigned int); --static bfd_boolean _bfd_vms_slurp_object_records (bfd * abfd); --static void sw_64_vms_add_fixup_lp (struct bfd_link_info *, bfd *, bfd *); --static void sw_64_vms_add_fixup_ca (struct bfd_link_info *, bfd *, bfd *); --static void sw_64_vms_add_fixup_qr (struct bfd_link_info *, bfd *, bfd *, -- bfd_vma); --static void sw_64_vms_add_fixup_lr (struct bfd_link_info *, unsigned int, -- bfd_vma); --static void sw_64_vms_add_lw_reloc (struct bfd_link_info *); --static void sw_64_vms_add_qw_reloc (struct bfd_link_info *); -- --struct vector_type --{ -- unsigned int max_el; -- unsigned int nbr_el; -- void *els; --}; -- --/* Number of elements in VEC. */ -- --#define VEC_COUNT(VEC) ((VEC).nbr_el) -- --/* Get the address of the Nth element. */ -- --#define VEC_EL(VEC, TYPE, N) (((TYPE *)((VEC).els))[N]) -- --#define VEC_INIT(VEC) \ -- do { \ -- (VEC).max_el = 0; \ -- (VEC).nbr_el = 0; \ -- (VEC).els = NULL; \ -- } while (0) -- --/* Be sure there is room for a new element. */ -- --static void vector_grow1 (struct vector_type *vec, size_t elsz); -- --/* Allocate room for a new element and return its address. */ -- --#define VEC_APPEND(VEC, TYPE) \ -- (vector_grow1 (&VEC, sizeof (TYPE)), &VEC_EL(VEC, TYPE, (VEC).nbr_el++)) -- --/* Append an element. */ -- --#define VEC_APPEND_EL(VEC, TYPE, EL) \ -- (*(VEC_APPEND (VEC, TYPE)) = EL) -- --struct sw_64_vms_vma_ref --{ -- bfd_vma vma; /* Vma in the output. */ -- bfd_vma ref; /* Reference in the input. */ --}; -- --struct sw_64_vms_shlib_el --{ -- bfd *abfd; -- bfd_boolean has_fixups; -- -- struct vector_type lp; /* Vector of bfd_vma. */ -- struct vector_type ca; /* Vector of bfd_vma. */ -- struct vector_type qr; /* Vector of struct sw_64_vms_vma_ref. */ --}; -- --/* Sw_64 VMS linker hash table. */ -- --struct sw_64_vms_link_hash_table --{ -- struct bfd_link_hash_table root; -- -- /* Vector of shared libraries. */ -- struct vector_type shrlibs; -- -- /* Fixup section. */ -- asection *fixup; -- -- /* Base address. Used by fixups. */ -- bfd_vma base_addr; --}; -- --#define sw_64_vms_link_hash(INFO) \ -- ((struct sw_64_vms_link_hash_table *)(INFO->hash)) -- --/* Sw_64 VMS linker hash table entry. */ -- --struct sw_64_vms_link_hash_entry --{ -- struct bfd_link_hash_entry root; -- -- /* Pointer to the original vms symbol. */ -- struct vms_symbol_entry *sym; --}; -- --/* Image reading. */ -- --/* Read & process EIHD record. -- Return TRUE on success, FALSE on error. */ -- --static bfd_boolean --_bfd_vms_slurp_eihd (bfd *abfd, unsigned int *eisd_offset, -- unsigned int *eihs_offset) --{ -- unsigned int imgtype, size; -- bfd_vma symvva; -- struct vms_eihd *eihd = (struct vms_eihd *)PRIV (recrd.rec); -- -- vms_debug2 ((8, "_bfd_vms_slurp_eihd\n")); -- -- /* PR 21813: Check for an undersized record. */ -- if (PRIV (recrd.buf_size) < sizeof (* eihd)) -- { -- _bfd_error_handler (_("corrupt EIHD record - size is too small")); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- -- size = bfd_getl32 (eihd->size); -- imgtype = bfd_getl32 (eihd->imgtype); -- -- if (imgtype == EIHD__K_EXE || imgtype == EIHD__K_LIM) -- abfd->flags |= EXEC_P; -- -- symvva = bfd_getl64 (eihd->symvva); -- if (symvva != 0) -- { -- PRIV (symvva) = symvva; -- abfd->flags |= DYNAMIC; -- } -- -- PRIV (ident) = bfd_getl32 (eihd->ident); -- PRIV (matchctl) = eihd->matchctl; -- -- *eisd_offset = bfd_getl32 (eihd->isdoff); -- *eihs_offset = bfd_getl32 (eihd->symdbgoff); -- -- vms_debug2 ((4, "EIHD size %d imgtype %d symvva 0x%lx eisd %d eihs %d\n", -- size, imgtype, (unsigned long)symvva, -- *eisd_offset, *eihs_offset)); -- (void) size; -- -- return TRUE; --} -- --/* Read & process EISD record. -- Return TRUE on success, FALSE on error. */ -- --static bfd_boolean --_bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) --{ -- int section_count = 0; -- -- vms_debug2 ((8, "_bfd_vms_slurp_eisd\n")); -- -- while (1) -- { -- struct vms_eisd *eisd; -- unsigned int rec_size; -- unsigned int size; -- bfd_uint64_t vaddr; -- unsigned int flags; -- unsigned int vbn; -- char *name = NULL; -- asection *section; -- flagword bfd_flags; -- -- /* PR 17512: file: 3d9e9fe9. */ -- if (offset > PRIV (recrd.rec_size) -- || (PRIV (recrd.rec_size) - offset -- < offsetof (struct vms_eisd, eisdsize) + 4)) -- return FALSE; -- eisd = (struct vms_eisd *) (PRIV (recrd.rec) + offset); -- rec_size = bfd_getl32 (eisd->eisdsize); -- if (rec_size == 0) -- break; -- -- /* Skip to next block if pad. */ -- if (rec_size == 0xffffffff) -- { -- offset = (offset + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1); -- continue; -- } -- -- /* Make sure that there is enough data present in the record. */ -- if (rec_size < offsetof (struct vms_eisd, type) + 1) -- return FALSE; -- /* Make sure that the record is not too big either. */ -- if (rec_size > PRIV (recrd.rec_size) - offset) -- return FALSE; -- -- offset += rec_size; -- -- size = bfd_getl32 (eisd->secsize); -- vaddr = bfd_getl64 (eisd->virt_addr); -- flags = bfd_getl32 (eisd->flags); -- vbn = bfd_getl32 (eisd->vbn); -- -- vms_debug2 ((4, "EISD at 0x%x size 0x%x addr 0x%lx flags 0x%x blk %d\n", -- offset, size, (unsigned long)vaddr, flags, vbn)); -- -- /* VMS combines psects from .obj files into isects in the .exe. This -- process doesn't preserve enough information to reliably determine -- what's in each section without examining the data. This is -- especially true of DWARF debug sections. */ -- bfd_flags = SEC_ALLOC; -- if (vbn != 0) -- bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD; -- -- if (flags & EISD__M_EXE) -- bfd_flags |= SEC_CODE; -- -- if (flags & EISD__M_NONSHRADR) -- bfd_flags |= SEC_DATA; -- -- if (!(flags & EISD__M_WRT)) -- bfd_flags |= SEC_READONLY; -- -- if (flags & EISD__M_DZRO) -- bfd_flags |= SEC_DATA; -- -- if (flags & EISD__M_FIXUPVEC) -- bfd_flags |= SEC_DATA; -- -- if (flags & EISD__M_CRF) -- bfd_flags |= SEC_DATA; -- -- if (flags & EISD__M_GBL) -- { -- if (rec_size <= offsetof (struct vms_eisd, gblnam)) -- return FALSE; -- else if (rec_size < sizeof (struct vms_eisd)) -- name = _bfd_vms_save_counted_string (abfd, eisd->gblnam, -- rec_size - offsetof (struct vms_eisd, gblnam)); -- else -- name = _bfd_vms_save_counted_string (abfd, eisd->gblnam, -- EISD__K_GBLNAMLEN); -- if (name == NULL || name[0] == 0) -- return FALSE; -- bfd_flags |= SEC_COFF_SHARED_LIBRARY; -- bfd_flags &= ~(SEC_ALLOC | SEC_LOAD); -- } -- else if (flags & EISD__M_FIXUPVEC) -- name = "$FIXUPVEC$"; -- else if (eisd->type == EISD__K_USRSTACK) -- name = "$STACK$"; -- else -- { -- const char *pfx; -- -- name = (char *) bfd_alloc (abfd, 32); -- if (name == NULL) -- return FALSE; -- if (flags & EISD__M_DZRO) -- pfx = "BSS"; -- else if (flags & EISD__M_EXE) -- pfx = "CODE"; -- else if (!(flags & EISD__M_WRT)) -- pfx = "RO"; -- else -- pfx = "LOCAL"; -- BFD_ASSERT (section_count < 999); -- sprintf (name, "$%s_%03d$", pfx, section_count++); -- } -- -- section = bfd_make_section (abfd, name); -- -- if (!section) -- return FALSE; -- -- section->filepos = vbn ? VMS_BLOCK_SIZE * (vbn - 1) : 0; -- section->size = size; -- section->vma = vaddr; -- -- if (!bfd_set_section_flags (section, bfd_flags)) -- return FALSE; -- } -- -- return TRUE; --} -- --/* Read & process EIHS record. -- Return TRUE on success, FALSE on error. */ -- --static bfd_boolean --_bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset) --{ -- unsigned char *p = PRIV (recrd.rec) + offset; -- unsigned int gstvbn; -- unsigned int gstsize ATTRIBUTE_UNUSED; -- unsigned int dstvbn; -- unsigned int dstsize; -- unsigned int dmtvbn; -- unsigned int dmtbytes; -- asection *section; -- -- /* PR 21611: Check that offset is valid. */ -- if (offset > PRIV (recrd.rec_size) - (EIHS__L_DMTBYTES + 4)) -- { -- _bfd_error_handler (_("unable to read EIHS record at offset %#x"), -- offset); -- bfd_set_error (bfd_error_file_truncated); -- return FALSE; -- } -- -- gstvbn = bfd_getl32 (p + EIHS__L_GSTVBN); -- gstsize = bfd_getl32 (p + EIHS__L_GSTSIZE); -- dstvbn = bfd_getl32 (p + EIHS__L_DSTVBN); -- dstsize = bfd_getl32 (p + EIHS__L_DSTSIZE); -- dmtvbn = bfd_getl32 (p + EIHS__L_DMTVBN); -- dmtbytes = bfd_getl32 (p + EIHS__L_DMTBYTES); -- --#if VMS_DEBUG -- vms_debug (8, "_bfd_vms_slurp_ihs\n"); -- vms_debug (4, "EIHS record gstvbn %d gstsize %d dstvbn %d dstsize %d dmtvbn %d dmtbytes %d\n", -- gstvbn, gstsize, dstvbn, dstsize, dmtvbn, dmtbytes); --#endif -- -- if (dstvbn) -- { -- flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING; -- -- section = bfd_make_section (abfd, "$DST$"); -- if (!section) -- return FALSE; -- -- section->size = dstsize; -- section->filepos = VMS_BLOCK_SIZE * (dstvbn - 1); -- -- if (!bfd_set_section_flags (section, bfd_flags)) -- return FALSE; -- -- PRIV (dst_section) = section; -- abfd->flags |= (HAS_DEBUG | HAS_LINENO); -- } -- -- if (dmtvbn) -- { -- flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING; -- -- section = bfd_make_section (abfd, "$DMT$"); -- if (!section) -- return FALSE; -- -- section->size = dmtbytes; -- section->filepos = VMS_BLOCK_SIZE * (dmtvbn - 1); -- -- if (!bfd_set_section_flags (section, bfd_flags)) -- return FALSE; -- } -- -- if (gstvbn) -- { -- if (bfd_seek (abfd, VMS_BLOCK_SIZE * (gstvbn - 1), SEEK_SET)) -- { -- bfd_set_error (bfd_error_file_truncated); -- return FALSE; -- } -- -- if (!_bfd_vms_slurp_object_records (abfd)) -- return FALSE; -- -- abfd->flags |= HAS_SYMS; -- } -- -- return TRUE; --} -- --/* Object file reading. */ -- --/* Object file input functions. */ -- --/* Get next record from object file to vms_buf. -- Set PRIV(buf_size) and return it -- -- This is a little tricky since it should be portable. -- -- The openVMS object file has 'variable length' which means that -- read() returns data in chunks of (hopefully) correct and expected -- size. The linker (and other tools on VMS) depend on that. Unix -- doesn't know about 'formatted' files, so reading and writing such -- an object file in a Unix environment is not trivial. -- -- With the tool 'file' (available on all VMS FTP sites), one -- can view and change the attributes of a file. Changing from -- 'variable length' to 'fixed length, 512 bytes' reveals the -- record size at the first 2 bytes of every record. The same -- may happen during the transfer of object files from VMS to Unix, -- at least with UCX, the DEC implementation of TCP/IP. -- -- The VMS format repeats the size at bytes 2 & 3 of every record. -- -- On the first call (file_format == FF_UNKNOWN) we check if -- the first and the third byte pair (!) of the record match. -- If they do it's an object file in an Unix environment or with -- wrong attributes (FF_FOREIGN), else we should be in a VMS -- environment where read() returns the record size (FF_NATIVE). -- -- Reading is always done in 2 steps: -- 1. first just the record header is read and the size extracted, -- 2. then the read buffer is adjusted and the remaining bytes are -- read in. -- -- All file I/O is done on even file positions. */ -- --#define VMS_OBJECT_ADJUSTMENT 2 -- --static void --maybe_adjust_record_pointer_for_object (bfd *abfd) --{ -- /* Set the file format once for all on the first invocation. */ -- if (PRIV (recrd.file_format) == FF_UNKNOWN) -- { -- if (PRIV (recrd.rec)[0] == PRIV (recrd.rec)[4] -- && PRIV (recrd.rec)[1] == PRIV (recrd.rec)[5]) -- PRIV (recrd.file_format) = FF_FOREIGN; -- else -- PRIV (recrd.file_format) = FF_NATIVE; -- } -- -- /* The adjustment is needed only in an Unix environment. */ -- if (PRIV (recrd.file_format) == FF_FOREIGN) -- PRIV (recrd.rec) += VMS_OBJECT_ADJUSTMENT; --} -- --/* Implement step #1 of the object record reading procedure. -- Return the record type or -1 on failure. */ -- --static int --_bfd_vms_get_object_record (bfd *abfd) --{ -- unsigned int test_len = 6; -- int type; -- -- vms_debug2 ((8, "_bfd_vms_get_obj_record\n")); -- -- /* Skip alignment byte if the current position is odd. */ -- if (PRIV (recrd.file_format) == FF_FOREIGN && (bfd_tell (abfd) & 1)) -- { -- if (bfd_bread (PRIV (recrd.buf), 1, abfd) != 1) -- { -- bfd_set_error (bfd_error_file_truncated); -- return -1; -- } -- } -- -- /* Read the record header */ -- if (bfd_bread (PRIV (recrd.buf), test_len, abfd) != test_len) -- { -- bfd_set_error (bfd_error_file_truncated); -- return -1; -- } -- -- /* Reset the record pointer. */ -- PRIV (recrd.rec) = PRIV (recrd.buf); -- maybe_adjust_record_pointer_for_object (abfd); -- -- if (vms_get_remaining_object_record (abfd, test_len) <= 0) -- return -1; -- -- type = bfd_getl16 (PRIV (recrd.rec)); -- -- vms_debug2 ((8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n", -- PRIV (recrd.rec), PRIV (recrd.rec_size), type)); -- -- return type; --} -- --/* Implement step #2 of the object record reading procedure. -- Return the size of the record or 0 on failure. */ -- --static int --vms_get_remaining_object_record (bfd *abfd, unsigned int read_so_far) --{ -- unsigned int to_read; -- -- vms_debug2 ((8, "vms_get_remaining_obj_record\n")); -- -- /* Extract record size. */ -- PRIV (recrd.rec_size) = bfd_getl16 (PRIV (recrd.rec) + 2); -- -- if (PRIV (recrd.rec_size) == 0) -- { -- bfd_set_error (bfd_error_file_truncated); -- return 0; -- } -- -- /* That's what the linker manual says. */ -- if (PRIV (recrd.rec_size) > EOBJ__C_MAXRECSIZ) -- { -- bfd_set_error (bfd_error_file_truncated); -- return 0; -- } -- -- /* Take into account object adjustment. */ -- to_read = PRIV (recrd.rec_size); -- if (PRIV (recrd.file_format) == FF_FOREIGN) -- to_read += VMS_OBJECT_ADJUSTMENT; -- -- /* Adjust the buffer. */ -- if (to_read > PRIV (recrd.buf_size)) -- { -- PRIV (recrd.buf) -- = (unsigned char *) bfd_realloc (PRIV (recrd.buf), to_read); -- if (PRIV (recrd.buf) == NULL) -- return 0; -- PRIV (recrd.buf_size) = to_read; -- } -- /* PR 17512: file: 025-1974-0.004. */ -- else if (to_read <= read_so_far) -- return 0; -- -- /* Read the remaining record. */ -- to_read -= read_so_far; -- -- vms_debug2 ((8, "vms_get_remaining_obj_record: to_read %d\n", to_read)); -- -- if (bfd_bread (PRIV (recrd.buf) + read_so_far, to_read, abfd) != to_read) -- { -- bfd_set_error (bfd_error_file_truncated); -- return 0; -- } -- -- /* Reset the record pointer. */ -- PRIV (recrd.rec) = PRIV (recrd.buf); -- maybe_adjust_record_pointer_for_object (abfd); -- -- vms_debug2 ((8, "vms_get_remaining_obj_record: size %d\n", -- PRIV (recrd.rec_size))); -- -- return PRIV (recrd.rec_size); --} -- --/* Read and process emh record. -- Return TRUE on success, FALSE on error. */ -- --static bfd_boolean --_bfd_vms_slurp_ehdr (bfd *abfd) --{ -- unsigned char *ptr; -- unsigned char *vms_rec; -- unsigned char *end; -- int subtype; -- -- vms_rec = PRIV (recrd.rec); -- /* PR 17512: file: 62736583. */ -- end = PRIV (recrd.buf) + PRIV (recrd.buf_size); -- -- vms_debug2 ((2, "HDR/EMH\n")); -- -- subtype = bfd_getl16 (vms_rec + 4); -- -- vms_debug2 ((3, "subtype %d\n", subtype)); -- -- switch (subtype) -- { -- case EMH__C_MHD: -- /* Module header. */ -- if (vms_rec + 21 >= end) -- goto fail; -- PRIV (hdr_data).hdr_b_strlvl = vms_rec[6]; -- PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8); -- PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12); -- PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16); -- if ((vms_rec + 20 + vms_rec[20] + 1) >= end) -- goto fail; -- PRIV (hdr_data).hdr_t_name -- = _bfd_vms_save_counted_string (abfd, vms_rec + 20, vms_rec[20]); -- ptr = vms_rec + 20 + vms_rec[20] + 1; -- if ((ptr + *ptr + 1) >= end) -- goto fail; -- PRIV (hdr_data).hdr_t_version -- = _bfd_vms_save_counted_string (abfd, ptr, *ptr); -- ptr += *ptr + 1; -- if (ptr + 17 >= end) -- goto fail; -- PRIV (hdr_data).hdr_t_date -- = _bfd_vms_save_sized_string (abfd, ptr, 17); -- break; -- -- case EMH__C_LNM: -- if (vms_rec + PRIV (recrd.rec_size - 6) > end) -- goto fail; -- PRIV (hdr_data).hdr_c_lnm -- = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6)); -- break; -- -- case EMH__C_SRC: -- if (vms_rec + PRIV (recrd.rec_size - 6) > end) -- goto fail; -- PRIV (hdr_data).hdr_c_src -- = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6)); -- break; -- -- case EMH__C_TTL: -- if (vms_rec + PRIV (recrd.rec_size - 6) > end) -- goto fail; -- PRIV (hdr_data).hdr_c_ttl -- = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6)); -- break; -- -- case EMH__C_CPR: -- case EMH__C_MTC: -- case EMH__C_GTX: -- break; -- -- default: -- fail: -- bfd_set_error (bfd_error_wrong_format); -- return FALSE; -- } -- -- return TRUE; --} -- --/* Typical sections for evax object files. */ -- --#define EVAX_ABS_NAME "$ABS$" --#define EVAX_CODE_NAME "$CODE$" --#define EVAX_LINK_NAME "$LINK$" --#define EVAX_DATA_NAME "$DATA$" --#define EVAX_BSS_NAME "$BSS$" --#define EVAX_READONLYADDR_NAME "$READONLY_ADDR$" --#define EVAX_READONLY_NAME "$READONLY$" --#define EVAX_LITERAL_NAME "$LITERAL$" --#define EVAX_LITERALS_NAME "$LITERALS" --#define EVAX_COMMON_NAME "$COMMON$" --#define EVAX_LOCAL_NAME "$LOCAL$" -- --struct sec_flags_struct --{ -- const char *name; /* Name of section. */ -- int vflags_always; -- flagword flags_always; /* Flags we set always. */ -- int vflags_hassize; -- flagword flags_hassize; /* Flags we set if the section has a size > 0. */ --}; -- --/* These flags are deccrtl/vaxcrtl (openVMS 6.2 Sw_64) compatible. */ -- --static const struct sec_flags_struct evax_section_flags[] = -- { -- { EVAX_ABS_NAME, -- EGPS__V_SHR, -- 0, -- EGPS__V_SHR, -- 0 }, -- { EVAX_CODE_NAME, -- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE, -- SEC_CODE | SEC_READONLY, -- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE, -- SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -- { EVAX_LITERAL_NAME, -- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD, -- SEC_DATA | SEC_READONLY, -- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD, -- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -- { EVAX_LINK_NAME, -- EGPS__V_REL | EGPS__V_RD, -- SEC_DATA | SEC_READONLY, -- EGPS__V_REL | EGPS__V_RD, -- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -- { EVAX_DATA_NAME, -- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD, -- SEC_DATA, -- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -- SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -- { EVAX_BSS_NAME, -- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD, -- SEC_NO_FLAGS, -- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD, -- SEC_ALLOC }, -- { EVAX_READONLYADDR_NAME, -- EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD, -- SEC_DATA | SEC_READONLY, -- EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD, -- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -- { EVAX_READONLY_NAME, -- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD, -- SEC_DATA | SEC_READONLY, -- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD, -- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -- { EVAX_LOCAL_NAME, -- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -- SEC_DATA, -- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -- SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -- { EVAX_LITERALS_NAME, -- EGPS__V_PIC | EGPS__V_OVR, -- SEC_DATA | SEC_READONLY, -- EGPS__V_PIC | EGPS__V_OVR, -- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -- { NULL, -- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -- SEC_DATA, -- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -- SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD } -- }; -- --/* Retrieve BFD section flags by name and size. */ -- --static flagword --vms_secflag_by_name (const struct sec_flags_struct *section_flags, -- const char *name, -- int hassize) --{ -- int i = 0; -- -- while (section_flags[i].name != NULL) -- { -- if (strcmp (name, section_flags[i].name) == 0) -- { -- if (hassize) -- return section_flags[i].flags_hassize; -- else -- return section_flags[i].flags_always; -- } -- i++; -- } -- if (hassize) -- return section_flags[i].flags_hassize; -- return section_flags[i].flags_always; --} -- --/* Retrieve VMS section flags by name and size. */ -- --static flagword --vms_esecflag_by_name (const struct sec_flags_struct *section_flags, -- const char *name, -- int hassize) --{ -- int i = 0; -- -- while (section_flags[i].name != NULL) -- { -- if (strcmp (name, section_flags[i].name) == 0) -- { -- if (hassize) -- return section_flags[i].vflags_hassize; -- else -- return section_flags[i].vflags_always; -- } -- i++; -- } -- if (hassize) -- return section_flags[i].vflags_hassize; -- return section_flags[i].vflags_always; --} -- --/* Add SYM to the symbol table of ABFD. -- Return FALSE in case of error. */ -- --static bfd_boolean --add_symbol_entry (bfd *abfd, struct vms_symbol_entry *sym) --{ -- if (PRIV (gsd_sym_count) >= PRIV (max_sym_count)) -- { -- if (PRIV (max_sym_count) == 0) -- { -- PRIV (max_sym_count) = 128; -- PRIV (syms) = bfd_malloc -- (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *)); -- } -- else -- { -- PRIV (max_sym_count) *= 2; -- PRIV (syms) = bfd_realloc -- (PRIV (syms), -- (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *))); -- } -- if (PRIV (syms) == NULL) -- return FALSE; -- } -- -- PRIV (syms)[PRIV (gsd_sym_count)++] = sym; -- return TRUE; --} -- --/* Create a symbol whose name is ASCIC and add it to ABFD. -- Return NULL in case of error. */ -- --static struct vms_symbol_entry * --add_symbol (bfd *abfd, const unsigned char *ascic, unsigned int max) --{ -- struct vms_symbol_entry *entry; -- unsigned int len; -- -- len = *ascic++; -- max -= 1; -- if (len > max) -- { -- _bfd_error_handler (_("record is too small for symbol name length")); -- bfd_set_error (bfd_error_bad_value); -- return NULL; -- } -- -- entry = (struct vms_symbol_entry *)bfd_zalloc (abfd, sizeof (*entry) + len); -- if (entry == NULL) -- return NULL; -- entry->namelen = len; -- memcpy (entry->name, ascic, len); -- entry->name[len] = 0; -- entry->owner = abfd; -- -- if (!add_symbol_entry (abfd, entry)) -- return NULL; -- return entry; --} -- --/* Read and process EGSD. Return FALSE on failure. */ -- --static bfd_boolean --_bfd_vms_slurp_egsd (bfd *abfd) --{ -- int gsd_type; -- unsigned int gsd_size; -- unsigned char *vms_rec; -- bfd_vma base_addr; -- long psindx; -- -- vms_debug2 ((2, "EGSD\n")); -- -- if (PRIV (recrd.rec_size) < 8) -- { -- _bfd_error_handler (_("corrupt EGSD record: its size (%#x) is too small"), -- PRIV (recrd.rec_size)); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- -- PRIV (recrd.rec) += 8; /* Skip type, size, align pad. */ -- PRIV (recrd.rec_size) -= 8; -- -- /* Calculate base address for each section. */ -- base_addr = 0; -- -- while (PRIV (recrd.rec_size) > 4) -- { -- vms_rec = PRIV (recrd.rec); -- -- gsd_type = bfd_getl16 (vms_rec); -- gsd_size = bfd_getl16 (vms_rec + 2); -- -- vms_debug2 ((3, "egsd_type %d\n", gsd_type)); -- -- /* PR 21615: Check for size overflow. */ -- if (PRIV (recrd.rec_size) < gsd_size) -- { -- _bfd_error_handler (_("corrupt EGSD record type %d: size (%#x) " -- "is larger than remaining space (%#x)"), -- gsd_type, gsd_size, PRIV (recrd.rec_size)); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- -- if (gsd_size < 4) -- { -- too_small: -- _bfd_error_handler (_("corrupt EGSD record type %d: size (%#x) " -- "is too small"), -- gsd_type, gsd_size); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- -- switch (gsd_type) -- { -- case EGSD__C_PSC: -- /* Program section definition. */ -- { -- struct vms_egps *egps = (struct vms_egps *) vms_rec; -- flagword new_flags, vms_flags; -- asection *section; -- -- if (offsetof (struct vms_egps, flags) + 2 > gsd_size) -- goto too_small; -- vms_flags = bfd_getl16 (egps->flags); -- -- if ((vms_flags & EGPS__V_REL) == 0) -- { -- /* Use the global absolute section for all -- absolute sections. */ -- section = bfd_abs_section_ptr; -- } -- else -- { -- char *name; -- bfd_vma align_addr; -- size_t left; -- -- if (offsetof (struct vms_egps, namlng) >= gsd_size) -- goto too_small; -- left = gsd_size - offsetof (struct vms_egps, namlng); -- name = _bfd_vms_save_counted_string (abfd, &egps->namlng, left); -- if (name == NULL || name[0] == 0) -- return FALSE; -- -- section = bfd_make_section (abfd, name); -- if (!section) -- return FALSE; -- -- section->filepos = 0; -- section->size = bfd_getl32 (egps->alloc); -- section->alignment_power = egps->align & 31; -- -- vms_section_data (section)->flags = vms_flags; -- vms_section_data (section)->no_flags = 0; -- -- new_flags = vms_secflag_by_name (evax_section_flags, -- section->name, -- section->size > 0); -- if (section->size > 0) -- new_flags |= SEC_LOAD; -- if (!(vms_flags & EGPS__V_NOMOD) && section->size > 0) -- { -- /* Set RELOC and HAS_CONTENTS if the section is not -- demand-zero and not empty. */ -- new_flags |= SEC_HAS_CONTENTS; -- if (vms_flags & EGPS__V_REL) -- new_flags |= SEC_RELOC; -- } -- if (vms_flags & EGPS__V_EXE) -- { -- /* Set CODE if section is executable. */ -- new_flags |= SEC_CODE; -- new_flags &= ~SEC_DATA; -- } -- if (!bfd_set_section_flags (section, new_flags)) -- return FALSE; -- -- /* Give a non-overlapping vma to non absolute sections. */ -- align_addr = (bfd_vma) 1 << section->alignment_power; -- base_addr = (base_addr + align_addr - 1) & -align_addr; -- section->vma = base_addr; -- base_addr += section->size; -- } -- -- /* Append it to the section array. */ -- if (PRIV (section_count) >= PRIV (section_max)) -- { -- if (PRIV (section_max) == 0) -- PRIV (section_max) = 16; -- else -- PRIV (section_max) *= 2; -- PRIV (sections) = bfd_realloc_or_free -- (PRIV (sections), PRIV (section_max) * sizeof (asection *)); -- if (PRIV (sections) == NULL) -- return FALSE; -- } -- -- PRIV (sections)[PRIV (section_count)] = section; -- PRIV (section_count)++; -- } -- break; -- -- case EGSD__C_SYM: -- { -- unsigned int nameoff; -- struct vms_symbol_entry *entry; -- struct vms_egsy *egsy = (struct vms_egsy *) vms_rec; -- flagword old_flags; -- -- if (offsetof (struct vms_egsy, flags) + 2 > gsd_size) -- goto too_small; -- old_flags = bfd_getl16 (egsy->flags); -- if (old_flags & EGSY__V_DEF) -- nameoff = ESDF__B_NAMLNG; -- else -- nameoff = ESRF__B_NAMLNG; -- -- if (nameoff >= gsd_size) -- goto too_small; -- entry = add_symbol (abfd, vms_rec + nameoff, gsd_size - nameoff); -- if (entry == NULL) -- return FALSE; -- -- /* Allow only duplicate reference. */ -- if ((entry->flags & EGSY__V_DEF) && (old_flags & EGSY__V_DEF)) -- abort (); -- -- if (entry->typ == 0) -- { -- entry->typ = gsd_type; -- entry->data_type = egsy->datyp; -- entry->flags = old_flags; -- } -- -- if (old_flags & EGSY__V_DEF) -- { -- struct vms_esdf *esdf = (struct vms_esdf *) vms_rec; -- -- entry->value = bfd_getl64 (esdf->value); -- if (PRIV (sections) == NULL) -- return FALSE; -- -- psindx = bfd_getl32 (esdf->psindx); -- /* PR 21813: Check for an out of range index. */ -- if (psindx < 0 || psindx >= (int) PRIV (section_count)) -- { -- bad_psindx: -- _bfd_error_handler (_("corrupt EGSD record: its psindx " -- "field is too big (%#lx)"), -- psindx); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- entry->section = PRIV (sections)[psindx]; -- -- if (old_flags & EGSY__V_NORM) -- { -- PRIV (norm_sym_count)++; -- -- entry->code_value = bfd_getl64 (esdf->code_address); -- psindx = bfd_getl32 (esdf->ca_psindx); -- /* PR 21813: Check for an out of range index. */ -- if (psindx < 0 || psindx >= (int) PRIV (section_count)) -- goto bad_psindx; -- entry->code_section = PRIV (sections)[psindx]; -- } -- } -- } -- break; -- -- case EGSD__C_SYMG: -- { -- struct vms_symbol_entry *entry; -- struct vms_egst *egst = (struct vms_egst *)vms_rec; -- flagword old_flags; -- unsigned int nameoff = offsetof (struct vms_egst, namlng); -- -- old_flags = bfd_getl16 (egst->header.flags); -- -- if (nameoff >= gsd_size) -- goto too_small; -- entry = add_symbol (abfd, &egst->namlng, gsd_size - nameoff); -- if (entry == NULL) -- return FALSE; -- -- entry->typ = gsd_type; -- entry->data_type = egst->header.datyp; -- entry->flags = old_flags; -- -- entry->symbol_vector = bfd_getl32 (egst->value); -- -- if (old_flags & EGSY__V_REL) -- { -- if (PRIV (sections) == NULL) -- return FALSE; -- psindx = bfd_getl32 (egst->psindx); -- /* PR 21813: Check for an out of range index. */ -- if (psindx < 0 || psindx >= (int) PRIV (section_count)) -- goto bad_psindx; -- entry->section = PRIV (sections)[psindx]; -- } -- else -- entry->section = bfd_abs_section_ptr; -- -- entry->value = bfd_getl64 (egst->lp_2); -- -- if (old_flags & EGSY__V_NORM) -- { -- PRIV (norm_sym_count)++; -- -- entry->code_value = bfd_getl64 (egst->lp_1); -- entry->code_section = bfd_abs_section_ptr; -- } -- } -- break; -- -- case EGSD__C_SPSC: -- case EGSD__C_IDC: -- /* Currently ignored. */ -- break; -- case EGSD__C_SYMM: -- case EGSD__C_SYMV: -- default: -- _bfd_error_handler (_("unknown EGSD subtype %d"), gsd_type); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- -- PRIV (recrd.rec_size) -= gsd_size; -- PRIV (recrd.rec) += gsd_size; -- } -- -- /* FIXME: Should we complain if PRIV (recrd.rec_size) is not zero ? */ -- -- if (PRIV (gsd_sym_count) > 0) -- abfd->flags |= HAS_SYMS; -- -- return TRUE; --} -- --/* Stack routines for vms ETIR commands. */ -- --/* Push value and section index. */ -- --static bfd_boolean --_bfd_vms_push (bfd *abfd, bfd_vma val, unsigned int reloc) --{ -- vms_debug2 ((4, "\n", -- (unsigned long)val, reloc, PRIV (stackptr))); -- -- PRIV (stack[PRIV (stackptr)]).value = val; -- PRIV (stack[PRIV (stackptr)]).reloc = reloc; -- PRIV (stackptr)++; -- if (PRIV (stackptr) >= STACKSIZE) -- { -- bfd_set_error (bfd_error_bad_value); -- _bfd_error_handler (_("stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr)); -- return FALSE; -- } -- return TRUE; --} -- --/* Pop value and section index. */ -- --static bfd_boolean --_bfd_vms_pop (bfd *abfd, bfd_vma *val, unsigned int *rel) --{ -- if (PRIV (stackptr) == 0) -- { -- bfd_set_error (bfd_error_bad_value); -- _bfd_error_handler (_("stack underflow in _bfd_vms_pop")); -- return FALSE; -- } -- PRIV (stackptr)--; -- *val = PRIV (stack[PRIV (stackptr)]).value; -- *rel = PRIV (stack[PRIV (stackptr)]).reloc; -- -- vms_debug2 ((4, "\n", (unsigned long)*val, *rel)); -- return TRUE; --} -- --/* Routines to fill sections contents during tir/etir read. */ -- --/* Initialize image buffer pointer to be filled. */ -- --static void --image_set_ptr (bfd *abfd, bfd_vma vma, int sect, struct bfd_link_info *info) --{ -- asection *sec; -- -- vms_debug2 ((4, "image_set_ptr (0x%08x, sect=%d)\n", (unsigned)vma, sect)); -- -- if (PRIV (sections) == NULL) -- return; -- if (sect < 0 || sect >= (int) PRIV (section_count)) -- return; -- -- sec = PRIV (sections)[sect]; -- -- if (info) -- { -- /* Reading contents to an output bfd. */ -- -- if (sec->output_section == NULL) -- { -- /* Section discarded. */ -- vms_debug2 ((5, " section %s discarded\n", sec->name)); -- -- /* This is not used. */ -- PRIV (image_section) = NULL; -- PRIV (image_offset) = 0; -- return; -- } -- PRIV (image_offset) = sec->output_offset + vma; -- PRIV (image_section) = sec->output_section; -- } -- else -- { -- PRIV (image_offset) = vma; -- PRIV (image_section) = sec; -- } --} -- --/* Increment image buffer pointer by offset. */ -- --static void --image_inc_ptr (bfd *abfd, bfd_vma offset) --{ -- vms_debug2 ((4, "image_inc_ptr (%u)\n", (unsigned)offset)); -- -- PRIV (image_offset) += offset; --} -- --/* Save current DST location counter under specified index. */ -- --static void --dst_define_location (bfd *abfd, unsigned int loc) --{ -- vms_debug2 ((4, "dst_define_location (%d)\n", (int)loc)); -- -- /* Grow the ptr offset table if necessary. */ -- if (loc + 1 > PRIV (dst_ptr_offsets_count)) -- { -- PRIV (dst_ptr_offsets) = bfd_realloc (PRIV (dst_ptr_offsets), -- (loc + 1) * sizeof (unsigned int)); -- PRIV (dst_ptr_offsets_count) = loc + 1; -- } -- -- PRIV (dst_ptr_offsets)[loc] = PRIV (image_offset); --} -- --/* Restore saved DST location counter from specified index. */ -- --static void --dst_restore_location (bfd *abfd, unsigned int loc) --{ -- vms_debug2 ((4, "dst_restore_location (%d)\n", (int)loc)); -- -- PRIV (image_offset) = PRIV (dst_ptr_offsets)[loc]; --} -- --/* Retrieve saved DST location counter from specified index. */ -- --static unsigned int --dst_retrieve_location (bfd *abfd, unsigned int loc) --{ -- vms_debug2 ((4, "dst_retrieve_location (%d)\n", (int)loc)); -- -- return PRIV (dst_ptr_offsets)[loc]; --} -- --/* Write multiple bytes to section image. */ -- --static bfd_boolean --image_write (bfd *abfd, unsigned char *ptr, unsigned int size) --{ --#if VMS_DEBUG -- _bfd_vms_debug (8, "image_write from (%p, %d) to (%ld)\n", ptr, size, -- (long)PRIV (image_offset)); --#endif -- -- if (PRIV (image_section)->contents != NULL) -- { -- asection *sec = PRIV (image_section); -- size_t off = PRIV (image_offset); -- -- /* Check bounds. */ -- if (off > sec->size -- || size > sec->size - off) -- { -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- -- memcpy (sec->contents + off, ptr, size); -- } --#if VMS_DEBUG -- _bfd_hexdump (9, ptr, size, 0); --#endif -- -- PRIV (image_offset) += size; -- return TRUE; --} -- --/* Write byte to section image. */ -- --static bfd_boolean --image_write_b (bfd * abfd, unsigned int value) --{ -- unsigned char data[1]; -- -- vms_debug2 ((6, "image_write_b (%02x)\n", (int) value)); -- -- *data = value; -- -- return image_write (abfd, data, sizeof (data)); --} -- --/* Write 2-byte word to image. */ -- --static bfd_boolean --image_write_w (bfd * abfd, unsigned int value) --{ -- unsigned char data[2]; -- -- vms_debug2 ((6, "image_write_w (%04x)\n", (int) value)); -- -- bfd_putl16 (value, data); -- return image_write (abfd, data, sizeof (data)); --} -- --/* Write 4-byte long to image. */ -- --static bfd_boolean --image_write_l (bfd * abfd, unsigned long value) --{ -- unsigned char data[4]; -- -- vms_debug2 ((6, "image_write_l (%08lx)\n", value)); -- -- bfd_putl32 (value, data); -- return image_write (abfd, data, sizeof (data)); --} -- --/* Write 8-byte quad to image. */ -- --static bfd_boolean --image_write_q (bfd * abfd, bfd_vma value) --{ -- unsigned char data[8]; -- -- vms_debug2 ((6, "image_write_q (%08lx)\n", (unsigned long)value)); -- -- bfd_putl64 (value, data); -- return image_write (abfd, data, sizeof (data)); --} -- --static const char * --_bfd_vms_etir_name (int cmd) --{ -- switch (cmd) -- { -- case ETIR__C_STA_GBL: return "ETIR__C_STA_GBL"; -- case ETIR__C_STA_LW: return "ETIR__C_STA_LW"; -- case ETIR__C_STA_QW: return "ETIR__C_STA_QW"; -- case ETIR__C_STA_PQ: return "ETIR__C_STA_PQ"; -- case ETIR__C_STA_LI: return "ETIR__C_STA_LI"; -- case ETIR__C_STA_MOD: return "ETIR__C_STA_MOD"; -- case ETIR__C_STA_CKARG: return "ETIR__C_STA_CKARG"; -- case ETIR__C_STO_B: return "ETIR__C_STO_B"; -- case ETIR__C_STO_W: return "ETIR__C_STO_W"; -- case ETIR__C_STO_GBL: return "ETIR__C_STO_GBL"; -- case ETIR__C_STO_CA: return "ETIR__C_STO_CA"; -- case ETIR__C_STO_RB: return "ETIR__C_STO_RB"; -- case ETIR__C_STO_AB: return "ETIR__C_STO_AB"; -- case ETIR__C_STO_OFF: return "ETIR__C_STO_OFF"; -- case ETIR__C_STO_IMM: return "ETIR__C_STO_IMM"; -- case ETIR__C_STO_IMMR: return "ETIR__C_STO_IMMR"; -- case ETIR__C_STO_LW: return "ETIR__C_STO_LW"; -- case ETIR__C_STO_QW: return "ETIR__C_STO_QW"; -- case ETIR__C_STO_GBL_LW: return "ETIR__C_STO_GBL_LW"; -- case ETIR__C_STO_LP_PSB: return "ETIR__C_STO_LP_PSB"; -- case ETIR__C_STO_HINT_GBL: return "ETIR__C_STO_HINT_GBL"; -- case ETIR__C_STO_HINT_PS: return "ETIR__C_STO_HINT_PS"; -- case ETIR__C_OPR_ADD: return "ETIR__C_OPR_ADD"; -- case ETIR__C_OPR_SUB: return "ETIR__C_OPR_SUB"; -- case ETIR__C_OPR_INSV: return "ETIR__C_OPR_INSV"; -- case ETIR__C_OPR_USH: return "ETIR__C_OPR_USH"; -- case ETIR__C_OPR_ROT: return "ETIR__C_OPR_ROT"; -- case ETIR__C_OPR_REDEF: return "ETIR__C_OPR_REDEF"; -- case ETIR__C_OPR_DFLIT: return "ETIR__C_OPR_DFLIT"; -- case ETIR__C_STC_LP: return "ETIR__C_STC_LP"; -- case ETIR__C_STC_GBL: return "ETIR__C_STC_GBL"; -- case ETIR__C_STC_GCA: return "ETIR__C_STC_GCA"; -- case ETIR__C_STC_PS: return "ETIR__C_STC_PS"; -- case ETIR__C_STC_NBH_PS: return "ETIR__C_STC_NBH_PS"; -- case ETIR__C_STC_NOP_GBL: return "ETIR__C_STC_NOP_GBL"; -- case ETIR__C_STC_NOP_PS: return "ETIR__C_STC_NOP_PS"; -- case ETIR__C_STC_BSR_GBL: return "ETIR__C_STC_BSR_GBL"; -- case ETIR__C_STC_BSR_PS: return "ETIR__C_STC_BSR_PS"; -- case ETIR__C_STC_LDA_GBL: return "ETIR__C_STC_LDA_GBL"; -- case ETIR__C_STC_LDA_PS: return "ETIR__C_STC_LDA_PS"; -- case ETIR__C_STC_BOH_GBL: return "ETIR__C_STC_BOH_GBL"; -- case ETIR__C_STC_BOH_PS: return "ETIR__C_STC_BOH_PS"; -- case ETIR__C_STC_NBH_GBL: return "ETIR__C_STC_NBH_GBL"; -- case ETIR__C_STC_LP_PSB: return "ETIR__C_STC_LP_PSB"; -- case ETIR__C_CTL_SETRB: return "ETIR__C_CTL_SETRB"; -- case ETIR__C_CTL_AUGRB: return "ETIR__C_CTL_AUGRB"; -- case ETIR__C_CTL_DFLOC: return "ETIR__C_CTL_DFLOC"; -- case ETIR__C_CTL_STLOC: return "ETIR__C_CTL_STLOC"; -- case ETIR__C_CTL_STKDL: return "ETIR__C_CTL_STKDL"; -- -- default: -- /* These names have not yet been added to this switch statement. */ -- _bfd_error_handler (_("unknown ETIR command %d"), cmd); -- } -- -- return NULL; --} --#define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L) -- --static void --_bfd_vms_get_value (bfd *abfd, -- const unsigned char *ascic, -- const unsigned char *max_ascic, -- struct bfd_link_info *info, -- bfd_vma *vma, -- struct sw_64_vms_link_hash_entry **hp) --{ -- char name[257]; -- unsigned int len; -- unsigned int i; -- struct sw_64_vms_link_hash_entry *h; -- -- /* Not linking. Do not try to resolve the symbol. */ -- if (info == NULL) -- { -- *vma = 0; -- *hp = NULL; -- return; -- } -- -- len = *ascic; -- if (ascic + len >= max_ascic) -- { -- _bfd_error_handler (_("corrupt vms value")); -- *vma = 0; -- *hp = NULL; -- return; -- } -- -- for (i = 0; i < len; i++) -- name[i] = ascic[i + 1]; -- name[i] = 0; -- -- h = (struct sw_64_vms_link_hash_entry *) -- bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE); -- -- *hp = h; -- -- if (h != NULL -- && (h->root.type == bfd_link_hash_defined -- || h->root.type == bfd_link_hash_defweak)) -- *vma = h->root.u.def.value -- + h->root.u.def.section->output_offset -- + h->root.u.def.section->output_section->vma; -- else if (h && h->root.type == bfd_link_hash_undefweak) -- *vma = 0; -- else -- { -- (*info->callbacks->undefined_symbol) -- (info, name, abfd, PRIV (image_section), PRIV (image_offset), TRUE); -- *vma = 0; -- } --} -- --#define RELC_NONE 0 --#define RELC_REL 1 --#define RELC_SHR_BASE 0x10000 --#define RELC_SEC_BASE 0x20000 --#define RELC_MASK 0x0ffff -- --static unsigned int --sw_64_vms_sym_to_ctxt (struct sw_64_vms_link_hash_entry *h) --{ -- /* Handle undefined symbols. */ -- if (h == NULL || h->sym == NULL) -- return RELC_NONE; -- -- if (h->sym->typ == EGSD__C_SYMG) -- { -- if (h->sym->flags & EGSY__V_REL) -- return RELC_SHR_BASE + PRIV2 (h->sym->owner, shr_index); -- else -- { -- /* Can this happen (non-relocatable symg) ? I'd like to see -- an example. */ -- abort (); -- } -- } -- if (h->sym->typ == EGSD__C_SYM) -- { -- if (h->sym->flags & EGSY__V_REL) -- return RELC_REL; -- else -- return RELC_NONE; -- } -- abort (); --} -- --static bfd_vma --sw_64_vms_get_sym_value (asection *sect, bfd_vma addr) --{ -- return sect->output_section->vma + sect->output_offset + addr; --} -- --static bfd_vma --sw_64_vms_fix_sec_rel (bfd *abfd, struct bfd_link_info *info, -- unsigned int rel, bfd_vma vma) --{ -- asection *sec; -- -- if (PRIV (sections) == NULL) -- return 0; -- -- sec = PRIV (sections)[rel & RELC_MASK]; -- -- if (info) -- { -- if (sec->output_section == NULL) -- abort (); -- return vma + sec->output_section->vma + sec->output_offset; -- } -- else -- return vma + sec->vma; --} -- --/* Read an ETIR record from ABFD. If INFO is not null, put the content into -- the output section (used during linking). -- Return FALSE in case of error. */ -- --static bfd_boolean --_bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) --{ -- unsigned char *ptr; -- unsigned int length; -- unsigned char *maxptr; -- bfd_vma op1 = 0; -- bfd_vma op2 = 0; -- unsigned int rel1 = RELC_NONE; -- unsigned int rel2 = RELC_NONE; -- struct sw_64_vms_link_hash_entry *h; -- -- PRIV (recrd.rec) += ETIR__C_HEADER_SIZE; -- PRIV (recrd.rec_size) -= ETIR__C_HEADER_SIZE; -- -- ptr = PRIV (recrd.rec); -- length = PRIV (recrd.rec_size); -- maxptr = ptr + length; -- -- vms_debug2 ((2, "ETIR: %d bytes\n", length)); -- -- while (ptr < maxptr) -- { -- int cmd, cmd_length; -- -- if (ptr + 4 > maxptr) -- goto corrupt_etir; -- -- cmd = bfd_getl16 (ptr); -- cmd_length = bfd_getl16 (ptr + 2); -- -- /* PR 21589 and 21579: Check for a corrupt ETIR record. */ -- if (cmd_length < 4 || ptr + cmd_length > maxptr) -- { -- corrupt_etir: -- _bfd_error_handler (_("corrupt ETIR record encountered")); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- ptr += 4; -- --#if VMS_DEBUG -- _bfd_vms_debug (4, "etir: %s(%d)\n", -- _bfd_vms_etir_name (cmd), cmd); -- _bfd_hexdump (8, ptr, cmd_length - 4, 0); --#endif -- -- switch (cmd) -- { -- /* Stack global -- arg: cs symbol name -- -- stack 32 bit value of symbol (high bits set to 0). */ -- case ETIR__C_STA_GBL: -- _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); -- if (!_bfd_vms_push (abfd, op1, sw_64_vms_sym_to_ctxt (h))) -- return FALSE; -- break; -- -- /* Stack longword -- arg: lw value -- -- stack 32 bit value, sign extend to 64 bit. */ -- case ETIR__C_STA_LW: -- if (ptr + 4 > maxptr) -- goto corrupt_etir; -- if (!_bfd_vms_push (abfd, bfd_getl32 (ptr), RELC_NONE)) -- return FALSE; -- break; -- -- /* Stack quadword -- arg: qw value -- -- stack 64 bit value of symbol. */ -- case ETIR__C_STA_QW: -- if (ptr + 8 > maxptr) -- goto corrupt_etir; -- if (!_bfd_vms_push (abfd, bfd_getl64 (ptr), RELC_NONE)) -- return FALSE; -- break; -- -- /* Stack psect base plus quadword offset -- arg: lw section index -- qw signed quadword offset (low 32 bits) -- -- Stack qw argument and section index -- (see ETIR__C_STO_OFF, ETIR__C_CTL_SETRB). */ -- case ETIR__C_STA_PQ: -- { -- int psect; -- -- if (ptr + 12 > maxptr) -- goto corrupt_etir; -- psect = bfd_getl32 (ptr); -- if ((unsigned int) psect >= PRIV (section_count)) -- { -- _bfd_error_handler (_("bad section index in %s"), -- _bfd_vms_etir_name (cmd)); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- op1 = bfd_getl64 (ptr + 4); -- if (!_bfd_vms_push (abfd, op1, psect | RELC_SEC_BASE)) -- return FALSE; -- } -- break; -- -- case ETIR__C_STA_LI: -- case ETIR__C_STA_MOD: -- case ETIR__C_STA_CKARG: -- _bfd_error_handler (_("unsupported STA cmd %s"), -- _bfd_vms_etir_name (cmd)); -- return FALSE; -- break; -- -- /* Store byte: pop stack, write byte -- arg: -. */ -- case ETIR__C_STO_B: -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 != RELC_NONE) -- goto bad_context; -- image_write_b (abfd, (unsigned int) op1 & 0xff); -- break; -- -- /* Store word: pop stack, write word -- arg: -. */ -- case ETIR__C_STO_W: -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 != RELC_NONE) -- goto bad_context; -- image_write_w (abfd, (unsigned int) op1 & 0xffff); -- break; -- -- /* Store longword: pop stack, write longword -- arg: -. */ -- case ETIR__C_STO_LW: -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 & RELC_SEC_BASE) -- { -- op1 = sw_64_vms_fix_sec_rel (abfd, info, rel1, op1); -- rel1 = RELC_REL; -- } -- else if (rel1 & RELC_SHR_BASE) -- { -- sw_64_vms_add_fixup_lr (info, rel1 & RELC_MASK, op1); -- rel1 = RELC_NONE; -- } -- if (rel1 != RELC_NONE) -- { -- if (rel1 != RELC_REL) -- abort (); -- sw_64_vms_add_lw_reloc (info); -- } -- image_write_l (abfd, op1); -- break; -- -- /* Store quadword: pop stack, write quadword -- arg: -. */ -- case ETIR__C_STO_QW: -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 & RELC_SEC_BASE) -- { -- op1 = sw_64_vms_fix_sec_rel (abfd, info, rel1, op1); -- rel1 = RELC_REL; -- } -- else if (rel1 & RELC_SHR_BASE) -- abort (); -- if (rel1 != RELC_NONE) -- { -- if (rel1 != RELC_REL) -- abort (); -- sw_64_vms_add_qw_reloc (info); -- } -- image_write_q (abfd, op1); -- break; -- -- /* Store immediate repeated: pop stack for repeat count -- arg: lw byte count -- da data. */ -- case ETIR__C_STO_IMMR: -- { -- int size; -- -- if (ptr + 4 > maxptr) -- goto corrupt_etir; -- size = bfd_getl32 (ptr); -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 != RELC_NONE) -- goto bad_context; -- while (op1-- > 0) -- image_write (abfd, ptr + 4, size); -- } -- break; -- -- /* Store global: write symbol value -- arg: cs global symbol name. */ -- case ETIR__C_STO_GBL: -- _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); -- if (h && h->sym) -- { -- if (h->sym->typ == EGSD__C_SYMG) -- { -- sw_64_vms_add_fixup_qr -- (info, abfd, h->sym->owner, h->sym->symbol_vector); -- op1 = 0; -- } -- else -- { -- op1 = sw_64_vms_get_sym_value (h->sym->section, -- h->sym->value); -- sw_64_vms_add_qw_reloc (info); -- } -- } -- image_write_q (abfd, op1); -- break; -- -- /* Store code address: write address of entry point -- arg: cs global symbol name (procedure). */ -- case ETIR__C_STO_CA: -- _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); -- if (h && h->sym) -- { -- if (h->sym->flags & EGSY__V_NORM) -- { -- /* That's really a procedure. */ -- if (h->sym->typ == EGSD__C_SYMG) -- { -- sw_64_vms_add_fixup_ca (info, abfd, h->sym->owner); -- op1 = h->sym->symbol_vector; -- } -- else -- { -- op1 = sw_64_vms_get_sym_value (h->sym->code_section, -- h->sym->code_value); -- sw_64_vms_add_qw_reloc (info); -- } -- } -- else -- { -- /* Symbol is not a procedure. */ -- abort (); -- } -- } -- image_write_q (abfd, op1); -- break; -- -- /* Store offset to psect: pop stack, add low 32 bits to base of psect -- arg: none. */ -- case ETIR__C_STO_OFF: -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- -- if (!(rel1 & RELC_SEC_BASE)) -- abort (); -- -- op1 = sw_64_vms_fix_sec_rel (abfd, info, rel1, op1); -- rel1 = RELC_REL; -- image_write_q (abfd, op1); -- break; -- -- /* Store immediate -- arg: lw count of bytes -- da data. */ -- case ETIR__C_STO_IMM: -- { -- unsigned int size; -- -- if (ptr + 4 > maxptr) -- goto corrupt_etir; -- size = bfd_getl32 (ptr); -- image_write (abfd, ptr + 4, size); -- } -- break; -- -- /* This code is 'reserved to digital' according to the openVMS -- linker manual, however it is generated by the DEC C compiler -- and defined in the include file. -- FIXME, since the following is just a guess -- store global longword: store 32bit value of symbol -- arg: cs symbol name. */ -- case ETIR__C_STO_GBL_LW: -- _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); --#if 0 -- abort (); --#endif -- image_write_l (abfd, op1); -- break; -- -- case ETIR__C_STO_RB: -- case ETIR__C_STO_AB: -- case ETIR__C_STO_LP_PSB: -- _bfd_error_handler (_("%s: not supported"), -- _bfd_vms_etir_name (cmd)); -- return FALSE; -- break; -- case ETIR__C_STO_HINT_GBL: -- case ETIR__C_STO_HINT_PS: -- _bfd_error_handler (_("%s: not implemented"), -- _bfd_vms_etir_name (cmd)); -- return FALSE; -- break; -- -- /* 200 Store-conditional Linkage Pair -- arg: none. */ -- case ETIR__C_STC_LP: -- -- /* 202 Store-conditional Address at global address -- lw linkage index -- cs global name. */ -- -- case ETIR__C_STC_GBL: -- -- /* 203 Store-conditional Code Address at global address -- lw linkage index -- cs procedure name. */ -- case ETIR__C_STC_GCA: -- -- /* 204 Store-conditional Address at psect + offset -- lw linkage index -- lw psect index -- qw offset. */ -- case ETIR__C_STC_PS: -- _bfd_error_handler (_("%s: not supported"), -- _bfd_vms_etir_name (cmd)); -- return FALSE; -- break; -- -- /* 201 Store-conditional Linkage Pair with Procedure Signature -- lw linkage index -- cs procedure name -- by signature length -- da signature. */ -- -- case ETIR__C_STC_LP_PSB: -- _bfd_vms_get_value (abfd, ptr + 4, maxptr, info, &op1, &h); -- if (h && h->sym) -- { -- if (h->sym->typ == EGSD__C_SYMG) -- { -- sw_64_vms_add_fixup_lp (info, abfd, h->sym->owner); -- op1 = h->sym->symbol_vector; -- op2 = 0; -- } -- else -- { -- op1 = sw_64_vms_get_sym_value (h->sym->code_section, -- h->sym->code_value); -- op2 = sw_64_vms_get_sym_value (h->sym->section, -- h->sym->value); -- } -- } -- else -- { -- /* Undefined symbol. */ -- op1 = 0; -- op2 = 0; -- } -- image_write_q (abfd, op1); -- image_write_q (abfd, op2); -- break; -- -- /* 205 Store-conditional NOP at address of global -- arg: none. */ -- case ETIR__C_STC_NOP_GBL: -- /* SW_64_R_NOP */ -- -- /* 207 Store-conditional BSR at global address -- arg: none. */ -- -- case ETIR__C_STC_BSR_GBL: -- /* SW_64_R_BSR */ -- -- /* 209 Store-conditional LDA at global address -- arg: none. */ -- -- case ETIR__C_STC_LDA_GBL: -- /* SW_64_R_LDA */ -- -- /* 211 Store-conditional BSR or Hint at global address -- arg: none. */ -- -- case ETIR__C_STC_BOH_GBL: -- /* Currentl ignored. */ -- break; -- -- /* 213 Store-conditional NOP,BSR or HINT at global address -- arg: none. */ -- -- case ETIR__C_STC_NBH_GBL: -- -- /* 206 Store-conditional NOP at pect + offset -- arg: none. */ -- -- case ETIR__C_STC_NOP_PS: -- -- /* 208 Store-conditional BSR at pect + offset -- arg: none. */ -- -- case ETIR__C_STC_BSR_PS: -- -- /* 210 Store-conditional LDA at psect + offset -- arg: none. */ -- -- case ETIR__C_STC_LDA_PS: -- -- /* 212 Store-conditional BSR or Hint at pect + offset -- arg: none. */ -- -- case ETIR__C_STC_BOH_PS: -- -- /* 214 Store-conditional NOP, BSR or HINT at psect + offset -- arg: none. */ -- case ETIR__C_STC_NBH_PS: -- _bfd_error_handler (_("%s: not supported"), -- _bfd_vms_etir_name (cmd)); -- return FALSE; -- break; -- -- /* Det relocation base: pop stack, set image location counter -- arg: none. */ -- case ETIR__C_CTL_SETRB: -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (!(rel1 & RELC_SEC_BASE)) -- abort (); -- image_set_ptr (abfd, op1, rel1 & RELC_MASK, info); -- break; -- -- /* Augment relocation base: increment image location counter by offset -- arg: lw offset value. */ -- case ETIR__C_CTL_AUGRB: -- if (ptr + 4 > maxptr) -- goto corrupt_etir; -- op1 = bfd_getl32 (ptr); -- image_inc_ptr (abfd, op1); -- break; -- -- /* Define location: pop index, save location counter under index -- arg: none. */ -- case ETIR__C_CTL_DFLOC: -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 != RELC_NONE) -- goto bad_context; -- dst_define_location (abfd, op1); -- break; -- -- /* Set location: pop index, restore location counter from index -- arg: none. */ -- case ETIR__C_CTL_STLOC: -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 != RELC_NONE) -- goto bad_context; -- dst_restore_location (abfd, op1); -- break; -- -- /* Stack defined location: pop index, push location counter from index -- arg: none. */ -- case ETIR__C_CTL_STKDL: -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 != RELC_NONE) -- goto bad_context; -- if (!_bfd_vms_push (abfd, dst_retrieve_location (abfd, op1), -- RELC_NONE)) -- return FALSE; -- break; -- -- case ETIR__C_OPR_NOP: /* No-op. */ -- break; -- -- case ETIR__C_OPR_ADD: /* Add. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1) -- || !_bfd_vms_pop (abfd, &op2, &rel2)) -- return FALSE; -- if (rel1 == RELC_NONE && rel2 != RELC_NONE) -- rel1 = rel2; -- else if (rel1 != RELC_NONE && rel2 != RELC_NONE) -- goto bad_context; -- if (!_bfd_vms_push (abfd, op1 + op2, rel1)) -- return FALSE; -- break; -- -- case ETIR__C_OPR_SUB: /* Subtract. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1) -- || !_bfd_vms_pop (abfd, &op2, &rel2)) -- return FALSE; -- if (rel1 == RELC_NONE && rel2 != RELC_NONE) -- rel1 = rel2; -- else if ((rel1 & RELC_SEC_BASE) && (rel2 & RELC_SEC_BASE)) -- { -- op1 = sw_64_vms_fix_sec_rel (abfd, info, rel1, op1); -- op2 = sw_64_vms_fix_sec_rel (abfd, info, rel2, op2); -- rel1 = RELC_NONE; -- } -- else if (rel1 != RELC_NONE && rel2 != RELC_NONE) -- goto bad_context; -- if (!_bfd_vms_push (abfd, op2 - op1, rel1)) -- return FALSE; -- break; -- -- case ETIR__C_OPR_MUL: /* Multiply. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1) -- || !_bfd_vms_pop (abfd, &op2, &rel2)) -- return FALSE; -- if (rel1 != RELC_NONE || rel2 != RELC_NONE) -- goto bad_context; -- if (!_bfd_vms_push (abfd, op1 * op2, RELC_NONE)) -- return FALSE; -- break; -- -- case ETIR__C_OPR_DIV: /* Divide. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1) -- || !_bfd_vms_pop (abfd, &op2, &rel2)) -- return FALSE; -- if (rel1 != RELC_NONE || rel2 != RELC_NONE) -- goto bad_context; -- if (op2 == 0) -- { -- if (!_bfd_vms_push (abfd, 0, RELC_NONE)) -- return FALSE; -- } -- else -- { -- if (!_bfd_vms_push (abfd, op2 / op1, RELC_NONE)) -- return FALSE; -- } -- break; -- -- case ETIR__C_OPR_AND: /* Logical AND. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1) -- || !_bfd_vms_pop (abfd, &op2, &rel2)) -- return FALSE; -- if (rel1 != RELC_NONE || rel2 != RELC_NONE) -- goto bad_context; -- if (!_bfd_vms_push (abfd, op1 & op2, RELC_NONE)) -- return FALSE; -- break; -- -- case ETIR__C_OPR_IOR: /* Logical inclusive OR. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1) -- || !_bfd_vms_pop (abfd, &op2, &rel2)) -- return FALSE; -- if (rel1 != RELC_NONE || rel2 != RELC_NONE) -- goto bad_context; -- if (!_bfd_vms_push (abfd, op1 | op2, RELC_NONE)) -- return FALSE; -- break; -- -- case ETIR__C_OPR_EOR: /* Logical exclusive OR. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1) -- || !_bfd_vms_pop (abfd, &op2, &rel2)) -- return FALSE; -- if (rel1 != RELC_NONE || rel2 != RELC_NONE) -- goto bad_context; -- if (!_bfd_vms_push (abfd, op1 ^ op2, RELC_NONE)) -- return FALSE; -- break; -- -- case ETIR__C_OPR_NEG: /* Negate. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 != RELC_NONE) -- goto bad_context; -- if (!_bfd_vms_push (abfd, -op1, RELC_NONE)) -- return FALSE; -- break; -- -- case ETIR__C_OPR_COM: /* Complement. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (rel1 != RELC_NONE) -- goto bad_context; -- if (!_bfd_vms_push (abfd, ~op1, RELC_NONE)) -- return FALSE; -- break; -- -- case ETIR__C_OPR_ASH: /* Arithmetic shift. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1) -- || !_bfd_vms_pop (abfd, &op2, &rel2)) -- return FALSE; -- if (rel1 != RELC_NONE || rel2 != RELC_NONE) -- { -- bad_context: -- _bfd_error_handler (_("invalid use of %s with contexts"), -- _bfd_vms_etir_name (cmd)); -- return FALSE; -- } -- if ((int)op2 < 0) /* Shift right. */ -- op1 >>= -(int)op2; -- else /* Shift left. */ -- op1 <<= (int)op2; -- if (!_bfd_vms_push (abfd, op1, RELC_NONE)) /* FIXME: sym. */ -- return FALSE; -- break; -- -- case ETIR__C_OPR_INSV: /* Insert field. */ -- case ETIR__C_OPR_USH: /* Unsigned shift. */ -- case ETIR__C_OPR_ROT: /* Rotate. */ -- case ETIR__C_OPR_REDEF: /* Redefine symbol to current location. */ -- case ETIR__C_OPR_DFLIT: /* Define a literal. */ -- _bfd_error_handler (_("%s: not supported"), -- _bfd_vms_etir_name (cmd)); -- return FALSE; -- break; -- -- case ETIR__C_OPR_SEL: /* Select. */ -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- if (op1 & 0x01L) -- { -- if (!_bfd_vms_pop (abfd, &op1, &rel1)) -- return FALSE; -- } -- else -- { -- if (!_bfd_vms_pop (abfd, &op1, &rel1) -- || !_bfd_vms_pop (abfd, &op2, &rel2)) -- return FALSE; -- if (!_bfd_vms_push (abfd, op1, rel1)) -- return FALSE; -- } -- break; -- -- default: -- _bfd_error_handler (_("reserved cmd %d"), cmd); -- return FALSE; -- break; -- } -- -- ptr += cmd_length - 4; -- } -- -- return TRUE; --} -- --/* Process EDBG/ETBT record. -- Return TRUE on success, FALSE on error */ -- --static bfd_boolean --vms_slurp_debug (bfd *abfd) --{ -- asection *section = PRIV (dst_section); -- -- if (section == NULL) -- { -- /* We have no way to find out beforehand how much debug info there -- is in an object file, so pick an initial amount and grow it as -- needed later. */ -- flagword flags = SEC_HAS_CONTENTS | SEC_DEBUGGING | SEC_RELOC -- | SEC_IN_MEMORY; -- -- section = bfd_make_section (abfd, "$DST$"); -- if (!section) -- return FALSE; -- if (!bfd_set_section_flags (section, flags)) -- return FALSE; -- PRIV (dst_section) = section; -- } -- -- PRIV (image_section) = section; -- PRIV (image_offset) = section->size; -- -- if (!_bfd_vms_slurp_etir (abfd, NULL)) -- return FALSE; -- -- section->size = PRIV (image_offset); -- return TRUE; --} -- --/* Process EDBG record. -- Return TRUE on success, FALSE on error. */ -- --static bfd_boolean --_bfd_vms_slurp_edbg (bfd *abfd) --{ -- vms_debug2 ((2, "EDBG\n")); -- -- abfd->flags |= HAS_DEBUG | HAS_LINENO; -- -- return vms_slurp_debug (abfd); --} -- --/* Process ETBT record. -- Return TRUE on success, FALSE on error. */ -- --static bfd_boolean --_bfd_vms_slurp_etbt (bfd *abfd) --{ -- vms_debug2 ((2, "ETBT\n")); -- -- abfd->flags |= HAS_LINENO; -- -- return vms_slurp_debug (abfd); --} -- --/* Process EEOM record. -- Return TRUE on success, FALSE on error. */ -- --static bfd_boolean --_bfd_vms_slurp_eeom (bfd *abfd) --{ -- struct vms_eeom *eeom = (struct vms_eeom *) PRIV (recrd.rec); -- -- vms_debug2 ((2, "EEOM\n")); -- -- /* PR 21813: Check for an undersized record. */ -- if (PRIV (recrd.buf_size) < sizeof (* eeom)) -- { -- _bfd_error_handler (_("corrupt EEOM record - size is too small")); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- -- PRIV (eom_data).eom_l_total_lps = bfd_getl32 (eeom->total_lps); -- PRIV (eom_data).eom_w_comcod = bfd_getl16 (eeom->comcod); -- if (PRIV (eom_data).eom_w_comcod > 1) -- { -- _bfd_error_handler (_("object module not error-free !")); -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -- -- PRIV (eom_data).eom_has_transfer = FALSE; -- if (PRIV (recrd.rec_size) > 10) -- { -- PRIV (eom_data).eom_has_transfer = TRUE; -- PRIV (eom_data).eom_b_tfrflg = eeom->tfrflg; -- PRIV (eom_data).eom_l_psindx = bfd_getl32 (eeom->psindx); -- PRIV (eom_data).eom_l_tfradr = bfd_getl32 (eeom->tfradr); -- -- abfd->start_address = PRIV (eom_data).eom_l_tfradr; -- } -- return TRUE; --} -- --/* Slurp an ordered set of VMS object records. Return FALSE on error. */ -- --static bfd_boolean --_bfd_vms_slurp_object_records (bfd * abfd) --{ -- bfd_boolean err; -- int type; -- -- do -- { -- vms_debug2 ((7, "reading at %08lx\n", (unsigned long)bfd_tell (abfd))); -- -- type = _bfd_vms_get_object_record (abfd); -- if (type < 0) -- { -- vms_debug2 ((2, "next_record failed\n")); -- return FALSE; -- } -- -- switch (type) -- { -- case EOBJ__C_EMH: -- err = _bfd_vms_slurp_ehdr (abfd); -- break; -- case EOBJ__C_EEOM: -- err = _bfd_vms_slurp_eeom (abfd); -- break; -- case EOBJ__C_EGSD: -- err = _bfd_vms_slurp_egsd (abfd); -- break; -- case EOBJ__C_ETIR: -- err = TRUE; /* _bfd_vms_slurp_etir (abfd); */ -- break; -- case EOBJ__C_EDBG: -- err = _bfd_vms_slurp_edbg (abfd); -- break; -- case EOBJ__C_ETBT: -- err = _bfd_vms_slurp_etbt (abfd); -- break; -- default: -- err = FALSE; -- } -- if (!err) -- { -- vms_debug2 ((2, "slurp type %d failed\n", type)); -- return FALSE; -- } -- } -- while (type != EOBJ__C_EEOM); -- -- return TRUE; --} -- --/* Initialize private data */ --static bfd_boolean --vms_initialize (bfd * abfd) --{ -- bfd_size_type amt; -- -- amt = sizeof (struct vms_private_data_struct); -- abfd->tdata.any = bfd_zalloc (abfd, amt); -- if (abfd->tdata.any == NULL) -- return FALSE; -- -- PRIV (recrd.file_format) = FF_UNKNOWN; -- -- amt = sizeof (struct stack_struct) * STACKSIZE; -- PRIV (stack) = bfd_alloc (abfd, amt); -- if (PRIV (stack) == NULL) -- goto error_ret1; -- -- return TRUE; -- -- error_ret1: -- bfd_release (abfd, abfd->tdata.any); -- abfd->tdata.any = NULL; -- return FALSE; --} -- --/* Free malloc'd memory. */ -- --static void --sw_64_vms_free_private (bfd *abfd) --{ -- struct module *module; -- -- free (PRIV (recrd.buf)); -- free (PRIV (sections)); -- free (PRIV (syms)); -- free (PRIV (dst_ptr_offsets)); -- -- for (module = PRIV (modules); module; module = module->next) -- free (module->file_table); --} -- --/* Check the format for a file being read. -- Return a (bfd_target *) if it's an object file or zero if not. */ -- --static const struct bfd_target * --sw_64_vms_object_p (bfd *abfd) --{ -- void *tdata_save = abfd->tdata.any; -- unsigned int test_len; -- unsigned char *buf; -- -- vms_debug2 ((1, "vms_object_p(%p)\n", abfd)); -- -- /* Allocate sw_64-vms specific data. */ -- if (!vms_initialize (abfd)) -- { -- abfd->tdata.any = tdata_save; -- return NULL; -- } -- -- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET)) -- goto err_wrong_format; -- -- /* The first challenge with VMS is to discover the kind of the file. -- -- Image files (executable or shared images) are stored as a raw -- stream of bytes (like on UNIX), but there is no magic number. -- -- Object files are written with RMS (record management service), ie -- each records are preceeded by its length (on a word - 2 bytes), and -- padded for word-alignment. That would be simple but when files -- are transfered to a UNIX filesystem (using ftp), records are lost. -- Only the raw content of the records are transfered. Fortunately, -- the Sw_64 Object file format also store the length of the record -- in the records. Is that clear ? */ -- -- /* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id, -- 2 bytes size repeated) and 12 bytes for images (4 bytes major id, -- 4 bytes minor id, 4 bytes length). */ -- test_len = 12; -- -- /* Size the main buffer. */ -- buf = (unsigned char *) bfd_malloc (test_len); -- if (buf == NULL) -- goto error_ret; -- PRIV (recrd.buf) = buf; -- PRIV (recrd.buf_size) = test_len; -- -- /* Initialize the record pointer. */ -- PRIV (recrd.rec) = buf; -- -- if (bfd_bread (buf, test_len, abfd) != test_len) -- goto err_wrong_format; -- -- /* Is it an image? */ -- if ((bfd_getl32 (buf) == EIHD__K_MAJORID) -- && (bfd_getl32 (buf + 4) == EIHD__K_MINORID)) -- { -- unsigned int to_read; -- unsigned int read_so_far; -- unsigned int remaining; -- unsigned int eisd_offset, eihs_offset; -- -- /* Extract the header size. */ -- PRIV (recrd.rec_size) = bfd_getl32 (buf + EIHD__L_SIZE); -- -- /* The header size is 0 for DSF files. */ -- if (PRIV (recrd.rec_size) == 0) -- PRIV (recrd.rec_size) = sizeof (struct vms_eihd); -- -- if (PRIV (recrd.rec_size) > PRIV (recrd.buf_size)) -- { -- buf = bfd_realloc_or_free (buf, PRIV (recrd.rec_size)); -- -- if (buf == NULL) -- { -- PRIV (recrd.buf) = NULL; -- goto error_ret; -- } -- PRIV (recrd.buf) = buf; -- PRIV (recrd.buf_size) = PRIV (recrd.rec_size); -- } -- -- /* PR 21813: Check for a truncated record. */ -- if (PRIV (recrd.rec_size < test_len)) -- goto error_ret; -- /* Read the remaining record. */ -- remaining = PRIV (recrd.rec_size) - test_len; -- to_read = MIN (VMS_BLOCK_SIZE - test_len, remaining); -- read_so_far = test_len; -- -- while (remaining > 0) -- { -- if (bfd_bread (buf + read_so_far, to_read, abfd) != to_read) -- goto err_wrong_format; -- -- read_so_far += to_read; -- remaining -= to_read; -- -- to_read = MIN (VMS_BLOCK_SIZE, remaining); -- } -- -- /* Reset the record pointer. */ -- PRIV (recrd.rec) = buf; -- -- /* PR 17512: file: 7d7c57c2. */ -- if (PRIV (recrd.rec_size) < sizeof (struct vms_eihd)) -- goto error_ret; -- vms_debug2 ((2, "file type is image\n")); -- -- if (!_bfd_vms_slurp_eihd (abfd, &eisd_offset, &eihs_offset)) -- goto err_wrong_format; -- -- if (!_bfd_vms_slurp_eisd (abfd, eisd_offset)) -- goto err_wrong_format; -- -- /* EIHS is optional. */ -- if (eihs_offset != 0 && !_bfd_vms_slurp_eihs (abfd, eihs_offset)) -- goto err_wrong_format; -- } -- else -- { -- int type; -- -- /* Assume it's a module and adjust record pointer if necessary. */ -- maybe_adjust_record_pointer_for_object (abfd); -- -- /* But is it really a module? */ -- if (bfd_getl16 (PRIV (recrd.rec)) <= EOBJ__C_MAXRECTYP -- && bfd_getl16 (PRIV (recrd.rec) + 2) <= EOBJ__C_MAXRECSIZ) -- { -- if (vms_get_remaining_object_record (abfd, test_len) <= 0) -- goto err_wrong_format; -- -- vms_debug2 ((2, "file type is module\n")); -- -- type = bfd_getl16 (PRIV (recrd.rec)); -- if (type != EOBJ__C_EMH || !_bfd_vms_slurp_ehdr (abfd)) -- goto err_wrong_format; -- -- if (!_bfd_vms_slurp_object_records (abfd)) -- goto err_wrong_format; -- } -- else -- goto err_wrong_format; -- } -- -- /* Set arch_info to sw_64. */ -- -- if (! bfd_default_set_arch_mach (abfd, bfd_arch_sw_64, 0)) -- goto err_wrong_format; -- -- return abfd->xvec; -- -- err_wrong_format: -- bfd_set_error (bfd_error_wrong_format); -- -- error_ret: -- sw_64_vms_free_private (abfd); -- if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL) -- bfd_release (abfd, abfd->tdata.any); -- abfd->tdata.any = tdata_save; -- return NULL; --} -- --/* Image write. */ -- --/* Write an EMH/MHD record. */ -- --static void --_bfd_vms_write_emh (bfd *abfd) --{ -- struct vms_rec_wr *recwr = &PRIV (recwr); -- -- _bfd_vms_output_alignment (recwr, 2); -- -- /* EMH. */ -- _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -- _bfd_vms_output_short (recwr, EMH__C_MHD); -- _bfd_vms_output_short (recwr, EOBJ__C_STRLVL); -- _bfd_vms_output_long (recwr, 0); -- _bfd_vms_output_long (recwr, 0); -- _bfd_vms_output_long (recwr, MAX_OUTREC_SIZE); -- -- /* Create module name from filename. */ -- if (bfd_get_filename (abfd) != 0) -- { -- char *module = vms_get_module_name (bfd_get_filename (abfd), TRUE); -- _bfd_vms_output_counted (recwr, module); -- free (module); -- } -- else -- _bfd_vms_output_counted (recwr, "NONAME"); -- -- _bfd_vms_output_counted (recwr, BFD_VERSION_STRING); -- _bfd_vms_output_dump (recwr, get_vms_time_string (), EMH_DATE_LENGTH); -- _bfd_vms_output_fill (recwr, 0, EMH_DATE_LENGTH); -- _bfd_vms_output_end (abfd, recwr); --} -- --/* Write an EMH/LMN record. */ -- --static void --_bfd_vms_write_lmn (bfd *abfd, const char *name) --{ -- char version [64]; -- struct vms_rec_wr *recwr = &PRIV (recwr); -- unsigned int ver = BFD_VERSION / 10000; -- -- /* LMN. */ -- _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -- _bfd_vms_output_short (recwr, EMH__C_LNM); -- snprintf (version, sizeof (version), "%s %d.%d.%d", name, -- ver / 10000, (ver / 100) % 100, ver % 100); -- _bfd_vms_output_dump (recwr, (unsigned char *)version, strlen (version)); -- _bfd_vms_output_end (abfd, recwr); --} -- -- --/* Write eom record for bfd abfd. Return FALSE on error. */ -- --static bfd_boolean --_bfd_vms_write_eeom (bfd *abfd) --{ -- struct vms_rec_wr *recwr = &PRIV (recwr); -- -- vms_debug2 ((2, "vms_write_eeom\n")); -- -- _bfd_vms_output_alignment (recwr, 2); -- -- _bfd_vms_output_begin (recwr, EOBJ__C_EEOM); -- _bfd_vms_output_long (recwr, PRIV (vms_linkage_index + 1) >> 1); -- _bfd_vms_output_byte (recwr, 0); /* Completion code. */ -- _bfd_vms_output_byte (recwr, 0); /* Fill byte. */ -- -- if ((abfd->flags & EXEC_P) == 0 -- && bfd_get_start_address (abfd) != (bfd_vma)-1) -- { -- asection *section; -- -- section = bfd_get_section_by_name (abfd, ".link"); -- if (section == 0) -- { -- bfd_set_error (bfd_error_nonrepresentable_section); -- return FALSE; -- } -- _bfd_vms_output_short (recwr, 0); -- _bfd_vms_output_long (recwr, (unsigned long) section->target_index); -- _bfd_vms_output_long (recwr, -- (unsigned long) bfd_get_start_address (abfd)); -- _bfd_vms_output_long (recwr, 0); -- } -- -- _bfd_vms_output_end (abfd, recwr); -- return TRUE; --} -- --static void --vector_grow1 (struct vector_type *vec, size_t elsz) --{ -- if (vec->nbr_el + 1 < vec->max_el) -- return; -- -- if (vec->max_el == 0) -- { -- vec->max_el = 16; -- vec->els = bfd_malloc2 (vec->max_el, elsz); -- } -- else -- { -- vec->max_el *= 2; -- vec->els = bfd_realloc2 (vec->els, vec->max_el, elsz); -- } --} -- --/* Bump ABFD file position to next block. */ -- --static void --sw_64_vms_file_position_block (bfd *abfd) --{ -- /* Next block. */ -- PRIV (file_pos) += VMS_BLOCK_SIZE - 1; -- PRIV (file_pos) -= (PRIV (file_pos) % VMS_BLOCK_SIZE); --} -- --/* Convert from internal structure SRC to external structure DST. */ -- --static void --sw_64_vms_swap_eisd_out (struct vms_internal_eisd_map *src, -- struct vms_eisd *dst) --{ -- bfd_putl32 (src->u.eisd.majorid, dst->majorid); -- bfd_putl32 (src->u.eisd.minorid, dst->minorid); -- bfd_putl32 (src->u.eisd.eisdsize, dst->eisdsize); -- if (src->u.eisd.eisdsize <= EISD__K_LENEND) -- return; -- bfd_putl32 (src->u.eisd.secsize, dst->secsize); -- bfd_putl64 (src->u.eisd.virt_addr, dst->virt_addr); -- bfd_putl32 (src->u.eisd.flags, dst->flags); -- bfd_putl32 (src->u.eisd.vbn, dst->vbn); -- dst->pfc = src->u.eisd.pfc; -- dst->matchctl = src->u.eisd.matchctl; -- dst->type = src->u.eisd.type; -- dst->fill_1 = 0; -- if (src->u.eisd.flags & EISD__M_GBL) -- { -- bfd_putl32 (src->u.gbl_eisd.ident, dst->ident); -- memcpy (dst->gblnam, src->u.gbl_eisd.gblnam, -- src->u.gbl_eisd.gblnam[0] + 1); -- } --} -- --/* Append EISD to the list of extra eisd for ABFD. */ -- --static void --sw_64_vms_append_extra_eisd (bfd *abfd, struct vms_internal_eisd_map *eisd) --{ -- eisd->next = NULL; -- if (PRIV (gbl_eisd_head) == NULL) -- PRIV (gbl_eisd_head) = eisd; -- else -- PRIV (gbl_eisd_tail)->next = eisd; -- PRIV (gbl_eisd_tail) = eisd; --} -- --/* Create an EISD for shared image SHRIMG. -- Return FALSE in case of error. */ -- --static bfd_boolean --sw_64_vms_create_eisd_for_shared (bfd *abfd, bfd *shrimg) --{ -- struct vms_internal_eisd_map *eisd; -- int namlen; -- -- namlen = strlen (PRIV2 (shrimg, hdr_data.hdr_t_name)); -- if (namlen + 5 > EISD__K_GBLNAMLEN) -- { -- /* Won't fit. */ -- return FALSE; -- } -- -- eisd = bfd_alloc (abfd, sizeof (*eisd)); -- if (eisd == NULL) -- return FALSE; -- -- /* Fill the fields. */ -- eisd->u.gbl_eisd.common.majorid = EISD__K_MAJORID; -- eisd->u.gbl_eisd.common.minorid = EISD__K_MINORID; -- eisd->u.gbl_eisd.common.eisdsize = (EISD__K_LEN + 4 + namlen + 5 + 3) & ~3; -- eisd->u.gbl_eisd.common.secsize = VMS_BLOCK_SIZE; /* Must not be 0. */ -- eisd->u.gbl_eisd.common.virt_addr = 0; -- eisd->u.gbl_eisd.common.flags = EISD__M_GBL; -- eisd->u.gbl_eisd.common.vbn = 0; -- eisd->u.gbl_eisd.common.pfc = 0; -- eisd->u.gbl_eisd.common.matchctl = PRIV2 (shrimg, matchctl); -- eisd->u.gbl_eisd.common.type = EISD__K_SHRPIC; -- -- eisd->u.gbl_eisd.ident = PRIV2 (shrimg, ident); -- eisd->u.gbl_eisd.gblnam[0] = namlen + 4; -- memcpy (eisd->u.gbl_eisd.gblnam + 1, PRIV2 (shrimg, hdr_data.hdr_t_name), -- namlen); -- memcpy (eisd->u.gbl_eisd.gblnam + 1 + namlen, "_001", 4); -- -- /* Append it to the list. */ -- sw_64_vms_append_extra_eisd (abfd, eisd); -- -- return TRUE; --} -- --/* Create an EISD for section SEC. -- Return FALSE in case of failure. */ -- --static bfd_boolean --sw_64_vms_create_eisd_for_section (bfd *abfd, asection *sec) --{ -- struct vms_internal_eisd_map *eisd; -- -- /* Only for allocating section. */ -- if (!(sec->flags & SEC_ALLOC)) -- return TRUE; -- -- BFD_ASSERT (vms_section_data (sec)->eisd == NULL); -- eisd = bfd_alloc (abfd, sizeof (*eisd)); -- if (eisd == NULL) -- return FALSE; -- vms_section_data (sec)->eisd = eisd; -- -- /* Fill the fields. */ -- eisd->u.eisd.majorid = EISD__K_MAJORID; -- eisd->u.eisd.minorid = EISD__K_MINORID; -- eisd->u.eisd.eisdsize = EISD__K_LEN; -- eisd->u.eisd.secsize = -- (sec->size + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1); -- eisd->u.eisd.virt_addr = sec->vma; -- eisd->u.eisd.flags = 0; -- eisd->u.eisd.vbn = 0; /* To be later defined. */ -- eisd->u.eisd.pfc = 0; /* Default. */ -- eisd->u.eisd.matchctl = EISD__K_MATALL; -- eisd->u.eisd.type = EISD__K_NORMAL; -- -- if (sec->flags & SEC_CODE) -- eisd->u.eisd.flags |= EISD__M_EXE; -- if (!(sec->flags & SEC_READONLY)) -- eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF; -- -- /* If relocations or fixup will be applied, make this isect writeable. */ -- if (sec->flags & SEC_RELOC) -- eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF; -- -- if (!(sec->flags & SEC_HAS_CONTENTS)) -- { -- eisd->u.eisd.flags |= EISD__M_DZRO; -- eisd->u.eisd.flags &= ~EISD__M_CRF; -- } -- if (sec->flags & SEC_LINKER_CREATED) -- { -- if (strcmp (sec->name, "$FIXUP$") == 0) -- eisd->u.eisd.flags |= EISD__M_FIXUPVEC; -- } -- -- /* Append it to the list. */ -- eisd->next = NULL; -- if (PRIV (eisd_head) == NULL) -- PRIV (eisd_head) = eisd; -- else -- PRIV (eisd_tail)->next = eisd; -- PRIV (eisd_tail) = eisd; -- -- return TRUE; --} -- --/* Layout executable ABFD and write it to the disk. -- Return FALSE in case of failure. */ -- --static bfd_boolean --sw_64_vms_write_exec (bfd *abfd) --{ -- struct vms_eihd eihd; -- struct vms_eiha *eiha; -- struct vms_eihi *eihi; -- struct vms_eihs *eihs = NULL; -- asection *sec; -- struct vms_internal_eisd_map *first_eisd; -- struct vms_internal_eisd_map *eisd; -- asection *dst; -- asection *dmt; -- file_ptr gst_filepos = 0; -- unsigned int lnkflags = 0; -- -- /* Build the EIHD. */ -- PRIV (file_pos) = EIHD__C_LENGTH; -- -- memset (&eihd, 0, sizeof (eihd)); -- memset (eihd.fill_2, 0xff, sizeof (eihd.fill_2)); -- -- bfd_putl32 (EIHD__K_MAJORID, eihd.majorid); -- bfd_putl32 (EIHD__K_MINORID, eihd.minorid); -- -- bfd_putl32 (sizeof (eihd), eihd.size); -- bfd_putl32 (0, eihd.isdoff); -- bfd_putl32 (0, eihd.activoff); -- bfd_putl32 (0, eihd.symdbgoff); -- bfd_putl32 (0, eihd.imgidoff); -- bfd_putl32 (0, eihd.patchoff); -- bfd_putl64 (0, eihd.iafva); -- bfd_putl32 (0, eihd.version_array_off); -- -- bfd_putl32 (EIHD__K_EXE, eihd.imgtype); -- bfd_putl32 (0, eihd.subtype); -- -- bfd_putl32 (0, eihd.imgiocnt); -- bfd_putl32 (-1, eihd.privreqs); -- bfd_putl32 (-1, eihd.privreqs + 4); -- -- bfd_putl32 ((sizeof (eihd) + VMS_BLOCK_SIZE - 1) / VMS_BLOCK_SIZE, -- eihd.hdrblkcnt); -- bfd_putl32 (0, eihd.ident); -- bfd_putl32 (0, eihd.sysver); -- -- eihd.matchctl = 0; -- bfd_putl32 (0, eihd.symvect_size); -- bfd_putl32 (16, eihd.virt_mem_block_size); -- bfd_putl32 (0, eihd.ext_fixup_off); -- bfd_putl32 (0, eihd.noopt_psect_off); -- bfd_putl32 (-1, eihd.alias); -- -- /* Alloc EIHA. */ -- eiha = (struct vms_eiha *)((char *) &eihd + PRIV (file_pos)); -- bfd_putl32 (PRIV (file_pos), eihd.activoff); -- PRIV (file_pos) += sizeof (struct vms_eiha); -- -- bfd_putl32 (sizeof (struct vms_eiha), eiha->size); -- bfd_putl32 (0, eiha->spare); -- bfd_putl64 (PRIV (transfer_address[0]), eiha->tfradr1); -- bfd_putl64 (PRIV (transfer_address[1]), eiha->tfradr2); -- bfd_putl64 (PRIV (transfer_address[2]), eiha->tfradr3); -- bfd_putl64 (PRIV (transfer_address[3]), eiha->tfradr4); -- bfd_putl64 (0, eiha->inishr); -- -- /* Alloc EIHI. */ -- eihi = (struct vms_eihi *)((char *) &eihd + PRIV (file_pos)); -- bfd_putl32 (PRIV (file_pos), eihd.imgidoff); -- PRIV (file_pos) += sizeof (struct vms_eihi); -- -- bfd_putl32 (EIHI__K_MAJORID, eihi->majorid); -- bfd_putl32 (EIHI__K_MINORID, eihi->minorid); -- { -- char *module; -- unsigned int len; -- -- /* Set module name. */ -- module = vms_get_module_name (bfd_get_filename (abfd), TRUE); -- len = strlen (module); -- if (len > sizeof (eihi->imgnam) - 1) -- len = sizeof (eihi->imgnam) - 1; -- eihi->imgnam[0] = len; -- memcpy (eihi->imgnam + 1, module, len); -- free (module); -- } -- { -- unsigned int lo; -- unsigned int hi; -- -- /* Set time. */ -- vms_get_time (&hi, &lo); -- bfd_putl32 (lo, eihi->linktime + 0); -- bfd_putl32 (hi, eihi->linktime + 4); -- } -- eihi->imgid[0] = 0; -- eihi->linkid[0] = 0; -- eihi->imgbid[0] = 0; -- -- /* Alloc EIHS. */ -- dst = PRIV (dst_section); -- dmt = bfd_get_section_by_name (abfd, "$DMT$"); -- if (dst != NULL && dst->size != 0) -- { -- eihs = (struct vms_eihs *)((char *) &eihd + PRIV (file_pos)); -- bfd_putl32 (PRIV (file_pos), eihd.symdbgoff); -- PRIV (file_pos) += sizeof (struct vms_eihs); -- -- bfd_putl32 (EIHS__K_MAJORID, eihs->majorid); -- bfd_putl32 (EIHS__K_MINORID, eihs->minorid); -- bfd_putl32 (0, eihs->dstvbn); -- bfd_putl32 (0, eihs->dstsize); -- bfd_putl32 (0, eihs->gstvbn); -- bfd_putl32 (0, eihs->gstsize); -- bfd_putl32 (0, eihs->dmtvbn); -- bfd_putl32 (0, eihs->dmtsize); -- } -- -- /* One EISD per section. */ -- for (sec = abfd->sections; sec; sec = sec->next) -- { -- if (!sw_64_vms_create_eisd_for_section (abfd, sec)) -- return FALSE; -- } -- -- /* Merge section EIDS which extra ones. */ -- if (PRIV (eisd_tail)) -- PRIV (eisd_tail)->next = PRIV (gbl_eisd_head); -- else -- PRIV (eisd_head) = PRIV (gbl_eisd_head); -- if (PRIV (gbl_eisd_tail)) -- PRIV (eisd_tail) = PRIV (gbl_eisd_tail); -- -- first_eisd = PRIV (eisd_head); -- -- /* Add end of eisd. */ -- if (first_eisd) -- { -- eisd = bfd_zalloc (abfd, sizeof (*eisd)); -- if (eisd == NULL) -- return FALSE; -- eisd->u.eisd.majorid = 0; -- eisd->u.eisd.minorid = 0; -- eisd->u.eisd.eisdsize = 0; -- sw_64_vms_append_extra_eisd (abfd, eisd); -- } -- -- /* Place EISD in the file. */ -- for (eisd = first_eisd; eisd; eisd = eisd->next) -- { -- file_ptr room = VMS_BLOCK_SIZE - (PRIV (file_pos) % VMS_BLOCK_SIZE); -- -- /* First block is a little bit special: there is a word at the end. */ -- if (PRIV (file_pos) < VMS_BLOCK_SIZE && room > 2) -- room -= 2; -- if (room < eisd->u.eisd.eisdsize + EISD__K_LENEND) -- sw_64_vms_file_position_block (abfd); -- -- eisd->file_pos = PRIV (file_pos); -- PRIV (file_pos) += eisd->u.eisd.eisdsize; -- -- if (eisd->u.eisd.flags & EISD__M_FIXUPVEC) -- bfd_putl64 (eisd->u.eisd.virt_addr, eihd.iafva); -- } -- -- if (first_eisd != NULL) -- { -- bfd_putl32 (first_eisd->file_pos, eihd.isdoff); -- /* Real size of end of eisd marker. */ -- PRIV (file_pos) += EISD__K_LENEND; -- } -- -- bfd_putl32 (PRIV (file_pos), eihd.size); -- bfd_putl32 ((PRIV (file_pos) + VMS_BLOCK_SIZE - 1) / VMS_BLOCK_SIZE, -- eihd.hdrblkcnt); -- -- /* Place sections. */ -- for (sec = abfd->sections; sec; sec = sec->next) -- { -- if (!(sec->flags & SEC_HAS_CONTENTS)) -- continue; -- -- eisd = vms_section_data (sec)->eisd; -- -- /* Align on a block. */ -- sw_64_vms_file_position_block (abfd); -- sec->filepos = PRIV (file_pos); -- -- if (eisd != NULL) -- eisd->u.eisd.vbn = (sec->filepos / VMS_BLOCK_SIZE) + 1; -- -- PRIV (file_pos) += sec->size; -- } -- -- /* Update EIHS. */ -- if (eihs != NULL && dst != NULL) -- { -- bfd_putl32 ((dst->filepos / VMS_BLOCK_SIZE) + 1, eihs->dstvbn); -- bfd_putl32 (dst->size, eihs->dstsize); -- -- if (dmt != NULL) -- { -- lnkflags |= EIHD__M_DBGDMT; -- bfd_putl32 ((dmt->filepos / VMS_BLOCK_SIZE) + 1, eihs->dmtvbn); -- bfd_putl32 (dmt->size, eihs->dmtsize); -- } -- if (PRIV (gsd_sym_count) != 0) -- { -- sw_64_vms_file_position_block (abfd); -- gst_filepos = PRIV (file_pos); -- bfd_putl32 ((gst_filepos / VMS_BLOCK_SIZE) + 1, eihs->gstvbn); -- bfd_putl32 ((PRIV (gsd_sym_count) + 4) / 5 + 4, eihs->gstsize); -- } -- } -- -- /* Write EISD in hdr. */ -- for (eisd = first_eisd; eisd && eisd->file_pos < VMS_BLOCK_SIZE; -- eisd = eisd->next) -- sw_64_vms_swap_eisd_out -- (eisd, (struct vms_eisd *)((char *)&eihd + eisd->file_pos)); -- -- /* Write first block. */ -- bfd_putl32 (lnkflags, eihd.lnkflags); -- if (bfd_bwrite (&eihd, sizeof (eihd), abfd) != sizeof (eihd)) -- return FALSE; -- -- /* Write remaining eisd. */ -- if (eisd != NULL) -- { -- unsigned char blk[VMS_BLOCK_SIZE]; -- struct vms_internal_eisd_map *next_eisd; -- -- memset (blk, 0xff, sizeof (blk)); -- while (eisd != NULL) -- { -- sw_64_vms_swap_eisd_out -- (eisd, -- (struct vms_eisd *)(blk + (eisd->file_pos % VMS_BLOCK_SIZE))); -- -- next_eisd = eisd->next; -- if (next_eisd == NULL -- || (next_eisd->file_pos / VMS_BLOCK_SIZE -- != eisd->file_pos / VMS_BLOCK_SIZE)) -- { -- if (bfd_bwrite (blk, sizeof (blk), abfd) != sizeof (blk)) -- return FALSE; -- -- memset (blk, 0xff, sizeof (blk)); -- } -- eisd = next_eisd; -- } -- } -- -- /* Write sections. */ -- for (sec = abfd->sections; sec; sec = sec->next) -- { -- unsigned char blk[VMS_BLOCK_SIZE]; -- bfd_size_type len; -- -- if (sec->size == 0 || !(sec->flags & SEC_HAS_CONTENTS)) -- continue; -- if (bfd_bwrite (sec->contents, sec->size, abfd) != sec->size) -- return FALSE; -- -- /* Pad. */ -- len = VMS_BLOCK_SIZE - sec->size % VMS_BLOCK_SIZE; -- if (len != VMS_BLOCK_SIZE) -- { -- memset (blk, 0, len); -- if (bfd_bwrite (blk, len, abfd) != len) -- return FALSE; -- } -- } -- -- /* Write GST. */ -- if (gst_filepos != 0) -- { -- struct vms_rec_wr *recwr = &PRIV (recwr); -- unsigned int i; -- -- _bfd_vms_write_emh (abfd); -- _bfd_vms_write_lmn (abfd, "GNU LD"); -- -- /* PSC for the absolute section. */ -- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -- _bfd_vms_output_long (recwr, 0); -- _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); -- _bfd_vms_output_short (recwr, 0); -- _bfd_vms_output_short (recwr, EGPS__V_PIC | EGPS__V_LIB | EGPS__V_RD); -- _bfd_vms_output_long (recwr, 0); -- _bfd_vms_output_counted (recwr, ".$$ABS$$."); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_end (abfd, recwr); -- -- for (i = 0; i < PRIV (gsd_sym_count); i++) -- { -- struct vms_symbol_entry *sym = PRIV (syms)[i]; -- bfd_vma val; -- bfd_vma ep; -- -- if ((i % 5) == 0) -- { -- _bfd_vms_output_alignment (recwr, 8); -- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -- _bfd_vms_output_long (recwr, 0); -- } -- _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYMG); -- _bfd_vms_output_short (recwr, 0); /* Data type, alignment. */ -- _bfd_vms_output_short (recwr, sym->flags); -- -- if (sym->code_section) -- ep = sw_64_vms_get_sym_value (sym->code_section, sym->code_value); -- else -- { -- BFD_ASSERT (sym->code_value == 0); -- ep = 0; -- } -- val = sw_64_vms_get_sym_value (sym->section, sym->value); -- _bfd_vms_output_quad -- (recwr, sym->typ == EGSD__C_SYMG ? sym->symbol_vector : val); -- _bfd_vms_output_quad (recwr, ep); -- _bfd_vms_output_quad (recwr, val); -- _bfd_vms_output_long (recwr, 0); -- _bfd_vms_output_counted (recwr, sym->name); -- _bfd_vms_output_end_subrec (recwr); -- if ((i % 5) == 4) -- _bfd_vms_output_end (abfd, recwr); -- } -- if ((i % 5) != 0) -- _bfd_vms_output_end (abfd, recwr); -- -- if (!_bfd_vms_write_eeom (abfd)) -- return FALSE; -- } -- return TRUE; --} -- --/* Object write. */ -- --/* Write section and symbol directory of bfd abfd. Return FALSE on error. */ -- --static bfd_boolean --_bfd_vms_write_egsd (bfd *abfd) --{ -- asection *section; -- asymbol *symbol; -- unsigned int symnum; -- const char *sname; -- flagword new_flags, old_flags; -- int abs_section_index = -1; -- unsigned int target_index = 0; -- struct vms_rec_wr *recwr = &PRIV (recwr); -- -- vms_debug2 ((2, "vms_write_egsd\n")); -- -- /* Egsd is quadword aligned. */ -- _bfd_vms_output_alignment (recwr, 8); -- -- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -- _bfd_vms_output_long (recwr, 0); -- -- /* Number sections. */ -- for (section = abfd->sections; section != NULL; section = section->next) -- { -- if (section->flags & SEC_DEBUGGING) -- continue; -- if (!strcmp (section->name, ".vmsdebug")) -- { -- section->flags |= SEC_DEBUGGING; -- continue; -- } -- section->target_index = target_index++; -- } -- -- for (section = abfd->sections; section != NULL; section = section->next) -- { -- vms_debug2 ((3, "Section #%d %s, %d bytes\n", -- section->target_index, section->name, (int)section->size)); -- -- /* Don't write out the VMS debug info section since it is in the -- ETBT and EDBG sections in etir. */ -- if (section->flags & SEC_DEBUGGING) -- continue; -- -- /* 13 bytes egsd, max 31 chars name -> should be 44 bytes. */ -- if (_bfd_vms_output_check (recwr, 64) < 0) -- { -- _bfd_vms_output_end (abfd, recwr); -- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -- _bfd_vms_output_long (recwr, 0); -- } -- -- /* Don't know if this is necessary for the linker but for now it keeps -- vms_slurp_gsd happy. */ -- sname = section->name; -- if (*sname == '.') -- { -- /* Remove leading dot. */ -- sname++; -- if ((*sname == 't') && (strcmp (sname, "text") == 0)) -- sname = EVAX_CODE_NAME; -- else if ((*sname == 'd') && (strcmp (sname, "data") == 0)) -- sname = EVAX_DATA_NAME; -- else if ((*sname == 'b') && (strcmp (sname, "bss") == 0)) -- sname = EVAX_BSS_NAME; -- else if ((*sname == 'l') && (strcmp (sname, "link") == 0)) -- sname = EVAX_LINK_NAME; -- else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0)) -- sname = EVAX_READONLY_NAME; -- else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) -- sname = EVAX_LITERAL_NAME; -- else if ((*sname == 'l') && (strcmp (sname, "literals") == 0)) -- sname = EVAX_LITERALS_NAME; -- else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) -- sname = EVAX_COMMON_NAME; -- else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) -- sname = EVAX_LOCAL_NAME; -- } -- -- if (bfd_is_com_section (section)) -- new_flags = (EGPS__V_OVR | EGPS__V_REL | EGPS__V_GBL | EGPS__V_RD -- | EGPS__V_WRT | EGPS__V_NOMOD | EGPS__V_COM); -- else -- new_flags = vms_esecflag_by_name (evax_section_flags, sname, -- section->size > 0); -- -- /* Modify them as directed. */ -- if (section->flags & SEC_READONLY) -- new_flags &= ~EGPS__V_WRT; -- -- new_flags &= ~vms_section_data (section)->no_flags; -- new_flags |= vms_section_data (section)->flags; -- -- vms_debug2 ((3, "sec flags %x\n", section->flags)); -- vms_debug2 ((3, "new_flags %x, _raw_size %lu\n", -- new_flags, (unsigned long)section->size)); -- -- _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); -- _bfd_vms_output_short (recwr, section->alignment_power & 0xff); -- _bfd_vms_output_short (recwr, new_flags); -- _bfd_vms_output_long (recwr, (unsigned long) section->size); -- _bfd_vms_output_counted (recwr, sname); -- _bfd_vms_output_end_subrec (recwr); -- -- /* If the section is an obsolute one, remind its index as it will be -- used later for absolute symbols. */ -- if ((new_flags & EGPS__V_REL) == 0 && abs_section_index < 0) -- abs_section_index = section->target_index; -- } -- -- /* Output symbols. */ -- vms_debug2 ((3, "%d symbols found\n", abfd->symcount)); -- -- bfd_set_start_address (abfd, (bfd_vma) -1); -- -- for (symnum = 0; symnum < abfd->symcount; symnum++) -- { -- symbol = abfd->outsymbols[symnum]; -- old_flags = symbol->flags; -- -- /* Work-around a missing feature: consider __main as the main entry -- point. */ -- if (symbol->name[0] == '_' && strcmp (symbol->name, "__main") == 0) -- bfd_set_start_address (abfd, (bfd_vma)symbol->value); -- -- /* Only put in the GSD the global and the undefined symbols. */ -- if (old_flags & BSF_FILE) -- continue; -- -- if ((old_flags & BSF_GLOBAL) == 0 && !bfd_is_und_section (symbol->section)) -- { -- /* If the LIB$INITIIALIZE section is present, add a reference to -- LIB$INITIALIZE symbol. FIXME: this should be done explicitely -- in the assembly file. */ -- if (!((old_flags & BSF_SECTION_SYM) != 0 -- && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0)) -- continue; -- } -- -- /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. Add 16 more -- bytes for a possible ABS section. */ -- if (_bfd_vms_output_check (recwr, 80 + 16) < 0) -- { -- _bfd_vms_output_end (abfd, recwr); -- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -- _bfd_vms_output_long (recwr, 0); -- } -- -- if ((old_flags & BSF_GLOBAL) != 0 -- && bfd_is_abs_section (symbol->section) -- && abs_section_index <= 0) -- { -- /* Create an absolute section if none was defined. It is highly -- unlikely that the name $ABS$ clashes with a user defined -- non-absolute section name. */ -- _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); -- _bfd_vms_output_short (recwr, 4); -- _bfd_vms_output_short (recwr, EGPS__V_SHR); -- _bfd_vms_output_long (recwr, 0); -- _bfd_vms_output_counted (recwr, "$ABS$"); -- _bfd_vms_output_end_subrec (recwr); -- -- abs_section_index = target_index++; -- } -- -- _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYM); -- -- /* Data type, alignment. */ -- _bfd_vms_output_short (recwr, 0); -- -- new_flags = 0; -- -- if (old_flags & BSF_WEAK) -- new_flags |= EGSY__V_WEAK; -- if (bfd_is_com_section (symbol->section)) /* .comm */ -- new_flags |= (EGSY__V_WEAK | EGSY__V_COMM); -- -- if (old_flags & BSF_FUNCTION) -- { -- new_flags |= EGSY__V_NORM; -- new_flags |= EGSY__V_REL; -- } -- if (old_flags & BSF_GLOBAL) -- { -- new_flags |= EGSY__V_DEF; -- if (!bfd_is_abs_section (symbol->section)) -- new_flags |= EGSY__V_REL; -- } -- _bfd_vms_output_short (recwr, new_flags); -- -- if (old_flags & BSF_GLOBAL) -- { -- /* Symbol definition. */ -- bfd_vma code_address = 0; -- unsigned long ca_psindx = 0; -- unsigned long psindx; -- -- if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL) -- { -- asymbol *sym; -- -- sym = -- ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym; -- code_address = sym->value; -- ca_psindx = sym->section->target_index; -- } -- if (bfd_is_abs_section (symbol->section)) -- psindx = abs_section_index; -- else -- psindx = symbol->section->target_index; -- -- _bfd_vms_output_quad (recwr, symbol->value); -- _bfd_vms_output_quad (recwr, code_address); -- _bfd_vms_output_long (recwr, ca_psindx); -- _bfd_vms_output_long (recwr, psindx); -- } -- _bfd_vms_output_counted (recwr, symbol->name); -- -- _bfd_vms_output_end_subrec (recwr); -- } -- -- _bfd_vms_output_alignment (recwr, 8); -- _bfd_vms_output_end (abfd, recwr); -- -- return TRUE; --} -- --/* Write object header for bfd abfd. Return FALSE on error. */ -- --static bfd_boolean --_bfd_vms_write_ehdr (bfd *abfd) --{ -- asymbol *symbol; -- unsigned int symnum; -- struct vms_rec_wr *recwr = &PRIV (recwr); -- -- vms_debug2 ((2, "vms_write_ehdr (%p)\n", abfd)); -- -- _bfd_vms_output_alignment (recwr, 2); -- -- _bfd_vms_write_emh (abfd); -- _bfd_vms_write_lmn (abfd, "GNU AS"); -- -- /* SRC. */ -- _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -- _bfd_vms_output_short (recwr, EMH__C_SRC); -- -- for (symnum = 0; symnum < abfd->symcount; symnum++) -- { -- symbol = abfd->outsymbols[symnum]; -- -- if (symbol->flags & BSF_FILE) -- { -- _bfd_vms_output_dump (recwr, (unsigned char *) symbol->name, -- (int) strlen (symbol->name)); -- break; -- } -- } -- -- if (symnum == abfd->symcount) -- _bfd_vms_output_dump (recwr, (unsigned char *) STRING_COMMA_LEN ("noname")); -- -- _bfd_vms_output_end (abfd, recwr); -- -- /* TTL. */ -- _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -- _bfd_vms_output_short (recwr, EMH__C_TTL); -- _bfd_vms_output_dump (recwr, (unsigned char *) STRING_COMMA_LEN ("TTL")); -- _bfd_vms_output_end (abfd, recwr); -- -- /* CPR. */ -- _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -- _bfd_vms_output_short (recwr, EMH__C_CPR); -- _bfd_vms_output_dump (recwr, -- (unsigned char *)"GNU BFD ported by Klaus Kämpf 1994-1996", -- 39); -- _bfd_vms_output_end (abfd, recwr); -- -- return TRUE; --} -- --/* Part 4.6, relocations. */ -- -- --/* WRITE ETIR SECTION -- -- This is still under construction and therefore not documented. */ -- --/* Close the etir/etbt record. */ -- --static void --end_etir_record (bfd * abfd) --{ -- struct vms_rec_wr *recwr = &PRIV (recwr); -- -- _bfd_vms_output_end (abfd, recwr); --} -- --static void --start_etir_or_etbt_record (bfd *abfd, asection *section, bfd_vma offset) --{ -- struct vms_rec_wr *recwr = &PRIV (recwr); -- -- if (section->flags & SEC_DEBUGGING) -- { -- _bfd_vms_output_begin (recwr, EOBJ__C_ETBT); -- -- if (offset == 0) -- { -- /* Push start offset. */ -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW); -- _bfd_vms_output_long (recwr, (unsigned long) 0); -- _bfd_vms_output_end_subrec (recwr); -- -- /* Set location. */ -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_CTL_DFLOC); -- _bfd_vms_output_end_subrec (recwr); -- } -- } -- else -- { -- _bfd_vms_output_begin (recwr, EOBJ__C_ETIR); -- -- if (offset == 0) -- { -- /* Push start offset. */ -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ); -- _bfd_vms_output_long (recwr, (unsigned long) section->target_index); -- _bfd_vms_output_quad (recwr, offset); -- _bfd_vms_output_end_subrec (recwr); -- -- /* Start = pop (). */ -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_CTL_SETRB); -- _bfd_vms_output_end_subrec (recwr); -- } -- } --} -- --/* Output a STO_IMM command for SSIZE bytes of data from CPR at virtual -- address VADDR in section specified by SEC_INDEX and NAME. */ -- --static void --sto_imm (bfd *abfd, asection *section, -- bfd_size_type ssize, unsigned char *cptr, bfd_vma vaddr) --{ -- bfd_size_type size; -- struct vms_rec_wr *recwr = &PRIV (recwr); -- --#if VMS_DEBUG -- _bfd_vms_debug (8, "sto_imm %d bytes\n", (int) ssize); -- _bfd_hexdump (9, cptr, (int) ssize, (int) vaddr); --#endif -- -- while (ssize > 0) -- { -- /* Try all the rest. */ -- size = ssize; -- -- if (_bfd_vms_output_check (recwr, size) < 0) -- { -- /* Doesn't fit, split ! */ -- end_etir_record (abfd); -- -- start_etir_or_etbt_record (abfd, section, vaddr); -- -- size = _bfd_vms_output_check (recwr, 0); /* get max size */ -- if (size > ssize) /* more than what's left ? */ -- size = ssize; -- } -- -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_IMM); -- _bfd_vms_output_long (recwr, (unsigned long) (size)); -- _bfd_vms_output_dump (recwr, cptr, size); -- _bfd_vms_output_end_subrec (recwr); -- --#if VMS_DEBUG -- _bfd_vms_debug (10, "dumped %d bytes\n", (int) size); -- _bfd_hexdump (10, cptr, (int) size, (int) vaddr); --#endif -- -- vaddr += size; -- cptr += size; -- ssize -= size; -- } --} -- --static void --etir_output_check (bfd *abfd, asection *section, bfd_vma vaddr, int checklen) --{ -- if (_bfd_vms_output_check (&PRIV (recwr), checklen) < 0) -- { -- /* Not enough room in this record. Close it and open a new one. */ -- end_etir_record (abfd); -- start_etir_or_etbt_record (abfd, section, vaddr); -- } --} -- --/* Return whether RELOC must be deferred till the end. */ -- --static bfd_boolean --defer_reloc_p (arelent *reloc) --{ -- switch (reloc->howto->type) -- { -- case SW_64_R_NOP: -- case SW_64_R_LDA: -- case SW_64_R_BSR: -- case SW_64_R_BOH: -- return TRUE; -- -- default: -- return FALSE; -- } --} -- --/* Write section contents for bfd abfd. Return FALSE on error. */ -- --static bfd_boolean --_bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) --{ -- asection *section; -- struct vms_rec_wr *recwr = &PRIV (recwr); -- -- vms_debug2 ((2, "vms_write_tir (%p, %d)\n", abfd, objtype)); -- -- _bfd_vms_output_alignment (recwr, 4); -- -- PRIV (vms_linkage_index) = 0; -- -- for (section = abfd->sections; section; section = section->next) -- { -- vms_debug2 ((4, "writing %d. section '%s' (%d bytes)\n", -- section->target_index, section->name, (int) (section->size))); -- -- if (!(section->flags & SEC_HAS_CONTENTS) -- || bfd_is_com_section (section)) -- continue; -- -- if (!section->contents) -- { -- bfd_set_error (bfd_error_no_contents); -- return FALSE; -- } -- -- start_etir_or_etbt_record (abfd, section, 0); -- -- if (section->flags & SEC_RELOC) -- { -- bfd_vma curr_addr = 0; -- unsigned char *curr_data = section->contents; -- bfd_size_type size; -- int pass2_needed = 0; -- int pass2_in_progress = 0; -- unsigned int irel; -- -- if (section->reloc_count == 0) -- _bfd_error_handler -- (_("SEC_RELOC with no relocs in section %pA"), section); -- --#if VMS_DEBUG -- else -- { -- int i = section->reloc_count; -- arelent **rptr = section->orelocation; -- _bfd_vms_debug (4, "%d relocations:\n", i); -- while (i-- > 0) -- { -- _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, " -- "addr %08lx, off %08lx, len %d: %s\n", -- (*(*rptr)->sym_ptr_ptr)->name, -- (*(*rptr)->sym_ptr_ptr)->section->name, -- (long) (*(*rptr)->sym_ptr_ptr)->value, -- (unsigned long)(*rptr)->address, -- (unsigned long)(*rptr)->addend, -- bfd_get_reloc_size ((*rptr)->howto), -- ( *rptr)->howto->name); -- rptr++; -- } -- } --#endif -- -- new_pass: -- for (irel = 0; irel < section->reloc_count; irel++) -- { -- struct evax_private_udata_struct *udata; -- arelent *rptr = section->orelocation [irel]; -- bfd_vma addr = rptr->address; -- asymbol *sym = *rptr->sym_ptr_ptr; -- asection *sec = sym->section; -- bfd_boolean defer = defer_reloc_p (rptr); -- unsigned int slen; -- -- if (pass2_in_progress) -- { -- /* Non-deferred relocs have already been output. */ -- if (!defer) -- continue; -- } -- else -- { -- /* Deferred relocs must be output at the very end. */ -- if (defer) -- { -- pass2_needed = 1; -- continue; -- } -- -- /* Regular relocs are intertwined with binary data. */ -- if (curr_addr > addr) -- _bfd_error_handler (_("size error in section %pA"), -- section); -- size = addr - curr_addr; -- sto_imm (abfd, section, size, curr_data, curr_addr); -- curr_data += size; -- curr_addr += size; -- } -- -- size = bfd_get_reloc_size (rptr->howto); -- -- switch (rptr->howto->type) -- { -- case SW_64_R_IGNORE: -- break; -- -- case SW_64_R_REFLONG: -- if (bfd_is_und_section (sym->section)) -- { -- bfd_vma addend = rptr->addend; -- slen = strlen ((char *) sym->name); -- etir_output_check (abfd, section, curr_addr, slen); -- if (addend) -- { -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL); -- _bfd_vms_output_counted (recwr, sym->name); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW); -- _bfd_vms_output_long (recwr, (unsigned long) addend); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_OPR_ADD); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW); -- _bfd_vms_output_end_subrec (recwr); -- } -- else -- { -- _bfd_vms_output_begin_subrec -- (recwr, ETIR__C_STO_GBL_LW); -- _bfd_vms_output_counted (recwr, sym->name); -- _bfd_vms_output_end_subrec (recwr); -- } -- } -- else if (bfd_is_abs_section (sym->section)) -- { -- etir_output_check (abfd, section, curr_addr, 16); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW); -- _bfd_vms_output_long (recwr, (unsigned long) sym->value); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW); -- _bfd_vms_output_end_subrec (recwr); -- } -- else -- { -- etir_output_check (abfd, section, curr_addr, 32); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ); -- _bfd_vms_output_long (recwr, -- (unsigned long) sec->target_index); -- _bfd_vms_output_quad (recwr, rptr->addend + sym->value); -- _bfd_vms_output_end_subrec (recwr); -- /* ??? Table B-8 of the OpenVMS Linker Utilily Manual -- says that we should have a ETIR__C_STO_OFF here. -- But the relocation would not be BFD_RELOC_32 then. -- This case is very likely unreachable. */ -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW); -- _bfd_vms_output_end_subrec (recwr); -- } -- break; -- -- case SW_64_R_REFQUAD: -- if (bfd_is_und_section (sym->section)) -- { -- bfd_vma addend = rptr->addend; -- slen = strlen ((char *) sym->name); -- etir_output_check (abfd, section, curr_addr, slen); -- if (addend) -- { -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL); -- _bfd_vms_output_counted (recwr, sym->name); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW); -- _bfd_vms_output_quad (recwr, addend); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_OPR_ADD); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_QW); -- _bfd_vms_output_end_subrec (recwr); -- } -- else -- { -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_GBL); -- _bfd_vms_output_counted (recwr, sym->name); -- _bfd_vms_output_end_subrec (recwr); -- } -- } -- else if (bfd_is_abs_section (sym->section)) -- { -- etir_output_check (abfd, section, curr_addr, 16); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW); -- _bfd_vms_output_quad (recwr, sym->value); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_QW); -- _bfd_vms_output_end_subrec (recwr); -- } -- else -- { -- etir_output_check (abfd, section, curr_addr, 32); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ); -- _bfd_vms_output_long (recwr, -- (unsigned long) sec->target_index); -- _bfd_vms_output_quad (recwr, rptr->addend + sym->value); -- _bfd_vms_output_end_subrec (recwr); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_OFF); -- _bfd_vms_output_end_subrec (recwr); -- } -- break; -- -- case SW_64_R_HINT: -- sto_imm (abfd, section, size, curr_data, curr_addr); -- break; -- -- case SW_64_R_LINKAGE: -- size = 16; -- etir_output_check (abfd, section, curr_addr, 64); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_LP_PSB); -- _bfd_vms_output_long -- (recwr, (unsigned long) rptr->addend); -- if (rptr->addend > PRIV (vms_linkage_index)) -- PRIV (vms_linkage_index) = rptr->addend; -- _bfd_vms_output_counted (recwr, sym->name); -- _bfd_vms_output_byte (recwr, 0); -- _bfd_vms_output_end_subrec (recwr); -- break; -- -- case SW_64_R_CODEADDR: -- slen = strlen ((char *) sym->name); -- etir_output_check (abfd, section, curr_addr, slen); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_CA); -- _bfd_vms_output_counted (recwr, sym->name); -- _bfd_vms_output_end_subrec (recwr); -- break; -- -- case SW_64_R_NOP: -- udata -- = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr; -- etir_output_check (abfd, section, curr_addr, -- 32 + 1 + strlen (udata->origname)); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_NOP_GBL); -- _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex); -- _bfd_vms_output_long -- (recwr, (unsigned long) section->target_index); -- _bfd_vms_output_quad (recwr, rptr->address); -- _bfd_vms_output_long (recwr, (unsigned long) 0x47ff041f); -- _bfd_vms_output_long -- (recwr, (unsigned long) section->target_index); -- _bfd_vms_output_quad (recwr, rptr->addend); -- _bfd_vms_output_counted (recwr, udata->origname); -- _bfd_vms_output_end_subrec (recwr); -- break; -- -- case SW_64_R_BSR: -- _bfd_error_handler (_("spurious SW_64_R_BSR reloc")); -- break; -- -- case SW_64_R_LDA: -- udata -- = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr; -- etir_output_check (abfd, section, curr_addr, -- 32 + 1 + strlen (udata->origname)); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_LDA_GBL); -- _bfd_vms_output_long -- (recwr, (unsigned long) udata->lkindex + 1); -- _bfd_vms_output_long -- (recwr, (unsigned long) section->target_index); -- _bfd_vms_output_quad (recwr, rptr->address); -- _bfd_vms_output_long (recwr, (unsigned long) 0x237B0000); -- _bfd_vms_output_long -- (recwr, (unsigned long) udata->bsym->section->target_index); -- _bfd_vms_output_quad (recwr, rptr->addend); -- _bfd_vms_output_counted (recwr, udata->origname); -- _bfd_vms_output_end_subrec (recwr); -- break; -- -- case SW_64_R_BOH: -- udata -- = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr; -- etir_output_check (abfd, section, curr_addr, -- 32 + 1 + strlen (udata->origname)); -- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_BOH_GBL); -- _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex); -- _bfd_vms_output_long -- (recwr, (unsigned long) section->target_index); -- _bfd_vms_output_quad (recwr, rptr->address); -- _bfd_vms_output_long (recwr, (unsigned long) 0xD3400000); -- _bfd_vms_output_long -- (recwr, (unsigned long) section->target_index); -- _bfd_vms_output_quad (recwr, rptr->addend); -- _bfd_vms_output_counted (recwr, udata->origname); -- _bfd_vms_output_end_subrec (recwr); -- break; -- -- default: -- _bfd_error_handler (_("unhandled relocation %s"), -- rptr->howto->name); -- break; -- } -- -- curr_data += size; -- curr_addr += size; -- } /* End of relocs loop. */ -- -- if (!pass2_in_progress) -- { -- /* Output rest of section. */ -- if (curr_addr > section->size) -- { -- _bfd_error_handler (_("size error in section %pA"), section); -- return FALSE; -- } -- size = section->size - curr_addr; -- sto_imm (abfd, section, size, curr_data, curr_addr); -- curr_data += size; -- curr_addr += size; -- -- if (pass2_needed) -- { -- pass2_in_progress = 1; -- goto new_pass; -- } -- } -- } -- -- else /* (section->flags & SEC_RELOC) */ -- sto_imm (abfd, section, section->size, section->contents, 0); -- -- end_etir_record (abfd); -- } -- -- _bfd_vms_output_alignment (recwr, 2); -- return TRUE; --} -- --/* Write cached information into a file being written, at bfd_close. */ -- --static bfd_boolean --sw_64_vms_write_object_contents (bfd *abfd) --{ -- vms_debug2 ((1, "vms_write_object_contents (%p)\n", abfd)); -- -- if (abfd->flags & (EXEC_P | DYNAMIC)) -- { -- return sw_64_vms_write_exec (abfd); -- } -- else -- { -- if (abfd->section_count > 0) /* we have sections */ -- { -- if (!_bfd_vms_write_ehdr (abfd)) -- return FALSE; -- if (!_bfd_vms_write_egsd (abfd)) -- return FALSE; -- if (!_bfd_vms_write_etir (abfd, EOBJ__C_ETIR)) -- return FALSE; -- if (!_bfd_vms_write_eeom (abfd)) -- return FALSE; -- } -- } -- return TRUE; --} -- --/* Debug stuff: nearest line. */ -- --#define SET_MODULE_PARSED(m) \ -- do { if ((m)->name == NULL) (m)->name = ""; } while (0) --#define IS_MODULE_PARSED(m) ((m)->name != NULL) -- --/* Build a new module for the specified BFD. */ -- --static struct module * --new_module (bfd *abfd) --{ -- struct module *module -- = (struct module *) bfd_zalloc (abfd, sizeof (struct module)); -- module->file_table_count = 16; /* Arbitrary. */ -- module->file_table -- = bfd_malloc (module->file_table_count * sizeof (struct fileinfo)); -- return module; --} -- --/* Parse debug info for a module and internalize it. */ -- --static void --parse_module (bfd *abfd, struct module *module, unsigned char *ptr, -- int length) --{ -- unsigned char *maxptr = ptr + length; -- unsigned char *src_ptr, *pcl_ptr; -- unsigned int prev_linum = 0, curr_linenum = 0; -- bfd_vma prev_pc = 0, curr_pc = 0; -- struct srecinfo *curr_srec, *srec; -- struct lineinfo *curr_line, *line; -- struct funcinfo *funcinfo; -- -- /* Initialize tables with zero element. */ -- curr_srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo)); -- module->srec_table = curr_srec; -- -- curr_line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo)); -- module->line_table = curr_line; -- -- while (length == -1 || ptr < maxptr) -- { -- /* The first byte is not counted in the recorded length. */ -- int rec_length = bfd_getl16 (ptr) + 1; -- int rec_type = bfd_getl16 (ptr + 2); -- -- vms_debug2 ((2, "DST record: leng %d, type %d\n", rec_length, rec_type)); -- -- if (length == -1 && rec_type == DST__K_MODEND) -- break; -- -- switch (rec_type) -- { -- case DST__K_MODBEG: -- module->name -- = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_MODBEG_NAME, -- maxptr - (ptr + DST_S_B_MODBEG_NAME)); -- -- curr_pc = 0; -- prev_pc = 0; -- curr_linenum = 0; -- prev_linum = 0; -- -- vms_debug2 ((3, "module: %s\n", module->name)); -- break; -- -- case DST__K_MODEND: -- break; -- -- case DST__K_RTNBEG: -- funcinfo = (struct funcinfo *) -- bfd_zalloc (abfd, sizeof (struct funcinfo)); -- funcinfo->name -- = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_RTNBEG_NAME, -- maxptr - (ptr + DST_S_B_RTNBEG_NAME)); -- funcinfo->low = bfd_getl32 (ptr + DST_S_L_RTNBEG_ADDRESS); -- funcinfo->next = module->func_table; -- module->func_table = funcinfo; -- -- vms_debug2 ((3, "routine: %s at 0x%lx\n", -- funcinfo->name, (unsigned long) funcinfo->low)); -- break; -- -- case DST__K_RTNEND: -- module->func_table->high = module->func_table->low -- + bfd_getl32 (ptr + DST_S_L_RTNEND_SIZE) - 1; -- -- if (module->func_table->high > module->high) -- module->high = module->func_table->high; -- -- vms_debug2 ((3, "end routine\n")); -- break; -- -- case DST__K_PROLOG: -- vms_debug2 ((3, "prologue\n")); -- break; -- -- case DST__K_EPILOG: -- vms_debug2 ((3, "epilog\n")); -- break; -- -- case DST__K_BLKBEG: -- vms_debug2 ((3, "block\n")); -- break; -- -- case DST__K_BLKEND: -- vms_debug2 ((3, "end block\n")); -- break; -- -- case DST__K_SOURCE: -- src_ptr = ptr + DST_S_C_SOURCE_HEADER_SIZE; -- -- vms_debug2 ((3, "source info\n")); -- -- while (src_ptr < ptr + rec_length) -- { -- int cmd = src_ptr[0], cmd_length, data; -- -- switch (cmd) -- { -- case DST__K_SRC_DECLFILE: -- { -- unsigned int fileid -- = bfd_getl16 (src_ptr + DST_S_W_SRC_DF_FILEID); -- char *filename = _bfd_vms_save_counted_string -- (abfd, -- src_ptr + DST_S_B_SRC_DF_FILENAME, -- ptr + rec_length - (src_ptr + DST_S_B_SRC_DF_FILENAME)); -- -- while (fileid >= module->file_table_count) -- { -- module->file_table_count *= 2; -- module->file_table -- = bfd_realloc (module->file_table, -- module->file_table_count -- * sizeof (struct fileinfo)); -- } -- -- module->file_table [fileid].name = filename; -- module->file_table [fileid].srec = 1; -- cmd_length = src_ptr[DST_S_B_SRC_DF_LENGTH] + 2; -- vms_debug2 ((4, "DST_S_C_SRC_DECLFILE: %d, %s\n", -- fileid, module->file_table [fileid].name)); -- } -- break; -- -- case DST__K_SRC_DEFLINES_B: -- /* Perform the association and set the next higher index -- to the limit. */ -- data = src_ptr[DST_S_B_SRC_UNSBYTE]; -- srec = (struct srecinfo *) -- bfd_zalloc (abfd, sizeof (struct srecinfo)); -- srec->line = curr_srec->line + data; -- srec->srec = curr_srec->srec + data; -- srec->sfile = curr_srec->sfile; -- curr_srec->next = srec; -- curr_srec = srec; -- cmd_length = 2; -- vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_B: %d\n", data)); -- break; -- -- case DST__K_SRC_DEFLINES_W: -- /* Perform the association and set the next higher index -- to the limit. */ -- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); -- srec = (struct srecinfo *) -- bfd_zalloc (abfd, sizeof (struct srecinfo)); -- srec->line = curr_srec->line + data; -- srec->srec = curr_srec->srec + data, -- srec->sfile = curr_srec->sfile; -- curr_srec->next = srec; -- curr_srec = srec; -- cmd_length = 3; -- vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_W: %d\n", data)); -- break; -- -- case DST__K_SRC_INCRLNUM_B: -- data = src_ptr[DST_S_B_SRC_UNSBYTE]; -- curr_srec->line += data; -- cmd_length = 2; -- vms_debug2 ((4, "DST_S_C_SRC_INCRLNUM_B: %d\n", data)); -- break; -- -- case DST__K_SRC_SETFILE: -- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); -- curr_srec->sfile = data; -- curr_srec->srec = module->file_table[data].srec; -- cmd_length = 3; -- vms_debug2 ((4, "DST_S_C_SRC_SETFILE: %d\n", data)); -- break; -- -- case DST__K_SRC_SETLNUM_L: -- data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG); -- curr_srec->line = data; -- cmd_length = 5; -- vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_L: %d\n", data)); -- break; -- -- case DST__K_SRC_SETLNUM_W: -- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); -- curr_srec->line = data; -- cmd_length = 3; -- vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_W: %d\n", data)); -- break; -- -- case DST__K_SRC_SETREC_L: -- data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG); -- curr_srec->srec = data; -- module->file_table[curr_srec->sfile].srec = data; -- cmd_length = 5; -- vms_debug2 ((4, "DST_S_C_SRC_SETREC_L: %d\n", data)); -- break; -- -- case DST__K_SRC_SETREC_W: -- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); -- curr_srec->srec = data; -- module->file_table[curr_srec->sfile].srec = data; -- cmd_length = 3; -- vms_debug2 ((4, "DST_S_C_SRC_SETREC_W: %d\n", data)); -- break; -- -- case DST__K_SRC_FORMFEED: -- cmd_length = 1; -- vms_debug2 ((4, "DST_S_C_SRC_FORMFEED\n")); -- break; -- -- default: -- _bfd_error_handler (_("unknown source command %d"), -- cmd); -- cmd_length = 2; -- break; -- } -- -- src_ptr += cmd_length; -- } -- break; -- -- case DST__K_LINE_NUM: -- pcl_ptr = ptr + DST_S_C_LINE_NUM_HEADER_SIZE; -- -- vms_debug2 ((3, "line info\n")); -- -- while (pcl_ptr < ptr + rec_length) -- { -- /* The command byte is signed so we must sign-extend it. */ -- int cmd = ((signed char *)pcl_ptr)[0], cmd_length, data; -- -- switch (cmd) -- { -- case DST__K_DELTA_PC_W: -- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); -- curr_pc += data; -- curr_linenum += 1; -- cmd_length = 3; -- vms_debug2 ((4, "DST__K_DELTA_PC_W: %d\n", data)); -- break; -- -- case DST__K_DELTA_PC_L: -- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -- curr_pc += data; -- curr_linenum += 1; -- cmd_length = 5; -- vms_debug2 ((4, "DST__K_DELTA_PC_L: %d\n", data)); -- break; -- -- case DST__K_INCR_LINUM: -- data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; -- curr_linenum += data; -- cmd_length = 2; -- vms_debug2 ((4, "DST__K_INCR_LINUM: %d\n", data)); -- break; -- -- case DST__K_INCR_LINUM_W: -- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); -- curr_linenum += data; -- cmd_length = 3; -- vms_debug2 ((4, "DST__K_INCR_LINUM_W: %d\n", data)); -- break; -- -- case DST__K_INCR_LINUM_L: -- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -- curr_linenum += data; -- cmd_length = 5; -- vms_debug2 ((4, "DST__K_INCR_LINUM_L: %d\n", data)); -- break; -- -- case DST__K_SET_LINUM_INCR: -- _bfd_error_handler -- (_("%s not implemented"), "DST__K_SET_LINUM_INCR"); -- cmd_length = 2; -- break; -- -- case DST__K_SET_LINUM_INCR_W: -- _bfd_error_handler -- (_("%s not implemented"), "DST__K_SET_LINUM_INCR_W"); -- cmd_length = 3; -- break; -- -- case DST__K_RESET_LINUM_INCR: -- _bfd_error_handler -- (_("%s not implemented"), "DST__K_RESET_LINUM_INCR"); -- cmd_length = 1; -- break; -- -- case DST__K_BEG_STMT_MODE: -- _bfd_error_handler -- (_("%s not implemented"), "DST__K_BEG_STMT_MODE"); -- cmd_length = 1; -- break; -- -- case DST__K_END_STMT_MODE: -- _bfd_error_handler -- (_("%s not implemented"), "DST__K_END_STMT_MODE"); -- cmd_length = 1; -- break; -- -- case DST__K_SET_LINUM_B: -- data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; -- curr_linenum = data; -- cmd_length = 2; -- vms_debug2 ((4, "DST__K_SET_LINUM_B: %d\n", data)); -- break; -- -- case DST__K_SET_LINUM: -- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); -- curr_linenum = data; -- cmd_length = 3; -- vms_debug2 ((4, "DST__K_SET_LINE_NUM: %d\n", data)); -- break; -- -- case DST__K_SET_LINUM_L: -- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -- curr_linenum = data; -- cmd_length = 5; -- vms_debug2 ((4, "DST__K_SET_LINUM_L: %d\n", data)); -- break; -- -- case DST__K_SET_PC: -- _bfd_error_handler -- (_("%s not implemented"), "DST__K_SET_PC"); -- cmd_length = 2; -- break; -- -- case DST__K_SET_PC_W: -- _bfd_error_handler -- (_("%s not implemented"), "DST__K_SET_PC_W"); -- cmd_length = 3; -- break; -- -- case DST__K_SET_PC_L: -- _bfd_error_handler -- (_("%s not implemented"), "DST__K_SET_PC_L"); -- cmd_length = 5; -- break; -- -- case DST__K_SET_STMTNUM: -- _bfd_error_handler -- (_("%s not implemented"), "DST__K_SET_STMTNUM"); -- cmd_length = 2; -- break; -- -- case DST__K_TERM: -- data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; -- curr_pc += data; -- cmd_length = 2; -- vms_debug2 ((4, "DST__K_TERM: %d\n", data)); -- break; -- -- case DST__K_TERM_W: -- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); -- curr_pc += data; -- cmd_length = 3; -- vms_debug2 ((4, "DST__K_TERM_W: %d\n", data)); -- break; -- -- case DST__K_TERM_L: -- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -- curr_pc += data; -- cmd_length = 5; -- vms_debug2 ((4, "DST__K_TERM_L: %d\n", data)); -- break; -- -- case DST__K_SET_ABS_PC: -- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -- curr_pc = data; -- cmd_length = 5; -- vms_debug2 ((4, "DST__K_SET_ABS_PC: 0x%x\n", data)); -- break; -- -- default: -- if (cmd <= 0) -- { -- curr_pc -= cmd; -- curr_linenum += 1; -- cmd_length = 1; -- vms_debug2 ((4, "bump pc to 0x%lx and line to %d\n", -- (unsigned long)curr_pc, curr_linenum)); -- } -- else -- { -- _bfd_error_handler (_("unknown line command %d"), cmd); -- cmd_length = 2; -- } -- break; -- } -- -- if ((curr_linenum != prev_linum && curr_pc != prev_pc) -- || cmd <= 0 -- || cmd == DST__K_DELTA_PC_L -- || cmd == DST__K_DELTA_PC_W) -- { -- line = (struct lineinfo *) -- bfd_zalloc (abfd, sizeof (struct lineinfo)); -- line->address = curr_pc; -- line->line = curr_linenum; -- -- curr_line->next = line; -- curr_line = line; -- -- prev_linum = curr_linenum; -- prev_pc = curr_pc; -- vms_debug2 ((4, "-> correlate pc 0x%lx with line %d\n", -- (unsigned long)curr_pc, curr_linenum)); -- } -- -- pcl_ptr += cmd_length; -- } -- break; -- -- case 0x17: /* Undocumented type used by DEC C to declare equates. */ -- vms_debug2 ((3, "undocumented type 0x17\n")); -- break; -- -- default: -- vms_debug2 ((3, "ignoring record\n")); -- break; -- -- } -- -- ptr += rec_length; -- } -- -- /* Finalize tables with EOL marker. */ -- srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo)); -- srec->line = (unsigned int) -1; -- srec->srec = (unsigned int) -1; -- curr_srec->next = srec; -- -- line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo)); -- line->line = (unsigned int) -1; -- line->address = (bfd_vma) -1; -- curr_line->next = line; -- -- /* Advertise that this module has been parsed. This is needed -- because parsing can be either performed at module creation -- or deferred until debug info is consumed. */ -- SET_MODULE_PARSED (module); --} -- --/* Build the list of modules for the specified BFD. */ -- --static struct module * --build_module_list (bfd *abfd) --{ -- struct module *module, *list = NULL; -- asection *dmt; -- -- if ((dmt = bfd_get_section_by_name (abfd, "$DMT$"))) -- { -- /* We have a DMT section so this must be an image. Parse the -- section and build the list of modules. This is sufficient -- since we can compute the start address and the end address -- of every module from the section contents. */ -- bfd_size_type size = bfd_section_size (dmt); -- //unsigned char *ptr, *end; -- unsigned char *buf, *ptr, *end; -- -- //ptr = (unsigned char *) bfd_alloc (abfd, size); -- //if (! ptr) -- // return NULL; -- -- //if (! bfd_get_section_contents (abfd, dmt, ptr, 0, size)) -- if (! bfd_malloc_and_get_section (abfd, dmt, &buf)) -- return NULL; -- -- vms_debug2 ((2, "DMT\n")); -- -- ptr = buf; -- end = ptr + size; -- -- while (end - ptr >= DBG_S_C_DMT_HEADER_SIZE) -- //while (ptr < end) -- { -- /* Each header declares a module with its start offset and size -- of debug info in the DST section, as well as the count of -- program sections (i.e. address spans) it contains. */ -- unsigned int modbeg = bfd_getl32 (ptr + DBG_S_L_DMT_MODBEG); -- unsigned int msize = bfd_getl32 (ptr + DBG_S_L_DST_SIZE); -- //int modbeg = bfd_getl32 (ptr + DBG_S_L_DMT_MODBEG); -- //int msize = bfd_getl32 (ptr + DBG_S_L_DST_SIZE); -- int count = bfd_getl16 (ptr + DBG_S_W_DMT_PSECT_COUNT); -- ptr += DBG_S_C_DMT_HEADER_SIZE; -- -- vms_debug2 ((3, "module: modbeg = %u, size = %u, count = %d\n", -- modbeg, msize, count)); -- //vms_debug2 ((3, "module: modbeg = %d, size = %d, count = %d\n", -- // modbeg, msize, count)); -- -- /* We create a 'module' structure for each program section since -- we only support contiguous addresses in a 'module' structure. -- As a consequence, the actual debug info in the DST section is -- shared and can be parsed multiple times; that doesn't seem to -- cause problems in practice. */ -- while (count-- > 0 && end - ptr >= DBG_S_C_DMT_PSECT_SIZE) -- //while (count-- > 0) -- { -- unsigned int start = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_START); -- unsigned int length = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_LENGTH); -- //int start = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_START); -- //int length = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_LENGTH); -- module = new_module (abfd); -- module->modbeg = modbeg; -- module->size = msize; -- module->low = start; -- module->high = start + length; -- module->next = list; -- list = module; -- ptr += DBG_S_C_DMT_PSECT_SIZE; -- -- vms_debug2 ((4, "section: start = 0x%x, length = %u\n", -- start, length)); -- //vms_debug2 ((4, "section: start = 0x%x, length = %d\n", -- // start, length)); -- } -- } -- free (buf); -- } -- else -- { -- /* We don't have a DMT section so this must be an object. Parse -- the module right now in order to compute its start address and -- end address. */ -- void *dst = PRIV (dst_section)->contents; -- -- if (dst == NULL) -- return NULL; -- -- module = new_module (abfd); -- parse_module (abfd, module, PRIV (dst_section)->contents, -1); -- list = module; -- } -- -- return list; --} -- --/* Calculate and return the name of the source file and the line nearest -- to the wanted location in the specified module. */ -- --static bfd_boolean --module_find_nearest_line (bfd *abfd, struct module *module, bfd_vma addr, -- const char **file, const char **func, -- unsigned int *line) --{ -- struct funcinfo *funcinfo; -- struct lineinfo *lineinfo; -- struct srecinfo *srecinfo; -- bfd_boolean ret = FALSE; -- -- /* Parse this module if that was not done at module creation. */ -- if (! IS_MODULE_PARSED (module)) -- { -- unsigned int size = module->size; -- unsigned int modbeg = PRIV (dst_section)->filepos + module->modbeg; -- unsigned char *buffer = (unsigned char *) bfd_malloc (module->size); -- -- if (bfd_seek (abfd, modbeg, SEEK_SET) != 0 -- || bfd_bread (buffer, size, abfd) != size) -- { -- bfd_set_error (bfd_error_no_debug_section); -- return FALSE; -- } -- -- parse_module (abfd, module, buffer, size); -- free (buffer); -- } -- -- /* Find out the function (if any) that contains the address. */ -- for (funcinfo = module->func_table; funcinfo; funcinfo = funcinfo->next) -- if (addr >= funcinfo->low && addr <= funcinfo->high) -- { -- *func = funcinfo->name; -- ret = TRUE; -- break; -- } -- -- /* Find out the source file and the line nearest to the address. */ -- for (lineinfo = module->line_table; lineinfo; lineinfo = lineinfo->next) -- if (lineinfo->next && addr < lineinfo->next->address) -- { -- for (srecinfo = module->srec_table; srecinfo; srecinfo = srecinfo->next) -- if (srecinfo->next && lineinfo->line < srecinfo->next->line) -- { -- if (srecinfo->sfile > 0) -- { -- *file = module->file_table[srecinfo->sfile].name; -- *line = srecinfo->srec + lineinfo->line - srecinfo->line; -- } -- else -- { -- *file = module->name; -- *line = lineinfo->line; -- } -- return TRUE; -- } -- -- break; -- } -- -- return ret; --} -- --/* 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. */ -- --static bfd_boolean --_bfd_vms_find_nearest_line (bfd *abfd, -- asymbol **symbols ATTRIBUTE_UNUSED, -- asection *section, -- bfd_vma offset, -- const char **file, -- const char **func, -- unsigned int *line, -- unsigned int *discriminator) --{ -- struct module *module; -- -- /* What address are we looking for? */ -- bfd_vma addr = section->vma + offset; -- -- *file = NULL; -- *func = NULL; -- *line = 0; -- if (discriminator) -- *discriminator = 0; -- -- /* We can't do anything if there is no DST (debug symbol table). */ -- if (PRIV (dst_section) == NULL) -- return FALSE; -- -- /* Create the module list - if not already done. */ -- if (PRIV (modules) == NULL) -- { -- PRIV (modules) = build_module_list (abfd); -- if (PRIV (modules) == NULL) -- return FALSE; -- } -- -- for (module = PRIV (modules); module; module = module->next) -- if (addr >= module->low && addr <= module->high) -- return module_find_nearest_line (abfd, module, addr, file, func, line); -- -- return FALSE; --} -- --/* Canonicalizations. */ --/* Set name, value, section and flags of SYM from E. */ -- --static bfd_boolean --sw_64_vms_convert_symbol (bfd *abfd, struct vms_symbol_entry *e, asymbol *sym) --{ -- flagword flags; -- symvalue value; -- asection *sec; -- const char *name; -- -- name = e->name; -- value = 0; -- flags = BSF_NO_FLAGS; -- sec = NULL; -- -- switch (e->typ) -- { -- case EGSD__C_SYM: -- if (e->flags & EGSY__V_WEAK) -- flags |= BSF_WEAK; -- -- if (e->flags & EGSY__V_DEF) -- { -- /* Symbol definition. */ -- flags |= BSF_GLOBAL; -- if (e->flags & EGSY__V_NORM) -- flags |= BSF_FUNCTION; -- value = e->value; -- sec = e->section; -- } -- else -- { -- /* Symbol reference. */ -- sec = bfd_und_section_ptr; -- } -- break; -- -- case EGSD__C_SYMG: -- /* A universal symbol is by definition global... */ -- flags |= BSF_GLOBAL; -- -- /* ...and dynamic in shared libraries. */ -- if (abfd->flags & DYNAMIC) -- flags |= BSF_DYNAMIC; -- -- if (e->flags & EGSY__V_WEAK) -- flags |= BSF_WEAK; -- -- if (!(e->flags & EGSY__V_DEF)) -- abort (); -- -- if (e->flags & EGSY__V_NORM) -- flags |= BSF_FUNCTION; -- -- value = e->value; -- /* sec = e->section; */ -- sec = bfd_abs_section_ptr; -- break; -- -- default: -- return FALSE; -- } -- -- sym->name = name; -- sym->section = sec; -- sym->flags = flags; -- sym->value = value; -- return TRUE; --} -- -- --/* Return the number of bytes required to store a vector of pointers -- to asymbols for all the symbols in the BFD abfd, including a -- terminal NULL pointer. If there are no symbols in the BFD, -- then return 0. If an error occurs, return -1. */ -- --static long --sw_64_vms_get_symtab_upper_bound (bfd *abfd) --{ -- vms_debug2 ((1, "sw_64_vms_get_symtab_upper_bound (%p), %d symbols\n", -- abfd, PRIV (gsd_sym_count))); -- -- return (PRIV (gsd_sym_count) + 1) * sizeof (asymbol *); --} -- --/* Read the symbols from the BFD abfd, and fills in the vector -- location with pointers to the symbols and a trailing NULL. -- -- Return number of symbols read. */ -- --static long --sw_64_vms_canonicalize_symtab (bfd *abfd, asymbol **symbols) --{ -- unsigned int i; -- -- vms_debug2 ((1, "sw_64_vms_canonicalize_symtab (%p, )\n", abfd)); -- -- if (PRIV (csymbols) == NULL) -- { -- PRIV (csymbols) = (asymbol **) bfd_alloc -- (abfd, PRIV (gsd_sym_count) * sizeof (asymbol *)); -- -- /* Traverse table and fill symbols vector. */ -- for (i = 0; i < PRIV (gsd_sym_count); i++) -- { -- struct vms_symbol_entry *e = PRIV (syms)[i]; -- asymbol *sym; -- -- sym = bfd_make_empty_symbol (abfd); -- if (sym == NULL || !sw_64_vms_convert_symbol (abfd, e, sym)) -- { -- bfd_release (abfd, PRIV (csymbols)); -- PRIV (csymbols) = NULL; -- return -1; -- } -- -- PRIV (csymbols)[i] = sym; -- } -- } -- -- if (symbols != NULL) -- { -- for (i = 0; i < PRIV (gsd_sym_count); i++) -- symbols[i] = PRIV (csymbols)[i]; -- symbols[i] = NULL; -- } -- -- return PRIV (gsd_sym_count); --} -- --/* Read and convert relocations from ETIR. We do it once for all sections. */ -- --static bfd_boolean --sw_64_vms_slurp_relocs (bfd *abfd) --{ -- int cur_psect = -1; -- -- vms_debug2 ((3, "sw_64_vms_slurp_relocs\n")); -- -- /* We slurp relocs only once, for all sections. */ -- if (PRIV (reloc_done)) -- return TRUE; -- PRIV (reloc_done) = TRUE; -- -- if (sw_64_vms_canonicalize_symtab (abfd, NULL) < 0) -- return FALSE; -- -- if (bfd_seek (abfd, 0, SEEK_SET) != 0) -- return FALSE; -- -- while (1) -- { -- unsigned char *begin; -- unsigned char *end; -- unsigned char *ptr; -- bfd_reloc_code_real_type reloc_code; -- int type; -- bfd_vma vaddr = 0; -- -- int length; -- -- bfd_vma cur_address; -- int cur_psidx = -1; -- unsigned char *cur_sym = NULL; -- int prev_cmd = -1; -- bfd_vma cur_addend = 0; -- -- /* Skip non-ETIR records. */ -- type = _bfd_vms_get_object_record (abfd); -- if (type == EOBJ__C_EEOM) -- break; -- if (type != EOBJ__C_ETIR) -- continue; -- -- begin = PRIV (recrd.rec) + 4; -- end = PRIV (recrd.rec) + PRIV (recrd.rec_size); -- -- for (ptr = begin; ptr < end; ptr += length) -- { -- int cmd; -- -- cmd = bfd_getl16 (ptr); -- length = bfd_getl16 (ptr + 2); -- -- cur_address = vaddr; -- -- vms_debug2 ((4, "sw_64_vms_slurp_relocs: etir %s\n", -- _bfd_vms_etir_name (cmd))); -- -- switch (cmd) -- { -- case ETIR__C_STA_GBL: /* SW_64_R_REFLONG und_section, step 1 */ -- /* SW_64_R_REFQUAD und_section, step 1 */ -- cur_sym = ptr + 4; -- prev_cmd = cmd; -- continue; -- -- case ETIR__C_STA_PQ: /* SW_64_R_REF{LONG|QUAD}, others part 1 */ -- cur_psidx = bfd_getl32 (ptr + 4); -- cur_addend = bfd_getl64 (ptr + 8); -- prev_cmd = cmd; -- continue; -- -- case ETIR__C_CTL_SETRB: -- if (prev_cmd != ETIR__C_STA_PQ) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("unknown reloc %s + %s"), _bfd_vms_etir_name (prev_cmd), -- _bfd_vms_etir_name (cmd)); -- return FALSE; -- } -- cur_psect = cur_psidx; -- vaddr = cur_addend; -- cur_psidx = -1; -- cur_addend = 0; -- continue; -- -- case ETIR__C_STA_LW: /* SW_64_R_REFLONG abs_section, step 1 */ -- /* SW_64_R_REFLONG und_section, step 2 */ -- if (prev_cmd != -1) -- { -- if (prev_cmd != ETIR__C_STA_GBL) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("unknown reloc %s + %s"), _bfd_vms_etir_name (cmd), -- _bfd_vms_etir_name (ETIR__C_STA_LW)); -- return FALSE; -- } -- } -- cur_addend = bfd_getl32 (ptr + 4); -- prev_cmd = cmd; -- continue; -- -- case ETIR__C_STA_QW: /* SW_64_R_REFQUAD abs_section, step 1 */ -- /* SW_64_R_REFQUAD und_section, step 2 */ -- if (prev_cmd != -1 && prev_cmd != ETIR__C_STA_GBL) -- { -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("unknown reloc %s + %s"), _bfd_vms_etir_name (cmd), -- _bfd_vms_etir_name (ETIR__C_STA_QW)); -- return FALSE; -- } -- cur_addend = bfd_getl64 (ptr + 4); -- prev_cmd = cmd; -- continue; -- -- case ETIR__C_STO_LW: /* SW_64_R_REFLONG und_section, step 4 */ -- /* SW_64_R_REFLONG abs_section, step 2 */ -- /* SW_64_R_REFLONG others, step 2 */ -- if (prev_cmd != ETIR__C_OPR_ADD -- && prev_cmd != ETIR__C_STA_LW -- && prev_cmd != ETIR__C_STA_PQ) -- { -- /* xgettext:c-format */ -- _bfd_error_handler (_("unknown reloc %s + %s"), -- _bfd_vms_etir_name (prev_cmd), -- _bfd_vms_etir_name (ETIR__C_STO_LW)); -- return FALSE; -- } -- reloc_code = BFD_RELOC_32; -- break; -- -- case ETIR__C_STO_QW: /* SW_64_R_REFQUAD und_section, step 4 */ -- /* SW_64_R_REFQUAD abs_section, step 2 */ -- if (prev_cmd != ETIR__C_OPR_ADD && prev_cmd != ETIR__C_STA_QW) -- { -- /* xgettext:c-format */ -- _bfd_error_handler (_("unknown reloc %s + %s"), -- _bfd_vms_etir_name (prev_cmd), -- _bfd_vms_etir_name (ETIR__C_STO_QW)); -- return FALSE; -- } -- reloc_code = BFD_RELOC_64; -- break; -- -- case ETIR__C_STO_OFF: /* SW_64_R_REFQUAD others, step 2 */ -- if (prev_cmd != ETIR__C_STA_PQ) -- { -- /* xgettext:c-format */ -- _bfd_error_handler (_("unknown reloc %s + %s"), -- _bfd_vms_etir_name (prev_cmd), -- _bfd_vms_etir_name (ETIR__C_STO_OFF)); -- return FALSE; -- } -- reloc_code = BFD_RELOC_64; -- break; -- -- case ETIR__C_OPR_ADD: /* SW_64_R_REFLONG und_section, step 3 */ -- /* SW_64_R_REFQUAD und_section, step 3 */ -- if (prev_cmd != ETIR__C_STA_LW && prev_cmd != ETIR__C_STA_QW) -- { -- /* xgettext:c-format */ -- _bfd_error_handler (_("unknown reloc %s + %s"), -- _bfd_vms_etir_name (prev_cmd), -- _bfd_vms_etir_name (ETIR__C_OPR_ADD)); -- return FALSE; -- } -- prev_cmd = ETIR__C_OPR_ADD; -- continue; -- -- case ETIR__C_STO_CA: /* SW_64_R_CODEADDR */ -- reloc_code = BFD_RELOC_SW_64_CODEADDR; -- cur_sym = ptr + 4; -- break; -- -- case ETIR__C_STO_GBL: /* SW_64_R_REFQUAD und_section */ -- reloc_code = BFD_RELOC_64; -- cur_sym = ptr + 4; -- break; -- -- case ETIR__C_STO_GBL_LW: /* SW_64_R_REFLONG und_section */ -- reloc_code = BFD_RELOC_32; -- cur_sym = ptr + 4; -- break; -- -- case ETIR__C_STC_LP_PSB: /* SW_64_R_LINKAGE */ -- reloc_code = BFD_RELOC_SW_64_LINKAGE; -- cur_sym = ptr + 8; -- break; -- -- case ETIR__C_STC_NOP_GBL: /* SW_64_R_NOP */ -- reloc_code = BFD_RELOC_SW_64_NOP; -- goto call_reloc; -- -- case ETIR__C_STC_BSR_GBL: /* SW_64_R_BSR */ -- reloc_code = BFD_RELOC_SW_64_BSR; -- goto call_reloc; -- -- case ETIR__C_STC_LDA_GBL: /* SW_64_R_LDA */ -- reloc_code = BFD_RELOC_SW_64_LDA; -- goto call_reloc; -- -- case ETIR__C_STC_BOH_GBL: /* SW_64_R_BOH */ -- reloc_code = BFD_RELOC_SW_64_BOH; -- goto call_reloc; -- -- call_reloc: -- cur_sym = ptr + 4 + 32; -- cur_address = bfd_getl64 (ptr + 4 + 8); -- cur_addend = bfd_getl64 (ptr + 4 + 24); -- break; -- -- case ETIR__C_STO_IMM: -- vaddr += bfd_getl32 (ptr + 4); -- continue; -- -- default: -- _bfd_error_handler (_("unknown reloc %s"), -- _bfd_vms_etir_name (cmd)); -- return FALSE; -- } -- -- { -- asection *sec; -- struct vms_section_data_struct *vms_sec; -- arelent *reloc; -- bfd_size_type size; -- -- /* Get section to which the relocation applies. */ -- if (cur_psect < 0 || cur_psect > (int)PRIV (section_count)) -- { -- _bfd_error_handler (_("invalid section index in ETIR")); -- return FALSE; -- } -- -- if (PRIV (sections) == NULL) -- return FALSE; -- sec = PRIV (sections)[cur_psect]; -- if (sec == bfd_abs_section_ptr) -- { -- _bfd_error_handler (_("relocation for non-REL psect")); -- return FALSE; -- } -- -- vms_sec = vms_section_data (sec); -- -- /* Allocate a reloc entry. */ -- if (sec->reloc_count >= vms_sec->reloc_max) -- { -- if (vms_sec->reloc_max == 0) -- { -- vms_sec->reloc_max = 64; -- sec->relocation = bfd_zmalloc -- (vms_sec->reloc_max * sizeof (arelent)); -- } -- else -- { -- vms_sec->reloc_max *= 2; -- sec->relocation = bfd_realloc -- (sec->relocation, vms_sec->reloc_max * sizeof (arelent)); -- } -- } -- reloc = &sec->relocation[sec->reloc_count]; -- sec->reloc_count++; -- -- reloc->howto = bfd_reloc_type_lookup (abfd, reloc_code); -- -- if (cur_sym != NULL) -- { -- unsigned int j; -- unsigned int symlen = *cur_sym; -- asymbol **sym; -- -- /* Linear search. */ -- symlen = *cur_sym; -- cur_sym++; -- sym = NULL; -- -- for (j = 0; j < PRIV (gsd_sym_count); j++) -- if (PRIV (syms)[j]->namelen == symlen -- && memcmp (PRIV (syms)[j]->name, cur_sym, symlen) == 0) -- { -- sym = &PRIV (csymbols)[j]; -- break; -- } -- if (sym == NULL) -- { -- _bfd_error_handler (_("unknown symbol in command %s"), -- _bfd_vms_etir_name (cmd)); -- reloc->sym_ptr_ptr = NULL; -- } -- else -- reloc->sym_ptr_ptr = sym; -- } -- else if (cur_psidx >= 0) -- { -- if (PRIV (sections) == NULL || cur_psidx >= (int) PRIV (section_count)) -- return FALSE; -- reloc->sym_ptr_ptr = -- PRIV (sections)[cur_psidx]->symbol_ptr_ptr; -- } -- else -- reloc->sym_ptr_ptr = NULL; -- -- reloc->address = cur_address; -- reloc->addend = cur_addend; -- -- if (reloc_code == SW_64_R_LINKAGE) -- size = 16; -- else -- size = bfd_get_reloc_size (reloc->howto); -- vaddr += size; -- } -- -- cur_addend = 0; -- prev_cmd = -1; -- cur_sym = NULL; -- cur_psidx = -1; -- } -- } -- vms_debug2 ((3, "sw_64_vms_slurp_relocs: result = TRUE\n")); -- -- return TRUE; --} -- --/* Return the number of bytes required to store the relocation -- information associated with the given section. */ -- --static long --sw_64_vms_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *section) --{ -- sw_64_vms_slurp_relocs (abfd); -- -- return (section->reloc_count + 1L) * sizeof (arelent *); -- //return (section->reloc_count + 1) * sizeof (arelent *); --} -- --/* Convert relocations from VMS (external) form into BFD internal -- form. Return the number of relocations. */ -- --static long --sw_64_vms_canonicalize_reloc (bfd *abfd, asection *section, arelent **relptr, -- asymbol **symbols ATTRIBUTE_UNUSED) --{ -- arelent *tblptr; -- int count; -- -- if (!sw_64_vms_slurp_relocs (abfd)) -- return -1; -- -- count = section->reloc_count; -- tblptr = section->relocation; -- -- while (count--) -- *relptr++ = tblptr++; -- -- *relptr = (arelent *) NULL; -- return section->reloc_count; --} -- --/* Install a new set of internal relocs. */ -- --#define sw_64_vms_set_reloc _bfd_generic_set_reloc -- -- --/* This is just copied from ecoff-sw_64, needs to be fixed probably. */ -- --/* How to process the various reloc types. */ -- --static bfd_reloc_status_type --reloc_nil (bfd * abfd ATTRIBUTE_UNUSED, -- arelent *reloc ATTRIBUTE_UNUSED, -- asymbol *sym ATTRIBUTE_UNUSED, -- void * data ATTRIBUTE_UNUSED, -- asection *sec ATTRIBUTE_UNUSED, -- bfd *output_bfd ATTRIBUTE_UNUSED, -- char **error_message ATTRIBUTE_UNUSED) --{ --#if VMS_DEBUG -- vms_debug (1, "reloc_nil (abfd %p, output_bfd %p)\n", abfd, output_bfd); -- vms_debug (2, "In section %s, symbol %s\n", -- sec->name, sym->name); -- vms_debug (2, "reloc sym %s, addr %08lx, addend %08lx, reloc is a %s\n", -- reloc->sym_ptr_ptr[0]->name, -- (unsigned long)reloc->address, -- (unsigned long)reloc->addend, reloc->howto->name); -- vms_debug (2, "data at %p\n", data); -- /* _bfd_hexdump (2, data, bfd_get_reloc_size (reloc->howto), 0); */ --#endif -- -- 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 sw_64_howto_table[] = --{ -- HOWTO (SW_64_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, /* Source mask */ -- 0, /* Dest mask. */ -- TRUE), /* PC rel offset. */ -- -- /* A 64 bit reference to a symbol. */ -- HOWTO (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "REFQUAD", /* Name. */ -- TRUE, /* Partial_inplace. */ -- MINUS_ONE, /* Source mask. */ -- MINUS_ONE, /* Dest mask. */ -- FALSE), /* PC rel 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 (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "BRADDR", /* Name. */ -- TRUE, /* Partial_inplace. */ -- 0x1fffff, /* Source mask. */ -- 0x1fffff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* A hint for a jump to a register. */ -- HOWTO (SW_64_R_HINT, /* Type. */ -- 2, /* Rightshift. */ -- 1, /* Size (0 = byte, 1 = short, 2 = long). */ -- 14, /* Bitsize. */ -- TRUE, /* PC relative. */ -- 0, /* Bitpos. */ -- complain_overflow_dont,/* Complain_on_overflow. */ -- reloc_nil, /* Special_function. */ -- "HINT", /* Name. */ -- TRUE, /* Partial_inplace. */ -- 0x3fff, /* Source mask. */ -- 0x3fff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* 16 bit PC relative offset. */ -- HOWTO (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "SREL16", /* Name. */ -- TRUE, /* Partial_inplace. */ -- 0xffff, /* Source mask. */ -- 0xffff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* 32 bit PC relative offset. */ -- HOWTO (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "SREL32", /* Name. */ -- TRUE, /* Partial_inplace. */ -- 0xffffffff, /* Source mask. */ -- 0xffffffff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* A 64 bit PC relative offset. */ -- HOWTO (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "SREL64", /* Name. */ -- TRUE, /* Partial_inplace. */ -- MINUS_ONE, /* Source mask. */ -- MINUS_ONE, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* Push a value on the reloc evaluation stack. */ -- HOWTO (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "OP_PUSH", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0, /* Source mask. */ -- 0, /* Dest mask. */ -- FALSE), /* PC rel 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 (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "OP_STORE", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0, /* Source mask. */ -- MINUS_ONE, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* Subtract the reloc address from the value on the top of the -- relocation stack. */ -- HOWTO (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "OP_PSUB", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0, /* Source mask. */ -- 0, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* Shift the value on the top of the relocation stack right by the -- given value. */ -- HOWTO (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "OP_PRSHIFT", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0, /* Source mask. */ -- 0, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* Hack. Linkage is done by linker. */ -- HOWTO (SW_64_R_LINKAGE, /* Type. */ -- 0, /* Rightshift. */ -- 0, /* Size (0 = byte, 1 = short, 2 = long). */ -- 0, /* Bitsize. */ -- FALSE, /* PC relative. */ -- 0, /* Bitpos. */ -- complain_overflow_dont,/* Complain_on_overflow. */ -- reloc_nil, /* Special_function. */ -- "LINKAGE", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0, /* Source mask. */ -- 0, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* A 32 bit reference to a symbol. */ -- HOWTO (SW_64_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. */ -- reloc_nil, /* Special_function. */ -- "REFLONG", /* Name. */ -- TRUE, /* Partial_inplace. */ -- 0xffffffff, /* Source mask. */ -- 0xffffffff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- /* A 64 bit reference to a procedure, written as 32 bit value. */ -- HOWTO (SW_64_R_CODEADDR, /* Type. */ -- 0, /* Rightshift. */ -- 4, /* Size (0 = byte, 1 = short, 2 = long). */ -- 64, /* Bitsize. */ -- FALSE, /* PC relative. */ -- 0, /* Bitpos. */ -- complain_overflow_signed,/* Complain_on_overflow. */ -- reloc_nil, /* Special_function. */ -- "CODEADDR", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0xffffffff, /* Source mask. */ -- 0xffffffff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- HOWTO (SW_64_R_NOP, /* Type. */ -- 0, /* Rightshift. */ -- 3, /* Size (0 = byte, 1 = short, 2 = long). */ -- 0, /* Bitsize. */ -- /* The following value must match that of SW_64_R_BSR/SW_64_R_BOH -- because the calculations for the 3 relocations are the same. -- See B.4.5.2 of the OpenVMS Linker Utility Manual. */ -- TRUE, /* PC relative. */ -- 0, /* Bitpos. */ -- complain_overflow_dont,/* Complain_on_overflow. */ -- reloc_nil, /* Special_function. */ -- "NOP", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0xffffffff, /* Source mask. */ -- 0xffffffff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- HOWTO (SW_64_R_BSR, /* Type. */ -- 0, /* Rightshift. */ -- 3, /* Size (0 = byte, 1 = short, 2 = long). */ -- 0, /* Bitsize. */ -- TRUE, /* PC relative. */ -- 0, /* Bitpos. */ -- complain_overflow_dont,/* Complain_on_overflow. */ -- reloc_nil, /* Special_function. */ -- "BSR", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0xffffffff, /* Source mask. */ -- 0xffffffff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- HOWTO (SW_64_R_LDA, /* Type. */ -- 0, /* Rightshift. */ -- 3, /* Size (0 = byte, 1 = short, 2 = long). */ -- 0, /* Bitsize. */ -- FALSE, /* PC relative. */ -- 0, /* Bitpos. */ -- complain_overflow_dont,/* Complain_on_overflow. */ -- reloc_nil, /* Special_function. */ -- "LDA", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0xffffffff, /* Source mask. */ -- 0xffffffff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ -- -- HOWTO (SW_64_R_BOH, /* Type. */ -- 0, /* Rightshift. */ -- 3, /* Size (0 = byte, 1 = short, 2 = long, 3 = nil). */ -- 0, /* Bitsize. */ -- TRUE, /* PC relative. */ -- 0, /* Bitpos. */ -- complain_overflow_dont,/* Complain_on_overflow. */ -- reloc_nil, /* Special_function. */ -- "BOH", /* Name. */ -- FALSE, /* Partial_inplace. */ -- 0xffffffff, /* Source mask. */ -- 0xffffffff, /* Dest mask. */ -- FALSE), /* PC rel offset. */ --}; -- --/* Return a pointer to a howto structure which, when invoked, will perform -- the relocation code on data from the architecture noted. */ -- --static reloc_howto_type * --sw_64_vms_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, -- bfd_reloc_code_real_type code) --{ -- int sw_64_type; -- -- vms_debug2 ((1, "vms_bfd_reloc_type_lookup (%p, %d)\t", abfd, code)); -- -- switch (code) -- { -- case BFD_RELOC_16: sw_64_type = SW_64_R_SREL16; break; -- case BFD_RELOC_32: sw_64_type = SW_64_R_REFLONG; break; -- case BFD_RELOC_64: sw_64_type = SW_64_R_REFQUAD; break; -- case BFD_RELOC_CTOR: sw_64_type = SW_64_R_REFQUAD; break; -- case BFD_RELOC_23_PCREL_S2: sw_64_type = SW_64_R_BRADDR; break; -- case BFD_RELOC_SW_64_HINT: sw_64_type = SW_64_R_HINT; break; -- case BFD_RELOC_16_PCREL: sw_64_type = SW_64_R_SREL16; break; -- case BFD_RELOC_32_PCREL: sw_64_type = SW_64_R_SREL32; break; -- case BFD_RELOC_64_PCREL: sw_64_type = SW_64_R_SREL64; break; -- case BFD_RELOC_SW_64_LINKAGE: sw_64_type = SW_64_R_LINKAGE; break; -- case BFD_RELOC_SW_64_CODEADDR: sw_64_type = SW_64_R_CODEADDR; break; -- case BFD_RELOC_SW_64_NOP: sw_64_type = SW_64_R_NOP; break; -- case BFD_RELOC_SW_64_BSR: sw_64_type = SW_64_R_BSR; break; -- case BFD_RELOC_SW_64_LDA: sw_64_type = SW_64_R_LDA; break; -- case BFD_RELOC_SW_64_BOH: sw_64_type = SW_64_R_BOH; break; -- default: -- _bfd_error_handler (_("reloc (%d) is *UNKNOWN*"), code); -- return NULL; -- } -- vms_debug2 ((2, "reloc is %s\n", sw_64_howto_table[sw_64_type].name)); -- return & sw_64_howto_table[sw_64_type]; --} -- --static reloc_howto_type * --sw_64_vms_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, -- const char *r_name) --{ -- unsigned int i; -- -- for (i = 0; -- i < sizeof (sw_64_howto_table) / sizeof (sw_64_howto_table[0]); -- i++) -- if (sw_64_howto_table[i].name != NULL -- && strcasecmp (sw_64_howto_table[i].name, r_name) == 0) -- return &sw_64_howto_table[i]; -- -- return NULL; --} -- --static long --sw_64_vms_get_synthetic_symtab (bfd *abfd, -- long symcount ATTRIBUTE_UNUSED, -- asymbol **usyms ATTRIBUTE_UNUSED, -- long dynsymcount ATTRIBUTE_UNUSED, -- asymbol **dynsyms ATTRIBUTE_UNUSED, -- asymbol **ret) --{ -- asymbol *syms; -- unsigned int i; -- unsigned int n = 0; -- -- syms = (asymbol *) bfd_malloc (PRIV (norm_sym_count) * sizeof (asymbol)); -- *ret = syms; -- if (syms == NULL) -- return -1; -- -- for (i = 0; i < PRIV (gsd_sym_count); i++) -- { -- struct vms_symbol_entry *e = PRIV (syms)[i]; -- asymbol *sym; -- flagword flags; -- symvalue value; -- asection *sec; -- const char *name; -- char *sname; -- int l; -- -- name = e->name; -- value = 0; -- flags = BSF_LOCAL | BSF_SYNTHETIC; -- sec = NULL; -- -- switch (e->typ) -- { -- case EGSD__C_SYM: -- case EGSD__C_SYMG: -- if ((e->flags & EGSY__V_DEF) && (e->flags & EGSY__V_NORM)) -- { -- value = e->code_value; -- sec = e->code_section; -- } -- else -- continue; -- break; -- -- default: -- continue; -- } -- -- l = strlen (name); -- sname = bfd_alloc (abfd, l + 5); -- if (sname == NULL) -- return FALSE; -- memcpy (sname, name, l); -- memcpy (sname + l, "..en", 5); -- -- sym = &syms[n++]; -- sym->name = sname; -- sym->section = sec; -- sym->flags = flags; -- sym->value = value; -- sym->udata.p = NULL; -- } -- -- return n; --} -- --/* Private dump. */ -- --static const char * --vms_time_to_str (unsigned char *buf) --{ -- time_t t = vms_rawtime_to_time_t (buf); -- char *res = ctime (&t); -- -- if (!res) -- res = "*invalid time*"; -- else -- res[24] = 0; -- return res; --} -- --static void --evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len) --{ -- struct vms_emh_common *emh = (struct vms_emh_common *)rec; -- unsigned int subtype; -- int extra; -- -- subtype = (unsigned) bfd_getl16 (emh->subtyp); -- -- /* xgettext:c-format */ -- fprintf (file, _(" EMH %u (len=%u): "), subtype, rec_len); -- -- /* PR 21618: Check for invalid lengths. */ -- if (rec_len < sizeof (* emh)) -- { -- fprintf (file, _(" Error: The length is less than the length of an EMH record\n")); -- return; -- } -- extra = rec_len - sizeof (struct vms_emh_common); -- -- switch (subtype) -- { -- case EMH__C_MHD: -- { -- struct vms_emh_mhd *mhd = (struct vms_emh_mhd *) rec; -- const char * name; -- const char * nextname; -- const char * maxname; -- -- /* PR 21840: Check for invalid lengths. */ -- if (rec_len < sizeof (* mhd)) -- { -- fprintf (file, _(" Error: The record length is less than the size of an EMH_MHD record\n")); -- return; -- } -- fprintf (file, _("Module header\n")); -- fprintf (file, _(" structure level: %u\n"), mhd->strlvl); -- fprintf (file, _(" max record size: %u\n"), -- (unsigned) bfd_getl32 (mhd->recsiz)); -- name = (char *)(mhd + 1); -- maxname = (char *) rec + rec_len; -- if (name > maxname - 2) -- { -- fprintf (file, _(" Error: The module name is missing\n")); -- return; -- } -- nextname = name + name[0] + 1; -- if (nextname >= maxname) -- { -- fprintf (file, _(" Error: The module name is too long\n")); -- return; -- } -- fprintf (file, _(" module name : %.*s\n"), name[0], name + 1); -- name = nextname; -- if (name > maxname - 2) -- { -- fprintf (file, _(" Error: The module version is missing\n")); -- return; -- } -- nextname = name + name[0] + 1; -- if (nextname >= maxname) -- { -- fprintf (file, _(" Error: The module version is too long\n")); -- return; -- } -- fprintf (file, _(" module version : %.*s\n"), name[0], name + 1); -- name = nextname; -- if ((maxname - name) < 17 && maxname[-1] != 0) -- fprintf (file, _(" Error: The compile date is truncated\n")); -- else -- fprintf (file, _(" compile date : %.17s\n"), name); -- } -- break; -- -- case EMH__C_LNM: -- fprintf (file, _("Language Processor Name\n")); -- fprintf (file, _(" language name: %.*s\n"), extra, (char *)(emh + 1)); -- break; -- -- case EMH__C_SRC: -- fprintf (file, _("Source Files Header\n")); -- fprintf (file, _(" file: %.*s\n"), extra, (char *)(emh + 1)); -- break; -- -- case EMH__C_TTL: -- fprintf (file, _("Title Text Header\n")); -- fprintf (file, _(" title: %.*s\n"), extra, (char *)(emh + 1)); -- break; -- -- case EMH__C_CPR: -- fprintf (file, _("Copyright Header\n")); -- fprintf (file, _(" copyright: %.*s\n"), extra, (char *)(emh + 1)); -- break; -- -- default: -- fprintf (file, _("unhandled emh subtype %u\n"), subtype); -- break; -- } --} -- --static void --evax_bfd_print_eeom (FILE *file, unsigned char *rec, unsigned int rec_len) --{ -- struct vms_eeom *eeom = (struct vms_eeom *)rec; -- -- fprintf (file, _(" EEOM (len=%u):\n"), rec_len); -- -- /* PR 21618: Check for invalid lengths. */ -- if (rec_len < sizeof (* eeom)) -- { -- fprintf (file, _(" Error: The length is less than the length of an EEOM record\n")); -- return; -- } -- -- fprintf (file, _(" number of cond linkage pairs: %u\n"), -- (unsigned)bfd_getl32 (eeom->total_lps)); -- fprintf (file, _(" completion code: %u\n"), -- (unsigned)bfd_getl16 (eeom->comcod)); -- if (rec_len > 10) -- { -- fprintf (file, _(" transfer addr flags: 0x%02x\n"), eeom->tfrflg); -- fprintf (file, _(" transfer addr psect: %u\n"), -- (unsigned)bfd_getl32 (eeom->psindx)); -- fprintf (file, _(" transfer address : 0x%08x\n"), -- (unsigned)bfd_getl32 (eeom->tfradr)); -- } --} -- --static void --exav_bfd_print_egsy_flags (unsigned int flags, FILE *file) --{ -- if (flags & EGSY__V_WEAK) -- fputs (_(" WEAK"), file); -- if (flags & EGSY__V_DEF) -- fputs (_(" DEF"), file); -- if (flags & EGSY__V_UNI) -- fputs (_(" UNI"), file); -- if (flags & EGSY__V_REL) -- fputs (_(" REL"), file); -- if (flags & EGSY__V_COMM) -- fputs (_(" COMM"), file); -- if (flags & EGSY__V_VECEP) -- fputs (_(" VECEP"), file); -- if (flags & EGSY__V_NORM) -- fputs (_(" NORM"), file); -- if (flags & EGSY__V_QUAD_VAL) -- fputs (_(" QVAL"), file); --} -- --static void --evax_bfd_print_egsd_flags (FILE *file, unsigned int flags) --{ -- if (flags & EGPS__V_PIC) -- fputs (_(" PIC"), file); -- if (flags & EGPS__V_LIB) -- fputs (_(" LIB"), file); -- if (flags & EGPS__V_OVR) -- fputs (_(" OVR"), file); -- if (flags & EGPS__V_REL) -- fputs (_(" REL"), file); -- if (flags & EGPS__V_GBL) -- fputs (_(" GBL"), file); -- if (flags & EGPS__V_SHR) -- fputs (_(" SHR"), file); -- if (flags & EGPS__V_EXE) -- fputs (_(" EXE"), file); -- if (flags & EGPS__V_RD) -- fputs (_(" RD"), file); -- if (flags & EGPS__V_WRT) -- fputs (_(" WRT"), file); -- if (flags & EGPS__V_VEC) -- fputs (_(" VEC"), file); -- if (flags & EGPS__V_NOMOD) -- fputs (_(" NOMOD"), file); -- if (flags & EGPS__V_COM) -- fputs (_(" COM"), file); -- if (flags & EGPS__V_ALLOC_64BIT) -- fputs (_(" 64B"), file); --} -- --static void --evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len) --{ -- unsigned int off = sizeof (struct vms_egsd); -- unsigned int n = 0; -- //unsigned int n; -- -- fprintf (file, _(" EGSD (len=%u):\n"), rec_len); -- if (rec_len < sizeof (struct vms_egsd) + sizeof (struct vms_egsd_entry)) -- return; -- -- while (off <= rec_len - sizeof (struct vms_egsd_entry)) -- //n = 0; -- //for (off = sizeof (struct vms_egsd); off < rec_len; ) -- { -- struct vms_egsd_entry *e = (struct vms_egsd_entry *)(rec + off); -- unsigned int type; -- unsigned int len; -- unsigned int rest; -- -- type = (unsigned)bfd_getl16 (e->gsdtyp); -- len = (unsigned)bfd_getl16 (e->gsdsiz); -- -- /* xgettext:c-format */ -- fprintf (file, _(" EGSD entry %2u (type: %u, len: %u): "), -- n, type, len); -- n++; -- -- if (len < sizeof (struct vms_egsd_entry) || len > rec_len - off) -- //if (off + len > rec_len || off + len < off) -- { -- fprintf (file, _(" Erroneous length\n")); -- //fprintf (file, _(" Error: length larger than remaining space in record\n")); -- return; -- } -- -- switch (type) -- { -- case EGSD__C_PSC: -- /* -- { -- struct vms_egps *egps = (struct vms_egps *)e; -- unsigned int flags = bfd_getl16 (egps->flags); -- unsigned int l; -- -- fprintf (file, _("PSC - Program section definition\n")); -- fprintf (file, _(" alignment : 2**%u\n"), egps->align); -- fprintf (file, _(" flags : 0x%04x"), flags); -- evax_bfd_print_egsd_flags (file, flags); -- fputc ('\n', file); -- l = bfd_getl32 (egps->alloc); -- fprintf (file, _(" alloc (len): %u (0x%08x)\n"), l, l); -- fprintf (file, _(" name : %.*s\n"), -- egps->namlng, egps->name); -- }*/ -- if (len >= offsetof (struct vms_egps, name)) -- { -- struct vms_egps *egps = (struct vms_egps *) e; -- unsigned int flags = bfd_getl16 (egps->flags); -- unsigned int l; -- -- fprintf (file, _("PSC - Program section definition\n")); -- fprintf (file, _(" alignment : 2**%u\n"), egps->align); -- fprintf (file, _(" flags : 0x%04x"), flags); -- evax_bfd_print_egsd_flags (file, flags); -- fputc ('\n', file); -- l = bfd_getl32 (egps->alloc); -- fprintf (file, _(" alloc (len): %u (0x%08x)\n"), l, l); -- rest = len - offsetof (struct vms_egps, name); -- fprintf (file, _(" name : %.*s\n"), -- egps->namlng > rest ? rest : egps->namlng, -- egps->name); -- } -- break; -- case EGSD__C_SPSC: -- /*{ -- struct vms_esgps *esgps = (struct vms_esgps *)e; -- unsigned int flags = bfd_getl16 (esgps->flags); -- unsigned int l; -- -- fprintf (file, _("SPSC - Shared Image Program section def\n")); -- fprintf (file, _(" alignment : 2**%u\n"), esgps->align); -- fprintf (file, _(" flags : 0x%04x"), flags); -- evax_bfd_print_egsd_flags (file, flags); -- fputc ('\n', file); -- l = bfd_getl32 (esgps->alloc); -- fprintf (file, _(" alloc (len) : %u (0x%08x)\n"), l, l); -- fprintf (file, _(" image offset : 0x%08x\n"), -- (unsigned int)bfd_getl32 (esgps->base)); -- fprintf (file, _(" symvec offset : 0x%08x\n"), -- (unsigned int)bfd_getl32 (esgps->value)); -- fprintf (file, _(" name : %.*s\n"), -- esgps->namlng, esgps->name); -- }*/ -- if (len >= offsetof (struct vms_esgps, name)) -- { -- struct vms_esgps *esgps = (struct vms_esgps *) e; -- unsigned int flags = bfd_getl16 (esgps->flags); -- unsigned int l; -- -- fprintf (file, _("SPSC - Shared Image Program section def\n")); -- fprintf (file, _(" alignment : 2**%u\n"), esgps->align); -- fprintf (file, _(" flags : 0x%04x"), flags); -- evax_bfd_print_egsd_flags (file, flags); -- fputc ('\n', file); -- l = bfd_getl32 (esgps->alloc); -- fprintf (file, _(" alloc (len) : %u (0x%08x)\n"), l, l); -- fprintf (file, _(" image offset : 0x%08x\n"), -- (unsigned int) bfd_getl32 (esgps->base)); -- fprintf (file, _(" symvec offset : 0x%08x\n"), -- (unsigned int) bfd_getl32 (esgps->value)); -- rest = len - offsetof (struct vms_esgps, name); -- fprintf (file, _(" name : %.*s\n"), -- esgps->namlng > rest ? rest : esgps->namlng, -- esgps->name); -- } -- break; -- case EGSD__C_SYM: -- if (len >= sizeof (struct vms_egsy)) -- { -- struct vms_egsy *egsy = (struct vms_egsy *) e; -- unsigned int flags = bfd_getl16 (egsy->flags); -- //{ -- //struct vms_egsy *egsy = (struct vms_egsy *)e; -- //unsigned int flags = bfd_getl16 (egsy->flags); -- -- if ((flags & EGSY__V_DEF) != 0 -- && len >= offsetof (struct vms_esdf, name)) -- { -- struct vms_esdf *esdf = (struct vms_esdf *) e; -- //if (flags & EGSY__V_DEF) -- //{ -- //struct vms_esdf *esdf = (struct vms_esdf *)e; -- /* -- fprintf (file, _("SYM - Global symbol definition\n")); -- fprintf (file, _(" flags: 0x%04x"), flags); -- exav_bfd_print_egsy_flags (flags, file); -- fputc ('\n', file); -- fprintf (file, _(" psect offset: 0x%08x\n"), -- (unsigned)bfd_getl32 (esdf->value)); -- if (flags & EGSY__V_NORM) -- { -- fprintf (file, _(" code address: 0x%08x\n"), -- (unsigned)bfd_getl32 (esdf->code_address)); -- fprintf (file, _(" psect index for entry point : %u\n"), -- (unsigned)bfd_getl32 (esdf->ca_psindx)); -- } -- fprintf (file, _(" psect index : %u\n"), -- (unsigned)bfd_getl32 (esdf->psindx)); -- fprintf (file, _(" name : %.*s\n"), -- esdf->namlng, esdf->name); -- } -- else -- { -- struct vms_esrf *esrf = (struct vms_esrf *)e;*/ -- -- fprintf (file, _("SYM - Global symbol definition\n")); -- fprintf (file, _(" flags: 0x%04x"), flags); -- exav_bfd_print_egsy_flags (flags, file); -- fputc ('\n', file); -- fprintf (file, _(" psect offset: 0x%08x\n"), -- (unsigned) bfd_getl32 (esdf->value)); -- if (flags & EGSY__V_NORM) -- { -- fprintf (file, _(" code address: 0x%08x\n"), -- (unsigned) bfd_getl32 (esdf->code_address)); -- fprintf (file, _(" psect index for entry point : %u\n"), -- (unsigned) bfd_getl32 (esdf->ca_psindx)); -- } -- fprintf (file, _(" psect index : %u\n"), -- (unsigned) bfd_getl32 (esdf->psindx)); -- rest = len - offsetof (struct vms_esdf, name); -- fprintf (file, _(" name : %.*s\n"), -- esdf->namlng > rest ? rest : esdf->namlng, -- esdf->name); -- } -- else if (len >= offsetof (struct vms_esrf, name)) -- { -- struct vms_esrf *esrf = (struct vms_esrf *)e; -- -- /*fprintf (file, _("SYM - Global symbol reference\n")); -- fprintf (file, _(" name : %.*s\n"), -- esrf->namlng, esrf->name); -- } -- }*/ -- fprintf (file, _("SYM - Global symbol reference\n")); -- rest = len - offsetof (struct vms_esrf, name); -- fprintf (file, _(" name : %.*s\n"), -- esrf->namlng > rest ? rest : esrf->namlng, -- esrf->name); -- } -- } -- break; -- case EGSD__C_IDC: -- /*{ -- struct vms_eidc *eidc = (struct vms_eidc *)e; -- unsigned int flags = bfd_getl32 (eidc->flags); -- unsigned char *p; -- -- fprintf (file, _("IDC - Ident Consistency check\n")); -- fprintf (file, _(" flags : 0x%08x"), flags); -- if (flags & EIDC__V_BINIDENT) -- fputs (" BINDENT", file); -- fputc ('\n', file); -- fprintf (file, _(" id match : %x\n"), -- (flags >> EIDC__V_IDMATCH_SH) & EIDC__V_IDMATCH_MASK); -- fprintf (file, _(" error severity: %x\n"), -- (flags >> EIDC__V_ERRSEV_SH) & EIDC__V_ERRSEV_MASK); -- p = eidc->name; -- fprintf (file, _(" entity name : %.*s\n"), p[0], p + 1); -- p += 1 + p[0]; -- fprintf (file, _(" object name : %.*s\n"), p[0], p + 1); -- p += 1 + p[0]; -- if (flags & EIDC__V_BINIDENT) -- fprintf (file, _(" binary ident : 0x%08x\n"), -- (unsigned)bfd_getl32 (p + 1)); -- else -- fprintf (file, _(" ascii ident : %.*s\n"), p[0], p + 1); -- }*/ -- if (len >= sizeof (struct vms_eidc)) -- { -- struct vms_eidc *eidc = (struct vms_eidc *) e; -- unsigned int flags = bfd_getl32 (eidc->flags); -- unsigned char *p; -- -- fprintf (file, _("IDC - Ident Consistency check\n")); -- fprintf (file, _(" flags : 0x%08x"), flags); -- if (flags & EIDC__V_BINIDENT) -- fputs (" BINDENT", file); -- fputc ('\n', file); -- fprintf (file, _(" id match : %x\n"), -- (flags >> EIDC__V_IDMATCH_SH) & EIDC__V_IDMATCH_MASK); -- fprintf (file, _(" error severity: %x\n"), -- (flags >> EIDC__V_ERRSEV_SH) & EIDC__V_ERRSEV_MASK); -- p = eidc->name; -- rest = len - (p - (unsigned char *) e); -- fprintf (file, _(" entity name : %.*s\n"), -- p[0] > rest - 1 ? rest - 1 : p[0], p + 1); -- if (rest > 1u + p[0]) -- { -- rest -= 1 + p[0]; -- p += 1 + p[0]; -- fprintf (file, _(" object name : %.*s\n"), -- p[0] > rest - 1 ? rest - 1 : p[0], p + 1); -- if (rest > 1u + p[0]) -- { -- rest -= 1 + p[0]; -- p += 1 + p[0]; -- if (flags & EIDC__V_BINIDENT) -- { -- if (rest >= 4) -- fprintf (file, _(" binary ident : 0x%08x\n"), -- (unsigned) bfd_getl32 (p)); -- } -- else -- fprintf (file, _(" ascii ident : %.*s\n"), -- p[0] > rest - 1 ? rest - 1 : p[0], p + 1); -- } -- } -- } -- break; -- case EGSD__C_SYMG: -- /*{ -- struct vms_egst *egst = (struct vms_egst *)e; -- unsigned int flags = bfd_getl16 (egst->header.flags);*/ -- if (len >= offsetof (struct vms_egst, name)) -- { -- struct vms_egst *egst = (struct vms_egst *) e; -- unsigned int flags = bfd_getl16 (egst->header.flags); -- -- /*fprintf (file, _("SYMG - Universal symbol definition\n")); -- fprintf (file, _(" flags: 0x%04x"), flags); -- exav_bfd_print_egsy_flags (flags, file); -- fputc ('\n', file); -- fprintf (file, _(" symbol vector offset: 0x%08x\n"), -- (unsigned)bfd_getl32 (egst->value)); -- fprintf (file, _(" entry point: 0x%08x\n"), -- (unsigned)bfd_getl32 (egst->lp_1)); -- fprintf (file, _(" proc descr : 0x%08x\n"), -- (unsigned)bfd_getl32 (egst->lp_2)); -- fprintf (file, _(" psect index: %u\n"), -- (unsigned)bfd_getl32 (egst->psindx)); -- fprintf (file, _(" name : %.*s\n"), -- egst->namlng, egst->name); -- }*/ -- fprintf (file, _("SYMG - Universal symbol definition\n")); -- fprintf (file, _(" flags: 0x%04x"), flags); -- exav_bfd_print_egsy_flags (flags, file); -- fputc ('\n', file); -- fprintf (file, _(" symbol vector offset: 0x%08x\n"), -- (unsigned) bfd_getl32 (egst->value)); -- fprintf (file, _(" entry point: 0x%08x\n"), -- (unsigned) bfd_getl32 (egst->lp_1)); -- fprintf (file, _(" proc descr : 0x%08x\n"), -- (unsigned) bfd_getl32 (egst->lp_2)); -- fprintf (file, _(" psect index: %u\n"), -- (unsigned) bfd_getl32 (egst->psindx)); -- rest = len - offsetof (struct vms_egst, name); -- fprintf (file, _(" name : %.*s\n"), -- egst->namlng > rest ? rest : egst->namlng, -- egst->name); -- } -- break; -- case EGSD__C_SYMV: -- /*{ -- struct vms_esdfv *esdfv = (struct vms_esdfv *)e; -- unsigned int flags = bfd_getl16 (esdfv->flags);*/ -- if (len >= offsetof (struct vms_esdfv, name)) -- { -- struct vms_esdfv *esdfv = (struct vms_esdfv *) e; -- unsigned int flags = bfd_getl16 (esdfv->flags); -- -- /*fprintf (file, _("SYMV - Vectored symbol definition\n")); -- fprintf (file, _(" flags: 0x%04x"), flags); -- exav_bfd_print_egsy_flags (flags, file); -- fputc ('\n', file); -- fprintf (file, _(" vector : 0x%08x\n"), -- (unsigned)bfd_getl32 (esdfv->vector)); -- fprintf (file, _(" psect offset: %u\n"), -- (unsigned)bfd_getl32 (esdfv->value)); -- fprintf (file, _(" psect index : %u\n"), -- (unsigned)bfd_getl32 (esdfv->psindx)); -- fprintf (file, _(" name : %.*s\n"), -- esdfv->namlng, esdfv->name); -- }*/ -- fprintf (file, _("SYMV - Vectored symbol definition\n")); -- fprintf (file, _(" flags: 0x%04x"), flags); -- exav_bfd_print_egsy_flags (flags, file); -- fputc ('\n', file); -- fprintf (file, _(" vector : 0x%08x\n"), -- (unsigned) bfd_getl32 (esdfv->vector)); -- fprintf (file, _(" psect offset: %u\n"), -- (unsigned) bfd_getl32 (esdfv->value)); -- fprintf (file, _(" psect index : %u\n"), -- (unsigned) bfd_getl32 (esdfv->psindx)); -- rest = len - offsetof (struct vms_esdfv, name); -- fprintf (file, _(" name : %.*s\n"), -- esdfv->namlng > rest ? rest : esdfv->namlng, -- esdfv->name); -- } -- break; -- case EGSD__C_SYMM: -- /*{ -- struct vms_esdfm *esdfm = (struct vms_esdfm *)e; -- unsigned int flags = bfd_getl16 (esdfm->flags);*/ -- if (len >= offsetof (struct vms_esdfm, name)) -- { -- struct vms_esdfm *esdfm = (struct vms_esdfm *) e; -- unsigned int flags = bfd_getl16 (esdfm->flags); -- -- /*fprintf (file, _("SYMM - Global symbol definition with version\n")); -- fprintf (file, _(" flags: 0x%04x"), flags); -- exav_bfd_print_egsy_flags (flags, file); -- fputc ('\n', file); -- fprintf (file, _(" version mask: 0x%08x\n"), -- (unsigned)bfd_getl32 (esdfm->version_mask)); -- fprintf (file, _(" psect offset: %u\n"), -- (unsigned)bfd_getl32 (esdfm->value)); -- fprintf (file, _(" psect index : %u\n"), -- (unsigned)bfd_getl32 (esdfm->psindx)); -- fprintf (file, _(" name : %.*s\n"), -- esdfm->namlng, esdfm->name); -- }*/ -- fprintf (file, -- _("SYMM - Global symbol definition with version\n")); -- fprintf (file, _(" flags: 0x%04x"), flags); -- exav_bfd_print_egsy_flags (flags, file); -- fputc ('\n', file); -- fprintf (file, _(" version mask: 0x%08x\n"), -- (unsigned)bfd_getl32 (esdfm->version_mask)); -- fprintf (file, _(" psect offset: %u\n"), -- (unsigned)bfd_getl32 (esdfm->value)); -- fprintf (file, _(" psect index : %u\n"), -- (unsigned)bfd_getl32 (esdfm->psindx)); -- rest = len - offsetof (struct vms_esdfm, name); -- fprintf (file, _(" name : %.*s\n"), -- esdfm->namlng > rest ? rest : esdfm->namlng, -- esdfm->name); -- } -- break; -- default: -- fprintf (file, _("unhandled egsd entry type %u\n"), type); -- break; -- } -- off += len; -- } --} -- --static void --evax_bfd_print_hex (FILE *file, const char *pfx, -- const unsigned char *buf, unsigned int len) --{ -- unsigned int i; -- unsigned int n; -- -- n = 0; -- for (i = 0; i < len; i++) -- { -- if (n == 0) -- fputs (pfx, file); -- fprintf (file, " %02x", buf[i]); -- n++; -- if (n == 16) -- { -- n = 0; -- fputc ('\n', file); -- } -- } -- if (n != 0) -- fputc ('\n', file); --} -- --static void --evax_bfd_print_etir_stc_ir (FILE *file, const unsigned char *buf, -- unsigned int len, int is_ps) --//evax_bfd_print_etir_stc_ir (FILE *file, const unsigned char *buf, int is_ps) --{ -- if (is_ps ? len < 44 : len < 33) -- return; -- -- /* xgettext:c-format */ -- fprintf (file, _(" linkage index: %u, replacement insn: 0x%08x\n"), -- (unsigned)bfd_getl32 (buf), -- (unsigned)bfd_getl32 (buf + 16)); -- /* xgettext:c-format */ -- fprintf (file, _(" psect idx 1: %u, offset 1: 0x%08x %08x\n"), -- (unsigned)bfd_getl32 (buf + 4), -- (unsigned)bfd_getl32 (buf + 12), -- (unsigned)bfd_getl32 (buf + 8)); -- /* xgettext:c-format */ -- fprintf (file, _(" psect idx 2: %u, offset 2: 0x%08x %08x\n"), -- (unsigned)bfd_getl32 (buf + 20), -- (unsigned)bfd_getl32 (buf + 28), -- (unsigned)bfd_getl32 (buf + 24)); -- if (is_ps) -- /* xgettext:c-format */ -- fprintf (file, _(" psect idx 3: %u, offset 3: 0x%08x %08x\n"), -- (unsigned)bfd_getl32 (buf + 32), -- (unsigned)bfd_getl32 (buf + 40), -- (unsigned)bfd_getl32 (buf + 36)); -- else -- //fprintf (file, _(" global name: %.*s\n"), buf[32], buf + 33); -- fprintf (file, _(" global name: %.*s\n"), -- buf[32] > len - 33 ? len - 33 : buf[32], -- buf + 33); --} -- --static void --evax_bfd_print_etir (FILE *file, const char *name, -- unsigned char *rec, unsigned int rec_len) --{ -- unsigned int off = sizeof (struct vms_eobjrec); -- //unsigned int off = sizeof (struct vms_egsd); -- //unsigned int sec_len = 0; -- -- /* xgettext:c-format */ -- fprintf (file, _(" %s (len=%u):\n"), name, (unsigned) rec_len); -- if (rec_len < sizeof (struct vms_eobjrec) + sizeof (struct vms_etir)) -- return; -- //fprintf (file, _(" %s (len=%u+%u):\n"), name, --// (unsigned)(rec_len - sizeof (struct vms_eobjrec)), --// (unsigned)sizeof (struct vms_eobjrec)); -- -- while (off <= rec_len - sizeof (struct vms_etir)) -- //for (off = sizeof (struct vms_eobjrec); off < rec_len; ) -- { -- struct vms_etir *etir = (struct vms_etir *)(rec + off); -- unsigned char *buf; -- unsigned int type; -- unsigned int size; -- unsigned int rest; -- -- type = bfd_getl16 (etir->rectyp); -- size = bfd_getl16 (etir->size); -- buf = rec + off + sizeof (struct vms_etir); -- -- if (size < sizeof (struct vms_etir) || size > rec_len - off) -- //if (off + size > rec_len || off + size < off) -- { -- fprintf (file, _(" Erroneous length\n")); -- //fprintf (file, _(" Error: length larger than remaining space in record\n")); -- return; -- } -- -- /* xgettext:c-format */ -- fprintf (file, _(" (type: %3u, size: %3u): "), type, size); -- rest = size - sizeof (struct vms_etir); -- //fprintf (file, _(" (type: %3u, size: 4+%3u): "), type, size - 4); -- switch (type) -- { -- case ETIR__C_STA_GBL: -- if (rest >= 1) -- fprintf (file, _("STA_GBL (stack global) %.*s\n"), -- buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1); -- //fprintf (file, _("STA_GBL (stack global) %.*s\n"), -- // buf[0], buf + 1); -- break; -- case ETIR__C_STA_LW: -- fprintf (file, _("STA_LW (stack longword)")); -- if (rest >= 4) -- fprintf (file, " 0x%08x\n", -- (unsigned) bfd_getl32 (buf)); -- //fprintf (file, _("STA_LW (stack longword) 0x%08x\n"), -- // (unsigned)bfd_getl32 (buf)); -- break; -- case ETIR__C_STA_QW: -- fprintf (file, _("STA_QW (stack quadword)")); -- if (rest >= 8) -- fprintf (file, " 0x%08x %08x\n", -- (unsigned) bfd_getl32 (buf + 4), -- (unsigned) bfd_getl32 (buf + 0)); -- //fprintf (file, _("STA_QW (stack quadword) 0x%08x %08x\n"), -- // (unsigned)bfd_getl32 (buf + 4), -- // (unsigned)bfd_getl32 (buf + 0)); -- break; -- case ETIR__C_STA_PQ: -- fprintf (file, _("STA_PQ (stack psect base + offset)\n")); -- if (rest >= 12) -- /* xgettext:c-format */ -- fprintf (file, _(" psect: %u, offset: 0x%08x %08x\n"), -- (unsigned) bfd_getl32 (buf + 0), -- (unsigned) bfd_getl32 (buf + 8), -- (unsigned) bfd_getl32 (buf + 4)); -- /*fprintf (file, _(" psect: %u, offset: 0x%08x %08x\n"), -- (unsigned)bfd_getl32 (buf + 0), -- (unsigned)bfd_getl32 (buf + 8), -- (unsigned)bfd_getl32 (buf + 4));*/ -- break; -- case ETIR__C_STA_LI: -- fprintf (file, _("STA_LI (stack literal)\n")); -- break; -- case ETIR__C_STA_MOD: -- fprintf (file, _("STA_MOD (stack module)\n")); -- break; -- case ETIR__C_STA_CKARG: -- fprintf (file, _("STA_CKARG (compare procedure argument)\n")); -- break; -- -- case ETIR__C_STO_B: -- fprintf (file, _("STO_B (store byte)\n")); -- break; -- case ETIR__C_STO_W: -- fprintf (file, _("STO_W (store word)\n")); -- break; -- case ETIR__C_STO_LW: -- fprintf (file, _("STO_LW (store longword)\n")); -- break; -- case ETIR__C_STO_QW: -- fprintf (file, _("STO_QW (store quadword)\n")); -- break; -- case ETIR__C_STO_IMMR: -- /*{ -- unsigned int len = bfd_getl32 (buf); -- fprintf (file, -- _("STO_IMMR (store immediate repeat) %u bytes\n"), -- len); -- evax_bfd_print_hex (file, " ", buf + 4, len); -- sec_len += len; -- }*/ -- if (rest >= 4) -- { -- unsigned int rpt = bfd_getl32 (buf); -- fprintf (file, -- _("STO_IMMR (store immediate repeat) %u bytes\n"), -- rpt); -- if (rpt > rest - 4) -- rpt = rest - 4; -- evax_bfd_print_hex (file, " ", buf + 4, rpt); -- } -- break; -- case ETIR__C_STO_GBL: -- /*fprintf (file, _("STO_GBL (store global) %.*s\n"), -- buf[0], buf + 1);*/ -- if (rest >= 1) -- fprintf (file, _("STO_GBL (store global) %.*s\n"), -- buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1); -- break; -- case ETIR__C_STO_CA: -- /*fprintf (file, _("STO_CA (store code address) %.*s\n"), -- buf[0], buf + 1);*/ -- if (rest >= 1) -- fprintf (file, _("STO_CA (store code address) %.*s\n"), -- buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1); -- break; -- case ETIR__C_STO_RB: -- fprintf (file, _("STO_RB (store relative branch)\n")); -- break; -- case ETIR__C_STO_AB: -- fprintf (file, _("STO_AB (store absolute branch)\n")); -- break; -- case ETIR__C_STO_OFF: -- fprintf (file, _("STO_OFF (store offset to psect)\n")); -- break; -- case ETIR__C_STO_IMM: -- /*{ -- unsigned int len = bfd_getl32 (buf); -- fprintf (file, -- _("STO_IMM (store immediate) %u bytes\n"), -- len); -- evax_bfd_print_hex (file, " ", buf + 4, len); -- sec_len += len; -- }*/ -- if (rest >= 4) -- { -- unsigned int rpt = bfd_getl32 (buf); -- fprintf (file, -- _("STO_IMM (store immediate) %u bytes\n"), -- rpt); -- if (rpt > rest - 4) -- rpt = rest - 4; -- evax_bfd_print_hex (file, " ", buf + 4, rpt); -- } -- break; -- case ETIR__C_STO_GBL_LW: -- /*fprintf (file, _("STO_GBL_LW (store global longword) %.*s\n"), -- buf[0], buf + 1);*/ -- if (rest >= 1) -- fprintf (file, _("STO_GBL_LW (store global longword) %.*s\n"), -- buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1); -- break; -- case ETIR__C_STO_LP_PSB: -- fprintf (file, _("STO_OFF (store LP with procedure signature)\n")); -- break; -- case ETIR__C_STO_HINT_GBL: -- fprintf (file, _("STO_BR_GBL (store branch global) *todo*\n")); -- break; -- case ETIR__C_STO_HINT_PS: -- fprintf (file, _("STO_BR_PS (store branch psect + offset) *todo*\n")); -- break; -- -- case ETIR__C_OPR_NOP: -- fprintf (file, _("OPR_NOP (no-operation)\n")); -- break; -- case ETIR__C_OPR_ADD: -- fprintf (file, _("OPR_ADD (add)\n")); -- break; -- case ETIR__C_OPR_SUB: -- fprintf (file, _("OPR_SUB (subtract)\n")); -- break; -- case ETIR__C_OPR_MUL: -- fprintf (file, _("OPR_MUL (multiply)\n")); -- break; -- case ETIR__C_OPR_DIV: -- fprintf (file, _("OPR_DIV (divide)\n")); -- break; -- case ETIR__C_OPR_AND: -- fprintf (file, _("OPR_AND (logical and)\n")); -- break; -- case ETIR__C_OPR_IOR: -- fprintf (file, _("OPR_IOR (logical inclusive or)\n")); -- break; -- case ETIR__C_OPR_EOR: -- fprintf (file, _("OPR_EOR (logical exclusive or)\n")); -- break; -- case ETIR__C_OPR_NEG: -- fprintf (file, _("OPR_NEG (negate)\n")); -- break; -- case ETIR__C_OPR_COM: -- fprintf (file, _("OPR_COM (complement)\n")); -- break; -- case ETIR__C_OPR_INSV: -- fprintf (file, _("OPR_INSV (insert field)\n")); -- break; -- case ETIR__C_OPR_ASH: -- fprintf (file, _("OPR_ASH (arithmetic shift)\n")); -- break; -- case ETIR__C_OPR_USH: -- fprintf (file, _("OPR_USH (unsigned shift)\n")); -- break; -- case ETIR__C_OPR_ROT: -- fprintf (file, _("OPR_ROT (rotate)\n")); -- break; -- case ETIR__C_OPR_SEL: -- fprintf (file, _("OPR_SEL (select)\n")); -- break; -- case ETIR__C_OPR_REDEF: -- fprintf (file, _("OPR_REDEF (redefine symbol to curr location)\n")); -- break; -- case ETIR__C_OPR_DFLIT: -- fprintf (file, _("OPR_REDEF (define a literal)\n")); -- break; -- -- case ETIR__C_STC_LP: -- fprintf (file, _("STC_LP (store cond linkage pair)\n")); -- break; -- case ETIR__C_STC_LP_PSB: -- fprintf (file, -- _("STC_LP_PSB (store cond linkage pair + signature)\n")); -- /* xgettext:c-format */ -- /*fprintf (file, _(" linkage index: %u, procedure: %.*s\n"), -- (unsigned)bfd_getl32 (buf), buf[4], buf + 5); -- buf += 4 + 1 + buf[4]; -- fprintf (file, _(" signature: %.*s\n"), buf[0], buf + 1);*/ -- if (rest >= 5) -- { -- /* xgettext:c-format */ -- fprintf (file, _(" linkage index: %u, procedure: %.*s\n"), -- (unsigned) bfd_getl32 (buf), -- buf[4] > rest - 5 ? rest - 5 : buf[4], buf + 5); -- if (rest > 4 + 1u + buf[4]) -- { -- rest -= 4 + 1 + buf[4]; -- buf += 4 + 1 + buf[4]; -- fprintf (file, _(" signature: %.*s\n"), -- buf[0] > rest - 1 ? rest - 1: buf[0], buf + 1); -- } -- } -- break; -- case ETIR__C_STC_GBL: -- fprintf (file, _("STC_GBL (store cond global)\n")); -- /* xgettext:c-format */ -- /*fprintf (file, _(" linkage index: %u, global: %.*s\n"), -- (unsigned)bfd_getl32 (buf), buf[4], buf + 5);*/ -- if (rest >= 5) -- /* xgettext:c-format */ -- fprintf (file, _(" linkage index: %u, global: %.*s\n"), -- (unsigned) bfd_getl32 (buf), -- buf[4] > rest - 5 ? rest - 5 : buf[4], buf + 5); -- break; -- case ETIR__C_STC_GCA: -- fprintf (file, _("STC_GCA (store cond code address)\n")); -- /* xgettext:c-format */ -- /*fprintf (file, _(" linkage index: %u, procedure name: %.*s\n"), -- (unsigned)bfd_getl32 (buf), buf[4], buf + 5);*/ -- if (rest >= 5) -- /* xgettext:c-format */ -- fprintf (file, _(" linkage index: %u, procedure name: %.*s\n"), -- (unsigned) bfd_getl32 (buf), -- buf[4] > rest - 5 ? rest - 5 : buf[4], buf + 5); -- break; -- case ETIR__C_STC_PS: -- fprintf (file, _("STC_PS (store cond psect + offset)\n")); -- /*fprintf (file, -- _(" linkage index: %u, psect: %u, offset: 0x%08x %08x\n"), -- (unsigned)bfd_getl32 (buf), -- (unsigned)bfd_getl32 (buf + 4), -- (unsigned)bfd_getl32 (buf + 12), -- (unsigned)bfd_getl32 (buf + 8));*/ -- if (rest >= 16) -- fprintf (file, -- /* xgettext:c-format */ -- _(" linkage index: %u, psect: %u, offset: 0x%08x %08x\n"), -- (unsigned)bfd_getl32 (buf), -- (unsigned)bfd_getl32 (buf + 4), -- (unsigned)bfd_getl32 (buf + 12), -- (unsigned)bfd_getl32 (buf + 8)); -- break; -- case ETIR__C_STC_NOP_GBL: -- fprintf (file, _("STC_NOP_GBL (store cond NOP at global addr)\n")); -- //evax_bfd_print_etir_stc_ir (file, buf, 0); -- evax_bfd_print_etir_stc_ir (file, buf, rest, 0); -- break; -- case ETIR__C_STC_NOP_PS: -- fprintf (file, _("STC_NOP_PS (store cond NOP at psect + offset)\n")); -- //evax_bfd_print_etir_stc_ir (file, buf, 1); -- evax_bfd_print_etir_stc_ir (file, buf, rest, 1); -- break; -- case ETIR__C_STC_BSR_GBL: -- fprintf (file, _("STC_BSR_GBL (store cond BSR at global addr)\n")); -- //evax_bfd_print_etir_stc_ir (file, buf, 0); -- evax_bfd_print_etir_stc_ir (file, buf, rest, 0); -- break; -- case ETIR__C_STC_BSR_PS: -- fprintf (file, _("STC_BSR_PS (store cond BSR at psect + offset)\n")); -- //evax_bfd_print_etir_stc_ir (file, buf, 1); -- evax_bfd_print_etir_stc_ir (file, buf, rest, 1); -- break; -- case ETIR__C_STC_LDA_GBL: -- fprintf (file, _("STC_LDA_GBL (store cond LDA at global addr)\n")); -- //evax_bfd_print_etir_stc_ir (file, buf, 0); -- evax_bfd_print_etir_stc_ir (file, buf, rest, 0); -- break; -- case ETIR__C_STC_LDA_PS: -- fprintf (file, _("STC_LDA_PS (store cond LDA at psect + offset)\n")); -- //evax_bfd_print_etir_stc_ir (file, buf, 1); -- evax_bfd_print_etir_stc_ir (file, buf, rest, 1); -- break; -- case ETIR__C_STC_BOH_GBL: -- fprintf (file, _("STC_BOH_GBL (store cond BOH at global addr)\n")); -- //evax_bfd_print_etir_stc_ir (file, buf, 0); -- evax_bfd_print_etir_stc_ir (file, buf, rest, 0); -- break; -- case ETIR__C_STC_BOH_PS: -- fprintf (file, _("STC_BOH_PS (store cond BOH at psect + offset)\n")); -- //evax_bfd_print_etir_stc_ir (file, buf, 1); -- evax_bfd_print_etir_stc_ir (file, buf, rest, 1); -- break; -- case ETIR__C_STC_NBH_GBL: -- fprintf (file, -- _("STC_NBH_GBL (store cond or hint at global addr)\n")); -- break; -- case ETIR__C_STC_NBH_PS: -- fprintf (file, -- _("STC_NBH_PS (store cond or hint at psect + offset)\n")); -- break; -- -- case ETIR__C_CTL_SETRB: -- fprintf (file, _("CTL_SETRB (set relocation base)\n")); -- //sec_len += 4; -- break; -- case ETIR__C_CTL_AUGRB: -- /*{ -- unsigned int val = bfd_getl32 (buf); -- fprintf (file, _("CTL_AUGRB (augment relocation base) %u\n"), val); -- }*/ -- if (rest >= 4) -- { -- unsigned int val = bfd_getl32 (buf); -- fprintf (file, _("CTL_AUGRB (augment relocation base) %u\n"), -- val); -- } -- break; -- case ETIR__C_CTL_DFLOC: -- fprintf (file, _("CTL_DFLOC (define location)\n")); -- break; -- case ETIR__C_CTL_STLOC: -- fprintf (file, _("CTL_STLOC (set location)\n")); -- break; -- case ETIR__C_CTL_STKDL: -- fprintf (file, _("CTL_STKDL (stack defined location)\n")); -- break; -- default: -- fprintf (file, _("*unhandled*\n")); -- break; -- } -- off += size; -- } --} -- --static void --evax_bfd_print_eobj (struct bfd *abfd, FILE *file) --{ -- bfd_boolean is_first = TRUE; -- bfd_boolean has_records = FALSE; -- -- while (1) -- { -- unsigned int rec_len; -- unsigned int pad_len; -- unsigned char *rec; -- unsigned int hdr_size; -- unsigned int type; -- -- if (is_first) -- { -- unsigned char buf[6]; -- -- is_first = FALSE; -- -- /* Read 6 bytes. */ -- if (bfd_bread (buf, sizeof (buf), abfd) != sizeof (buf)) -- { -- fprintf (file, _("cannot read GST record length\n")); -- return; -- } -- rec_len = bfd_getl16 (buf + 0); -- if (rec_len == bfd_getl16 (buf + 4) -- && bfd_getl16 (buf + 2) == EOBJ__C_EMH) -- { -- /* The format is raw: record-size, type, record-size. */ -- has_records = TRUE; -- pad_len = (rec_len + 1) & ~1U; -- hdr_size = 4; -- } -- else if (rec_len == EOBJ__C_EMH) -- { -- has_records = FALSE; -- pad_len = bfd_getl16 (buf + 2); -- hdr_size = 6; -- } -- else -- { -- /* Ill-formed. */ -- fprintf (file, _("cannot find EMH in first GST record\n")); -- return; -- } -- rec = bfd_malloc (pad_len); -- memcpy (rec, buf + sizeof (buf) - hdr_size, hdr_size); -- } -- else -- { -- unsigned int rec_len2 = 0; -- unsigned char hdr[4]; -- -- if (has_records) -- { -- unsigned char buf_len[2]; -- -- if (bfd_bread (buf_len, sizeof (buf_len), abfd) -- != sizeof (buf_len)) -- { -- fprintf (file, _("cannot read GST record length\n")); -- return; -- } -- rec_len2 = (unsigned)bfd_getl16 (buf_len); -- } -- -- if (bfd_bread (hdr, sizeof (hdr), abfd) != sizeof (hdr)) -- { -- fprintf (file, _("cannot read GST record header\n")); -- return; -- } -- rec_len = (unsigned)bfd_getl16 (hdr + 2); -- if (has_records) -- pad_len = (rec_len + 1) & ~1U; -- else -- pad_len = rec_len; -- rec = bfd_malloc (pad_len); -- memcpy (rec, hdr, sizeof (hdr)); -- hdr_size = sizeof (hdr); -- if (has_records && rec_len2 != rec_len) -- { -- fprintf (file, _(" corrupted GST\n")); -- break; -- } -- } -- -- if (bfd_bread (rec + hdr_size, pad_len - hdr_size, abfd) -- != pad_len - hdr_size) -- { -- fprintf (file, _("cannot read GST record\n")); -- return; -- } -- -- type = (unsigned)bfd_getl16 (rec); -- -- switch (type) -- { -- case EOBJ__C_EMH: -- evax_bfd_print_emh (file, rec, rec_len); -- break; -- case EOBJ__C_EGSD: -- evax_bfd_print_egsd (file, rec, rec_len); -- break; -- case EOBJ__C_EEOM: -- evax_bfd_print_eeom (file, rec, rec_len); -- free (rec); -- return; -- break; -- case EOBJ__C_ETIR: -- evax_bfd_print_etir (file, "ETIR", rec, rec_len); -- break; -- case EOBJ__C_EDBG: -- evax_bfd_print_etir (file, "EDBG", rec, rec_len); -- break; -- case EOBJ__C_ETBT: -- evax_bfd_print_etir (file, "ETBT", rec, rec_len); -- break; -- default: -- fprintf (file, _(" unhandled EOBJ record type %u\n"), type); -- break; -- } -- free (rec); -- } --} -- --static void --evax_bfd_print_relocation_records (FILE *file, const unsigned char *buf, -- size_t buf_size, size_t off, --//evax_bfd_print_relocation_records (FILE *file, const unsigned char *rel, -- unsigned int stride) --{ -- //while (1) -- while (off <= buf_size - 8) -- { -- unsigned int base; -- unsigned int count; -- unsigned int j; -- -- //count = bfd_getl32 (rel + 0); -- count = bfd_getl32 (buf + off + 0); -- -- if (count == 0) -- break; -- //base = bfd_getl32 (rel + 4); -- base = bfd_getl32 (buf + off + 4); -- -- /* xgettext:c-format */ -- fprintf (file, _(" bitcount: %u, base addr: 0x%08x\n"), -- count, base); -- -- //rel += 8; -- //for (j = 0; count > 0; j += 4, count -= 32) -- off += 8; -- for (j = 0; count > 0 && off <= buf_size - 4; j += 4, count -= 32) -- { -- unsigned int k; -- unsigned int n = 0; -- unsigned int val; -- -- //val = bfd_getl32 (rel); -- //rel += 4; -- val = bfd_getl32 (buf + off); -- off += 4; -- -- /* xgettext:c-format */ -- fprintf (file, _(" bitmap: 0x%08x (count: %u):\n"), val, count); -- -- for (k = 0; k < 32; k++) -- if (val & (1u << k)) -- { -- if (n == 0) -- fputs (" ", file); -- fprintf (file, _(" %08x"), base + (j * 8 + k) * stride); -- n++; -- if (n == 8) -- { -- fputs ("\n", file); -- n = 0; -- } -- } -- if (n) -- fputs ("\n", file); -- } -- } --} -- --static void --//evax_bfd_print_address_fixups (FILE *file, const unsigned char *rel) --evax_bfd_print_address_fixups (FILE *file, const unsigned char *buf, -- size_t buf_size, size_t off) --{ -- //while (1) -- while (off <= buf_size - 8) -- { -- unsigned int j; -- unsigned int count; -- -- //count = bfd_getl32 (rel + 0); -- count = bfd_getl32 (buf + off + 0); -- if (count == 0) -- return; -- /* xgettext:c-format */ -- fprintf (file, _(" image %u (%u entries)\n"), -- //(unsigned)bfd_getl32 (rel + 4), count); -- //rel += 8; -- //for (j = 0; j < count; j++) -- (unsigned) bfd_getl32 (buf + off + 4), count); -- off += 8; -- for (j = 0; j < count && off <= buf_size - 8; j++) -- { -- /* xgettext:c-format */ -- fprintf (file, _(" offset: 0x%08x, val: 0x%08x\n"), -- //(unsigned)bfd_getl32 (rel + 0), -- //(unsigned)bfd_getl32 (rel + 4)); -- //rel += 8; -- (unsigned) bfd_getl32 (buf + off + 0), -- (unsigned) bfd_getl32 (buf + off + 4)); -- off += 8; -- } -- } --} -- --static void --//evax_bfd_print_reference_fixups (FILE *file, const unsigned char *rel) --evax_bfd_print_reference_fixups (FILE *file, const unsigned char *buf, -- size_t buf_size, size_t off) --{ -- unsigned int count; -- -- //while (1) -- while (off <= buf_size - 8) -- { -- unsigned int j; -- unsigned int n = 0; -- -- //count = bfd_getl32 (rel + 0); -- count = bfd_getl32 (buf + off + 0); -- if (count == 0) -- break; -- /* xgettext:c-format */ -- fprintf (file, _(" image %u (%u entries), offsets:\n"), -- //(unsigned)bfd_getl32 (rel + 4), count); -- //rel += 8; -- //for (j = 0; j < count; j++) -- (unsigned) bfd_getl32 (buf + off + 4), count); -- off += 8; -- for (j = 0; j < count && off <= buf_size - 4; j++) -- { -- if (n == 0) -- fputs (" ", file); -- //fprintf (file, _(" 0x%08x"), (unsigned)bfd_getl32 (rel)); -- fprintf (file, _(" 0x%08x"), (unsigned) bfd_getl32 (buf + off)); -- n++; -- if (n == 7) -- { -- fputs ("\n", file); -- n = 0; -- } -- //rel += 4; -- off += 4; -- } -- if (n) -- fputs ("\n", file); -- } --} -- --static void --evax_bfd_print_indent (int indent, FILE *file) --{ -- for (; indent; indent--) -- fputc (' ', file); --} -- --static const char * --evax_bfd_get_dsc_name (unsigned int v) --{ -- switch (v) -- { -- case DSC__K_DTYPE_Z: -- return "Z (Unspecified)"; -- case DSC__K_DTYPE_V: -- return "V (Bit)"; -- case DSC__K_DTYPE_BU: -- return "BU (Byte logical)"; -- case DSC__K_DTYPE_WU: -- return "WU (Word logical)"; -- case DSC__K_DTYPE_LU: -- return "LU (Longword logical)"; -- case DSC__K_DTYPE_QU: -- return "QU (Quadword logical)"; -- case DSC__K_DTYPE_B: -- return "B (Byte integer)"; -- case DSC__K_DTYPE_W: -- return "W (Word integer)"; -- case DSC__K_DTYPE_L: -- return "L (Longword integer)"; -- case DSC__K_DTYPE_Q: -- return "Q (Quadword integer)"; -- case DSC__K_DTYPE_F: -- return "F (Single-precision floating)"; -- case DSC__K_DTYPE_D: -- return "D (Double-precision floating)"; -- case DSC__K_DTYPE_FC: -- return "FC (Complex)"; -- case DSC__K_DTYPE_DC: -- return "DC (Double-precision Complex)"; -- case DSC__K_DTYPE_T: -- return "T (ASCII text string)"; -- case DSC__K_DTYPE_NU: -- return "NU (Numeric string, unsigned)"; -- case DSC__K_DTYPE_NL: -- return "NL (Numeric string, left separate sign)"; -- case DSC__K_DTYPE_NLO: -- return "NLO (Numeric string, left overpunched sign)"; -- case DSC__K_DTYPE_NR: -- return "NR (Numeric string, right separate sign)"; -- case DSC__K_DTYPE_NRO: -- return "NRO (Numeric string, right overpunched sig)"; -- case DSC__K_DTYPE_NZ: -- return "NZ (Numeric string, zoned sign)"; -- case DSC__K_DTYPE_P: -- return "P (Packed decimal string)"; -- case DSC__K_DTYPE_ZI: -- return "ZI (Sequence of instructions)"; -- case DSC__K_DTYPE_ZEM: -- return "ZEM (Procedure entry mask)"; -- case DSC__K_DTYPE_DSC: -- return "DSC (Descriptor, used for arrays of dyn strings)"; -- case DSC__K_DTYPE_OU: -- return "OU (Octaword logical)"; -- case DSC__K_DTYPE_O: -- return "O (Octaword integer)"; -- case DSC__K_DTYPE_G: -- return "G (Double precision G floating, 64 bit)"; -- case DSC__K_DTYPE_H: -- return "H (Quadruple precision floating, 128 bit)"; -- case DSC__K_DTYPE_GC: -- return "GC (Double precision complex, G floating)"; -- case DSC__K_DTYPE_HC: -- return "HC (Quadruple precision complex, H floating)"; -- case DSC__K_DTYPE_CIT: -- return "CIT (COBOL intermediate temporary)"; -- case DSC__K_DTYPE_BPV: -- return "BPV (Bound Procedure Value)"; -- case DSC__K_DTYPE_BLV: -- return "BLV (Bound Label Value)"; -- case DSC__K_DTYPE_VU: -- return "VU (Bit Unaligned)"; -- case DSC__K_DTYPE_ADT: -- return "ADT (Absolute Date-Time)"; -- case DSC__K_DTYPE_VT: -- return "VT (Varying Text)"; -- case DSC__K_DTYPE_T2: -- return "T2 (16-bit char)"; -- case DSC__K_DTYPE_VT2: -- return "VT2 (16-bit varying char)"; -- default: -- return "?? (unknown)"; -- } --} -- --static void --//evax_bfd_print_desc (const unsigned char *buf, int indent, FILE *file) --evax_bfd_print_desc (const unsigned char *buf, unsigned int bufsize, -- int indent, FILE *file) --{ -- if (bufsize < 8) -- return; -- -- unsigned char bclass = buf[3]; -- unsigned char dtype = buf[2]; -- unsigned int len = (unsigned)bfd_getl16 (buf); -- unsigned int pointer = (unsigned)bfd_getl32 (buf + 4); -- -- evax_bfd_print_indent (indent, file); -- -- if (len == 1 && pointer == 0xffffffffUL) -- { -- /* 64 bits. */ -- fprintf (file, _("64 bits *unhandled*\n")); -- } -- else -- { -- /* xgettext:c-format */ -- fprintf (file, _("class: %u, dtype: %u, length: %u, pointer: 0x%08x\n"), -- bclass, dtype, len, pointer); -- switch (bclass) -- { -- case DSC__K_CLASS_NCA: -- { -- const struct vms_dsc_nca *dsc = (const void *)buf; -- unsigned int i; -- const unsigned char *b; -- -- evax_bfd_print_indent (indent, file); -- fprintf (file, _("non-contiguous array of %s\n"), -- evax_bfd_get_dsc_name (dsc->dtype)); -- if (bufsize >= sizeof (*dsc)) -- { -- evax_bfd_print_indent (indent + 1, file); -- fprintf (file, -- /* xgettext:c-format */ -- _("dimct: %u, aflags: 0x%02x, digits: %u, scale: %u\n"), -- dsc->dimct, dsc->aflags, dsc->digits, dsc->scale); -- evax_bfd_print_indent (indent + 1, file); -- fprintf (file, -- /* xgettext:c-format */ -- _("arsize: %u, a0: 0x%08x\n"), -- (unsigned) bfd_getl32 (dsc->arsize), -- (unsigned) bfd_getl32 (dsc->a0)); -- evax_bfd_print_indent (indent + 1, file); -- fprintf (file, _("Strides:\n")); -- b = buf + sizeof (*dsc); -- bufsize -= sizeof (*dsc); -- for (i = 0; i < dsc->dimct; i++) -- { -- if (bufsize < 4) -- break; -- } -- } -- break; -- case DSC__K_CLASS_UBS: -- { -- const struct vms_dsc_ubs *ubs = (const void *)buf; -- -- evax_bfd_print_indent (indent, file); -- fprintf (file, _("unaligned bit-string of %s\n"), -- evax_bfd_get_dsc_name (ubs->dtype)); -- if (bufsize >= sizeof (*ubs)) -- { -- evax_bfd_print_indent (indent + 1, file); -- fprintf (file, -- /* xgettext:c-format */ -- _("base: %u, pos: %u\n"), -- (unsigned) bfd_getl32 (ubs->base), -- (unsigned) bfd_getl32 (ubs->pos)); -- } -- } -- break; -- default: -- fprintf (file, _("*unhandled*\n")); -- break; -- } -- } --} -- --static unsigned int --//evax_bfd_print_valspec (const unsigned char *buf, int indent, FILE *file) --evax_bfd_print_valspec (const unsigned char *buf, unsigned int bufsize, -- int indent, FILE *file) --{ -- if (bufsize < 5) -- return bufsize; -- -- unsigned int vflags = buf[0]; -- unsigned int value = (unsigned) bfd_getl32 (buf + 1); -- unsigned int len = 5; -- -- evax_bfd_print_indent (indent, file); -- /* xgettext:c-format */ -- fprintf (file, _("vflags: 0x%02x, value: 0x%08x "), vflags, value); -- buf += 5; -- bufsize -= 5; -- -- switch (vflags) -- { -- case DST__K_VFLAGS_NOVAL: -- fprintf (file, _("(no value)\n")); -- break; -- case DST__K_VFLAGS_NOTACTIVE: -- fprintf (file, _("(not active)\n")); -- break; -- case DST__K_VFLAGS_UNALLOC: -- fprintf (file, _("(not allocated)\n")); -- break; -- case DST__K_VFLAGS_DSC: -- fprintf (file, _("(descriptor)\n")); -- //evax_bfd_print_desc (buf + value, indent + 1, file); -- if (value <= bufsize) -- evax_bfd_print_desc (buf + value, bufsize - value, indent + 1, file); -- break; -- case DST__K_VFLAGS_TVS: -- fprintf (file, _("(trailing value)\n")); -- break; -- case DST__K_VS_FOLLOWS: -- fprintf (file, _("(value spec follows)\n")); -- break; -- case DST__K_VFLAGS_BITOFFS: -- fprintf (file, _("(at bit offset %u)\n"), value); -- break; -- default: -- /* xgettext:c-format */ -- fprintf (file, _("(reg: %u, disp: %u, indir: %u, kind: "), -- (vflags & DST__K_REGNUM_MASK) >> DST__K_REGNUM_SHIFT, -- vflags & DST__K_DISP ? 1 : 0, -- vflags & DST__K_INDIR ? 1 : 0); -- switch (vflags & DST__K_VALKIND_MASK) -- { -- case DST__K_VALKIND_LITERAL: -- fputs (_("literal"), file); -- break; -- case DST__K_VALKIND_ADDR: -- fputs (_("address"), file); -- break; -- case DST__K_VALKIND_DESC: -- fputs (_("desc"), file); -- break; -- case DST__K_VALKIND_REG: -- fputs (_("reg"), file); -- break; -- } -- fputs (")\n", file); -- break; -- } -- return len; --} -- --static void --//evax_bfd_print_typspec (const unsigned char *buf, int indent, FILE *file) --evax_bfd_print_typspec (const unsigned char *buf, unsigned int bufsize, -- int indent, FILE *file) --{ -- if (bufsize < 3) -- return; -- -- unsigned char kind = buf[2]; -- unsigned int len = (unsigned) bfd_getl16 (buf); -- -- evax_bfd_print_indent (indent, file); -- /* xgettext:c-format */ -- fprintf (file, _("len: %2u, kind: %2u "), len, kind); -- buf += 3; -- bufsize -= 3; -- switch (kind) -- { -- case DST__K_TS_ATOM: -- /* xgettext:c-format */ -- //fprintf (file, _("atomic, type=0x%02x %s\n"), -- // buf[0], evax_bfd_get_dsc_name (buf[0])); -- if (bufsize >= 1) -- fprintf (file, _("atomic, type=0x%02x %s\n"), -- buf[0], evax_bfd_get_dsc_name (buf[0])); -- break; -- case DST__K_TS_IND: -- //fprintf (file, _("indirect, defined at 0x%08x\n"), -- // (unsigned)bfd_getl32 (buf)); -- if (bufsize >= 4) -- fprintf (file, _("indirect, defined at 0x%08x\n"), -- (unsigned) bfd_getl32 (buf)); -- break; -- case DST__K_TS_TPTR: -- fprintf (file, _("typed pointer\n")); -- //evax_bfd_print_typspec (buf, indent + 1, file); -- evax_bfd_print_typspec (buf, bufsize, indent + 1, file); -- break; -- case DST__K_TS_PTR: -- fprintf (file, _("pointer\n")); -- break; -- case DST__K_TS_ARRAY: -- { -- const unsigned char *vs; -- unsigned int vs_len; -- unsigned int vec_len; -- unsigned int i; -- -- if (bufsize == 0) -- return; -- fprintf (file, _("array, dim: %u, bitmap: "), buf[0]); -- --bufsize; -- vec_len = (buf[0] + 1 + 7) / 8; -- for (i = 0; i < vec_len; i++) -- //fprintf (file, " %02x", buf[i + 1]); -- { -- if (bufsize == 0) -- break; -- fprintf (file, " %02x", buf[i + 1]); -- --bufsize; -- } -- fputc ('\n', file); -- if (bufsize == 0) -- return; -- vs = buf + 1 + vec_len; -- evax_bfd_print_indent (indent, file); -- fprintf (file, _("array descriptor:\n")); -- vs_len = evax_bfd_print_valspec (vs, bufsize, indent + 1, file); -- vs += vs_len; -- if (bufsize > vs_len) -- { -- bufsize -= vs_len; -- for (i = 0; i < buf[0] + 1U; i++) -- if (buf[1 + i / 8] & (1 << (i % 8))) -- { -- evax_bfd_print_indent (indent, file); -- if (i == 0) -- fprintf (file, _("type spec for element:\n")); -- else -- fprintf (file, _("type spec for subscript %u:\n"), i); -- evax_bfd_print_typspec (vs, bufsize, indent + 1, file); -- if (bufsize < 2) -- break; -- vs_len = bfd_getl16 (vs); -- if (bufsize <= vs_len) -- break; -- vs += vs_len; -- bufsize -= vs_len; -- } -- } -- } -- break; -- default: -- fprintf (file, _("*unhandled*\n")); -- } --} -- --static void --evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file) --{ -- unsigned int off = 0; -- unsigned int pc = 0; -- unsigned int line = 0; -- -- fprintf (file, _("Debug symbol table:\n")); -- -- while (dst_size > 0) -- { -- struct vms_dst_header dsth; -- unsigned int len; -- unsigned int type; -- unsigned char *buf; -- -- if (bfd_bread (&dsth, sizeof (dsth), abfd) != sizeof (dsth)) -- { -- fprintf (file, _("cannot read DST header\n")); -- return; -- } -- len = bfd_getl16 (dsth.length); -- type = bfd_getl16 (dsth.type); -- /* xgettext:c-format */ -- fprintf (file, _(" type: %3u, len: %3u (at 0x%08x): "), -- type, len, off); -- //if (len == 0) -- if (len < sizeof (dsth)) -- { -- fputc ('\n', file); -- break; -- } -- //len++; -- dst_size -= len; -- off += len; -- len -= sizeof (dsth); -- //buf = bfd_malloc (len); -- //if (bfd_bread (buf, len, abfd) != len) -- if (len == 0) -- buf = NULL; -- else -- { -- buf = _bfd_malloc_and_read (abfd, len, len); -- if (buf == NULL) -- { -- fprintf (file, _("cannot read DST symbol\n")); -- return; -- } -- } -- switch (type) -- { -- case DSC__K_DTYPE_V: -- case DSC__K_DTYPE_BU: -- case DSC__K_DTYPE_WU: -- case DSC__K_DTYPE_LU: -- case DSC__K_DTYPE_QU: -- case DSC__K_DTYPE_B: -- case DSC__K_DTYPE_W: -- case DSC__K_DTYPE_L: -- case DSC__K_DTYPE_Q: -- case DSC__K_DTYPE_F: -- case DSC__K_DTYPE_D: -- case DSC__K_DTYPE_FC: -- case DSC__K_DTYPE_DC: -- case DSC__K_DTYPE_T: -- case DSC__K_DTYPE_NU: -- case DSC__K_DTYPE_NL: -- case DSC__K_DTYPE_NLO: -- case DSC__K_DTYPE_NR: -- case DSC__K_DTYPE_NRO: -- case DSC__K_DTYPE_NZ: -- case DSC__K_DTYPE_P: -- case DSC__K_DTYPE_ZI: -- case DSC__K_DTYPE_ZEM: -- case DSC__K_DTYPE_DSC: -- case DSC__K_DTYPE_OU: -- case DSC__K_DTYPE_O: -- case DSC__K_DTYPE_G: -- case DSC__K_DTYPE_H: -- case DSC__K_DTYPE_GC: -- case DSC__K_DTYPE_HC: -- case DSC__K_DTYPE_CIT: -- case DSC__K_DTYPE_BPV: -- case DSC__K_DTYPE_BLV: -- case DSC__K_DTYPE_VU: -- case DSC__K_DTYPE_ADT: -- case DSC__K_DTYPE_VT: -- case DSC__K_DTYPE_T2: -- case DSC__K_DTYPE_VT2: -- fprintf (file, _("standard data: %s\n"), -- evax_bfd_get_dsc_name (type)); -- evax_bfd_print_valspec (buf, len, 4, file); -- fprintf (file, _(" name: %.*s\n"), buf[5], buf + 6); -- break; -- case DST__K_MODBEG: -- { -- struct vms_dst_modbeg *dst = (void *)buf; -- const char *name = (const char *)buf + sizeof (*dst); -- -- fprintf (file, _("modbeg\n")); -- if (len < sizeof (*dst)) -- break; -- /* xgettext:c-format */ -- fprintf (file, _(" flags: %d, language: %u, " -- "major: %u, minor: %u\n"), -- dst->flags, -- (unsigned)bfd_getl32 (dst->language), -- (unsigned)bfd_getl16 (dst->major), -- (unsigned)bfd_getl16 (dst->minor)); -- len -= sizeof (*dst); -- if (len > 0) -- { -- int nlen = len - 1; -- fprintf (file, _(" module name: %.*s\n"), -- name[0] > nlen ? nlen : name[0], name + 1); -- if (name[0] < nlen) -- { -- len -= name[0] + 1; -- name += name[0] + 1; -- nlen = len - 1; -- fprintf (file, _(" compiler : %.*s\n"), -- name[0] > nlen ? nlen: name[0], name + 1); -- } -- } -- } -- break; -- case DST__K_MODEND: -- fprintf (file, _("modend\n")); -- break; -- case DST__K_RTNBEG: -- { -- struct vms_dst_rtnbeg *dst = (void *)buf; -- const char *name = (const char *)buf + sizeof (*dst); -- -- fputs (_("rtnbeg\n"), file); -- if (len >= sizeof (*dst)) -- { -- /* xgettext:c-format */ -- fprintf (file, _(" flags: %u, address: 0x%08x, " -- "pd-address: 0x%08x\n"), -- dst->flags, -- (unsigned) bfd_getl32 (dst->address), -- (unsigned) bfd_getl32 (dst->pd_address)); -- len -= sizeof (*dst); -- if (len > 0) -- { -- int nlen = len - 1; -- fprintf (file, _(" routine name: %.*s\n"), -- name[0] > nlen ? nlen : name[0], name + 1); -- } -- } -- } -- break; -- case DST__K_RTNEND: -- { -- struct vms_dst_rtnend *dst = (void *)buf; -- -- if (len >= sizeof (*dst)) -- fprintf (file, _("rtnend: size 0x%08x\n"), -- (unsigned) bfd_getl32 (dst->size)); -- } -- break; -- case DST__K_PROLOG: -- { -- struct vms_dst_prolog *dst = (void *)buf; -- -- if (len >= sizeof (*dst)) -- /* xgettext:c-format */ -- fprintf (file, _("prolog: bkpt address 0x%08x\n"), -- (unsigned) bfd_getl32 (dst->bkpt_addr)); -- } -- break; -- case DST__K_EPILOG: -- { -- struct vms_dst_epilog *dst = (void *)buf; -- -- if (len >= sizeof (*dst)) -- /* xgettext:c-format */ -- fprintf (file, _("epilog: flags: %u, count: %u\n"), -- dst->flags, (unsigned) bfd_getl32 (dst->count)); -- } -- break; -- case DST__K_BLKBEG: -- { -- struct vms_dst_blkbeg *dst = (void *)buf; -- const char *name = (const char *)buf + sizeof (*dst); -- -- if (len > sizeof (*dst)) -- { -- int nlen; -- len -= sizeof (*dst); -- nlen = len - 1; -- /* xgettext:c-format */ -- fprintf (file, _("blkbeg: address: 0x%08x, name: %.*s\n"), -- (unsigned) bfd_getl32 (dst->address), -- name[0] > nlen ? nlen : name[0], name + 1); -- } -- } -- break; -- case DST__K_BLKEND: -- { -- struct vms_dst_blkend *dst = (void *)buf; -- -- if (len >= sizeof (*dst)) -- /* xgettext:c-format */ -- fprintf (file, _("blkend: size: 0x%08x\n"), -- (unsigned) bfd_getl32 (dst->size)); -- } -- break; -- case DST__K_TYPSPEC: -- { -- fprintf (file, _("typspec (len: %u)\n"), len); -- if (len >= 1) -- { -- int nlen = len - 1; -- fprintf (file, _(" name: %.*s\n"), -- buf[0] > nlen ? nlen : buf[0], buf + 1); -- if (nlen > buf[0]) -- evax_bfd_print_typspec (buf + 1 + buf[0], len - (1 + buf[0]), -- 5, file); -- } -- } -- break; -- case DST__K_SEPTYP: -- { -- if (len >= 6) -- { -- fprintf (file, _("septyp, name: %.*s\n"), -- buf[5] > len - 6 ? len - 6 : buf[5], buf + 6); -- evax_bfd_print_valspec (buf, len, 4, file); -- } -- } -- break; -- case DST__K_RECBEG: -- { -- struct vms_dst_recbeg *recbeg = (void *)buf; -- const char *name = (const char *)buf + sizeof (*recbeg); -- -- if (len > sizeof (*recbeg)) -- { -- int nlen = len - sizeof (*recbeg) - 1; -- if (name[0] < nlen) -- nlen = name[0]; -- fprintf (file, _("recbeg: name: %.*s\n"), nlen, name + 1); -- evax_bfd_print_valspec (buf, len, 4, file); -- len -= 1 + nlen; -- if (len >= 4) -- fprintf (file, _(" len: %u bits\n"), -- (unsigned) bfd_getl32 (name + 1 + nlen)); -- } -- } -- break; -- case DST__K_RECEND: -- fprintf (file, _("recend\n")); -- break; -- case DST__K_ENUMBEG: -- if (len >= 2) -- /* xgettext:c-format */ -- fprintf (file, _("enumbeg, len: %u, name: %.*s\n"), -- buf[0], buf[1] > len - 2 ? len - 2 : buf[1], buf + 2); -- break; -- case DST__K_ENUMELT: -- if (len >= 6) -- { -- fprintf (file, _("enumelt, name: %.*s\n"), -- buf[5] > len - 6 ? len - 6 : buf[5], buf + 6); -- evax_bfd_print_valspec (buf, len, 4, file); -- } -- break; -- case DST__K_ENUMEND: -- fprintf (file, _("enumend\n")); -- break; -- case DST__K_LABEL: -- { -- struct vms_dst_label *lab = (void *)buf; -- if (len >= sizeof (*lab)) -- { -- fprintf (file, _("label, name: %.*s\n"), -- lab->name[0] > len - 1 ? len - 1 : lab->name[0], -- lab->name + 1); -- fprintf (file, _(" address: 0x%08x\n"), -- (unsigned) bfd_getl32 (lab->value)); -- } -- } -- break; -- case DST__K_DIS_RANGE: -- if (len >= 4) -- { -- unsigned int cnt = bfd_getl32 (buf); -- unsigned char *rng = buf + 4; -- unsigned int i; -- -- fprintf (file, _("discontiguous range (nbr: %u)\n"), cnt); -- len -= 4; -- for (i = 0; i < cnt; i++, rng += 8) -- { -- if (len < 8) -- break; -- /* xgettext:c-format */ -- fprintf (file, _(" address: 0x%08x, size: %u\n"), -- (unsigned) bfd_getl32 (rng), -- (unsigned) bfd_getl32 (rng + 4)); -- len -= 8; -- } -- } -- break; -- case DST__K_LINE_NUM: -- { -- unsigned char *buf_orig = buf; -- -- fprintf (file, _("line num (len: %u)\n"), len); -- -- while (len > 0) -- { -- int cmd; -- unsigned int val; -- int cmdlen = -1; -- -- cmd = *buf++; -- len--; -- -- fputs (" ", file); -- -- switch (cmd) -- { -- case DST__K_DELTA_PC_W: -- if (len < 2) -- break; -- val = bfd_getl16 (buf); -- fprintf (file, _("delta_pc_w %u\n"), val); -- pc += val; -- line++; -- cmdlen = 2; -- break; -- case DST__K_INCR_LINUM: -- if (len < 1) -- break; -- val = *buf; -- fprintf (file, _("incr_linum(b): +%u\n"), val); -- line += val; -- cmdlen = 1; -- break; -- case DST__K_INCR_LINUM_W: -- if (len < 2) -- break; -- val = bfd_getl16 (buf); -- fprintf (file, _("incr_linum_w: +%u\n"), val); -- line += val; -- cmdlen = 2; -- break; -- case DST__K_INCR_LINUM_L: -- if (len < 4) -- break; -- val = bfd_getl32 (buf); -- fprintf (file, _("incr_linum_l: +%u\n"), val); -- line += val; -- cmdlen = 4; -- break; -- case DST__K_SET_LINUM: -- if (len < 2) -- break; -- line = bfd_getl16 (buf); -- fprintf (file, _("set_line_num(w) %u\n"), line); -- cmdlen = 2; -- break; -- case DST__K_SET_LINUM_B: -- if (len < 1) -- break; -- line = *buf; -- fprintf (file, _("set_line_num_b %u\n"), line); -- cmdlen = 1; -- break; -- case DST__K_SET_LINUM_L: -- if (len < 4) -- break; -- line = bfd_getl32 (buf); -- fprintf (file, _("set_line_num_l %u\n"), line); -- cmdlen = 4; -- break; -- case DST__K_SET_ABS_PC: -- if (len < 4) -- break; -- pc = bfd_getl32 (buf); -- fprintf (file, _("set_abs_pc: 0x%08x\n"), pc); -- cmdlen = 4; -- break; -- case DST__K_DELTA_PC_L: -- if (len < 4) -- break; -- fprintf (file, _("delta_pc_l: +0x%08x\n"), -- (unsigned) bfd_getl32 (buf)); -- cmdlen = 4; -- break; -- case DST__K_TERM: -- if (len < 1) -- break; -- fprintf (file, _("term(b): 0x%02x"), *buf); -- pc += *buf; -- fprintf (file, _(" pc: 0x%08x\n"), pc); -- cmdlen = 1; -- break; -- case DST__K_TERM_W: -- if (len < 2) -- break; -- val = bfd_getl16 (buf); -- fprintf (file, _("term_w: 0x%04x"), val); -- pc += val; -- fprintf (file, _(" pc: 0x%08x\n"), pc); -- cmdlen = 2; -- break; -- default: -- if (cmd <= 0) -- { -- fprintf (file, _("delta pc +%-4d"), -cmd); -- line++; /* FIXME: curr increment. */ -- pc += -cmd; -- /* xgettext:c-format */ -- fprintf (file, _(" pc: 0x%08x line: %5u\n"), -- pc, line); -- cmdlen = 0; -- } -- else -- fprintf (file, _(" *unhandled* cmd %u\n"), cmd); -- break; -- } -- if (cmdlen < 0) -- break; -- len -= cmdlen; -- buf += cmdlen; -- } -- buf = buf_orig; -- } -- break; -- case DST__K_SOURCE: -- { -- unsigned char *buf_orig = buf; -- -- fprintf (file, _("source (len: %u)\n"), len); -- -- while (len > 0) -- { -- int cmd = *buf++; -- int cmdlen = -1; -- -- len--; -- switch (cmd) -- { -- case DST__K_SRC_DECLFILE: -- { -- struct vms_dst_src_decl_src *src = (void *) buf; -- const char *name; -- int nlen; -- -- if (len < sizeof (*src)) -- break; -- /* xgettext:c-format */ -- fprintf (file, _(" declfile: len: %u, flags: %u, " -- "fileid: %u\n"), -- src->length, src->flags, -- (unsigned)bfd_getl16 (src->fileid)); -- /* xgettext:c-format */ -- fprintf (file, _(" rms: cdt: 0x%08x %08x, " -- "ebk: 0x%08x, ffb: 0x%04x, " -- "rfo: %u\n"), -- (unsigned)bfd_getl32 (src->rms_cdt + 4), -- (unsigned)bfd_getl32 (src->rms_cdt + 0), -- (unsigned)bfd_getl32 (src->rms_ebk), -- (unsigned)bfd_getl16 (src->rms_ffb), -- src->rms_rfo); -- if (src->length > len || src->length <= sizeof (*src)) -- break; -- nlen = src->length - sizeof (*src) - 1; -- name = (const char *) buf + sizeof (*src); -- fprintf (file, _(" filename : %.*s\n"), -- name[0] > nlen ? nlen : name[0], name + 1); -- if (name[0] >= nlen) -- break; -- nlen -= name[0] + 1; -- name += name[0] + 1; -- fprintf (file, _(" module name: %.*s\n"), -- name[0] > nlen ? nlen : name[0], name + 1); -- if (name[0] > nlen) -- break; -- cmdlen = src->length; -- } -- break; -- case DST__K_SRC_SETFILE: -- if (len < 2) -- break; -- fprintf (file, _(" setfile %u\n"), -- (unsigned) bfd_getl16 (buf)); -- cmdlen = 2; -- break; -- case DST__K_SRC_SETREC_W: -- if (len < 2) -- break; -- fprintf (file, _(" setrec %u\n"), -- (unsigned) bfd_getl16 (buf)); -- cmdlen = 2; -- break; -- case DST__K_SRC_SETREC_L: -- if (len < 4) -- break; -- fprintf (file, _(" setrec %u\n"), -- (unsigned) bfd_getl32 (buf)); -- cmdlen = 4; -- break; -- case DST__K_SRC_SETLNUM_W: -- if (len < 2) -- break; -- fprintf (file, _(" setlnum %u\n"), -- (unsigned) bfd_getl16 (buf)); -- cmdlen = 2; -- break; -- case DST__K_SRC_SETLNUM_L: -- if (len < 4) -- break; -- fprintf (file, _(" setlnum %u\n"), -- (unsigned) bfd_getl32 (buf)); -- cmdlen = 4; -- break; -- case DST__K_SRC_DEFLINES_W: -- if (len < 2) -- break; -- fprintf (file, _(" deflines %u\n"), -- (unsigned) bfd_getl16 (buf)); -- cmdlen = 2; -- break; -- case DST__K_SRC_DEFLINES_B: -- if (len < 1) -- break; -- fprintf (file, _(" deflines %u\n"), *buf); -- cmdlen = 1; -- break; -- case DST__K_SRC_FORMFEED: -- fprintf (file, _(" formfeed\n")); -- cmdlen = 0; -- break; -- default: -- fprintf (file, _(" *unhandled* cmd %u\n"), cmd); -- break; -- } -- if (cmdlen < 0) -- break; -- len -= cmdlen; -- buf += cmdlen; -- } -- buf = buf_orig; -- } -- break; -- default: -- fprintf (file, _("*unhandled* dst type %u\n"), type); -- break; -- } -- free (buf); -- } --} -- --static void --evax_bfd_print_image (bfd *abfd, FILE *file) --{ -- struct vms_eihd eihd; -- const char *name; -- unsigned int val; -- unsigned int eiha_off; -- unsigned int eihi_off; -- unsigned int eihs_off; -- unsigned int eisd_off; -- unsigned int eihef_off = 0; -- unsigned int eihnp_off = 0; -- unsigned int dmt_vbn = 0; -- unsigned int dmt_size = 0; -- unsigned int dst_vbn = 0; -- unsigned int dst_size = 0; -- unsigned int gst_vbn = 0; -- unsigned int gst_size = 0; -- unsigned int eiaf_vbn = 0; -- unsigned int eiaf_size = 0; -- unsigned int eihvn_off; -- -- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) -- || bfd_bread (&eihd, sizeof (eihd), abfd) != sizeof (eihd)) -- { -- fprintf (file, _("cannot read EIHD\n")); -- return; -- } -- /* xgettext:c-format */ -- fprintf (file, _("EIHD: (size: %u, nbr blocks: %u)\n"), -- (unsigned)bfd_getl32 (eihd.size), -- (unsigned)bfd_getl32 (eihd.hdrblkcnt)); -- /* xgettext:c-format */ -- fprintf (file, _(" majorid: %u, minorid: %u\n"), -- (unsigned)bfd_getl32 (eihd.majorid), -- (unsigned)bfd_getl32 (eihd.minorid)); -- -- val = (unsigned)bfd_getl32 (eihd.imgtype); -- switch (val) -- { -- case EIHD__K_EXE: -- name = _("executable"); -- break; -- case EIHD__K_LIM: -- name = _("linkable image"); -- break; -- default: -- name = _("unknown"); -- break; -- } -- /* xgettext:c-format */ -- fprintf (file, _(" image type: %u (%s)"), val, name); -- -- val = (unsigned)bfd_getl32 (eihd.subtype); -- switch (val) -- { -- case EIHD__C_NATIVE: -- name = _("native"); -- break; -- case EIHD__C_CLI: -- name = _("CLI"); -- break; -- default: -- name = _("unknown"); -- break; -- } -- /* xgettext:c-format */ -- fprintf (file, _(", subtype: %u (%s)\n"), val, name); -- -- eisd_off = bfd_getl32 (eihd.isdoff); -- eiha_off = bfd_getl32 (eihd.activoff); -- eihi_off = bfd_getl32 (eihd.imgidoff); -- eihs_off = bfd_getl32 (eihd.symdbgoff); -- /* xgettext:c-format */ -- fprintf (file, _(" offsets: isd: %u, activ: %u, symdbg: %u, " -- "imgid: %u, patch: %u\n"), -- eisd_off, eiha_off, eihs_off, eihi_off, -- (unsigned)bfd_getl32 (eihd.patchoff)); -- fprintf (file, _(" fixup info rva: ")); -- bfd_fprintf_vma (abfd, file, bfd_getl64 (eihd.iafva)); -- fprintf (file, _(", symbol vector rva: ")); -- bfd_fprintf_vma (abfd, file, bfd_getl64 (eihd.symvva)); -- eihvn_off = bfd_getl32 (eihd.version_array_off); -- fprintf (file, _("\n" -- " version array off: %u\n"), -- eihvn_off); -- fprintf (file, -- /* xgettext:c-format */ -- _(" img I/O count: %u, nbr channels: %u, req pri: %08x%08x\n"), -- (unsigned)bfd_getl32 (eihd.imgiocnt), -- (unsigned)bfd_getl32 (eihd.iochancnt), -- (unsigned)bfd_getl32 (eihd.privreqs + 4), -- (unsigned)bfd_getl32 (eihd.privreqs + 0)); -- val = (unsigned)bfd_getl32 (eihd.lnkflags); -- fprintf (file, _(" linker flags: %08x:"), val); -- if (val & EIHD__M_LNKDEBUG) -- fprintf (file, " LNKDEBUG"); -- if (val & EIHD__M_LNKNOTFR) -- fprintf (file, " LNKNOTFR"); -- if (val & EIHD__M_NOP0BUFS) -- fprintf (file, " NOP0BUFS"); -- if (val & EIHD__M_PICIMG) -- fprintf (file, " PICIMG"); -- if (val & EIHD__M_P0IMAGE) -- fprintf (file, " P0IMAGE"); -- if (val & EIHD__M_DBGDMT) -- fprintf (file, " DBGDMT"); -- if (val & EIHD__M_INISHR) -- fprintf (file, " INISHR"); -- if (val & EIHD__M_XLATED) -- fprintf (file, " XLATED"); -- if (val & EIHD__M_BIND_CODE_SEC) -- fprintf (file, " BIND_CODE_SEC"); -- if (val & EIHD__M_BIND_DATA_SEC) -- fprintf (file, " BIND_DATA_SEC"); -- if (val & EIHD__M_MKTHREADS) -- fprintf (file, " MKTHREADS"); -- if (val & EIHD__M_UPCALLS) -- fprintf (file, " UPCALLS"); -- if (val & EIHD__M_OMV_READY) -- fprintf (file, " OMV_READY"); -- if (val & EIHD__M_EXT_BIND_SECT) -- fprintf (file, " EXT_BIND_SECT"); -- fprintf (file, "\n"); -- /* xgettext:c-format */ -- fprintf (file, _(" ident: 0x%08x, sysver: 0x%08x, " -- "match ctrl: %u, symvect_size: %u\n"), -- (unsigned)bfd_getl32 (eihd.ident), -- (unsigned)bfd_getl32 (eihd.sysver), -- eihd.matchctl, -- (unsigned)bfd_getl32 (eihd.symvect_size)); -- fprintf (file, _(" BPAGE: %u"), -- (unsigned)bfd_getl32 (eihd.virt_mem_block_size)); -- if (val & (EIHD__M_OMV_READY | EIHD__M_EXT_BIND_SECT)) -- { -- eihef_off = bfd_getl32 (eihd.ext_fixup_off); -- eihnp_off = bfd_getl32 (eihd.noopt_psect_off); -- /* xgettext:c-format */ -- fprintf (file, _(", ext fixup offset: %u, no_opt psect off: %u"), -- eihef_off, eihnp_off); -- } -- fprintf (file, _(", alias: %u\n"), (unsigned)bfd_getl16 (eihd.alias)); -- -- if (eihvn_off != 0) -- { -- struct vms_eihvn eihvn; -- unsigned int mask; -- unsigned int j; -- -- fprintf (file, _("system version array information:\n")); -- if (bfd_seek (abfd, (file_ptr) eihvn_off, SEEK_SET) -- || bfd_bread (&eihvn, sizeof (eihvn), abfd) != sizeof (eihvn)) -- { -- fprintf (file, _("cannot read EIHVN header\n")); -- return; -- } -- mask = bfd_getl32 (eihvn.subsystem_mask); -- for (j = 0; j < 32; j++) -- if (mask & (1u << j)) -- { -- struct vms_eihvn_subversion ver; -- if (bfd_bread (&ver, sizeof (ver), abfd) != sizeof (ver)) -- { -- fprintf (file, _("cannot read EIHVN version\n")); -- return; -- } -- fprintf (file, _(" %02u "), j); -- switch (j) -- { -- case EIHVN__BASE_IMAGE_BIT: -- fputs (_("BASE_IMAGE "), file); -- break; -- case EIHVN__MEMORY_MANAGEMENT_BIT: -- fputs (_("MEMORY_MANAGEMENT"), file); -- break; -- case EIHVN__IO_BIT: -- fputs (_("IO "), file); -- break; -- case EIHVN__FILES_VOLUMES_BIT: -- fputs (_("FILES_VOLUMES "), file); -- break; -- case EIHVN__PROCESS_SCHED_BIT: -- fputs (_("PROCESS_SCHED "), file); -- break; -- case EIHVN__SYSGEN_BIT: -- fputs (_("SYSGEN "), file); -- break; -- case EIHVN__CLUSTERS_LOCKMGR_BIT: -- fputs (_("CLUSTERS_LOCKMGR "), file); -- break; -- case EIHVN__LOGICAL_NAMES_BIT: -- fputs (_("LOGICAL_NAMES "), file); -- break; -- case EIHVN__SECURITY_BIT: -- fputs (_("SECURITY "), file); -- break; -- case EIHVN__IMAGE_ACTIVATOR_BIT: -- fputs (_("IMAGE_ACTIVATOR "), file); -- break; -- case EIHVN__NETWORKS_BIT: -- fputs (_("NETWORKS "), file); -- break; -- case EIHVN__COUNTERS_BIT: -- fputs (_("COUNTERS "), file); -- break; -- case EIHVN__STABLE_BIT: -- fputs (_("STABLE "), file); -- break; -- case EIHVN__MISC_BIT: -- fputs (_("MISC "), file); -- break; -- case EIHVN__CPU_BIT: -- fputs (_("CPU "), file); -- break; -- case EIHVN__VOLATILE_BIT: -- fputs (_("VOLATILE "), file); -- break; -- case EIHVN__SHELL_BIT: -- fputs (_("SHELL "), file); -- break; -- case EIHVN__POSIX_BIT: -- fputs (_("POSIX "), file); -- break; -- case EIHVN__MULTI_PROCESSING_BIT: -- fputs (_("MULTI_PROCESSING "), file); -- break; -- case EIHVN__GALAXY_BIT: -- fputs (_("GALAXY "), file); -- break; -- default: -- fputs (_("*unknown* "), file); -- break; -- } -- fprintf (file, ": %u.%u\n", -- (unsigned)bfd_getl16 (ver.major), -- (unsigned)bfd_getl16 (ver.minor)); -- } -- } -- -- if (eiha_off != 0) -- { -- struct vms_eiha eiha; -- -- if (bfd_seek (abfd, (file_ptr) eiha_off, SEEK_SET) -- || bfd_bread (&eiha, sizeof (eiha), abfd) != sizeof (eiha)) -- { -- fprintf (file, _("cannot read EIHA\n")); -- return; -- } -- fprintf (file, _("Image activation: (size=%u)\n"), -- (unsigned)bfd_getl32 (eiha.size)); -- /* xgettext:c-format */ -- fprintf (file, _(" First address : 0x%08x 0x%08x\n"), -- (unsigned)bfd_getl32 (eiha.tfradr1_h), -- (unsigned)bfd_getl32 (eiha.tfradr1)); -- /* xgettext:c-format */ -- fprintf (file, _(" Second address: 0x%08x 0x%08x\n"), -- (unsigned)bfd_getl32 (eiha.tfradr2_h), -- (unsigned)bfd_getl32 (eiha.tfradr2)); -- /* xgettext:c-format */ -- fprintf (file, _(" Third address : 0x%08x 0x%08x\n"), -- (unsigned)bfd_getl32 (eiha.tfradr3_h), -- (unsigned)bfd_getl32 (eiha.tfradr3)); -- /* xgettext:c-format */ -- fprintf (file, _(" Fourth address: 0x%08x 0x%08x\n"), -- (unsigned)bfd_getl32 (eiha.tfradr4_h), -- (unsigned)bfd_getl32 (eiha.tfradr4)); -- /* xgettext:c-format */ -- fprintf (file, _(" Shared image : 0x%08x 0x%08x\n"), -- (unsigned)bfd_getl32 (eiha.inishr_h), -- (unsigned)bfd_getl32 (eiha.inishr)); -- } -- if (eihi_off != 0) -- { -- struct vms_eihi eihi; -- -- if (bfd_seek (abfd, (file_ptr) eihi_off, SEEK_SET) -- || bfd_bread (&eihi, sizeof (eihi), abfd) != sizeof (eihi)) -- { -- fprintf (file, _("cannot read EIHI\n")); -- return; -- } -- /* xgettext:c-format */ -- fprintf (file, _("Image identification: (major: %u, minor: %u)\n"), -- (unsigned)bfd_getl32 (eihi.majorid), -- (unsigned)bfd_getl32 (eihi.minorid)); -- fprintf (file, _(" image name : %.*s\n"), -- eihi.imgnam[0], eihi.imgnam + 1); -- fprintf (file, _(" link time : %s\n"), -- vms_time_to_str (eihi.linktime)); -- fprintf (file, _(" image ident : %.*s\n"), -- eihi.imgid[0], eihi.imgid + 1); -- fprintf (file, _(" linker ident : %.*s\n"), -- eihi.linkid[0], eihi.linkid + 1); -- fprintf (file, _(" image build ident: %.*s\n"), -- eihi.imgbid[0], eihi.imgbid + 1); -- } -- if (eihs_off != 0) -- { -- struct vms_eihs eihs; -- -- if (bfd_seek (abfd, (file_ptr) eihs_off, SEEK_SET) -- || bfd_bread (&eihs, sizeof (eihs), abfd) != sizeof (eihs)) -- { -- fprintf (file, _("cannot read EIHS\n")); -- return; -- } -- /* xgettext:c-format */ -- fprintf (file, _("Image symbol & debug table: (major: %u, minor: %u)\n"), -- (unsigned)bfd_getl32 (eihs.majorid), -- (unsigned)bfd_getl32 (eihs.minorid)); -- dst_vbn = bfd_getl32 (eihs.dstvbn); -- dst_size = bfd_getl32 (eihs.dstsize); -- /* xgettext:c-format */ -- fprintf (file, _(" debug symbol table : vbn: %u, size: %u (0x%x)\n"), -- dst_vbn, dst_size, dst_size); -- gst_vbn = bfd_getl32 (eihs.gstvbn); -- gst_size = bfd_getl32 (eihs.gstsize); -- /* xgettext:c-format */ -- fprintf (file, _(" global symbol table: vbn: %u, records: %u\n"), -- gst_vbn, gst_size); -- dmt_vbn = bfd_getl32 (eihs.dmtvbn); -- dmt_size = bfd_getl32 (eihs.dmtsize); -- /* xgettext:c-format */ -- fprintf (file, _(" debug module table : vbn: %u, size: %u\n"), -- dmt_vbn, dmt_size); -- } -- while (eisd_off != 0) -- { -- struct vms_eisd eisd; -- unsigned int len; -- -- while (1) -- { -- if (bfd_seek (abfd, (file_ptr) eisd_off, SEEK_SET) -- || bfd_bread (&eisd, sizeof (eisd), abfd) != sizeof (eisd)) -- { -- fprintf (file, _("cannot read EISD\n")); -- return; -- } -- len = (unsigned)bfd_getl32 (eisd.eisdsize); -- if (len != (unsigned)-1) -- break; -- -- /* Next block. */ -- eisd_off = (eisd_off + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1); -- } -- /* xgettext:c-format */ -- fprintf (file, _("Image section descriptor: (major: %u, minor: %u, " -- "size: %u, offset: %u)\n"), -- (unsigned)bfd_getl32 (eisd.majorid), -- (unsigned)bfd_getl32 (eisd.minorid), -- len, eisd_off); -- if (len == 0) -- break; -- /* xgettext:c-format */ -- fprintf (file, _(" section: base: 0x%08x%08x size: 0x%08x\n"), -- (unsigned)bfd_getl32 (eisd.virt_addr + 4), -- (unsigned)bfd_getl32 (eisd.virt_addr + 0), -- (unsigned)bfd_getl32 (eisd.secsize)); -- val = (unsigned)bfd_getl32 (eisd.flags); -- fprintf (file, _(" flags: 0x%04x"), val); -- if (val & EISD__M_GBL) -- fprintf (file, " GBL"); -- if (val & EISD__M_CRF) -- fprintf (file, " CRF"); -- if (val & EISD__M_DZRO) -- fprintf (file, " DZRO"); -- if (val & EISD__M_WRT) -- fprintf (file, " WRT"); -- if (val & EISD__M_INITALCODE) -- fprintf (file, " INITALCODE"); -- if (val & EISD__M_BASED) -- fprintf (file, " BASED"); -- if (val & EISD__M_FIXUPVEC) -- fprintf (file, " FIXUPVEC"); -- if (val & EISD__M_RESIDENT) -- fprintf (file, " RESIDENT"); -- if (val & EISD__M_VECTOR) -- fprintf (file, " VECTOR"); -- if (val & EISD__M_PROTECT) -- fprintf (file, " PROTECT"); -- if (val & EISD__M_LASTCLU) -- fprintf (file, " LASTCLU"); -- if (val & EISD__M_EXE) -- fprintf (file, " EXE"); -- if (val & EISD__M_NONSHRADR) -- fprintf (file, " NONSHRADR"); -- if (val & EISD__M_QUAD_LENGTH) -- fprintf (file, " QUAD_LENGTH"); -- if (val & EISD__M_ALLOC_64BIT) -- fprintf (file, " ALLOC_64BIT"); -- fprintf (file, "\n"); -- if (val & EISD__M_FIXUPVEC) -- { -- eiaf_vbn = bfd_getl32 (eisd.vbn); -- eiaf_size = bfd_getl32 (eisd.secsize); -- } -- /* xgettext:c-format */ -- fprintf (file, _(" vbn: %u, pfc: %u, matchctl: %u type: %u ("), -- (unsigned)bfd_getl32 (eisd.vbn), -- eisd.pfc, eisd.matchctl, eisd.type); -- switch (eisd.type) -- { -- case EISD__K_NORMAL: -- fputs (_("NORMAL"), file); -- break; -- case EISD__K_SHRFXD: -- fputs (_("SHRFXD"), file); -- break; -- case EISD__K_PRVFXD: -- fputs (_("PRVFXD"), file); -- break; -- case EISD__K_SHRPIC: -- fputs (_("SHRPIC"), file); -- break; -- case EISD__K_PRVPIC: -- fputs (_("PRVPIC"), file); -- break; -- case EISD__K_USRSTACK: -- fputs (_("USRSTACK"), file); -- break; -- default: -- fputs (_("*unknown*"), file); -- break; -- } -- fputs (_(")\n"), file); -- if (val & EISD__M_GBL) -- /* xgettext:c-format */ -- fprintf (file, _(" ident: 0x%08x, name: %.*s\n"), -- (unsigned)bfd_getl32 (eisd.ident), -- eisd.gblnam[0], eisd.gblnam + 1); -- eisd_off += len; -- } -- -- if (dmt_vbn != 0) -- { -- if (bfd_seek (abfd, (file_ptr) (dmt_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET)) -- { -- fprintf (file, _("cannot read DMT\n")); -- return; -- } -- -- fprintf (file, _("Debug module table:\n")); -- -- while (dmt_size > 0) -- { -- struct vms_dmt_header dmth; -- unsigned int count; -- -- if (bfd_bread (&dmth, sizeof (dmth), abfd) != sizeof (dmth)) -- { -- fprintf (file, _("cannot read DMT header\n")); -- return; -- } -- count = bfd_getl16 (dmth.psect_count); -- fprintf (file, -- /* xgettext:c-format */ -- _(" module offset: 0x%08x, size: 0x%08x, (%u psects)\n"), -- (unsigned)bfd_getl32 (dmth.modbeg), -- (unsigned)bfd_getl32 (dmth.size), count); -- dmt_size -= sizeof (dmth); -- while (count > 0) -- { -- struct vms_dmt_psect dmtp; -- -- if (bfd_bread (&dmtp, sizeof (dmtp), abfd) != sizeof (dmtp)) -- { -- fprintf (file, _("cannot read DMT psect\n")); -- return; -- } -- /* xgettext:c-format */ -- fprintf (file, _(" psect start: 0x%08x, length: %u\n"), -- (unsigned)bfd_getl32 (dmtp.start), -- (unsigned)bfd_getl32 (dmtp.length)); -- count--; -- dmt_size -= sizeof (dmtp); -- } -- } -- } -- -- if (dst_vbn != 0) -- { -- if (bfd_seek (abfd, (file_ptr) (dst_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET)) -- { -- fprintf (file, _("cannot read DST\n")); -- return; -- } -- -- evax_bfd_print_dst (abfd, dst_size, file); -- } -- if (gst_vbn != 0) -- { -- if (bfd_seek (abfd, (file_ptr) (gst_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET)) -- { -- fprintf (file, _("cannot read GST\n")); -- return; -- } -- -- fprintf (file, _("Global symbol table:\n")); -- evax_bfd_print_eobj (abfd, file); -- } -- if (eiaf_vbn != 0 && eiaf_size >= sizeof (struct vms_eiaf)) -- { -- unsigned char *buf; -- struct vms_eiaf *eiaf; -- unsigned int qrelfixoff; -- unsigned int lrelfixoff; -- unsigned int qdotadroff; -- unsigned int ldotadroff; -- unsigned int shrimgcnt; -- unsigned int shlstoff; -- unsigned int codeadroff; -- unsigned int lpfixoff; -- unsigned int chgprtoff; -- -- buf = bfd_malloc (eiaf_size); -- -- if (bfd_seek (abfd, (file_ptr) (eiaf_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET) -- || bfd_bread (buf, eiaf_size, abfd) != eiaf_size) -- { -- fprintf (file, _("cannot read EIHA\n")); -- free (buf); -- return; -- } -- eiaf = (struct vms_eiaf *)buf; -- fprintf (file, -- /* xgettext:c-format */ -- _("Image activator fixup: (major: %u, minor: %u)\n"), -- (unsigned)bfd_getl32 (eiaf->majorid), -- (unsigned)bfd_getl32 (eiaf->minorid)); -- /* xgettext:c-format */ -- fprintf (file, _(" iaflink : 0x%08x %08x\n"), -- (unsigned)bfd_getl32 (eiaf->iaflink + 0), -- (unsigned)bfd_getl32 (eiaf->iaflink + 4)); -- /* xgettext:c-format */ -- fprintf (file, _(" fixuplnk: 0x%08x %08x\n"), -- (unsigned)bfd_getl32 (eiaf->fixuplnk + 0), -- (unsigned)bfd_getl32 (eiaf->fixuplnk + 4)); -- fprintf (file, _(" size : %u\n"), -- (unsigned)bfd_getl32 (eiaf->size)); -- fprintf (file, _(" flags: 0x%08x\n"), -- (unsigned)bfd_getl32 (eiaf->flags)); -- qrelfixoff = bfd_getl32 (eiaf->qrelfixoff); -- lrelfixoff = bfd_getl32 (eiaf->lrelfixoff); -- /* xgettext:c-format */ -- fprintf (file, _(" qrelfixoff: %5u, lrelfixoff: %5u\n"), -- qrelfixoff, lrelfixoff); -- qdotadroff = bfd_getl32 (eiaf->qdotadroff); -- ldotadroff = bfd_getl32 (eiaf->ldotadroff); -- /* xgettext:c-format */ -- fprintf (file, _(" qdotadroff: %5u, ldotadroff: %5u\n"), -- qdotadroff, ldotadroff); -- codeadroff = bfd_getl32 (eiaf->codeadroff); -- lpfixoff = bfd_getl32 (eiaf->lpfixoff); -- /* xgettext:c-format */ -- fprintf (file, _(" codeadroff: %5u, lpfixoff : %5u\n"), -- codeadroff, lpfixoff); -- chgprtoff = bfd_getl32 (eiaf->chgprtoff); -- fprintf (file, _(" chgprtoff : %5u\n"), chgprtoff); -- shrimgcnt = bfd_getl32 (eiaf->shrimgcnt); -- shlstoff = bfd_getl32 (eiaf->shlstoff); -- /* xgettext:c-format */ -- fprintf (file, _(" shlstoff : %5u, shrimgcnt : %5u\n"), -- shlstoff, shrimgcnt); -- /* xgettext:c-format */ -- fprintf (file, _(" shlextra : %5u, permctx : %5u\n"), -- (unsigned)bfd_getl32 (eiaf->shlextra), -- (unsigned)bfd_getl32 (eiaf->permctx)); -- fprintf (file, _(" base_va : 0x%08x\n"), -- (unsigned)bfd_getl32 (eiaf->base_va)); -- fprintf (file, _(" lppsbfixoff: %5u\n"), -- (unsigned)bfd_getl32 (eiaf->lppsbfixoff)); -- -- if (shlstoff) -- { -- //struct vms_shl *shl = (struct vms_shl *)(buf + shlstoff); -- unsigned int j; -- -- fprintf (file, _(" Shareable images:\n")); -- for (j = 0; -- j < shrimgcnt && shlstoff <= eiaf_size - sizeof (struct vms_shl); -- j++, shlstoff += sizeof (struct vms_shl)) -- { -- struct vms_shl *shl = (struct vms_shl *) (buf + shlstoff); -- fprintf (file, -- /* xgettext:c-format */ -- _(" %u: size: %u, flags: 0x%02x, name: %.*s\n"), -- j, shl->size, shl->flags, -- shl->imgnam[0], shl->imgnam + 1); -- } -- } -- if (qrelfixoff != 0) -- { -- fprintf (file, _(" quad-word relocation fixups:\n")); -- evax_bfd_print_relocation_records (file, buf, eiaf_size, -- qrelfixoff, 8); -- } -- if (lrelfixoff != 0) -- { -- fprintf (file, _(" long-word relocation fixups:\n")); -- evax_bfd_print_relocation_records (file, buf, eiaf_size, -- lrelfixoff, 4); -- } -- if (qdotadroff != 0) -- { -- fprintf (file, _(" quad-word .address reference fixups:\n")); -- evax_bfd_print_address_fixups (file, buf, eiaf_size, qdotadroff); -- } -- if (ldotadroff != 0) -- { -- fprintf (file, _(" long-word .address reference fixups:\n")); -- evax_bfd_print_address_fixups (file, buf, eiaf_size, ldotadroff); -- } -- if (codeadroff != 0) -- { -- fprintf (file, _(" Code Address Reference Fixups:\n")); -- evax_bfd_print_reference_fixups (file, buf, eiaf_size, codeadroff); -- } -- if (lpfixoff != 0) -- { -- fprintf (file, _(" Linkage Pairs Reference Fixups:\n")); -- evax_bfd_print_reference_fixups (file, buf, eiaf_size, lpfixoff); -- } -- if (chgprtoff && chgprtoff <= eiaf_size - 4) -- { -- unsigned int count = (unsigned) bfd_getl32 (buf + chgprtoff); -- unsigned int j; -- -- fprintf (file, _(" Change Protection (%u entries):\n"), count); -- for (j = 0, chgprtoff += 4; -- j < count && chgprtoff <= eiaf_size - sizeof (struct vms_eicp); -- j++, chgprtoff += sizeof (struct vms_eicp)) -- { -- struct vms_eicp *eicp = (struct vms_eicp *) (buf + chgprtoff); -- unsigned int prot = bfd_getl32 (eicp->newprt); -- fprintf (file, -- /* xgettext:c-format */ -- _(" base: 0x%08x %08x, size: 0x%08x, prot: 0x%08x "), -- (unsigned) bfd_getl32 (eicp->baseva + 4), -- (unsigned) bfd_getl32 (eicp->baseva + 0), -- (unsigned) bfd_getl32 (eicp->size), -- (unsigned) bfd_getl32 (eicp->newprt)); -- switch (prot) -- { -- case PRT__C_NA: -- fprintf (file, "NA"); -- break; -- case PRT__C_RESERVED: -- fprintf (file, "RES"); -- break; -- case PRT__C_KW: -- fprintf (file, "KW"); -- break; -- case PRT__C_KR: -- fprintf (file, "KR"); -- break; -- case PRT__C_UW: -- fprintf (file, "UW"); -- break; -- case PRT__C_EW: -- fprintf (file, "EW"); -- break; -- case PRT__C_ERKW: -- fprintf (file, "ERKW"); -- break; -- case PRT__C_ER: -- fprintf (file, "ER"); -- break; -- case PRT__C_SW: -- fprintf (file, "SW"); -- break; -- case PRT__C_SREW: -- fprintf (file, "SREW"); -- break; -- case PRT__C_SRKW: -- fprintf (file, "SRKW"); -- break; -- case PRT__C_SR: -- fprintf (file, "SR"); -- break; -- case PRT__C_URSW: -- fprintf (file, "URSW"); -- break; -- case PRT__C_UREW: -- fprintf (file, "UREW"); -- break; -- case PRT__C_URKW: -- fprintf (file, "URKW"); -- break; -- case PRT__C_UR: -- fprintf (file, "UR"); -- break; -- default: -- fputs ("??", file); -- break; -- } -- fputc ('\n', file); -- } -- } -- free (buf); -- } --} -- --static bfd_boolean --vms_bfd_print_private_bfd_data (bfd *abfd, void *ptr) --{ -- FILE *file = (FILE *)ptr; -- -- if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) -- evax_bfd_print_image (abfd, file); -- else -- { -- if (bfd_seek (abfd, 0, SEEK_SET)) -- return FALSE; -- evax_bfd_print_eobj (abfd, file); -- } -- return TRUE; --} -- --/* Linking. */ -- --/* Slurp ETIR/EDBG/ETBT VMS object records. */ -- --static bfd_boolean --sw_64_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info) --{ -- asection *cur_section; -- file_ptr cur_offset; -- asection *dst_section; -- file_ptr dst_offset; -- -- if (bfd_seek (abfd, 0, SEEK_SET) != 0) -- return FALSE; -- -- cur_section = NULL; -- cur_offset = 0; -- -- dst_section = PRIV (dst_section); -- dst_offset = 0; -- if (info) -- { -- if (info->strip == strip_all || info->strip == strip_debugger) -- { -- /* Discard the DST section. */ -- dst_offset = 0; -- dst_section = NULL; -- } -- else if (dst_section) -- { -- dst_offset = dst_section->output_offset; -- dst_section = dst_section->output_section; -- } -- } -- -- while (1) -- { -- int type; -- bfd_boolean res; -- -- type = _bfd_vms_get_object_record (abfd); -- if (type < 0) -- { -- vms_debug2 ((2, "next_record failed\n")); -- return FALSE; -- } -- switch (type) -- { -- case EOBJ__C_ETIR: -- PRIV (image_section) = cur_section; -- PRIV (image_offset) = cur_offset; -- res = _bfd_vms_slurp_etir (abfd, info); -- cur_section = PRIV (image_section); -- cur_offset = PRIV (image_offset); -- break; -- case EOBJ__C_EDBG: -- case EOBJ__C_ETBT: -- if (dst_section == NULL) -- continue; -- PRIV (image_section) = dst_section; -- PRIV (image_offset) = dst_offset; -- res = _bfd_vms_slurp_etir (abfd, info); -- dst_offset = PRIV (image_offset); -- break; -- case EOBJ__C_EEOM: -- return TRUE; -- default: -- continue; -- } -- if (!res) -- { -- vms_debug2 ((2, "slurp eobj type %d failed\n", type)); -- return FALSE; -- } -- } --} -- --static int --sw_64_vms_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, -- struct bfd_link_info *info ATTRIBUTE_UNUSED) --{ -- return 0; --} -- --/* Add a linkage pair fixup at address SECT + OFFSET to SHLIB. */ -- --static void --sw_64_vms_add_fixup_lp (struct bfd_link_info *info, bfd *src, bfd *shlib) --{ -- struct sw_64_vms_shlib_el *sl; -- asection *sect = PRIV2 (src, image_section); -- file_ptr offset = PRIV2 (src, image_offset); -- -- sl = &VEC_EL (sw_64_vms_link_hash (info)->shrlibs, -- struct sw_64_vms_shlib_el, PRIV2 (shlib, shr_index)); -- sl->has_fixups = TRUE; -- VEC_APPEND_EL (sl->lp, bfd_vma, -- sect->output_section->vma + sect->output_offset + offset); -- sect->output_section->flags |= SEC_RELOC; --} -- --/* Add a code address fixup at address SECT + OFFSET to SHLIB. */ -- --static void --sw_64_vms_add_fixup_ca (struct bfd_link_info *info, bfd *src, bfd *shlib) --{ -- struct sw_64_vms_shlib_el *sl; -- asection *sect = PRIV2 (src, image_section); -- file_ptr offset = PRIV2 (src, image_offset); -- -- sl = &VEC_EL (sw_64_vms_link_hash (info)->shrlibs, -- struct sw_64_vms_shlib_el, PRIV2 (shlib, shr_index)); -- sl->has_fixups = TRUE; -- VEC_APPEND_EL (sl->ca, bfd_vma, -- sect->output_section->vma + sect->output_offset + offset); -- sect->output_section->flags |= SEC_RELOC; --} -- --/* Add a quad word relocation fixup at address SECT + OFFSET to SHLIB. */ -- --static void --sw_64_vms_add_fixup_qr (struct bfd_link_info *info, bfd *src, -- bfd *shlib, bfd_vma vec) --{ -- struct sw_64_vms_shlib_el *sl; -- struct sw_64_vms_vma_ref *r; -- asection *sect = PRIV2 (src, image_section); -- file_ptr offset = PRIV2 (src, image_offset); -- -- sl = &VEC_EL (sw_64_vms_link_hash (info)->shrlibs, -- struct sw_64_vms_shlib_el, PRIV2 (shlib, shr_index)); -- sl->has_fixups = TRUE; -- r = VEC_APPEND (sl->qr, struct sw_64_vms_vma_ref); -- r->vma = sect->output_section->vma + sect->output_offset + offset; -- r->ref = vec; -- sect->output_section->flags |= SEC_RELOC; --} -- --static void --sw_64_vms_add_fixup_lr (struct bfd_link_info *info ATTRIBUTE_UNUSED, -- unsigned int shr ATTRIBUTE_UNUSED, -- bfd_vma vec ATTRIBUTE_UNUSED) --{ -- /* Not yet supported. */ -- abort (); --} -- --/* Add relocation. FIXME: Not yet emitted. */ -- --static void --sw_64_vms_add_lw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED) --{ --} -- --static void --sw_64_vms_add_qw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED) --{ --} -- --static struct bfd_hash_entry * --sw_64_vms_link_hash_newfunc (struct bfd_hash_entry *entry, -- struct bfd_hash_table *table, -- const char *string) --{ -- struct sw_64_vms_link_hash_entry *ret = -- (struct sw_64_vms_link_hash_entry *) entry; -- -- /* Allocate the structure if it has not already been allocated by a -- subclass. */ -- if (ret == NULL) -- ret = ((struct sw_64_vms_link_hash_entry *) -- bfd_hash_allocate (table, -- sizeof (struct sw_64_vms_link_hash_entry))); -- if (ret == NULL) -- return NULL; -- -- /* Call the allocation method of the superclass. */ -- ret = ((struct sw_64_vms_link_hash_entry *) -- _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, -- table, string)); -- -- ret->sym = NULL; -- -- return (struct bfd_hash_entry *) ret; --} -- --static void --sw_64_vms_bfd_link_hash_table_free (bfd *abfd) --{ -- struct sw_64_vms_link_hash_table *t; -- unsigned i; -- -- t = (struct sw_64_vms_link_hash_table *) abfd->link.hash; -- for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -- { -- struct sw_64_vms_shlib_el *shlib; -- -- shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -- free (&VEC_EL (shlib->ca, bfd_vma, 0)); -- free (&VEC_EL (shlib->lp, bfd_vma, 0)); -- free (&VEC_EL (shlib->qr, struct sw_64_vms_vma_ref, 0)); -- } -- free (&VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, 0)); -- -- _bfd_generic_link_hash_table_free (abfd); --} -- --/* Create an Sw_64/VMS link hash table. */ -- --static struct bfd_link_hash_table * --sw_64_vms_bfd_link_hash_table_create (bfd *abfd) --{ -- struct sw_64_vms_link_hash_table *ret; -- bfd_size_type amt = sizeof (struct sw_64_vms_link_hash_table); -- -- ret = (struct sw_64_vms_link_hash_table *) bfd_malloc (amt); -- if (ret == NULL) -- return NULL; -- if (!_bfd_link_hash_table_init (&ret->root, abfd, -- sw_64_vms_link_hash_newfunc, -- sizeof (struct sw_64_vms_link_hash_entry))) -- { -- free (ret); -- return NULL; -- } -- -- VEC_INIT (ret->shrlibs); -- ret->fixup = NULL; -- ret->root.hash_table_free = sw_64_vms_bfd_link_hash_table_free; -- -- return &ret->root; --} -- --static bfd_boolean --sw_64_vms_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) --{ -- unsigned int i; -- -- for (i = 0; i < PRIV (gsd_sym_count); i++) -- { -- struct vms_symbol_entry *e = PRIV (syms)[i]; -- struct sw_64_vms_link_hash_entry *h; -- struct bfd_link_hash_entry *h_root; -- asymbol sym; -- -- if (!sw_64_vms_convert_symbol (abfd, e, &sym)) -- return FALSE; -- -- if ((e->flags & EGSY__V_DEF) && abfd->selective_search) -- { -- /* In selective_search mode, only add definition that are -- required. */ -- h = (struct sw_64_vms_link_hash_entry *)bfd_link_hash_lookup -- (info->hash, sym.name, FALSE, FALSE, FALSE); -- if (h == NULL || h->root.type != bfd_link_hash_undefined) -- continue; -- } -- else -- h = NULL; -- -- h_root = (struct bfd_link_hash_entry *) h; -- if (!_bfd_generic_link_add_one_symbol (info, abfd, sym.name, sym.flags, -- sym.section, sym.value, NULL, -- FALSE, FALSE, &h_root)) -- return FALSE; -- h = (struct sw_64_vms_link_hash_entry *) h_root; -- -- if ((e->flags & EGSY__V_DEF) -- && h->sym == NULL -- && abfd->xvec == info->output_bfd->xvec) -- h->sym = e; -- } -- -- if (abfd->flags & DYNAMIC) -- { -- struct sw_64_vms_shlib_el *shlib; -- -- /* We do not want to include any of the sections in a dynamic -- object in the output file. See comment in elflink.c. */ -- bfd_section_list_clear (abfd); -- -- shlib = VEC_APPEND (sw_64_vms_link_hash (info)->shrlibs, -- struct sw_64_vms_shlib_el); -- shlib->abfd = abfd; -- VEC_INIT (shlib->ca); -- VEC_INIT (shlib->lp); -- VEC_INIT (shlib->qr); -- PRIV (shr_index) = VEC_COUNT (sw_64_vms_link_hash (info)->shrlibs) - 1; -- } -- -- return TRUE; --} -- --static bfd_boolean --sw_64_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) --{ -- int pass; -- struct bfd_link_hash_entry **pundef; -- struct bfd_link_hash_entry **next_pundef; -- -- /* We only accept VMS libraries. */ -- if (info->output_bfd->xvec != abfd->xvec) -- { -- bfd_set_error (bfd_error_wrong_format); -- return FALSE; -- } -- -- /* The archive_pass field in the archive itself is used to -- initialize PASS, since we may search the same archive multiple -- times. */ -- pass = ++abfd->archive_pass; -- -- /* Look through the list of undefined symbols. */ -- for (pundef = &info->hash->undefs; *pundef != NULL; pundef = next_pundef) -- { -- struct bfd_link_hash_entry *h; -- symindex symidx; -- bfd *element; -- bfd *orig_element; -- -- h = *pundef; -- next_pundef = &(*pundef)->u.undef.next; -- -- /* 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 = *next_pundef; -- next_pundef = pundef; -- } -- continue; -- } -- -- /* Look for this symbol in the archive hash table. */ -- symidx = _bfd_vms_lib_find_symbol (abfd, h->root.string); -- if (symidx == BFD_NO_MORE_SYMBOLS) -- { -- /* Nothing in this slot. */ -- continue; -- } -- -- element = bfd_get_elt_at_index (abfd, symidx); -- if (element == NULL) -- return FALSE; -- -- if (element->archive_pass == -1 || element->archive_pass == pass) -- { -- /* Next symbol if this archive is wrong or already handled. */ -- continue; -- } -- -- if (! bfd_check_format (element, bfd_object)) -- { -- element->archive_pass = -1; -- return FALSE; -- } -- -- orig_element = element; -- if (bfd_is_thin_archive (abfd)) -- { -- element = _bfd_vms_lib_get_imagelib_file (element); -- if (element == NULL || !bfd_check_format (element, bfd_object)) -- { -- orig_element->archive_pass = -1; -- 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, h->root.string, &element)) -- continue; -- if (!sw_64_vms_link_add_object_symbols (element, info)) -- return FALSE; -- -- orig_element->archive_pass = pass; -- } -- -- return TRUE; --} -- --static bfd_boolean --sw_64_vms_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info) --{ -- switch (bfd_get_format (abfd)) -- { -- case bfd_object: -- vms_debug2 ((2, "vms_link_add_symbols for object %s\n", -- abfd->filename)); -- return sw_64_vms_link_add_object_symbols (abfd, info); -- break; -- case bfd_archive: -- vms_debug2 ((2, "vms_link_add_symbols for archive %s\n", -- abfd->filename)); -- return sw_64_vms_link_add_archive_symbols (abfd, info); -- break; -- default: -- bfd_set_error (bfd_error_wrong_format); -- return FALSE; -- } --} -- --static bfd_boolean --sw_64_vms_build_fixups (struct bfd_link_info *info) --{ -- struct sw_64_vms_link_hash_table *t = sw_64_vms_link_hash (info); -- unsigned char *content; -- unsigned int i; -- unsigned int sz = 0; -- unsigned int lp_sz = 0; -- unsigned int ca_sz = 0; -- unsigned int qr_sz = 0; -- unsigned int shrimg_cnt = 0; -- unsigned int chgprt_num = 0; -- unsigned int chgprt_sz = 0; -- struct vms_eiaf *eiaf; -- unsigned int off; -- asection *sec; -- -- /* Shared libraries. */ -- for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -- { -- struct sw_64_vms_shlib_el *shlib; -- -- shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -- -- if (!shlib->has_fixups) -- continue; -- -- shrimg_cnt++; -- -- if (VEC_COUNT (shlib->ca) > 0) -- { -- /* Header + entries. */ -- ca_sz += 8; -- ca_sz += VEC_COUNT (shlib->ca) * 4; -- } -- if (VEC_COUNT (shlib->lp) > 0) -- { -- /* Header + entries. */ -- lp_sz += 8; -- lp_sz += VEC_COUNT (shlib->lp) * 4; -- } -- if (VEC_COUNT (shlib->qr) > 0) -- { -- /* Header + entries. */ -- qr_sz += 8; -- qr_sz += VEC_COUNT (shlib->qr) * 8; -- } -- } -- /* Add markers. */ -- if (ca_sz > 0) -- ca_sz += 8; -- if (lp_sz > 0) -- lp_sz += 8; -- if (qr_sz > 0) -- qr_sz += 8; -- -- /* Finish now if there is no content. */ -- if (ca_sz + lp_sz + qr_sz == 0) -- return TRUE; -- -- /* Add an eicp entry for the fixup itself. */ -- chgprt_num = 1; -- for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next) -- { -- /* This isect could be made RO or EXE after relocations are applied. */ -- if ((sec->flags & SEC_RELOC) != 0 -- && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) -- chgprt_num++; -- } -- chgprt_sz = 4 + chgprt_num * sizeof (struct vms_eicp); -- -- /* Allocate section content (round-up size) */ -- sz = sizeof (struct vms_eiaf) + shrimg_cnt * sizeof (struct vms_shl) -- + ca_sz + lp_sz + qr_sz + chgprt_sz; -- sz = (sz + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1); -- content = bfd_zalloc (info->output_bfd, sz); -- if (content == NULL) -- return FALSE; -- -- sec = sw_64_vms_link_hash (info)->fixup; -- sec->contents = content; -- sec->size = sz; -- -- eiaf = (struct vms_eiaf *)content; -- off = sizeof (struct vms_eiaf); -- bfd_putl32 (0, eiaf->majorid); -- bfd_putl32 (0, eiaf->minorid); -- bfd_putl32 (0, eiaf->iaflink); -- bfd_putl32 (0, eiaf->fixuplnk); -- bfd_putl32 (sizeof (struct vms_eiaf), eiaf->size); -- bfd_putl32 (0, eiaf->flags); -- bfd_putl32 (0, eiaf->qrelfixoff); -- bfd_putl32 (0, eiaf->lrelfixoff); -- bfd_putl32 (0, eiaf->qdotadroff); -- bfd_putl32 (0, eiaf->ldotadroff); -- bfd_putl32 (0, eiaf->codeadroff); -- bfd_putl32 (0, eiaf->lpfixoff); -- bfd_putl32 (0, eiaf->chgprtoff); -- bfd_putl32 (shrimg_cnt ? off : 0, eiaf->shlstoff); -- bfd_putl32 (shrimg_cnt, eiaf->shrimgcnt); -- bfd_putl32 (0, eiaf->shlextra); -- bfd_putl32 (0, eiaf->permctx); -- bfd_putl32 (0, eiaf->base_va); -- bfd_putl32 (0, eiaf->lppsbfixoff); -- -- if (shrimg_cnt) -- { -- shrimg_cnt = 0; -- -- /* Write shl. */ -- for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -- { -- struct sw_64_vms_shlib_el *shlib; -- struct vms_shl *shl; -- -- shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -- -- if (!shlib->has_fixups) -- continue; -- -- /* Renumber shared images. */ -- PRIV2 (shlib->abfd, shr_index) = shrimg_cnt++; -- -- shl = (struct vms_shl *)(content + off); -- bfd_putl32 (0, shl->baseva); -- bfd_putl32 (0, shl->shlptr); -- bfd_putl32 (0, shl->ident); -- bfd_putl32 (0, shl->permctx); -- shl->size = sizeof (struct vms_shl); -- bfd_putl16 (0, shl->fill_1); -- shl->flags = 0; -- bfd_putl32 (0, shl->icb); -- shl->imgnam[0] = strlen (PRIV2 (shlib->abfd, hdr_data.hdr_t_name)); -- memcpy (shl->imgnam + 1, PRIV2 (shlib->abfd, hdr_data.hdr_t_name), -- shl->imgnam[0]); -- -- off += sizeof (struct vms_shl); -- } -- -- /* CA fixups. */ -- if (ca_sz != 0) -- { -- bfd_putl32 (off, eiaf->codeadroff); -- -- for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -- { -- struct sw_64_vms_shlib_el *shlib; -- unsigned int j; -- -- shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -- -- if (VEC_COUNT (shlib->ca) == 0) -- continue; -- -- bfd_putl32 (VEC_COUNT (shlib->ca), content + off); -- bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4); -- off += 8; -- -- for (j = 0; j < VEC_COUNT (shlib->ca); j++) -- { -- bfd_putl32 (VEC_EL (shlib->ca, bfd_vma, j) - t->base_addr, -- content + off); -- off += 4; -- } -- } -- -- bfd_putl32 (0, content + off); -- bfd_putl32 (0, content + off + 4); -- off += 8; -- } -- -- /* LP fixups. */ -- if (lp_sz != 0) -- { -- bfd_putl32 (off, eiaf->lpfixoff); -- -- for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -- { -- struct sw_64_vms_shlib_el *shlib; -- unsigned int j; -- -- shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -- -- if (VEC_COUNT (shlib->lp) == 0) -- continue; -- -- bfd_putl32 (VEC_COUNT (shlib->lp), content + off); -- bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4); -- off += 8; -- -- for (j = 0; j < VEC_COUNT (shlib->lp); j++) -- { -- bfd_putl32 (VEC_EL (shlib->lp, bfd_vma, j) - t->base_addr, -- content + off); -- off += 4; -- } -- } -- -- bfd_putl32 (0, content + off); -- bfd_putl32 (0, content + off + 4); -- off += 8; -- } -- -- /* QR fixups. */ -- if (qr_sz != 0) -- { -- bfd_putl32 (off, eiaf->qdotadroff); -- -- for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -- { -- struct sw_64_vms_shlib_el *shlib; -- unsigned int j; -- -- shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -- -- if (VEC_COUNT (shlib->qr) == 0) -- continue; -- -- bfd_putl32 (VEC_COUNT (shlib->qr), content + off); -- bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4); -- off += 8; -- -- for (j = 0; j < VEC_COUNT (shlib->qr); j++) -- { -- struct sw_64_vms_vma_ref *r; -- r = &VEC_EL (shlib->qr, struct sw_64_vms_vma_ref, j); -- bfd_putl32 (r->vma - t->base_addr, content + off); -- bfd_putl32 (r->ref, content + off + 4); -- off += 8; -- } -- } -- -- bfd_putl32 (0, content + off); -- bfd_putl32 (0, content + off + 4); -- off += 8; -- } -- } -- -- /* Write the change protection table. */ -- bfd_putl32 (off, eiaf->chgprtoff); -- bfd_putl32 (chgprt_num, content + off); -- off += 4; -- -- for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next) -- { -- struct vms_eicp *eicp; -- unsigned int prot; -- -- if ((sec->flags & SEC_LINKER_CREATED) != 0 && -- strcmp (sec->name, "$FIXUP$") == 0) -- prot = PRT__C_UREW; -- else if ((sec->flags & SEC_RELOC) != 0 -- && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) -- prot = PRT__C_UR; -- else -- continue; -- -- eicp = (struct vms_eicp *)(content + off); -- bfd_putl64 (sec->vma - t->base_addr, eicp->baseva); -- bfd_putl32 ((sec->size + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1), -- eicp->size); -- bfd_putl32 (prot, eicp->newprt); -- off += sizeof (struct vms_eicp); -- } -- -- return TRUE; --} -- --/* Called by bfd_hash_traverse to fill the symbol table. -- Return FALSE in case of failure. */ -- --static bfd_boolean --sw_64_vms_link_output_symbol (struct bfd_hash_entry *bh, void *infov) --{ -- struct bfd_link_hash_entry *hc = (struct bfd_link_hash_entry *) bh; -- struct bfd_link_info *info = (struct bfd_link_info *)infov; -- struct sw_64_vms_link_hash_entry *h; -- struct vms_symbol_entry *sym; -- -- if (hc->type == bfd_link_hash_warning) -- { -- hc = hc->u.i.link; -- if (hc->type == bfd_link_hash_new) -- return TRUE; -- } -- h = (struct sw_64_vms_link_hash_entry *) hc; -- -- switch (h->root.type) -- { -- case bfd_link_hash_undefined: -- return TRUE; -- case bfd_link_hash_new: -- case bfd_link_hash_warning: -- abort (); -- case bfd_link_hash_undefweak: -- return TRUE; -- case bfd_link_hash_defined: -- case bfd_link_hash_defweak: -- { -- asection *sec = h->root.u.def.section; -- -- /* FIXME: this is certainly a symbol from a dynamic library. */ -- if (bfd_is_abs_section (sec)) -- return TRUE; -- -- if (sec->owner->flags & DYNAMIC) -- return TRUE; -- } -- break; -- case bfd_link_hash_common: -- break; -- case bfd_link_hash_indirect: -- return TRUE; -- } -- -- /* Do not write not kept symbols. */ -- if (info->strip == strip_some -- && bfd_hash_lookup (info->keep_hash, h->root.root.string, -- FALSE, FALSE) != NULL) -- return TRUE; -- -- if (h->sym == NULL) -- { -- /* This symbol doesn't come from a VMS object. So we suppose it is -- a data. */ -- int len = strlen (h->root.root.string); -- -- sym = (struct vms_symbol_entry *)bfd_zalloc (info->output_bfd, -- sizeof (*sym) + len); -- if (sym == NULL) -- abort (); -- sym->namelen = len; -- memcpy (sym->name, h->root.root.string, len); -- sym->name[len] = 0; -- sym->owner = info->output_bfd; -- -- sym->typ = EGSD__C_SYMG; -- sym->data_type = 0; -- sym->flags = EGSY__V_DEF | EGSY__V_REL; -- sym->symbol_vector = h->root.u.def.value; -- sym->section = h->root.u.def.section; -- sym->value = h->root.u.def.value; -- } -- else -- sym = h->sym; -- -- if (!add_symbol_entry (info->output_bfd, sym)) -- return FALSE; -- -- return TRUE; --} -- --static bfd_boolean --sw_64_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) --{ -- asection *o; -- struct bfd_link_order *p; -- bfd *sub; -- asection *fixupsec; -- bfd_vma base_addr; -- bfd_vma last_addr; -- asection *dst; -- asection *dmt; -- -- if (bfd_link_relocatable (info)) -- { -- /* FIXME: we do not yet support relocatable link. It is not obvious -- how to do it for debug infos. */ -- (*info->callbacks->einfo)(_("%P: relocatable link is not supported\n")); -- return FALSE; -- } -- -- abfd->outsymbols = NULL; -- abfd->symcount = 0; -- -- /* Mark all sections which will be included in the output file. */ -- for (o = abfd->sections; o != NULL; o = o->next) -- for (p = o->map_head.link_order; p != NULL; p = p->next) -- if (p->type == bfd_indirect_link_order) -- p->u.indirect.section->linker_mark = TRUE; -- --#if 0 -- /* Handle all the link order information for the sections. */ -- for (o = abfd->sections; o != NULL; o = o->next) -- { -- printf ("For section %s (at 0x%08x, flags=0x%08x):\n", -- o->name, (unsigned)o->vma, (unsigned)o->flags); -- -- for (p = o->map_head.link_order; p != NULL; p = p->next) -- { -- printf (" at 0x%08x - 0x%08x: ", -- (unsigned)p->offset, (unsigned)(p->offset + p->size - 1)); -- switch (p->type) -- { -- case bfd_section_reloc_link_order: -- case bfd_symbol_reloc_link_order: -- printf (" section/symbol reloc\n"); -- break; -- case bfd_indirect_link_order: -- printf (" section %s of %s\n", -- p->u.indirect.section->name, -- p->u.indirect.section->owner->filename); -- break; -- case bfd_data_link_order: -- printf (" explicit data\n"); -- break; -- default: -- printf (" *unknown* type %u\n", p->type); -- break; -- } -- } -- } --#endif -- -- /* Generate the symbol table. */ -- BFD_ASSERT (PRIV (syms) == NULL); -- if (info->strip != strip_all) -- bfd_hash_traverse (&info->hash->table, sw_64_vms_link_output_symbol, info); -- -- /* Find the entry point. */ -- if (bfd_get_start_address (abfd) == 0) -- { -- bfd *startbfd = NULL; -- -- for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) -- { -- /* Consider only VMS object files. */ -- if (sub->xvec != abfd->xvec) -- continue; -- -- if (!PRIV2 (sub, eom_data).eom_has_transfer) -- continue; -- if ((PRIV2 (sub, eom_data).eom_b_tfrflg & EEOM__M_WKTFR) && startbfd) -- continue; -- if (startbfd != NULL -- && !(PRIV2 (sub, eom_data).eom_b_tfrflg & EEOM__M_WKTFR)) -- { -- (*info->callbacks->einfo) -- /* xgettext:c-format */ -- (_("%P: multiple entry points: in modules %pB and %pB\n"), -- startbfd, sub); -- continue; -- } -- startbfd = sub; -- } -- -- if (startbfd) -- { -- unsigned int ps_idx = PRIV2 (startbfd, eom_data).eom_l_psindx; -- bfd_vma tfradr = PRIV2 (startbfd, eom_data).eom_l_tfradr; -- asection *sec; -- -- sec = PRIV2 (startbfd, sections)[ps_idx]; -- -- bfd_set_start_address -- (abfd, sec->output_section->vma + sec->output_offset + tfradr); -- } -- } -- -- /* Set transfer addresses. */ -- { -- int i; -- struct bfd_link_hash_entry *h; -- -- i = 0; -- PRIV (transfer_address[i++]) = 0xffffffff00000340ULL; /* SYS$IMGACT */ -- h = bfd_link_hash_lookup (info->hash, "LIB$INITIALIZE", FALSE, FALSE, TRUE); -- if (h != NULL && h->type == bfd_link_hash_defined) -- PRIV (transfer_address[i++]) = -- sw_64_vms_get_sym_value (h->u.def.section, h->u.def.value); -- PRIV (transfer_address[i++]) = bfd_get_start_address (abfd); -- while (i < 4) -- PRIV (transfer_address[i++]) = 0; -- } -- -- /* Allocate contents. -- Also compute the virtual base address. */ -- base_addr = (bfd_vma)-1; -- last_addr = 0; -- for (o = abfd->sections; o != NULL; o = o->next) -- { -- if (o->flags & SEC_HAS_CONTENTS) -- { -- o->contents = bfd_alloc (abfd, o->size); -- if (o->contents == NULL) -- return FALSE; -- } -- if (o->flags & SEC_LOAD) -- { -- if (o->vma < base_addr) -- base_addr = o->vma; -- if (o->vma + o->size > last_addr) -- last_addr = o->vma + o->size; -- } -- /* Clear the RELOC flags. Currently we don't support incremental -- linking. We use the RELOC flag for computing the eicp entries. */ -- o->flags &= ~SEC_RELOC; -- } -- -- /* Create the fixup section. */ -- fixupsec = bfd_make_section_anyway_with_flags -- (info->output_bfd, "$FIXUP$", -- SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_LINKER_CREATED); -- if (fixupsec == NULL) -- return FALSE; -- last_addr = (last_addr + 0xffff) & ~0xffff; -- fixupsec->vma = last_addr; -- -- sw_64_vms_link_hash (info)->fixup = fixupsec; -- sw_64_vms_link_hash (info)->base_addr = base_addr; -- -- /* Create the DMT section, if necessary. */ -- BFD_ASSERT (PRIV (dst_section) == NULL); -- dst = bfd_get_section_by_name (abfd, "$DST$"); -- if (dst != NULL && dst->size == 0) -- dst = NULL; -- if (dst != NULL) -- { -- PRIV (dst_section) = dst; -- dmt = bfd_make_section_anyway_with_flags -- (info->output_bfd, "$DMT$", -- SEC_DEBUGGING | SEC_HAS_CONTENTS | SEC_LINKER_CREATED); -- if (dmt == NULL) -- return FALSE; -- } -- else -- dmt = NULL; -- -- /* Read all sections from the inputs. */ -- for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) -- { -- if (sub->flags & DYNAMIC) -- { -- sw_64_vms_create_eisd_for_shared (abfd, sub); -- continue; -- } -- -- if (!sw_64_vms_read_sections_content (sub, info)) -- return FALSE; -- } -- -- /* Handle all the link order information for the sections. -- Note: past this point, it is not possible to create new sections. */ -- for (o = abfd->sections; o != NULL; o = o->next) -- { -- for (p = o->map_head.link_order; p != NULL; p = p->next) -- { -- switch (p->type) -- { -- case bfd_section_reloc_link_order: -- case bfd_symbol_reloc_link_order: -- abort (); -- return FALSE; -- case bfd_indirect_link_order: -- /* Already done. */ -- break; -- default: -- if (! _bfd_default_link_order (abfd, info, o, p)) -- return FALSE; -- break; -- } -- } -- } -- -- /* Compute fixups. */ -- if (!sw_64_vms_build_fixups (info)) -- return FALSE; -- -- /* Compute the DMT. */ -- if (dmt != NULL) -- { -- int pass; -- unsigned char *contents = NULL; -- -- /* In pass 1, compute the size. In pass 2, write the DMT contents. */ -- for (pass = 0; pass < 2; pass++) -- { -- unsigned int off = 0; -- -- /* For each object file (ie for each module). */ -- for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) -- { -- asection *sub_dst; -- struct vms_dmt_header *dmth = NULL; -- unsigned int psect_count; -- -- /* Skip this module if it has no DST. */ -- sub_dst = PRIV2 (sub, dst_section); -- if (sub_dst == NULL || sub_dst->size == 0) -- continue; -- -- if (pass == 1) -- { -- /* Write the header. */ -- dmth = (struct vms_dmt_header *)(contents + off); -- bfd_putl32 (sub_dst->output_offset, dmth->modbeg); -- bfd_putl32 (sub_dst->size, dmth->size); -- } -- -- off += sizeof (struct vms_dmt_header); -- psect_count = 0; -- -- /* For each section (ie for each psect). */ -- for (o = sub->sections; o != NULL; o = o->next) -- { -- /* Only consider interesting sections. */ -- if (!(o->flags & SEC_ALLOC)) -- continue; -- if (o->flags & SEC_LINKER_CREATED) -- continue; -- -- if (pass == 1) -- { -- /* Write an entry. */ -- struct vms_dmt_psect *dmtp; -- -- dmtp = (struct vms_dmt_psect *)(contents + off); -- bfd_putl32 (o->output_offset + o->output_section->vma, -- dmtp->start); -- bfd_putl32 (o->size, dmtp->length); -- psect_count++; -- } -- off += sizeof (struct vms_dmt_psect); -- } -- if (pass == 1) -- bfd_putl32 (psect_count, dmth->psect_count); -- } -- -- if (pass == 0) -- { -- contents = bfd_zalloc (info->output_bfd, off); -- if (contents == NULL) -- return FALSE; -- dmt->contents = contents; -- dmt->size = off; -- } -- else -- { -- BFD_ASSERT (off == dmt->size); -- } -- } -- } -- -- return TRUE; --} -- --/* Read the contents of a section. -- buf points to a buffer of buf_size bytes to be filled with -- section data (starting at offset into section) */ -- --static bfd_boolean --sw_64_vms_get_section_contents (bfd *abfd, asection *section, -- void *buf, file_ptr offset, -- bfd_size_type count) --{ -- asection *sec; -- -- /* Image are easy. */ -- if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) -- return _bfd_generic_get_section_contents (abfd, section, -- buf, offset, count); -- -- /* Safety check. */ -- if (offset + count < count -- || offset + count > section->size) -- { -- bfd_set_error (bfd_error_invalid_operation); -- return FALSE; -- } -- -- /* If the section is already in memory, just copy it. */ -- if (section->flags & SEC_IN_MEMORY) -- { -- BFD_ASSERT (section->contents != NULL); -- memcpy (buf, section->contents + offset, count); -- return TRUE; -- } -- if (section->size == 0) -- return TRUE; -- -- /* Alloc in memory and read ETIRs. */ -- for (sec = abfd->sections; sec; sec = sec->next) -- { -- BFD_ASSERT (sec->contents == NULL); -- -- if (sec->size != 0 && (sec->flags & SEC_HAS_CONTENTS)) -- { -- sec->contents = bfd_alloc (abfd, sec->size); -- if (sec->contents == NULL) -- return FALSE; -- } -- } -- if (!sw_64_vms_read_sections_content (abfd, NULL)) -- return FALSE; -- for (sec = abfd->sections; sec; sec = sec->next) -- if (sec->contents) -- sec->flags |= SEC_IN_MEMORY; -- memcpy (buf, section->contents + offset, count); -- return TRUE; --} -- -- --/* Set the format of a file being written. */ -- --static bfd_boolean --sw_64_vms_mkobject (bfd * abfd) --{ -- const bfd_arch_info_type *arch; -- -- vms_debug2 ((1, "sw_64_vms_mkobject (%p)\n", abfd)); -- -- if (!vms_initialize (abfd)) -- return FALSE; -- -- PRIV (recwr.buf) = bfd_alloc (abfd, MAX_OUTREC_SIZE); -- if (PRIV (recwr.buf) == NULL) -- return FALSE; -- -- arch = bfd_scan_arch ("sw_64"); -- -- if (arch == 0) -- { -- bfd_set_error (bfd_error_wrong_format); -- return FALSE; -- } -- -- abfd->arch_info = arch; -- return TRUE; --} -- -- --/* 4.1, generic. */ -- --/* Called when the BFD is being closed to do any necessary cleanup. */ -- --static bfd_boolean --vms_close_and_cleanup (bfd * abfd) --{ -- vms_debug2 ((1, "vms_close_and_cleanup (%p)\n", abfd)); -- -- if (abfd == NULL || abfd->tdata.any == NULL) -- return TRUE; -- -- if (abfd->format == bfd_object) -- { -- sw_64_vms_free_private (abfd); -- --#ifdef VMS -- if (abfd->direction == write_direction) -- { -- /* Last step on VMS is to convert the file to variable record length -- format. */ -- if (!bfd_cache_close (abfd)) -- return FALSE; -- if (!_bfd_vms_convert_to_var_unix_filename (abfd->filename)) -- return FALSE; -- } --#endif -- } -- -- return _bfd_generic_close_and_cleanup (abfd); --} -- --/* Called when a new section is created. */ -- --static bfd_boolean --vms_new_section_hook (bfd * abfd, asection *section) --{ -- bfd_size_type amt; -- -- vms_debug2 ((1, "vms_new_section_hook (%p, [%u]%s)\n", -- abfd, section->index, section->name)); -- -- if (!bfd_set_section_alignment (section, 0)) -- return FALSE; -- -- vms_debug2 ((7, "%u: %s\n", section->index, section->name)); -- -- amt = sizeof (struct vms_section_data_struct); -- section->used_by_bfd = bfd_zalloc (abfd, amt); -- if (section->used_by_bfd == NULL) -- return FALSE; -- -- /* Create the section symbol. */ -- return _bfd_generic_new_section_hook (abfd, section); --} -- --/* Part 4.5, symbols. */ -- --/* Print symbol to file according to how. how is one of -- bfd_print_symbol_name just print the name -- bfd_print_symbol_more print more (???) -- bfd_print_symbol_all print all we know, which is not much right now :-). */ -- --static void --vms_print_symbol (bfd * abfd, -- void * file, -- asymbol *symbol, -- bfd_print_symbol_type how) --{ -- vms_debug2 ((1, "vms_print_symbol (%p, %p, %p, %d)\n", -- abfd, file, symbol, how)); -- -- switch (how) -- { -- case bfd_print_symbol_name: -- case bfd_print_symbol_more: -- fprintf ((FILE *)file," %s", symbol->name); -- break; -- -- case bfd_print_symbol_all: -- { -- const char *section_name = symbol->section->name; -- -- bfd_print_symbol_vandf (abfd, file, symbol); -- -- fprintf ((FILE *) file," %-8s %s", section_name, symbol->name); -- } -- break; -- } --} -- --/* Return information about symbol in ret. -- -- fill type, value and name -- type: -- A absolute -- B bss segment symbol -- C common symbol -- D data segment symbol -- f filename -- t a static function symbol -- T text segment symbol -- U undefined -- - debug. */ -- --static void --vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED, -- asymbol *symbol, -- symbol_info *ret) --{ -- asection *sec; -- -- vms_debug2 ((1, "vms_get_symbol_info (%p, %p, %p)\n", abfd, symbol, ret)); -- -- sec = symbol->section; -- -- if (ret == NULL) -- return; -- -- if (sec == NULL) -- ret->type = 'U'; -- else if (bfd_is_com_section (sec)) -- ret->type = 'C'; -- else if (bfd_is_abs_section (sec)) -- ret->type = 'A'; -- else if (bfd_is_und_section (sec)) -- ret->type = 'U'; -- else if (bfd_is_ind_section (sec)) -- ret->type = 'I'; -- else if ((symbol->flags & BSF_FUNCTION) -- || (bfd_section_flags (sec) & SEC_CODE)) -- ret->type = 'T'; -- else if (bfd_section_flags (sec) & SEC_DATA) -- ret->type = 'D'; -- else if (bfd_section_flags (sec) & SEC_ALLOC) -- ret->type = 'B'; -- else -- ret->type = '?'; -- -- if (ret->type != 'U') -- ret->value = symbol->value + symbol->section->vma; -- else -- ret->value = 0; -- ret->name = symbol->name; --} -- --/* Return TRUE if the given symbol sym in the BFD abfd is -- a compiler generated local label, else return FALSE. */ -- --static bfd_boolean --vms_bfd_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED, -- const char *name) --{ -- return name[0] == '$'; --} -- --/* Part 4.7, writing an object file. */ -- --/* Sets the contents of the section section in BFD abfd to the data starting -- in memory at LOCATION. The data is written to the output section starting -- at offset offset for count bytes. -- -- Normally TRUE is returned, else FALSE. Possible error returns are: -- o bfd_error_no_contents - The output section does not have the -- SEC_HAS_CONTENTS attribute, so nothing can be written to it. -- o and some more too */ -- --static bfd_boolean --_bfd_vms_set_section_contents (bfd * abfd, -- asection *section, -- const void * location, -- file_ptr offset, -- bfd_size_type count) --{ -- if (section->contents == NULL) -- { -- section->contents = bfd_alloc (abfd, section->size); -- if (section->contents == NULL) -- return FALSE; -- -- memcpy (section->contents + offset, location, (size_t) count); -- } -- -- return TRUE; --} -- --/* Set the architecture and machine type in BFD abfd to arch and mach. -- Find the correct pointer to a structure and insert it into the arch_info -- pointer. */ -- --static bfd_boolean --sw_64_vms_set_arch_mach (bfd *abfd, -- enum bfd_architecture arch, unsigned long mach) --{ -- if (arch != bfd_arch_sw_64 -- && arch != bfd_arch_unknown) -- return FALSE; -- -- return bfd_default_set_arch_mach (abfd, arch, mach); --} -- --/* Set section VMS flags. Clear NO_FLAGS and set FLAGS. */ -- --void --bfd_vms_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED, -- asection *sec, flagword no_flags, flagword flags) --{ -- vms_section_data (sec)->no_flags = no_flags; -- vms_section_data (sec)->flags = flags; --} -- --struct vms_private_data_struct * --bfd_vms_get_data (bfd *abfd) --{ -- return (struct vms_private_data_struct *)abfd->tdata.any; --} -- --#define vms_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false --#define vms_bfd_link_just_syms _bfd_generic_link_just_syms --#define vms_bfd_copy_link_hash_symbol_type \ -- _bfd_generic_copy_link_hash_symbol_type --#define vms_bfd_is_group_section bfd_generic_is_group_section --#define vms_bfd_group_name bfd_generic_group_name --#define vms_bfd_discard_group bfd_generic_discard_group --#define vms_section_already_linked _bfd_generic_section_already_linked --#define vms_bfd_define_common_symbol bfd_generic_define_common_symbol --#define vms_bfd_link_hide_symbol _bfd_generic_link_hide_symbol --#define vms_bfd_define_start_stop bfd_generic_define_start_stop --#define vms_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data -- --#define vms_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data --#define vms_bfd_free_cached_info _bfd_generic_bfd_free_cached_info --#define vms_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data --#define vms_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data --#define vms_bfd_set_private_flags _bfd_generic_bfd_set_private_flags --#define vms_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data -- --/* Symbols table. */ --#define sw_64_vms_make_empty_symbol _bfd_generic_make_empty_symbol --#define sw_64_vms_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false --#define sw_64_vms_print_symbol vms_print_symbol --#define sw_64_vms_get_symbol_info vms_get_symbol_info --#define sw_64_vms_get_symbol_version_string \ -- _bfd_nosymbols_get_symbol_version_string -- --#define sw_64_vms_read_minisymbols _bfd_generic_read_minisymbols --#define sw_64_vms_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol --#define sw_64_vms_get_lineno _bfd_nosymbols_get_lineno --#define sw_64_vms_find_inliner_info _bfd_nosymbols_find_inliner_info --#define sw_64_vms_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol --#define sw_64_vms_find_nearest_line _bfd_vms_find_nearest_line --#define sw_64_vms_find_line _bfd_nosymbols_find_line --#define sw_64_vms_bfd_is_local_label_name vms_bfd_is_local_label_name -- --/* Generic table. */ --#define sw_64_vms_close_and_cleanup vms_close_and_cleanup --#define sw_64_vms_bfd_free_cached_info vms_bfd_free_cached_info --#define sw_64_vms_new_section_hook vms_new_section_hook --#define sw_64_vms_set_section_contents _bfd_vms_set_section_contents --#define sw_64_vms_get_section_contents_in_window _bfd_generic_get_section_contents_in_window -- --#define sw_64_vms_bfd_get_relocated_section_contents \ -- bfd_generic_get_relocated_section_contents -- --#define sw_64_vms_bfd_relax_section bfd_generic_relax_section --#define sw_64_vms_bfd_gc_sections bfd_generic_gc_sections --#define sw_64_vms_bfd_lookup_section_flags bfd_generic_lookup_section_flags --#define sw_64_vms_bfd_merge_sections bfd_generic_merge_sections --#define sw_64_vms_bfd_is_group_section bfd_generic_is_group_section --#define sw_64_vms_bfd_group_name bfd_generic_group_name --#define sw_64_vms_bfd_discard_group bfd_generic_discard_group --#define sw_64_vms_section_already_linked \ -- _bfd_generic_section_already_linked -- --#define sw_64_vms_bfd_define_common_symbol bfd_generic_define_common_symbol --#define sw_64_vms_bfd_link_hide_symbol _bfd_generic_link_hide_symbol --#define sw_64_vms_bfd_define_start_stop bfd_generic_define_start_stop --#define sw_64_vms_bfd_link_just_syms _bfd_generic_link_just_syms --#define sw_64_vms_bfd_copy_link_hash_symbol_type \ -- _bfd_generic_copy_link_hash_symbol_type -- --#define sw_64_vms_bfd_link_split_section _bfd_generic_link_split_section -- --#define sw_64_vms_get_dynamic_symtab_upper_bound \ -- _bfd_nodynamic_get_dynamic_symtab_upper_bound --#define sw_64_vms_canonicalize_dynamic_symtab \ -- _bfd_nodynamic_canonicalize_dynamic_symtab --#define sw_64_vms_get_dynamic_reloc_upper_bound \ -- _bfd_nodynamic_get_dynamic_reloc_upper_bound --#define sw_64_vms_canonicalize_dynamic_reloc \ -- _bfd_nodynamic_canonicalize_dynamic_reloc --#define sw_64_vms_bfd_link_check_relocs _bfd_generic_link_check_relocs -- --const bfd_target sw_64_vms_vec = --{ -- "vms-sw_64", /* Name. */ -- bfd_target_evax_flavour, -- BFD_ENDIAN_LITTLE, /* Data byte order is little. */ -- BFD_ENDIAN_LITTLE, /* Header byte order is little. */ -- -- (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS -- | WP_TEXT | D_PAGED), /* Object flags. */ -- (SEC_ALLOC | SEC_LOAD | SEC_RELOC -- | SEC_READONLY | SEC_CODE | SEC_DATA -- | SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */ -- 0, /* symbol_leading_char. */ -- ' ', /* ar_pad_char. */ -- 15, /* ar_max_namelen. */ -- 0, /* match priority. */ -- 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_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. */ -- _bfd_dummy_target, -- sw_64_vms_object_p, -- _bfd_vms_lib_sw_64_archive_p, -- _bfd_dummy_target -- }, -- { /* bfd_set_format. */ -- _bfd_bool_bfd_false_error, -- sw_64_vms_mkobject, -- _bfd_vms_lib_sw_64_mkarchive, -- _bfd_bool_bfd_false_error -- }, -- { /* bfd_write_contents. */ -- _bfd_bool_bfd_false_error, -- sw_64_vms_write_object_contents, -- _bfd_vms_lib_write_archive_contents, -- _bfd_bool_bfd_false_error -- }, -- -- BFD_JUMP_TABLE_GENERIC (sw_64_vms), -- BFD_JUMP_TABLE_COPY (vms), -- BFD_JUMP_TABLE_CORE (_bfd_nocore), -- BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib), -- BFD_JUMP_TABLE_SYMBOLS (sw_64_vms), -- BFD_JUMP_TABLE_RELOCS (sw_64_vms), -- BFD_JUMP_TABLE_WRITE (sw_64_vms), -- BFD_JUMP_TABLE_LINK (sw_64_vms), -- BFD_JUMP_TABLE_DYNAMIC (sw_64_vms), -- -- NULL, -- -- NULL --}; ---- b/elfcpp/sw_64.def.h -+++ /dev/null -@@ -1,39 +0,0 @@ --#ifndef ELF_RELOC --#error "ELF_RELOC must be defined" --#endif -- --ELF_RELOC(R_SW_64_NONE , 0) /* No reloc */ --ELF_RELOC(R_SW_64_REFLONG , 1) /* Direct 32 bit */ --ELF_RELOC(R_SW_64_REFQUAD , 2) /* Direct 64 bit */ --ELF_RELOC(R_SW_64_GPREL32 , 3) /* GP relative 32 bit */ --ELF_RELOC(R_SW_64_LITERAL , 4) /* GP relative 16 bit w/optimization */ --ELF_RELOC(R_SW_64_LITUSE , 5) /* Optimization hint for LITERAL */ --ELF_RELOC(R_SW_64_GPDISP , 6) /* Add displacement to GP */ --ELF_RELOC(R_SW_64_BRADDR , 7) /* PC+4 relative 23 bit shifted */ --ELF_RELOC(R_SW_64_HINT , 8) /* PC+4 relative 16 bit shifted */ --ELF_RELOC(R_SW_64_SREL16 , 9) /* PC relative 16 bit */ --ELF_RELOC(R_SW_64_SREL32 , 10) /* PC relative 32 bit */ --ELF_RELOC(R_SW_64_SREL64 , 11) /* PC relative 64 bit */ --ELF_RELOC(R_SW_64_GPRELHIGH , 17) /* GP relative 32 bit, high 16 bits */ --ELF_RELOC(R_SW_64_GPRELLOW , 18) /* GP relative 32 bit, low 16 bits */ --ELF_RELOC(R_SW_64_GPREL16 , 19) /* GP relative 16 bit */ --ELF_RELOC(R_SW_64_COPY , 24) /* Copy symbol at runtime */ --ELF_RELOC(R_SW_64_GLOB_DAT , 25) /* Create GOT entry */ --ELF_RELOC(R_SW_64_JMP_SLOT , 26) /* Create PLT entry */ --ELF_RELOC(R_SW_64_RELATIVE , 27) /* Adjust by program base */ --ELF_RELOC(R_SW_64_BRSGP , 28) /* Like BRADDR, but assert that the source and target object file share the same GP value, and adjust the target address for STO_SW64_STD_GPLOAD. */ --ELF_RELOC(R_SW_64_TLSGD , 29) --ELF_RELOC(R_SW_64_TLS_LDM , 30) --ELF_RELOC(R_SW_64_DTPMOD64 , 31) --ELF_RELOC(R_SW_64_GOTDTPREL , 32) --ELF_RELOC(R_SW_64_DTPREL64 , 33) --ELF_RELOC(R_SW_64_DTPRELHI , 34) --ELF_RELOC(R_SW_64_DTPRELLO , 35) --ELF_RELOC(R_SW_64_DTPREL16 , 36) --ELF_RELOC(R_SW_64_GOTTPREL , 37) --ELF_RELOC(R_SW_64_TPREL64 , 38) --ELF_RELOC(R_SW_64_TPRELHI , 39) --ELF_RELOC(R_SW_64_TPRELLO , 40) --ELF_RELOC(R_SW_64_TPREL16 , 41) --ELF_RELOC(R_SW_64_BR26ADDR , 42) --ELF_RELOC(R_SW_64_LITERAL_GOT , 43) ---- b/elfcpp/sw_64.h -+++ /dev/null -@@ -1,15 +0,0 @@ --// sw_64.h -- --// Copyright (C) 2021-2021 LiNaKeSi Ltd. --// Written by Kid Lee . -- --#ifndef ELFCPP_SW_64_H --namespace elfcpp{ --enum SwRelType{ --# define ELF_RELOC(name, value) name = value, --# include "sw_64.def.h" --# undef ELF_RELOC --}; --} // namespace elfcpp --#define ELFCPP_SW_64_H --#endif // !defined(ELFCPP_SW_64_H) ---- b/gas/config/tc-sw_64.c -+++ /dev/null -@@ -1,6585 +0,0 @@ --/* tc-sw_64.c - Processor-specific code for the Sw_64 AXP CPU. -- Copyright (C) 1989-2018 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. -- Modified by Richard Henderson for ELF support. -- Modified by Klaus K"ampf for EVAX (OpenVMS/Sw_64) 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA -- 02110-1301, 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. */ -- --#include "as.h" --#include "subsegs.h" --#include "ecoff.h" -- --#include "opcode/sw_64.h" -- --#ifdef OBJ_ELF --#include "elf/sw_64.h" --#endif -- --#ifdef OBJ_EVAX --#include "vms.h" --#include "vms/egps.h" --#endif -- --#include "dwarf2dbg.h" --#include "dw2gencfi.h" --#include "safe-ctype.h" -- --/* Local types. */ -- --#define TOKENIZE_ERROR -1 --#define TOKENIZE_ERROR_REPORT -2 --#define MAX_INSN_FIXUPS 2 --#define MAX_INSN_ARGS 5 -- --/* Used since new relocation types are introduced in this -- file (DUMMY_RELOC_LITUSE_*) */ --typedef int extended_bfd_reloc_code_real_type; -- --struct sw_64_fixup --{ -- expressionS exp; -- /* bfd_reloc_code_real_type reloc; */ -- extended_bfd_reloc_code_real_type reloc; --#ifdef OBJ_EVAX -- /* The symbol of the item in the linkage section. */ -- symbolS *xtrasym; -- -- /* The symbol of the procedure descriptor. */ -- symbolS *procsym; --#endif --}; -- --struct sw_64_insn --{ -- unsigned insn; -- int nfixups; -- struct sw_64_fixup fixups[MAX_INSN_FIXUPS]; -- long sequence; --}; -- --enum sw_64_macro_arg -- { -- MACRO_EOA = 1, -- MACRO_IR, -- MACRO_PIR, -- MACRO_OPIR, -- MACRO_CPIR, -- MACRO_FPR, -- MACRO_EXP -- }; -- --struct sw_64_macro --{ -- const char *name; -- void (*emit) (const expressionS *, int, const void *); -- const void * arg; -- enum sw_64_macro_arg argsets[16]; --}; -- --/* Extra expression types. */ -- --#define O_pregister O_md1 /* O_register, in parentheses. */ --#define O_cpregister O_md2 /* + a leading comma. */ -- --/* The sw_64_reloc_op table below depends on the ordering of these. */ --#define O_literal O_md3 /* !literal relocation. */ --#define O_lituse_addr O_md4 /* !lituse_addr relocation. */ --#define O_lituse_base O_md5 /* !lituse_base relocation. */ --#define O_lituse_bytoff O_md6 /* !lituse_bytoff relocation. */ --#define O_lituse_jsr O_md7 /* !lituse_jsr relocation. */ --#define O_lituse_tlsgd O_md8 /* !lituse_tlsgd relocation. */ --#define O_lituse_tlsldm O_md9 /* !lituse_tlsldm relocation. */ --#define O_lituse_jsrdirect O_md10 /* !lituse_jsrdirect relocation. */ --#define O_gpdisp O_md11 /* !gpdisp relocation. */ --#define O_gprelhigh O_md12 /* !gprelhigh relocation. */ --#define O_gprellow O_md13 /* !gprellow relocation. */ --#define O_gprel O_md14 /* !gprel relocation. */ --#define O_samegp O_md15 /* !samegp relocation. */ --#define O_tlsgd O_md16 /* !tlsgd relocation. */ --#define O_tlsldm O_md17 /* !tlsldm relocation. */ --#define O_gotdtprel O_md18 /* !gotdtprel relocation. */ --#define O_dtprelhi O_md19 /* !dtprelhi relocation. */ --#define O_dtprello O_md20 /* !dtprello relocation. */ --#define O_dtprel O_md21 /* !dtprel relocation. */ --#define O_gottprel O_md22 /* !gottprel relocation. */ --#define O_tprelhi O_md23 /* !tprelhi relocation. */ --#define O_tprello O_md24 /* !tprello relocation. */ --#define O_tprel O_md25 /* !tprel relocation. */ -- --#define DUMMY_RELOC_LITUSE_ADDR (BFD_RELOC_UNUSED + 1) --#define DUMMY_RELOC_LITUSE_BASE (BFD_RELOC_UNUSED + 2) --#define DUMMY_RELOC_LITUSE_BYTOFF (BFD_RELOC_UNUSED + 3) --#define DUMMY_RELOC_LITUSE_JSR (BFD_RELOC_UNUSED + 4) --#define DUMMY_RELOC_LITUSE_TLSGD (BFD_RELOC_UNUSED + 5) --#define DUMMY_RELOC_LITUSE_TLSLDM (BFD_RELOC_UNUSED + 6) --#define DUMMY_RELOC_LITUSE_JSRDIRECT (BFD_RELOC_UNUSED + 7) -- --#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_tprel) -- --/* Macros for extracting the type and number of encoded register tokens. */ -- --#define is_ir_num(x) (((x) & 32) == 0) --#define is_fpr_num(x) (((x) & 32) != 0) --#define regno(x) ((x) & 31) -- --/* Something odd inherited from the old assembler. */ -- --#define note_gpreg(R) (sw_64_gprmask |= (1 << (R))) --#define note_fpreg(R) (sw_64_fprmask |= (1 << (R))) -- --/* Predicates for 16- and 32-bit ranges */ --/* XXX: The non-shift version appears to trigger a compiler bug when -- cross-assembling from x86 w/ gcc 2.7.2. */ -- --#if 1 --#define range_signed_16(x) \ -- (((offsetT) (x) >> 15) == 0 || ((offsetT) (x) >> 15) == -1) --#define range_signed_32(x) \ -- (((offsetT) (x) >> 31) == 0 || ((offsetT) (x) >> 31) == -1) --#else --#define range_signed_16(x) ((offsetT) (x) >= -(offsetT) 0x8000 && \ -- (offsetT) (x) <= (offsetT) 0x7FFF) --#define range_signed_32(x) ((offsetT) (x) >= -(offsetT) 0x80000000 && \ -- (offsetT) (x) <= (offsetT) 0x7FFFFFFF) --#endif -- --/* Macros for sign extending from 16- and 32-bits. */ --/* XXX: The cast macros will work on all the systems that I care about, -- but really a predicate should be found to use the non-cast forms. */ -- --#if 1 --#define sign_extend_16(x) ((short) (x)) --#define sign_extend_32(x) ((int) (x)) --#else --#define sign_extend_16(x) ((offsetT) (((x) & 0xFFFF) ^ 0x8000) - 0x8000) --#define sign_extend_32(x) ((offsetT) (((x) & 0xFFFFFFFF) \ -- ^ 0x80000000) - 0x80000000) --#endif -- --/* Macros to build tokens. */ -- --#define set_tok_reg(t, r) (memset (&(t), 0, sizeof (t)), \ -- (t).X_op = O_register, \ -- (t).X_add_number = (r)) --#define set_tok_preg(t, r) (memset (&(t), 0, sizeof (t)), \ -- (t).X_op = O_pregister, \ -- (t).X_add_number = (r)) --#define set_tok_cpreg(t, r) (memset (&(t), 0, sizeof (t)), \ -- (t).X_op = O_cpregister, \ -- (t).X_add_number = (r)) --#define set_tok_freg(t, r) (memset (&(t), 0, sizeof (t)), \ -- (t).X_op = O_register, \ -- (t).X_add_number = (r) + 32) --#define set_tok_sym(t, s, a) (memset (&(t), 0, sizeof (t)), \ -- (t).X_op = O_symbol, \ -- (t).X_add_symbol = (s), \ -- (t).X_add_number = (a)) --#define set_tok_const(t, n) (memset (&(t), 0, sizeof (t)), \ -- (t).X_op = O_constant, \ -- (t).X_add_number = (n)) -- --/* Generic assembler global variables which must be defined by all -- targets. */ -- --/* Characters which always start a comment. */ --const char comment_chars[] = "#"; -- --/* Characters which start a comment at the beginning of a line. */ --const char line_comment_chars[] = "#"; -- --/* Characters which may be used to separate multiple commands on a -- single line. */ --const char line_separator_chars[] = ";"; -- --/* Characters which are used to indicate an exponent in a floating -- point number. */ --const char EXP_CHARS[] = "eE"; -- --/* Characters which mean that a number is a floating point constant, -- as in 0d1.0. */ --/* XXX: Do all of these really get used on the sw_64?? */ --const char FLT_CHARS[] = "rRsSfFdDxXpP"; -- --/* The argument of the -march= flag. The architecture we are assembling. */ --static int file_sw_64_arch = CPU_UNKNOWN; --static const char *sw_64_arch_string; -- --struct sw_64_cpu_info --{ -- const char *name; /* CPU or ISA name. */ -- int flags; /* SW_64_CPU_* flags. */ -- int ase; /* Set of ASEs implemented by the CPU. */ -- int isa; /* ISA level. */ -- int cpu; /* CPU number (default CPU if ISA). */ --}; -- --#define SW_64_CPU_IS_ISA 0x0001 /* Is this an ISA? (If 0, a CPU.) */ -- --struct sw_64_set_options --{ -- int isa; -- int ase; -- int sw_64_tmp; -- int micromips; -- int noreorder; -- unsigned int at; -- int warn_about_macros; -- int nomove; -- int nobopt; -- int noautoextend; -- bfd_boolean insn32; -- int gp32; -- int fp32; -- int arch; -- bfd_boolean sym32; -- bfd_boolean soft_float; -- bfd_boolean single_float; --}; -- --static struct sw_64_set_options sw_64_opts = --{ -- /* isa */ ISA_UNKNOWN, /* ase */ 0, /* sw_64_tmp */ -1, /* micromips */ -1, -- /* noreorder */ 0, /* at */ FALSE, /* warn_about_macros */ 0, -- /* nomove */ 0, /* nobopt */ 0, /* noautoextend */ 0, /* insn32 */ FALSE, -- /* gp32 */ 0, /* fp32 */ 0, /* arch */ CPU_UNKNOWN, /* sym32 */ FALSE, -- /* soft_float */ FALSE, /* single_float */ FALSE --}; -- --static const struct sw_64_cpu_info *sw_64_parse_cpu (const char *, const char *); --static const struct sw_64_cpu_info *sw_64_cpu_info_from_isa (int); --static const struct sw_64_cpu_info *sw_64_cpu_info_from_arch (int); -- --#ifdef OBJ_EVAX --const char *md_shortopts = "Fm:g+1h:HG:"; --#else --const char *md_shortopts = "Fm:gG:"; --#endif -- --struct option md_longopts[] = -- { --#define OPTION_32ADDR (OPTION_MD_BASE) -- { "32addr", no_argument, NULL, OPTION_32ADDR }, --#define OPTION_NOCHECK_SAMEREG (OPTION_32ADDR + 1) -- { "nocheck-samereg", no_argument, NULL, OPTION_NOCHECK_SAMEREG}, --#define OPTION_RELAX (OPTION_NOCHECK_SAMEREG + 1) -- { "relax", no_argument, NULL, OPTION_RELAX }, --#ifdef OBJ_ELF --#define OPTION_MDEBUG (OPTION_RELAX + 1) --#define OPTION_NO_MDEBUG (OPTION_MDEBUG + 1) -- { "mdebug", no_argument, NULL, OPTION_MDEBUG }, -- { "no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG }, --#endif --#ifdef OBJ_EVAX --#define OPTION_REPLACE (OPTION_RELAX + 1) --#define OPTION_NOREPLACE (OPTION_REPLACE+1) -- { "replace", no_argument, NULL, OPTION_REPLACE }, -- { "noreplace", no_argument, NULL, OPTION_NOREPLACE }, --#endif -- { NULL, no_argument, NULL, 0 } -- }; -- --size_t md_longopts_size = sizeof (md_longopts); -- --#ifdef OBJ_EVAX --#define AXP_REG_R0 0 --#define AXP_REG_R16 16 --#define AXP_REG_R17 17 --#undef AXP_REG_T9 --#define AXP_REG_T9 22 --#undef AXP_REG_T10 --#define AXP_REG_T10 23 --#undef AXP_REG_T11 --#define AXP_REG_T11 24 --#undef AXP_REG_T12 --#define AXP_REG_T12 25 --#define AXP_REG_AI 25 --#undef AXP_REG_FP --#define AXP_REG_FP 29 -- --#undef AXP_REG_GP --#define AXP_REG_GP AXP_REG_PV -- --#endif /* OBJ_EVAX */ -- --/* The cpu for which we are generating code. */ --static unsigned sw_64_target; --static const char *sw_64_target_name; -- --/* The hash table of instruction opcodes. */ --static htab_t sw_64_opcode_hash; -- --/* The hash table of macro opcodes. */ --static htab_t sw_64_macro_hash; -- --#ifdef OBJ_ECOFF --/* The $gp relocation symbol. */ --static symbolS *sw_64_gp_symbol; -- --/* XXX: what is this, and why is it exported? */ --valueT sw_64_gp_value; --#endif -- --/* The current $gp register. */ --static int sw_64_gp_register = AXP_REG_GP; -- --/* A table of the register symbols. */ --static symbolS *sw_64_register_table[64]; -- --/* Constant sections, or sections of constants. */ --#ifdef OBJ_ECOFF --static segT sw_64_lita_section; --#endif --#ifdef OBJ_EVAX --segT sw_64_link_section; --#endif --#ifndef OBJ_EVAX --static segT sw_64_lit8_section; --#endif -- --/* Symbols referring to said sections. */ --#ifdef OBJ_ECOFF --static symbolS *sw_64_lita_symbol; --#endif --#ifdef OBJ_EVAX --static symbolS *sw_64_link_symbol; --#endif --#ifndef OBJ_EVAX --static symbolS *sw_64_lit8_symbol; --#endif -- --/* Literal for .litX+0x8000 within .lita. */ --#ifdef OBJ_ECOFF --static offsetT sw_64_lit8_literal; --#endif -- --/* Is the assembler not allowed to use $at? */ --static int sw_64_noat_on = 0; -- --/* Are macros enabled? */ --static int sw_64_macros_on = 1; -- --/* Are floats disabled? */ --static int sw_64_nofloats_on = 0; -- --/* Are addresses 32 bit? */ --static int sw_64_addr32_on = 0; -- --/* Symbol labelling the current insn. When the Sw_64 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 *sw_64_insn_label; --#if defined(OBJ_ELF) || defined (OBJ_EVAX) --static symbolS *sw_64_prologue_label; --#endif -- --#ifdef OBJ_EVAX --/* Symbol associate with the current call instruction. */ --static symbolS *sw_64_linkage_symbol; --#endif -- --/* Whether we should automatically align data generation pseudo-ops. -- .align 0 will turn this off. */ --static int sw_64_auto_align_on = 1; -- --/* The known current alignment of the current section. */ --static int sw_64_current_align; -- --/* These are exported to ECOFF code. */ --unsigned long sw_64_gprmask, sw_64_fprmask; -- --/* Whether the debugging option was seen. */ --static int sw_64_debug; -- --#ifdef OBJ_ELF --/* Whether we are emitting an mdebug section. */ --int sw_64_flag_mdebug = -1; --#endif -- --#ifdef OBJ_EVAX --/* Whether to perform the VMS procedure call optimization. */ --int sw_64_flag_replace = 1; --#endif -- --/* Don't fully resolve relocations, allowing code movement in the linker. */ --static int sw_64_flag_relax; -- --/* What value to give to bfd_set_gp_size. */ --static int g_switch_value = 8; -- --static int sw_64_flag_nocheck_samereg = 0; -- --#ifdef OBJ_EVAX --/* Collect information about current procedure here. */ --struct sw_64_evax_procs --{ -- symbolS *symbol; /* Proc pdesc symbol. */ -- int pdsckind; -- int framereg; /* Register for frame pointer. */ -- int framesize; /* Size of frame. */ -- int rsa_offset; -- int ra_save; -- int fp_save; -- long imask; -- long fmask; -- int type; -- int prologue; -- symbolS *handler; -- int handler_data; --}; -- --/* Linked list of .linkage fixups. */ --struct sw_64_linkage_fixups *sw_64_linkage_fixup_root; --static struct sw_64_linkage_fixups *sw_64_linkage_fixup_tail; -- --/* Current procedure descriptor. */ --static struct sw_64_evax_procs *sw_64_evax_proc; --static struct sw_64_evax_procs sw_64_evax_proc_data; -- --static int sw_64_flag_hash_long_names = 0; /* -+ */ --static int sw_64_flag_show_after_trunc = 0; /* -H */ -- --/* If the -+ switch is given, then a hash is appended to any name that is -- longer than 64 characters, else longer symbol names are truncated. */ -- --#endif -- --#ifdef RELOC_OP_P --/* A table to map the spelling of a relocation operand into an appropriate -- bfd_reloc_code_real_type type. The table is assumed to be ordered such -- that op-O_literal indexes into it. */ -- --#define SW_64_RELOC_TABLE(op) \ --(&sw_64_reloc_op[ ((!USER_RELOC_P (op)) \ -- ? (abort (), 0) \ -- : (int) (op) - (int) O_literal) ]) -- --#define DEF(NAME, RELOC, REQ, ALLOW) \ -- { #NAME, sizeof(#NAME)-1, O_##NAME, RELOC, REQ, ALLOW} -- --static const struct sw_64_reloc_op_tag --{ -- const char *name; /* String to lookup. */ -- size_t length; /* Size of the string. */ -- operatorT op; /* Which operator to use. */ -- extended_bfd_reloc_code_real_type reloc; -- unsigned int require_seq : 1; /* Require a sequence number. */ -- unsigned int allow_seq : 1; /* Allow a sequence number. */ --} --sw_64_reloc_op[] = --{ -- DEF (literal, BFD_RELOC_SW_64_ELF_LITERAL, 0, 1), -- DEF (lituse_addr, DUMMY_RELOC_LITUSE_ADDR, 1, 1), -- DEF (lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1), -- DEF (lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1), -- DEF (lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1), -- DEF (lituse_tlsgd, DUMMY_RELOC_LITUSE_TLSGD, 1, 1), -- DEF (lituse_tlsldm, DUMMY_RELOC_LITUSE_TLSLDM, 1, 1), -- DEF (lituse_jsrdirect, DUMMY_RELOC_LITUSE_JSRDIRECT, 1, 1), -- DEF (gpdisp, BFD_RELOC_SW_64_GPDISP, 1, 1), -- DEF (gprelhigh, BFD_RELOC_SW_64_GPREL_HI16, 0, 0), -- DEF (gprellow, BFD_RELOC_SW_64_GPREL_LO16, 0, 0), -- DEF (gprel, BFD_RELOC_GPREL16, 0, 0), -- DEF (samegp, BFD_RELOC_SW_64_BRSGP, 0, 0), -- DEF (tlsgd, BFD_RELOC_SW_64_TLSGD, 0, 1), -- DEF (tlsldm, BFD_RELOC_SW_64_TLSLDM, 0, 1), -- DEF (gotdtprel, BFD_RELOC_SW_64_GOTDTPREL16, 0, 0), -- DEF (dtprelhi, BFD_RELOC_SW_64_DTPREL_HI16, 0, 0), -- DEF (dtprello, BFD_RELOC_SW_64_DTPREL_LO16, 0, 0), -- DEF (dtprel, BFD_RELOC_SW_64_DTPREL16, 0, 0), -- DEF (gottprel, BFD_RELOC_SW_64_GOTTPREL16, 0, 0), -- DEF (tprelhi, BFD_RELOC_SW_64_TPREL_HI16, 0, 0), -- DEF (tprello, BFD_RELOC_SW_64_TPREL_LO16, 0, 0), -- DEF (tprel, BFD_RELOC_SW_64_TPREL16, 0, 0), --}; -- --#undef DEF -- --static const int sw_64_num_reloc_op -- = sizeof (sw_64_reloc_op) / sizeof (*sw_64_reloc_op); --#endif /* RELOC_OP_P */ -- --/* Maximum # digits needed to hold the largest sequence #. */ --#define SW_64_RELOC_DIGITS 25 -- --/* Structure to hold explicit sequence information. */ --struct sw_64_reloc_tag --{ -- fixS *master; /* The literal reloc. */ --#ifdef OBJ_EVAX -- struct symbol *sym; /* Linkage section item symbol. */ -- struct symbol *psym; /* Pdesc symbol. */ --#endif -- fixS *slaves; /* Head of linked list of lituses. */ -- segT segment; /* Segment relocs are in or undefined_section. */ -- long sequence; /* Sequence #. */ -- unsigned n_master; /* # of literals. */ -- unsigned n_slaves; /* # of lituses. */ -- unsigned saw_tlsgd : 1; /* True if ... */ -- unsigned saw_tlsldm : 1; -- unsigned saw_lu_tlsgd : 1; -- unsigned saw_lu_tlsldm : 1; -- unsigned multi_section_p : 1; /* True if more than one section was used. */ -- char string[1]; /* Printable form of sequence to hash with. */ --}; -- --/* Hash table to link up literals with the appropriate lituse. */ --static htab_t sw_64_literal_hash; -- --/* Sequence numbers for internal use by macros. */ --static long next_sequence_num = -1; -- --/* A table of CPU names and opcode sets. */ -- --static const struct cpu_type --{ -- const char *name; -- unsigned flags; --} --cpu_types[] = --{ -- { "sw6a", AXP_OPCODE_SW6|AXP_OPCODE_SW6A}, -- { "sw6b", AXP_OPCODE_SW6|AXP_OPCODE_SW6B}, -- { 0, 0 } --}; -- --/* Some instruction sets indexed by lg(size). */ --static const char * const sextX_op[] = { "sextb", "sexth", "sextw", NULL }; --static const char * const insXl_op[] = { "ins0b", "ins1b", "ins2b", "ins3b" }; --static const char * const insXh_op[] = { NULL, "ins5b", "ins6b", "ins7b" }; --static const char * const extXl_op[] = { "ext0b", "ext1b", "ext2b", "ext3b" }; --static const char * const extXh_op[] = { NULL, "ext5b", "ext6b", "ext7b" }; --static const char * const mskXl_op[] = { "mask0b", "mask1b", "mask2b", "mask3b" }; --static const char * const mskXh_op[] = { NULL, "mask5b", "mask6b", "mask7b" }; --static const char * const stX_op[] = { "stb", "stb", "stw", "stl" }; --static const char * const ldXu_op[] = { "ldbu", "ldhu", NULL, NULL }; -- --static void assemble_insn (const struct sw_64_opcode *, const expressionS *, int, struct sw_64_insn *, extended_bfd_reloc_code_real_type); --static void emit_insn (struct sw_64_insn *); --static void assemble_tokens (const char *, const expressionS *, int, int); --#ifdef OBJ_EVAX --static const char *s_sw_64_section_name (void); --static symbolS *add_to_link_pool (symbolS *, offsetT); --#endif -- --static struct sw_64_reloc_tag * --get_sw_64_reloc_tag (long sequence) --{ -- char buffer[SW_64_RELOC_DIGITS]; -- struct sw_64_reloc_tag *info; -- -- sprintf (buffer, "!%ld", sequence); -- -- info = (struct sw_64_reloc_tag *) str_hash_find (sw_64_literal_hash, buffer); -- if (! info) -- { -- size_t len = strlen (buffer); -- -- info = (struct sw_64_reloc_tag *) -- xcalloc (sizeof (struct sw_64_reloc_tag) + len, 1); -- -- info->segment = now_seg; -- info->sequence = sequence; -- strcpy (info->string, buffer); -- str_hash_insert (sw_64_literal_hash, info->string, info, 0); -- --#ifdef OBJ_EVAX -- info->sym = 0; -- info->psym = 0; --#endif -- } -- -- return info; --} -- --#ifndef OBJ_EVAX -- --static void --sw_64_adjust_relocs (bfd *abfd ATTRIBUTE_UNUSED, -- asection *sec, -- void * ptr ATTRIBUTE_UNUSED) --{ -- segment_info_type *seginfo = seg_info (sec); -- fixS **prevP; -- fixS *fixp; -- fixS *next; -- fixS *slave; -- -- /* If seginfo is NULL, we did not create this section; don't do -- anything with it. By using a pointer to a pointer, we can update -- the links in place. */ -- if (seginfo == NULL) -- return; -- -- /* If there are no relocations, skip the section. */ -- if (! seginfo->fix_root) -- return; -- -- /* First rebuild the fixup chain without the explicit lituse and -- gpdisp_lo16 relocs. */ -- prevP = &seginfo->fix_root; -- for (fixp = seginfo->fix_root; fixp; fixp = next) -- { -- next = fixp->fx_next; -- fixp->fx_next = (fixS *) 0; -- -- switch (fixp->fx_r_type) -- { -- case BFD_RELOC_SW_64_LITUSE: -- if (fixp->tc_fix_data.info->n_master == 0) -- as_bad_where (fixp->fx_file, fixp->fx_line, -- _("No !literal!%ld was found"), -- fixp->tc_fix_data.info->sequence); --#ifdef RELOC_OP_P -- if (fixp->fx_offset == LITUSE_SW_64_TLSGD) -- { -- if (! fixp->tc_fix_data.info->saw_tlsgd) -- as_bad_where (fixp->fx_file, fixp->fx_line, -- _("No !tlsgd!%ld was found"), -- fixp->tc_fix_data.info->sequence); -- } -- else if (fixp->fx_offset == LITUSE_SW_64_TLSLDM) -- { -- if (! fixp->tc_fix_data.info->saw_tlsldm) -- as_bad_where (fixp->fx_file, fixp->fx_line, -- _("No !tlsldm!%ld was found"), -- fixp->tc_fix_data.info->sequence); -- } --#endif -- break; -- -- case BFD_RELOC_SW_64_GPDISP_LO16: -- if (fixp->tc_fix_data.info->n_master == 0) -- as_bad_where (fixp->fx_file, fixp->fx_line, -- _("No ldih !gpdisp!%ld was found"), -- fixp->tc_fix_data.info->sequence); -- break; -- -- case BFD_RELOC_SW_64_ELF_LITERAL: -- if (fixp->tc_fix_data.info -- && (fixp->tc_fix_data.info->saw_tlsgd -- || fixp->tc_fix_data.info->saw_tlsldm)) -- break; -- /* FALLTHRU */ -- -- default: -- *prevP = fixp; -- prevP = &fixp->fx_next; -- break; -- } -- } -- -- /* Go back and re-chain dependent relocations. They are currently -- linked through the next_reloc field in reverse order, so as we -- go through the next_reloc chain, we effectively reverse the chain -- once again. -- -- Except if there is more than one !literal for a given sequence -- number. In that case, the programmer and/or compiler is not sure -- how control flows from literal to lituse, and we can't be sure to -- get the relaxation correct. -- -- ??? Well, actually we could, if there are enough lituses such that -- we can make each literal have at least one of each lituse type -- present. Not implemented. -- -- Also suppress the optimization if the !literals/!lituses are spread -- in different segments. This can happen with "interesting" uses of -- inline assembly; examples are present in the Linux kernel semaphores. */ -- -- for (fixp = seginfo->fix_root; fixp; fixp = next) -- { -- next = fixp->fx_next; -- switch (fixp->fx_r_type) -- { -- case BFD_RELOC_SW_64_TLSGD: -- case BFD_RELOC_SW_64_TLSLDM: -- if (!fixp->tc_fix_data.info) -- break; -- if (fixp->tc_fix_data.info->n_master == 0) -- break; -- else if (fixp->tc_fix_data.info->n_master > 1) -- { -- as_bad_where (fixp->fx_file, fixp->fx_line, -- _("too many !literal!%ld for %s"), -- fixp->tc_fix_data.info->sequence, -- (fixp->fx_r_type == BFD_RELOC_SW_64_TLSGD -- ? "!tlsgd" : "!tlsldm")); -- break; -- } -- -- fixp->tc_fix_data.info->master->fx_next = fixp->fx_next; -- fixp->fx_next = fixp->tc_fix_data.info->master; -- fixp = fixp->fx_next; -- /* Fall through. */ -- -- case BFD_RELOC_SW_64_ELF_LITERAL: -- if (fixp->tc_fix_data.info -- && fixp->tc_fix_data.info->n_master == 1 -- && ! fixp->tc_fix_data.info->multi_section_p) -- { -- for (slave = fixp->tc_fix_data.info->slaves; -- slave != (fixS *) 0; -- slave = slave->tc_fix_data.next_reloc) -- { -- slave->fx_next = fixp->fx_next; -- fixp->fx_next = slave; -- } -- } -- break; -- -- case BFD_RELOC_SW_64_GPDISP_HI16: -- if (fixp->tc_fix_data.info->n_slaves == 0) -- as_bad_where (fixp->fx_file, fixp->fx_line, -- _("No ldi !gpdisp!%ld was found"), -- fixp->tc_fix_data.info->sequence); -- else -- { -- slave = fixp->tc_fix_data.info->slaves; -- slave->fx_next = next; -- fixp->fx_next = slave; -- } -- break; -- -- default: -- break; -- } -- } --} -- --/* Before the relocations are written, reorder them, so that user -- supplied !lituse relocations follow the appropriate !literal -- relocations, and similarly for !gpdisp relocations. */ -- --void --sw_64_before_fix (void) --{ -- if (sw_64_literal_hash) -- bfd_map_over_sections (stdoutput, sw_64_adjust_relocs, NULL); --} -- --#endif -- --#ifdef DEBUG_SW_64 --static void --debug_exp (expressionS tok[], int ntok) --{ -- int i; -- -- fprintf (stderr, "debug_exp: %d tokens", ntok); -- for (i = 0; i < ntok; i++) -- { -- expressionS *t = &tok[i]; -- const char *name; -- -- switch (t->X_op) -- { -- default: name = "unknown"; break; -- case O_illegal: name = "O_illegal"; break; -- case O_absent: name = "O_absent"; break; -- case O_constant: name = "O_constant"; break; -- case O_symbol: name = "O_symbol"; break; -- case O_symbol_rva: name = "O_symbol_rva"; break; -- case O_register: name = "O_register"; break; -- case O_big: name = "O_big"; break; -- case O_uminus: name = "O_uminus"; break; -- case O_bit_not: name = "O_bit_not"; break; -- case O_logical_not: name = "O_logical_not"; break; -- case O_multiply: name = "O_multiply"; break; -- case O_divide: name = "O_divide"; break; -- case O_modulus: name = "O_modulus"; break; -- case O_left_shift: name = "O_left_shift"; break; -- case O_right_shift: name = "O_right_shift"; break; -- case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break; -- case O_bit_or_not: name = "O_bit_or_not"; break; -- case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break; -- case O_bit_and: name = "O_bit_and"; break; -- case O_add: name = "O_add"; break; -- case O_subtract: name = "O_subtract"; break; -- case O_eq: name = "O_eq"; break; -- case O_ne: name = "O_ne"; break; -- case O_lt: name = "O_lt"; break; -- case O_le: name = "O_le"; break; -- case O_ge: name = "O_ge"; break; -- case O_gt: name = "O_gt"; break; -- case O_logical_and: name = "O_logical_and"; break; -- case O_logical_or: name = "O_logical_or"; break; -- case O_index: name = "O_index"; break; -- case O_pregister: name = "O_pregister"; break; -- case O_cpregister: name = "O_cpregister"; break; -- case O_literal: name = "O_literal"; break; -- case O_lituse_addr: name = "O_lituse_addr"; break; -- case O_lituse_base: name = "O_lituse_base"; break; -- case O_lituse_bytoff: name = "O_lituse_bytoff"; break; -- case O_lituse_jsr: name = "O_lituse_jsr"; break; -- case O_lituse_tlsgd: name = "O_lituse_tlsgd"; break; -- case O_lituse_tlsldm: name = "O_lituse_tlsldm"; break; -- case O_lituse_jsrdirect: name = "O_lituse_jsrdirect"; break; -- case O_gpdisp: name = "O_gpdisp"; break; -- case O_gprelhigh: name = "O_gprelhigh"; break; -- case O_gprellow: name = "O_gprellow"; break; -- case O_gprel: name = "O_gprel"; break; -- case O_samegp: name = "O_samegp"; break; -- case O_tlsgd: name = "O_tlsgd"; break; -- case O_tlsldm: name = "O_tlsldm"; break; -- case O_gotdtprel: name = "O_gotdtprel"; break; -- case O_dtprelhi: name = "O_dtprelhi"; break; -- case O_dtprello: name = "O_dtprello"; break; -- case O_dtprel: name = "O_dtprel"; break; -- case O_gottprel: name = "O_gottprel"; break; -- case O_tprelhi: name = "O_tprelhi"; break; -- case O_tprello: name = "O_tprello"; break; -- case O_tprel: name = "O_tprel"; break; -- } -- -- fprintf (stderr, ", %s(%s, %s, %d)", name, -- (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--", -- (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--", -- (int) t->X_add_number); -- } -- fprintf (stderr, "\n"); -- fflush (stderr); --} --#endif -- --/* Parse the arguments to an opcode. */ -- --static int --tokenize_arguments (char *str, -- expressionS tok[], -- int ntok) --{ -- expressionS *end_tok = tok + ntok; -- char *old_input_line_pointer; -- int saw_comma = 0, saw_arg = 0; --#ifdef DEBUG_SW_64 -- expressionS *orig_tok = tok; --#endif --#ifdef RELOC_OP_P -- char *p; -- const struct sw_64_reloc_op_tag *r; -- int c, i; -- size_t len; -- int reloc_found_p = 0; --#endif -- -- memset (tok, 0, sizeof (*tok) * ntok); -- -- /* Save and restore input_line_pointer around this function. */ -- old_input_line_pointer = input_line_pointer; -- input_line_pointer = str; -- --#ifdef RELOC_OP_P -- /* ??? Wrest control of ! away from the regular expression parser. */ -- is_end_of_line[(unsigned char) '!'] = 1; --#endif -- -- while (tok < end_tok && *input_line_pointer) -- { -- SKIP_WHITESPACE (); -- switch (*input_line_pointer) -- { -- case '\0': -- goto fini; -- --#ifdef RELOC_OP_P -- case '!': -- /* A relocation operand can be placed after the normal operand on an -- assembly language statement, and has the following form: -- !relocation_type!sequence_number. */ -- if (reloc_found_p) -- { -- /* Only support one relocation op per insn. */ -- as_bad (_("More than one relocation op per insn")); -- goto err_report; -- } -- -- if (!saw_arg) -- goto err; -- -- ++input_line_pointer; -- SKIP_WHITESPACE (); -- c = get_symbol_name (&p); -- -- /* Parse !relocation_type. */ -- len = input_line_pointer - p; -- if (len == 0) -- { -- as_bad (_("No relocation operand")); -- goto err_report; -- } -- -- r = &sw_64_reloc_op[0]; -- for (i = sw_64_num_reloc_op - 1; i >= 0; i--, r++) -- if (len == r->length && memcmp (p, r->name, len) == 0) -- break; -- if (i < 0) -- { -- as_bad (_("Unknown relocation operand: !%s"), p); -- goto err_report; -- } -- -- *input_line_pointer = c; -- SKIP_WHITESPACE_AFTER_NAME (); -- if (*input_line_pointer != '!') -- { -- if (r->require_seq) -- { -- as_bad (_("no sequence number after !%s"), p); -- goto err_report; -- } -- -- tok->X_add_number = 0; -- } -- else -- { -- if (! r->allow_seq) -- { -- as_bad (_("!%s does not use a sequence number"), p); -- goto err_report; -- } -- -- input_line_pointer++; -- -- /* Parse !sequence_number. */ -- expression (tok); -- if (tok->X_op != O_constant || tok->X_add_number <= 0) -- { -- as_bad (_("Bad sequence number: !%s!%s"), -- r->name, input_line_pointer); -- goto err_report; -- } -- } -- -- tok->X_op = r->op; -- reloc_found_p = 1; -- ++tok; -- break; --#endif /* RELOC_OP_P */ -- -- case ',': -- ++input_line_pointer; -- if (saw_comma || !saw_arg) -- goto err; -- saw_comma = 1; -- break; -- -- case '(': -- { -- char *hold = input_line_pointer++; -- -- /* First try for parenthesized register ... */ -- expression (tok); -- if (*input_line_pointer == ')' && tok->X_op == O_register) -- { -- tok->X_op = (saw_comma ? O_cpregister : O_pregister); -- saw_comma = 0; -- saw_arg = 1; -- ++input_line_pointer; -- ++tok; -- break; -- } -- -- /* ... then fall through to plain expression. */ -- input_line_pointer = hold; -- } -- /* Fall through. */ -- -- default: -- if (saw_arg && !saw_comma) -- goto err; -- -- expression (tok); -- if (tok->X_op == O_illegal || tok->X_op == O_absent) -- goto err; -- -- saw_comma = 0; -- saw_arg = 1; -- ++tok; -- break; -- } -- } -- --fini: -- if (saw_comma) -- goto err; -- input_line_pointer = old_input_line_pointer; -- --#ifdef DEBUG_SW_64 -- debug_exp (orig_tok, ntok - (end_tok - tok)); --#endif --#ifdef RELOC_OP_P -- is_end_of_line[(unsigned char) '!'] = 0; --#endif -- -- return ntok - (end_tok - tok); -- --err: --#ifdef RELOC_OP_P -- is_end_of_line[(unsigned char) '!'] = 0; --#endif -- input_line_pointer = old_input_line_pointer; -- return TOKENIZE_ERROR; -- --#ifdef RELOC_OP_P --err_report: -- is_end_of_line[(unsigned char) '!'] = 0; --#endif -- input_line_pointer = old_input_line_pointer; -- return TOKENIZE_ERROR_REPORT; --} -- --/* Search forward through all variants of an opcode looking for a -- syntax match. */ -- --static const struct sw_64_opcode * --find_opcode_match (const struct sw_64_opcode *first_opcode, -- const expressionS *tok, -- int *pntok, -- int *pcpumatch) --{ -- const struct sw_64_opcode *opcode = first_opcode; -- int ntok = *pntok; -- int got_cpu_match = 0; -- -- do -- { -- const unsigned char *opidx; -- int tokidx = 0; -- -- /* Don't match opcodes that don't exist on this architecture. */ -- if (!(opcode->flags & sw_64_target)) -- goto match_failed; -- -- got_cpu_match = 1; -- -- for (opidx = opcode->operands; *opidx; ++opidx) -- { -- const struct sw_64_operand *operand = &sw_64_operands[*opidx]; -- -- /* Only take input from real operands. */ -- if (operand->flags & AXP_OPERAND_FAKE) -- continue; -- -- /* When we expect input, make sure we have it. */ -- if (tokidx >= ntok) -- { -- /* -pal: don't allowed to use default result register. */ -- if (pal_org_backwrards) -- goto match_failed; -- else -- if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0) -- goto match_failed; -- continue; -- } -- -- /* Match operand type with expression type. */ -- switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK) -- { -- case AXP_OPERAND_IR: -- if (tok[tokidx].X_op != O_register -- || !is_ir_num (tok[tokidx].X_add_number)) -- goto match_failed; -- break; -- case AXP_OPERAND_FPR: -- if (tok[tokidx].X_op != O_register -- || !is_fpr_num (tok[tokidx].X_add_number)) -- goto match_failed; -- break; -- case AXP_OPERAND_IR | AXP_OPERAND_PARENS: -- if (tok[tokidx].X_op != O_pregister -- || !is_ir_num (tok[tokidx].X_add_number)) -- goto match_failed; -- break; -- case AXP_OPERAND_IR | AXP_OPERAND_PARENS | AXP_OPERAND_COMMA: -- if (tok[tokidx].X_op != O_cpregister -- || !is_ir_num (tok[tokidx].X_add_number)) -- goto match_failed; -- break; -- -- case AXP_OPERAND_RELATIVE: -- case AXP_OPERAND_SIGNED: -- case AXP_OPERAND_UNSIGNED: -- switch (tok[tokidx].X_op) -- { -- case O_illegal: -- case O_absent: -- case O_register: -- case O_pregister: -- case O_cpregister: -- goto match_failed; -- -- default: -- break; -- } -- break; -- -- default: -- /* Everything else should have been fake. */ -- abort (); -- } -- ++tokidx; -- } -- -- /* Possible match -- did we use all of our input? */ -- if (tokidx == ntok) -- { -- *pntok = ntok; -- return opcode; -- } -- -- match_failed:; -- } -- while (++opcode - sw_64_opcodes < (int) sw_64_num_opcodes -- && !strcmp (opcode->name, first_opcode->name)); -- -- if (*pcpumatch) -- *pcpumatch = got_cpu_match; -- -- return NULL; --} -- --/* Given an opcode name and a pre-tokenized set of arguments, assemble -- the insn, but do not emit it. -- -- Note that this implies no macros allowed, since we can't store more -- than one insn in an insn structure. */ -- --static void --assemble_tokens_to_insn (const char *opname, -- const expressionS *tok, -- int ntok, -- struct sw_64_insn *insn) --{ -- const struct sw_64_opcode *opcode; -- -- /* Search opcodes. */ -- opcode = (const struct sw_64_opcode *) str_hash_find (sw_64_opcode_hash, opname); -- if (opcode) -- { -- int cpumatch; -- opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch); -- if (opcode) -- { -- assemble_insn (opcode, tok, ntok, insn, BFD_RELOC_UNUSED); -- return; -- } -- else if (cpumatch) -- as_bad (_("inappropriate arguments for opcode `%s'"), opname); -- else -- as_bad (_("opcode `%s' not supported for target %s"), opname, -- sw_64_target_name); -- } -- else -- as_bad (_("unknown opcode `%s'"), opname); --} -- --/* Build a BFD section with its flags set appropriately for the .lita, -- .lit8, or .lit4 sections. */ -- --static void --create_literal_section (const char *name, -- segT *secp, -- symbolS **symp) --{ -- 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 (new_sec, 4); -- bfd_set_section_flags (new_sec, (SEC_RELOC | SEC_ALLOC | SEC_LOAD -- | SEC_READONLY | SEC_DATA)); -- -- S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec)); --} -- --/* Load a (partial) expression into a target register. -- -- If poffset is not null, after the call it will either contain -- O_constant 0, or a 16-bit offset appropriate for any MEM format -- instruction. In addition, pbasereg will be modified to point to -- the base register to use in that MEM format instruction. -- -- In any case, *pbasereg should contain a base register to add to the -- expression. This will normally be either AXP_REG_ZERO or -- sw_64_gp_register. Symbol addresses will always be loaded via $gp, -- so "foo($0)" is interpreted as adding the address of foo to $0; -- i.e. "ldl $targ, LIT($gp); addl $targ, $0, $targ". Odd, perhaps, -- but this is what OSF/1 does. -- -- If explicit relocations of the form !literal! are allowed, -- and used, then explicit_reloc with be an expression pointer. -- -- Finally, the return value is nonzero if the calling macro may emit -- a LITUSE reloc if otherwise appropriate; the return value is the -- sequence number to use. */ -- --static long --load_expression (int targreg, -- const expressionS *exp, -- int *pbasereg, -- expressionS *poffset, -- const char *opname) --{ -- long emit_lituse = 0; -- offsetT addend = exp->X_add_number; -- int basereg = *pbasereg; -- struct sw_64_insn insn; -- expressionS newtok[3]; -- -- switch (exp->X_op) -- { -- case O_symbol: -- { --#ifdef OBJ_ECOFF -- offsetT lit; -- -- /* Attempt to reduce .lit load by splitting the offset from -- its symbol when possible, but don't create a situation in -- which we'd fail. */ -- if (!range_signed_32 (addend) && -- (sw_64_noat_on || targreg == AXP_REG_AT)) -- { -- lit = add_to_literal_pool (exp->X_add_symbol, addend, -- sw_64_lita_section, 8); -- addend = 0; -- } -- else -- lit = add_to_literal_pool (exp->X_add_symbol, 0, -- sw_64_lita_section, 8); -- -- if (lit >= 0x8000) -- as_fatal (_("overflow in literal (.lita) table")); -- -- /* Emit "ldl r, lit(gp)". */ -- -- if (basereg != sw_64_gp_register && targreg == basereg) -- { -- if (sw_64_noat_on) -- as_warn (_("macro requires $at register while noat in effect")); -- if (targreg == AXP_REG_AT) -- as_warn (_("macro requires $at while $at in use")); -- -- set_tok_reg (newtok[0], AXP_REG_AT); -- } -- else -- set_tok_reg (newtok[0], targreg); -- -- set_tok_sym (newtok[1], sw_64_lita_symbol, lit); -- set_tok_preg (newtok[2], sw_64_gp_register); -- -- -- assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -- -- gas_assert (insn.nfixups == 1); -- insn.fixups[0].reloc = BFD_RELOC_SW_64_LITERAL; -- insn.sequence = emit_lituse = next_sequence_num--; --#endif /* OBJ_ECOFF */ --#ifdef OBJ_ELF -- /* Emit "ldl r, gotoff(gp)". */ -- -- if (basereg != sw_64_gp_register && targreg == basereg) -- { -- if (sw_64_noat_on) -- as_bad (_("macro requires $at register while noat in effect")); -- if (targreg == AXP_REG_AT) -- as_bad (_("macro requires $at while $at in use")); -- -- set_tok_reg (newtok[0], AXP_REG_AT); -- } -- else -- set_tok_reg (newtok[0], targreg); -- -- /* XXX: Disable this .got minimizing optimization so that we can get -- better instruction offset knowledge in the compiler. This happens -- very infrequently anyway. */ -- if (1 -- || (!range_signed_32 (addend) -- && (sw_64_noat_on || targreg == AXP_REG_AT))) -- { -- newtok[1] = *exp; -- addend = 0; -- } -- else -- set_tok_sym (newtok[1], exp->X_add_symbol, 0); -- -- set_tok_preg (newtok[2], sw_64_gp_register); -- -- assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -- -- gas_assert (insn.nfixups == 1); -- insn.fixups[0].reloc = BFD_RELOC_SW_64_ELF_LITERAL; -- insn.sequence = emit_lituse = next_sequence_num--; --#endif /* OBJ_ELF */ --#ifdef OBJ_EVAX -- /* Find symbol or symbol pointer in link section. */ -- -- if (exp->X_add_symbol == sw_64_evax_proc->symbol) -- { -- /* Linkage-relative expression. */ -- set_tok_reg (newtok[0], targreg); -- -- if (range_signed_16 (addend)) -- { -- set_tok_const (newtok[1], addend); -- addend = 0; -- } -- else -- { -- set_tok_const (newtok[1], 0); -- } -- set_tok_preg (newtok[2], basereg); -- assemble_tokens_to_insn ("ldi", newtok, 3, &insn); -- } -- else -- { -- const char *symname = S_GET_NAME (exp->X_add_symbol); -- const char *ptr1, *ptr2; -- int symlen = strlen (symname); -- -- if ((symlen > 4 && -- strcmp (ptr2 = &symname [symlen - 4], "..lk") == 0)) -- { -- /* Access to an item whose address is stored in the linkage -- section. Just read the address. */ -- set_tok_reg (newtok[0], targreg); -- -- newtok[1] = *exp; -- newtok[1].X_op = O_subtract; -- newtok[1].X_op_symbol = sw_64_evax_proc->symbol; -- -- set_tok_preg (newtok[2], basereg); -- assemble_tokens_to_insn ("ldi", newtok, 3, &insn); -- sw_64_linkage_symbol = exp->X_add_symbol; -- -- if (poffset) -- set_tok_const (*poffset, 0); -- -- if (sw_64_flag_replace && targreg == 26) -- { -- /* Add a NOP fixup for 'ldX $26,YYY..NAME..lk'. */ -- char *ensymname; -- symbolS *ensym; -- -- /* Build the entry name as 'NAME..en'. */ -- ptr1 = strstr (symname, "..") + 2; -- if (ptr1 > ptr2) -- ptr1 = symname; -- ensymname = XNEWVEC (char, ptr2 - ptr1 + 5); -- memcpy (ensymname, ptr1, ptr2 - ptr1); -- memcpy (ensymname + (ptr2 - ptr1), "..en", 5); -- -- gas_assert (insn.nfixups + 1 <= MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = BFD_RELOC_SW_64_NOP; -- ensym = symbol_find_or_make (ensymname); -- free (ensymname); -- symbol_mark_used (ensym); -- /* The fixup must be the same as the BFD_RELOC_SW_64_BOH -- case in emit_jsrjmp. See B.4.5.2 of the OpenVMS Linker -- Utility Manual. */ -- insn.fixups[insn.nfixups].exp.X_op = O_symbol; -- insn.fixups[insn.nfixups].exp.X_add_symbol = ensym; -- insn.fixups[insn.nfixups].exp.X_add_number = 0; -- insn.fixups[insn.nfixups].xtrasym = sw_64_linkage_symbol; -- insn.fixups[insn.nfixups].procsym = sw_64_evax_proc->symbol; -- insn.nfixups++; -- -- /* ??? Force bsym to be instantiated now, as it will be -- too late to do so in tc_gen_reloc. */ -- symbol_get_bfdsym (exp->X_add_symbol); -- } -- else if (sw_64_flag_replace && targreg == 27) -- { -- /* Add a ldi fixup for 'ldX $27,YYY.NAME..lk+8'. */ -- char *psymname; -- symbolS *psym; -- -- /* Extract NAME. */ -- ptr1 = strstr (symname, "..") + 2; -- if (ptr1 > ptr2) -- ptr1 = symname; -- psymname = xmemdup0 (ptr1, ptr2 - ptr1); -- -- gas_assert (insn.nfixups + 1 <= MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = BFD_RELOC_SW_64_LDA; -- psym = symbol_find_or_make (psymname); -- free (psymname); -- symbol_mark_used (psym); -- insn.fixups[insn.nfixups].exp.X_op = O_subtract; -- insn.fixups[insn.nfixups].exp.X_add_symbol = psym; -- insn.fixups[insn.nfixups].exp.X_op_symbol = sw_64_evax_proc->symbol; -- insn.fixups[insn.nfixups].exp.X_add_number = 0; -- insn.fixups[insn.nfixups].xtrasym = sw_64_linkage_symbol; -- insn.fixups[insn.nfixups].procsym = sw_64_evax_proc->symbol; -- insn.nfixups++; -- } -- -- emit_insn (&insn); -- return 0; -- } -- else -- { -- /* Not in the linkage section. Put the value into the linkage -- section. */ -- symbolS *linkexp; -- -- if (!range_signed_32 (addend)) -- addend = sign_extend_32 (addend); -- linkexp = add_to_link_pool (exp->X_add_symbol, 0); -- set_tok_reg (newtok[0], targreg); -- set_tok_sym (newtok[1], linkexp, 0); -- set_tok_preg (newtok[2], basereg); -- assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -- } -- } --#endif /* OBJ_EVAX */ -- -- emit_insn (&insn); -- --#ifndef OBJ_EVAX -- if (basereg != sw_64_gp_register && basereg != AXP_REG_ZERO) -- { -- /* Emit "addl r, base, r". */ -- -- set_tok_reg (newtok[1], basereg); -- set_tok_reg (newtok[2], targreg); -- assemble_tokens ("addl", newtok, 3, 0); -- } --#endif -- basereg = targreg; -- } -- break; -- -- case O_constant: -- break; --/* -- * .text -- * call_hmc__tbi_addr: -- * ldi $4, ((tbi_tbl - call_hmc__tbi_addr) & 0xFFFF)($4) -- * tbi_tbl: -- * -- * the value of label tbi_tbl can't be calculated,so the op of the expression "((tbi_tbl - call_hmc__tbi_addr) & 0xFFFF)" -- * is "O_bit_and" but not "O_constant", so we must pass it ! -- * */ -- case O_bit_and: -- set_tok_reg (newtok[0], targreg); -- newtok[1] = *exp; -- set_tok_preg (newtok[2], basereg); -- assemble_tokens ("ldi", newtok, 3, 0); -- break; -- -- case O_subtract: -- /* Assume that this difference expression will be resolved to an -- absolute value and that that value will fit in 16 bits. */ -- -- set_tok_reg (newtok[0], targreg); -- newtok[1] = *exp; -- set_tok_preg (newtok[2], basereg); -- assemble_tokens (opname, newtok, 3, 0); -- -- if (poffset) -- set_tok_const (*poffset, 0); -- return 0; -- -- case O_big: -- if (exp->X_add_number > 0) -- as_bad (_("bignum invalid; zero assumed")); -- else -- as_bad (_("floating point number invalid; zero assumed")); -- addend = 0; -- break; -- -- default: -- as_bad (_("can't handle expression")); -- addend = 0; -- break; -- } -- -- if (!range_signed_32 (addend)) -- { --#ifdef OBJ_EVAX -- symbolS *litexp; --#else -- offsetT lit; -- long seq_num = next_sequence_num--; --#endif -- -- /* For 64-bit addends, just put it in the literal pool. */ --#ifdef OBJ_EVAX -- /* Emit "ldl targreg, lit(basereg)". */ -- litexp = add_to_link_pool (section_symbol (absolute_section), addend); -- set_tok_reg (newtok[0], targreg); -- set_tok_sym (newtok[1], litexp, 0); -- set_tok_preg (newtok[2], sw_64_gp_register); -- assemble_tokens ("ldl", newtok, 3, 0); --#else -- -- if (sw_64_lit8_section == NULL) -- { -- create_literal_section (".lit8", -- &sw_64_lit8_section, -- &sw_64_lit8_symbol); -- --#ifdef OBJ_ECOFF -- sw_64_lit8_literal = add_to_literal_pool (sw_64_lit8_symbol, 0x8000, -- sw_64_lita_section, 8); -- if (sw_64_lit8_literal >= 0x8000) -- as_fatal (_("overflow in literal (.lita) table")); --#endif -- } -- -- lit = add_to_literal_pool (NULL, addend, sw_64_lit8_section, 8) - 0x8000; -- if (lit >= 0x8000) -- as_fatal (_("overflow in literal (.lit8) table")); -- -- /* Emit "ldi litreg, .lit8+0x8000". */ -- -- if (targreg == basereg) -- { -- if (sw_64_noat_on) -- as_bad (_("macro requires $at register while noat in effect")); -- if (targreg == AXP_REG_AT) -- as_bad (_("macro requires $at while $at in use")); -- -- set_tok_reg (newtok[0], AXP_REG_AT); -- } -- else -- set_tok_reg (newtok[0], targreg); --#ifdef OBJ_ECOFF -- set_tok_sym (newtok[1], sw_64_lita_symbol, sw_64_lit8_literal); --#endif --#ifdef OBJ_ELF -- set_tok_sym (newtok[1], sw_64_lit8_symbol, 0x8000); --#endif -- set_tok_preg (newtok[2], sw_64_gp_register); -- -- assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -- -- gas_assert (insn.nfixups == 1); --#ifdef OBJ_ECOFF -- insn.fixups[0].reloc = BFD_RELOC_SW_64_LITERAL; --#endif --#ifdef OBJ_ELF -- insn.fixups[0].reloc = BFD_RELOC_SW_64_ELF_LITERAL; --#endif -- insn.sequence = seq_num; -- -- emit_insn (&insn); -- -- /* Emit "ldl litreg, lit(litreg)". */ -- -- set_tok_const (newtok[1], lit); -- set_tok_preg (newtok[2], newtok[0].X_add_number); -- -- assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -- -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = seq_num; -- emit_lituse = 0; -- -- emit_insn (&insn); -- -- /* Emit "addl litreg, base, target". */ -- -- if (basereg != AXP_REG_ZERO) -- { -- set_tok_reg (newtok[1], basereg); -- set_tok_reg (newtok[2], targreg); -- assemble_tokens ("addl", newtok, 3, 0); -- } --#endif /* !OBJ_EVAX */ -- -- if (poffset) -- set_tok_const (*poffset, 0); -- *pbasereg = targreg; -- } -- else -- { -- offsetT low, high, extra, tmp; -- -- /* For 32-bit operands, break up the addend. */ -- -- low = sign_extend_16 (addend); -- tmp = addend - low; -- high = sign_extend_16 (tmp >> 16); -- -- if (tmp - (high << 16)) -- { -- extra = 0x4000; -- tmp -= 0x40000000; -- high = sign_extend_16 (tmp >> 16); -- } -- else -- extra = 0; -- -- set_tok_reg (newtok[0], targreg); -- set_tok_preg (newtok[2], basereg); -- -- if (extra) -- { -- /* Emit "ldih r, extra(r). */ -- set_tok_const (newtok[1], extra); -- assemble_tokens ("ldih", newtok, 3, 0); -- set_tok_preg (newtok[2], basereg = targreg); -- } -- -- if (high) -- { -- /* Emit "ldih r, high(r). */ -- set_tok_const (newtok[1], high); -- if (newtok[0].X_add_number==31 && newtok[0].X_op == O_register) -- as_warn (_(" the disp is out of range ,may be incorrect !")); -- else -- assemble_tokens ("ldih", newtok, 3, 0); -- basereg = targreg; -- set_tok_preg (newtok[2], basereg); -- } -- -- if ((low && !poffset) || (!poffset && basereg != targreg)) -- { -- /* Emit "ldi r, low(base)". */ -- set_tok_const (newtok[1], low); -- assemble_tokens ("ldi", newtok, 3, 0); -- basereg = targreg; -- low = 0; -- } -- -- if (poffset) -- set_tok_const (*poffset, low); -- *pbasereg = basereg; -- } -- -- return emit_lituse; --} -- --/* The ldi macro differs from the ldi instruction in that it handles -- most simple expressions, particularly symbol address loads and -- large constants. */ -- --static void --emit_ldi (const expressionS *tok, -- int ntok, -- const void * unused ATTRIBUTE_UNUSED) --{ -- int basereg; -- -- if (ntok == 2) -- basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : sw_64_gp_register); -- else -- basereg = tok[2].X_add_number; -- -- (void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL, "ldi"); --} -- --/* The ldih macro differs from the ldih instruction in that it has $31 -- as an implied base register. */ -- --static void --emit_ldih (const expressionS *tok, -- int ntok ATTRIBUTE_UNUSED, -- const void * unused ATTRIBUTE_UNUSED) --{ -- expressionS newtok[3]; -- -- newtok[0] = tok[0]; -- newtok[1] = tok[1]; -- set_tok_preg (newtok[2], AXP_REG_ZERO); -- -- assemble_tokens ("ldih", newtok, 3, 0); --} -- --/* Called internally to handle all alignment needs. This takes care -- of eliding calls to frag_align if'n the cached current alignment -- says we've already got it, as well as taking care of the auto-align -- feature wrt labels. */ -- --static void --sw_64_align (int n, -- char *pfill, -- symbolS *label, -- int force ATTRIBUTE_UNUSED) --{ -- if (sw_64_current_align >= n) -- return; -- -- if (pfill == NULL) -- { -- if (subseg_text_p (now_seg)) -- frag_align_code (n, 0); -- else -- frag_align (n, 0, 0); -- } -- else -- frag_align (n, *pfill, 0); -- -- sw_64_current_align = n; -- -- if (label != NULL && S_GET_SEGMENT (label) == now_seg) -- { -- symbol_set_frag (label, frag_now); -- S_SET_VALUE (label, (valueT) frag_now_fix ()); -- } -- -- record_alignment (now_seg, n); -- -- /* ??? If sw_64_flag_relax && force && elf, record the requested alignment -- in a reloc for the linker to see. */ --} -- --/* Actually output an instruction with its fixup. */ -- --static void --emit_insn (struct sw_64_insn *insn) --{ -- char *f; -- int i; -- -- /* Take care of alignment duties. */ -- if (sw_64_auto_align_on && sw_64_current_align < 2) -- sw_64_align (2, (char *) NULL, sw_64_insn_label, 0); -- if (sw_64_current_align > 2) -- sw_64_current_align = 2; -- sw_64_insn_label = NULL; -- -- /* Write out the instruction. */ -- f = frag_more (4); -- md_number_to_chars (f, insn->insn, 4); -- --#ifdef OBJ_ELF -- dwarf2_emit_insn (4); --#endif -- -- /* Apply the fixups in order. */ -- for (i = 0; i < insn->nfixups; ++i) -- { -- const struct sw_64_operand *operand = (const struct sw_64_operand *) 0; -- struct sw_64_fixup *fixup = &insn->fixups[i]; -- struct sw_64_reloc_tag *info = NULL; -- int size, pcrel; -- fixS *fixP; -- -- /* Some fixups are only used internally and so have no howto. */ -- if ((int) fixup->reloc < 0) -- { -- operand = &sw_64_operands[-(int) fixup->reloc]; -- size = 4; -- pcrel = ((operand->flags & AXP_OPERAND_RELATIVE) != 0); -- } -- else if (fixup->reloc > BFD_RELOC_UNUSED -- || fixup->reloc == BFD_RELOC_SW_64_GPDISP_HI16 -- || fixup->reloc == BFD_RELOC_SW_64_GPDISP_LO16) -- { -- size = 2; -- pcrel = 0; -- } -- else -- { -- reloc_howto_type *reloc_howto = -- bfd_reloc_type_lookup (stdoutput, -- (bfd_reloc_code_real_type) fixup->reloc); -- gas_assert (reloc_howto); -- -- size = bfd_get_reloc_size (reloc_howto); -- -- switch (fixup->reloc) -- { --#ifdef OBJ_EVAX -- case BFD_RELOC_SW_64_NOP: -- case BFD_RELOC_SW_64_BSR: -- case BFD_RELOC_SW_64_LDA: -- case BFD_RELOC_SW_64_BOH: -- break; --#endif -- default: -- gas_assert (size >= 1 && size <= 4); -- } -- -- pcrel = reloc_howto->pc_relative; -- } -- -- fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size, -- &fixup->exp, pcrel, (bfd_reloc_code_real_type) fixup->reloc); -- -- /* Turn off complaints that the addend is too large for some fixups, -- and copy in the sequence number for the explicit relocations. */ -- switch (fixup->reloc) -- { -- case BFD_RELOC_SW_64_HINT: -- case BFD_RELOC_GPREL32: -- case BFD_RELOC_GPREL16: -- case BFD_RELOC_SW_64_GPREL_HI16: -- case BFD_RELOC_SW_64_GPREL_LO16: -- case BFD_RELOC_SW_64_GOTDTPREL16: -- case BFD_RELOC_SW_64_DTPREL_HI16: -- case BFD_RELOC_SW_64_DTPREL_LO16: -- case BFD_RELOC_SW_64_DTPREL16: -- case BFD_RELOC_SW_64_GOTTPREL16: -- case BFD_RELOC_SW_64_TPREL_HI16: -- case BFD_RELOC_SW_64_TPREL_LO16: -- case BFD_RELOC_SW_64_TPREL16: -- fixP->fx_no_overflow = 1; -- break; -- -- case BFD_RELOC_SW_64_GPDISP_HI16: -- fixP->fx_no_overflow = 1; -- fixP->fx_addsy = section_symbol (now_seg); -- fixP->fx_offset = 0; -- -- info = get_sw_64_reloc_tag (insn->sequence); -- if (++info->n_master > 1) -- as_bad (_("too many ldih insns for !gpdisp!%ld"), insn->sequence); -- if (info->segment != now_seg) -- as_bad (_("both insns for !gpdisp!%ld must be in the same section"), -- insn->sequence); -- fixP->tc_fix_data.info = info; -- break; -- -- case BFD_RELOC_SW_64_GPDISP_LO16: -- fixP->fx_no_overflow = 1; -- -- info = get_sw_64_reloc_tag (insn->sequence); -- if (++info->n_slaves > 1) -- as_bad (_("too many ldi insns for !gpdisp!%ld"), insn->sequence); -- if (info->segment != now_seg) -- as_bad (_("both insns for !gpdisp!%ld must be in the same section"), -- insn->sequence); -- fixP->tc_fix_data.info = info; -- info->slaves = fixP; -- break; -- -- case BFD_RELOC_SW_64_LITERAL: -- case BFD_RELOC_SW_64_ELF_LITERAL: -- fixP->fx_no_overflow = 1; -- -- if (insn->sequence == 0) -- break; -- info = get_sw_64_reloc_tag (insn->sequence); -- info->master = fixP; -- info->n_master++; -- if (info->segment != now_seg) -- info->multi_section_p = 1; -- fixP->tc_fix_data.info = info; -- break; -- --#ifdef RELOC_OP_P -- case DUMMY_RELOC_LITUSE_ADDR: -- fixP->fx_offset = LITUSE_SW_64_ADDR; -- goto do_lituse; -- case DUMMY_RELOC_LITUSE_BASE: -- fixP->fx_offset = LITUSE_SW_64_BASE; -- goto do_lituse; -- case DUMMY_RELOC_LITUSE_BYTOFF: -- fixP->fx_offset = LITUSE_SW_64_BYTOFF; -- goto do_lituse; -- case DUMMY_RELOC_LITUSE_JSR: -- fixP->fx_offset = LITUSE_SW_64_JSR; -- goto do_lituse; -- case DUMMY_RELOC_LITUSE_TLSGD: -- fixP->fx_offset = LITUSE_SW_64_TLSGD; -- goto do_lituse; -- case DUMMY_RELOC_LITUSE_TLSLDM: -- fixP->fx_offset = LITUSE_SW_64_TLSLDM; -- goto do_lituse; -- case DUMMY_RELOC_LITUSE_JSRDIRECT: -- fixP->fx_offset = LITUSE_SW_64_JSRDIRECT; -- goto do_lituse; -- do_lituse: -- fixP->fx_addsy = section_symbol (now_seg); -- fixP->fx_r_type = BFD_RELOC_SW_64_LITUSE; -- -- info = get_sw_64_reloc_tag (insn->sequence); -- if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSGD) -- info->saw_lu_tlsgd = 1; -- else if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSLDM) -- info->saw_lu_tlsldm = 1; -- if (++info->n_slaves > 1) -- { -- if (info->saw_lu_tlsgd) -- as_bad (_("too many lituse insns for !lituse_tlsgd!%ld"), -- insn->sequence); -- else if (info->saw_lu_tlsldm) -- as_bad (_("too many lituse insns for !lituse_tlsldm!%ld"), -- insn->sequence); -- } -- fixP->tc_fix_data.info = info; -- fixP->tc_fix_data.next_reloc = info->slaves; -- info->slaves = fixP; -- if (info->segment != now_seg) -- info->multi_section_p = 1; -- break; -- -- case BFD_RELOC_SW_64_TLSGD: -- fixP->fx_no_overflow = 1; -- -- if (insn->sequence == 0) -- break; -- info = get_sw_64_reloc_tag (insn->sequence); -- if (info->saw_tlsgd) -- as_bad (_("duplicate !tlsgd!%ld"), insn->sequence); -- else if (info->saw_tlsldm) -- as_bad (_("sequence number in use for !tlsldm!%ld"), -- insn->sequence); -- else -- info->saw_tlsgd = 1; -- fixP->tc_fix_data.info = info; -- break; -- -- case BFD_RELOC_SW_64_TLSLDM: -- fixP->fx_no_overflow = 1; -- -- if (insn->sequence == 0) -- break; -- info = get_sw_64_reloc_tag (insn->sequence); -- if (info->saw_tlsldm) -- as_bad (_("duplicate !tlsldm!%ld"), insn->sequence); -- else if (info->saw_tlsgd) -- as_bad (_("sequence number in use for !tlsgd!%ld"), -- insn->sequence); -- else -- info->saw_tlsldm = 1; -- fixP->tc_fix_data.info = info; -- break; --#endif --#ifdef OBJ_EVAX -- case BFD_RELOC_SW_64_NOP: -- case BFD_RELOC_SW_64_LDA: -- case BFD_RELOC_SW_64_BSR: -- case BFD_RELOC_SW_64_BOH: -- info = get_sw_64_reloc_tag (next_sequence_num--); -- fixP->tc_fix_data.info = info; -- fixP->tc_fix_data.info->sym = fixup->xtrasym; -- fixP->tc_fix_data.info->psym = fixup->procsym; -- break; --#endif -- -- default: -- if ((int) fixup->reloc < 0) -- { -- if (operand->flags & AXP_OPERAND_NOOVERFLOW) -- fixP->fx_no_overflow = 1; -- } -- break; -- } -- } --} -- --/* Insert an operand value into an instruction. */ -- --static unsigned --insert_operand (unsigned insn, -- const struct sw_64_operand *operand, -- offsetT val, -- const char *file, -- unsigned line) --{ -- if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW)) -- { -- offsetT min, max; -- -- if (operand->flags & AXP_OPERAND_SIGNED) -- { -- max = (1 << (operand->bits - 1)) - 1; -- min = -(1 << (operand->bits - 1)); -- } -- else -- { -- max = (1 << operand->bits) - 1; -- min = 0; -- } -- -- if (val < min || val > max) -- as_warn_value_out_of_range (_("operand"), val, min, max, file, line); -- } -- -- if (operand->insert) -- { -- const char *errmsg = NULL; -- -- insn = (*operand->insert) (insn, val, &errmsg); -- if (errmsg) -- as_warn ("%s", errmsg); -- } -- else -- insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift); -- -- return insn; --} -- -- static unsigned int need_rd_f = 0; -- static unsigned int next_insn = 0; -- --/* Turn an opcode description and a set of arguments into -- an instruction and a fixup. */ -- --static void --assemble_insn (const struct sw_64_opcode *opcode, -- const expressionS *tok, -- int ntok, -- struct sw_64_insn *insn, -- extended_bfd_reloc_code_real_type reloc) --{ -- const struct sw_64_operand *reloc_operand = NULL; -- const expressionS *reloc_exp = NULL; -- const unsigned char *argidx; -- unsigned image; -- int tokidx = 0; -- next_insn++; -- -- memset (insn, 0, sizeof (*insn)); -- image = opcode->opcode; -- -- for (argidx = opcode->operands; *argidx; ++argidx) -- { -- const struct sw_64_operand *operand = &sw_64_operands[*argidx]; -- const expressionS *t = (const expressionS *) 0; -- -- if (operand->flags & AXP_OPERAND_FAKE) -- { -- /* Fake operands take no value and generate no fixup. */ -- image = insert_operand (image, operand, 0, NULL, 0); -- continue; -- } -- -- if (tokidx >= ntok) -- { -- switch (operand->flags & AXP_OPERAND_OPTIONAL_MASK) -- { -- case AXP_OPERAND_DEFAULT_FIRST: -- t = &tok[0]; -- break; -- case AXP_OPERAND_DEFAULT_SECOND: -- t = &tok[1]; -- break; -- case AXP_OPERAND_DEFAULT_THIRD: -- t = &tok[2]; -- break; -- case AXP_OPERAND_DEFAULT_ZERO: -- { -- static expressionS zero_exp; -- t = &zero_exp; -- zero_exp.X_op = O_constant; -- zero_exp.X_unsigned = 1; -- } -- break; -- default: -- abort (); -- } -- } -- else -- t = &tok[tokidx++]; -- -- switch (t->X_op) -- { -- case O_register: -- case O_pregister: -- case O_cpregister: -- image = insert_operand (image, operand, regno (t->X_add_number), -- NULL, 0); -- break; -- -- case O_constant: -- image = insert_operand (image, operand, t->X_add_number, NULL, 0); -- gas_assert (reloc_operand == NULL); -- reloc_operand = operand; -- reloc_exp = t; -- break; -- -- default: -- /* This is only 0 for fields that should contain registers, -- which means this pattern shouldn't have matched. */ -- if (operand->default_reloc == 0) -- abort (); -- -- /* There is one special case for which an insn receives two -- relocations, and thus the user-supplied reloc does not -- override the operand reloc. */ -- if (operand->default_reloc == BFD_RELOC_SW_64_HINT) -- { -- struct sw_64_fixup *fixup; -- -- if (insn->nfixups >= MAX_INSN_FIXUPS) -- as_fatal (_("too many fixups")); -- -- fixup = &insn->fixups[insn->nfixups++]; -- fixup->exp = *t; -- fixup->reloc = BFD_RELOC_SW_64_HINT; -- } -- else -- { -- if (reloc == BFD_RELOC_UNUSED) -- reloc = operand->default_reloc; -- -- gas_assert (reloc_operand == NULL); -- reloc_operand = operand; -- reloc_exp = t; -- } -- break; -- } -- } -- -- if (reloc != BFD_RELOC_UNUSED) -- { -- struct sw_64_fixup *fixup; -- -- if (insn->nfixups >= MAX_INSN_FIXUPS) -- as_fatal (_("too many fixups")); -- -- /* ??? My but this is hacky. But the OSF/1 assembler uses the same -- relocation tag for both ldih and ldi with gpdisp. Choose the -- correct internal relocation based on the opcode. */ -- if (reloc == BFD_RELOC_SW_64_GPDISP) -- { -- if (strcmp (opcode->name, "ldih") == 0) -- reloc = BFD_RELOC_SW_64_GPDISP_HI16; -- else if (strcmp (opcode->name, "ldi") == 0) -- reloc = BFD_RELOC_SW_64_GPDISP_LO16; -- else -- as_bad (_("invalid relocation for instruction")); -- } -- -- /* If this is a real relocation (as opposed to a lituse hint), then -- the relocation width should match the operand width. -- Take care of -MDISP in operand table. */ -- else if (reloc < BFD_RELOC_UNUSED && reloc > 0) -- { -- reloc_howto_type *reloc_howto -- = bfd_reloc_type_lookup (stdoutput, -- (bfd_reloc_code_real_type) reloc); -- if (reloc_operand == NULL -- || reloc_howto->bitsize != reloc_operand->bits) -- { -- as_bad (_("invalid relocation for field")); -- return; -- } -- } -- -- fixup = &insn->fixups[insn->nfixups++]; -- if (reloc_exp) -- fixup->exp = *reloc_exp; -- else -- fixup->exp.X_op = O_absent; -- fixup->reloc = reloc; -- } -- -- insn->insn = image; -- -- if (!strcmp(sw_64_target_name, "sw6a") -- || !strcmp(sw_64_target_name, "sw6b")) -- { -- if (!strcmp (opcode->name, "lstw") || !strcmp (opcode->name,"lstl") -- || !strcmp (opcode->name,"stl_c") || !strcmp (opcode->name,"stq_c")) -- { -- sw_64_align (3, (char *) NULL, sw_64_insn_label, 0); -- need_rd_f = 1; -- next_insn = 0; -- } -- if (strcmp (opcode->name, "rd_f") && need_rd_f && (next_insn == 1) ) -- as_bad (_("missing \"rd_f\" before \"%s\" !!"), (char *)opcode->name); -- } --} -- --/* Handle all "simple" integer register loads -- ldl, ldl_l, ldl_u, -- etc. They differ from the real instructions in that they do simple -- expressions like the ldi macro. */ -- --static void --emit_ir_load (const expressionS *tok, -- int ntok, -- const void * opname) --{ -- int basereg; -- long lituse; -- expressionS newtok[3]; -- struct sw_64_insn insn; -- const char *symname -- = tok[1].X_add_symbol ? S_GET_NAME (tok[1].X_add_symbol): ""; -- int symlen = strlen (symname); -- -- if (ntok == 2) -- basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : sw_64_gp_register); -- else -- basereg = tok[2].X_add_number; -- -- lituse = load_expression (tok[0].X_add_number, &tok[1], -- &basereg, &newtok[1], (const char *) opname); -- -- if (basereg == sw_64_gp_register && -- (symlen > 4 && strcmp (&symname [symlen - 4], "..lk") == 0)) -- return; -- -- newtok[0] = tok[0]; -- set_tok_preg (newtok[2], basereg); -- -- assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); -- -- if (lituse) -- { -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = lituse; -- } -- -- emit_insn (&insn); --} -- --/* Handle fp register loads, and both integer and fp register stores. -- Again, we handle simple expressions. */ -- --static void --emit_loadstore (const expressionS *tok, -- int ntok, -- const void * opname) --{ -- int basereg; -- long lituse; -- expressionS newtok[3]; -- struct sw_64_insn insn; -- -- if (ntok == 2) -- basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : sw_64_gp_register); -- else -- basereg = tok[2].X_add_number; -- -- if (tok[1].X_op != O_constant || !range_signed_16 (tok[1].X_add_number)) -- { -- if (sw_64_noat_on) -- as_bad (_("macro requires $at register while noat in effect")); -- else -- as_warn (_("assembler requires $28 register for the marco !")); -- -- lituse = load_expression (AXP_REG_AT, &tok[1], -- &basereg, &newtok[1], (const char *) opname); -- } -- else -- { -- newtok[1] = tok[1]; -- lituse = 0; -- } -- -- newtok[0] = tok[0]; -- set_tok_preg (newtok[2], basereg); -- -- assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); -- -- if (lituse) -- { -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = lituse; -- } -- -- emit_insn (&insn); --} -- --/* Load a half-word or byte as an unsigned value. */ -- --static void --emit_ldXu (const expressionS *tok, -- int ntok, -- const void * vlgsize) --{ -- if (sw_64_target & AXP_OPCODE_SW6) -- emit_ir_load (tok, ntok, ldXu_op[(long) vlgsize]); -- else -- { -- expressionS newtok[3]; -- struct sw_64_insn insn; -- int basereg; -- long lituse; -- -- if (sw_64_noat_on) -- as_bad (_("macro requires $at register while noat in effect")); -- -- if (ntok == 2) -- basereg = (tok[1].X_op == O_constant -- ? AXP_REG_ZERO : sw_64_gp_register); -- else -- basereg = tok[2].X_add_number; -- -- /* Emit "ldi $at, exp". */ -- lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL, "ldi"); -- -- /* Emit "ldl_u targ, 0($at)". */ -- newtok[0] = tok[0]; -- set_tok_const (newtok[1], 0); -- set_tok_preg (newtok[2], basereg); -- assemble_tokens_to_insn ("ldl_u", newtok, 3, &insn); -- -- if (lituse) -- { -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = lituse; -- } -- -- emit_insn (&insn); -- -- /* Emit "extXl targ, $at, targ". */ -- set_tok_reg (newtok[1], basereg); -- newtok[2] = newtok[0]; -- assemble_tokens_to_insn (extXl_op[(long) vlgsize], newtok, 3, &insn); -- -- if (lituse) -- { -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = lituse; -- } -- -- emit_insn (&insn); -- } --} -- --/* Load a half-word or byte as a signed value. */ -- --static void --emit_ldX (const expressionS *tok, -- int ntok, -- const void * vlgsize) --{ -- emit_ldXu (tok, ntok, vlgsize); -- assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1); --} -- --/* Load an integral value from an unaligned address as an unsigned -- value. */ -- --static void --emit_uldXu (const expressionS *tok, -- int ntok, -- const void * vlgsize) --{ -- long lgsize = (long) vlgsize; -- expressionS newtok[3]; -- -- if (sw_64_noat_on) -- as_bad (_("macro requires $at register while noat in effect")); -- -- /* Emit "ldi $at, exp". */ -- memcpy (newtok, tok, sizeof (expressionS) * ntok); -- newtok[0].X_add_number = AXP_REG_AT; -- assemble_tokens ("ldi", newtok, ntok, 1); -- -- /* Emit "ldl_u $t9, 0($at)". */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- set_tok_const (newtok[1], 0); -- set_tok_preg (newtok[2], AXP_REG_AT); -- assemble_tokens ("ldl_u", newtok, 3, 1); -- -- /* Emit "ldl_u $t10, size-1($at)". */ -- set_tok_reg (newtok[0], AXP_REG_T10); -- set_tok_const (newtok[1], (1 << lgsize) - 1); -- assemble_tokens ("ldl_u", newtok, 3, 1); -- -- /* Emit "extXl $t9, $at, $t9". */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- set_tok_reg (newtok[1], AXP_REG_AT); -- set_tok_reg (newtok[2], AXP_REG_T9); -- assemble_tokens (extXl_op[lgsize], newtok, 3, 1); -- -- /* Emit "extXh $t10, $at, $t10". */ -- set_tok_reg (newtok[0], AXP_REG_T10); -- set_tok_reg (newtok[2], AXP_REG_T10); -- assemble_tokens (extXh_op[lgsize], newtok, 3, 1); -- -- /* Emit "or $t9, $t10, targ". */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- set_tok_reg (newtok[1], AXP_REG_T10); -- newtok[2] = tok[0]; -- assemble_tokens ("or", newtok, 3, 1); --} -- --/* Load an integral value from an unaligned address as a signed value. -- Note that quads should get funneled to the unsigned load since we -- don't have to do the sign extension. */ -- --static void --emit_uldX (const expressionS *tok, -- int ntok, -- const void * vlgsize) --{ -- emit_uldXu (tok, ntok, vlgsize); -- assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1); --} -- --/* Implement the ldil macro. */ -- --static void --emit_ldil (const expressionS *tok, -- int ntok, -- const void * unused ATTRIBUTE_UNUSED) --{ -- expressionS newtok[2]; -- -- memcpy (newtok, tok, sizeof (newtok)); -- newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number); -- -- assemble_tokens ("ldi", newtok, ntok, 1); --} -- --/* Store a half-word or byte. */ -- --static void --emit_stX (const expressionS *tok, -- int ntok, -- const void * vlgsize) --{ -- int lgsize = (int) (long) vlgsize; -- -- -- if (sw_64_target & AXP_OPCODE_SW6) -- emit_loadstore (tok, ntok, stX_op[lgsize]); -- else -- { -- expressionS newtok[3]; -- struct sw_64_insn insn; -- int basereg; -- long lituse; -- -- if (sw_64_noat_on) -- as_bad (_("macro requires $at register while noat in effect")); -- -- if (ntok == 2) -- basereg = (tok[1].X_op == O_constant -- ? AXP_REG_ZERO : sw_64_gp_register); -- else -- basereg = tok[2].X_add_number; -- -- /* Emit "ldi $at, exp". */ -- lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL, "ldi"); -- -- /* Emit "ldl_u $t9, 0($at)". */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- set_tok_const (newtok[1], 0); -- set_tok_preg (newtok[2], basereg); -- assemble_tokens_to_insn ("ldl_u", newtok, 3, &insn); -- -- if (lituse) -- { -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = lituse; -- } -- -- emit_insn (&insn); -- -- /* Emit "insXl src, $at, $t10". */ -- newtok[0] = tok[0]; -- set_tok_reg (newtok[1], basereg); -- set_tok_reg (newtok[2], AXP_REG_T10); -- assemble_tokens_to_insn (insXl_op[lgsize], newtok, 3, &insn); -- -- if (lituse) -- { -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = lituse; -- } -- -- emit_insn (&insn); -- -- /* Emit "mskXl $t9, $at, $t9". */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- newtok[2] = newtok[0]; -- assemble_tokens_to_insn (mskXl_op[lgsize], newtok, 3, &insn); -- -- if (lituse) -- { -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = lituse; -- } -- -- emit_insn (&insn); -- -- /* Emit "or $t9, $t10, $t9". */ -- set_tok_reg (newtok[1], AXP_REG_T10); -- assemble_tokens ("or", newtok, 3, 1); -- -- /* Emit "stq_u $t9, 0($at). */ -- set_tok_const(newtok[1], 0); -- set_tok_preg (newtok[2], AXP_REG_AT); -- assemble_tokens_to_insn ("stl_u", newtok, 3, &insn); -- -- if (lituse) -- { -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = lituse; -- } -- -- emit_insn (&insn); -- } --} -- --/* Store an integer to an unaligned address. */ -- --static void --emit_ustX (const expressionS *tok, -- int ntok, -- const void * vlgsize) --{ -- int lgsize = (int) (long) vlgsize; -- expressionS newtok[3]; -- -- /* Emit "ldi $at, exp". */ -- memcpy (newtok, tok, sizeof (expressionS) * ntok); -- newtok[0].X_add_number = AXP_REG_AT; -- assemble_tokens ("ldi", newtok, ntok, 1); -- -- /* Emit "ldl_u $9, 0($at)". */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- set_tok_const (newtok[1], 0); -- set_tok_preg (newtok[2], AXP_REG_AT); -- assemble_tokens ("ldl_u", newtok, 3, 1); -- -- /* Emit "ldl_u $10, size-1($at)". */ -- set_tok_reg (newtok[0], AXP_REG_T10); -- set_tok_const (newtok[1], (1 << lgsize) - 1); -- assemble_tokens ("ldl_u", newtok, 3, 1); -- -- /* Emit "insXl src, $at, $t11". */ -- newtok[0] = tok[0]; -- set_tok_reg (newtok[1], AXP_REG_AT); -- set_tok_reg (newtok[2], AXP_REG_T11); -- assemble_tokens (insXl_op[lgsize], newtok, 3, 1); -- -- /* Emit "insXh src, $at, $t12". */ -- set_tok_reg (newtok[2], AXP_REG_T12); -- assemble_tokens (insXh_op[lgsize], newtok, 3, 1); -- -- /* Emit "mskXl $t9, $at, $t9". */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- newtok[2] = newtok[0]; -- assemble_tokens (mskXl_op[lgsize], newtok, 3, 1); -- -- /* Emit "mskXh $t10, $at, $t10". */ -- set_tok_reg (newtok[0], AXP_REG_T10); -- newtok[2] = newtok[0]; -- assemble_tokens (mskXh_op[lgsize], newtok, 3, 1); -- -- /* Emit "or $t9, $t11, $t9". */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- set_tok_reg (newtok[1], AXP_REG_T11); -- newtok[2] = newtok[0]; -- assemble_tokens ("or", newtok, 3, 1); -- -- /* Emit "or $t10, $t12, $t10". */ -- set_tok_reg (newtok[0], AXP_REG_T10); -- set_tok_reg (newtok[1], AXP_REG_T12); -- newtok[2] = newtok[0]; -- assemble_tokens ("or", newtok, 3, 1); -- -- /* Emit "stq_u $t10, size-1($at)". */ -- set_tok_reg (newtok[0], AXP_REG_T10); -- set_tok_const (newtok[1], (1 << lgsize) - 1); -- set_tok_preg (newtok[2], AXP_REG_AT); -- assemble_tokens ("stl_u", newtok, 3, 1); -- -- /* Emit "stq_u $t9, 0($at)". */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- set_tok_const (newtok[1], 0); -- assemble_tokens ("stl_u", newtok, 3, 1); --} -- --/* Sign extend a half-word or byte. The 32-bit sign extend is -- implemented as "addl $31, $r, $t" in the opcode table. */ -- --static void --emit_sextX (const expressionS *tok, -- int ntok, -- const void * vlgsize) --{ -- long lgsize = (long) vlgsize; -- -- if (sw_64_target & AXP_OPCODE_SW6) -- assemble_tokens (sextX_op[lgsize], tok, ntok, 0); -- else -- { -- int bitshift = 64 - 8 * (1 << lgsize); -- expressionS newtok[3]; -- -- /* Emit "sll src,bits,dst". */ -- newtok[0] = tok[0]; -- set_tok_const (newtok[1], bitshift); -- newtok[2] = tok[ntok - 1]; -- assemble_tokens ("sll", newtok, 3, 1); -- -- /* Emit "sra dst,bits,dst". */ -- newtok[0] = newtok[2]; -- assemble_tokens ("sra", newtok, 3, 1); -- } --} -- --static void --emit_vlogx(const expressionS *tok, -- int ntok, -- const void * unused ATTRIBUTE_UNUSED) --{ -- unsigned int mask=0; -- struct sw_64_insn insn; -- assemble_tokens_to_insn("vlog",tok,ntok-1,&insn); -- mask=(tok[4].X_add_number>>6)<<26; -- mask+=(tok[4].X_add_number & 0x3f)<<10; -- insn.insn|=mask; -- emit_insn(&insn); --} -- --/* Implement the division and modulus macros. */ -- --#ifdef OBJ_EVAX -- --/* Make register usage like in normal procedure call. -- Don't clobber PV and RA. */ -- --static void --emit_division (const expressionS *tok, -- int ntok, -- const void * symname) --{ -- /* DIVISION and MODULUS. Yech. -- -- Convert -- OP x,y,result -- to -- mov x,R16 # if x != R16 -- mov y,R17 # if y != R17 -- ldi AT,__OP -- call AT,(AT),0 -- mov R0,result -- -- with appropriate optimizations if R0,R16,R17 are the registers -- specified by the compiler. */ -- -- int xr, yr, rr; -- symbolS *sym; -- expressionS newtok[3]; -- -- xr = regno (tok[0].X_add_number); -- yr = regno (tok[1].X_add_number); -- -- if (ntok < 3) -- rr = xr; -- else -- rr = regno (tok[2].X_add_number); -- -- /* Move the operands into the right place. */ -- if (yr == AXP_REG_R16 && xr == AXP_REG_R17) -- { -- /* They are in exactly the wrong order -- swap through AT. */ -- if (sw_64_noat_on) -- as_bad (_("macro requires $at register while noat in effect")); -- -- set_tok_reg (newtok[0], AXP_REG_R16); -- set_tok_reg (newtok[1], AXP_REG_AT); -- assemble_tokens ("mov", newtok, 2, 1); -- -- set_tok_reg (newtok[0], AXP_REG_R17); -- set_tok_reg (newtok[1], AXP_REG_R16); -- assemble_tokens ("mov", newtok, 2, 1); -- -- set_tok_reg (newtok[0], AXP_REG_AT); -- set_tok_reg (newtok[1], AXP_REG_R17); -- assemble_tokens ("mov", newtok, 2, 1); -- } -- else -- { -- if (yr == AXP_REG_R16) -- { -- set_tok_reg (newtok[0], AXP_REG_R16); -- set_tok_reg (newtok[1], AXP_REG_R17); -- assemble_tokens ("mov", newtok, 2, 1); -- } -- -- if (xr != AXP_REG_R16) -- { -- set_tok_reg (newtok[0], xr); -- set_tok_reg (newtok[1], AXP_REG_R16); -- assemble_tokens ("mov", newtok, 2, 1); -- } -- -- if (yr != AXP_REG_R16 && yr != AXP_REG_R17) -- { -- set_tok_reg (newtok[0], yr); -- set_tok_reg (newtok[1], AXP_REG_R17); -- assemble_tokens ("mov", newtok, 2, 1); -- } -- } -- -- sym = symbol_find_or_make ((const char *) symname); -- -- set_tok_reg (newtok[0], AXP_REG_AT); -- set_tok_sym (newtok[1], sym, 0); -- assemble_tokens ("ldi", newtok, 2, 1); -- -- /* Call the division routine. */ -- set_tok_reg (newtok[0], AXP_REG_AT); -- set_tok_cpreg (newtok[1], AXP_REG_AT); -- set_tok_const (newtok[2], 0); -- assemble_tokens ("call", newtok, 3, 1); -- -- /* Move the result to the right place. */ -- if (rr != AXP_REG_R0) -- { -- set_tok_reg (newtok[0], AXP_REG_R0); -- set_tok_reg (newtok[1], rr); -- assemble_tokens ("mov", newtok, 2, 1); -- } --} -- --#else /* !OBJ_EVAX */ -- --static void --emit_division (const expressionS *tok, -- int ntok, -- const void * symname) --{ -- /* DIVISION and MODULUS. Yech. -- Convert -- OP x,y,result -- to -- ldi pv,__OP -- mov x,t10 -- mov y,t11 -- call t9,(pv),__OP -- mov t12,result -- -- with appropriate optimizations if t10,t11,t12 are the registers -- specified by the compiler. */ -- -- int xr, yr, rr; -- symbolS *sym; -- expressionS newtok[3]; -- -- xr = regno (tok[0].X_add_number); -- yr = regno (tok[1].X_add_number); -- -- if (ntok < 3) -- rr = xr; -- else -- rr = regno (tok[2].X_add_number); -- -- sym = symbol_find_or_make ((const char *) symname); -- -- /* Move the operands into the right place. */ -- if (yr == AXP_REG_T10 && xr == AXP_REG_T11) -- { -- /* They are in exactly the wrong order -- swap through AT. */ -- if (sw_64_noat_on) -- as_bad (_("macro requires $at register while noat in effect")); -- -- set_tok_reg (newtok[0], AXP_REG_T10); -- set_tok_reg (newtok[1], AXP_REG_AT); -- assemble_tokens ("mov", newtok, 2, 1); -- -- set_tok_reg (newtok[0], AXP_REG_T11); -- set_tok_reg (newtok[1], AXP_REG_T10); -- assemble_tokens ("mov", newtok, 2, 1); -- -- set_tok_reg (newtok[0], AXP_REG_AT); -- set_tok_reg (newtok[1], AXP_REG_T11); -- assemble_tokens ("mov", newtok, 2, 1); -- } -- else -- { -- if (yr == AXP_REG_T10) -- { -- set_tok_reg (newtok[0], AXP_REG_T10); -- set_tok_reg (newtok[1], AXP_REG_T11); -- assemble_tokens ("mov", newtok, 2, 1); -- } -- -- if (xr != AXP_REG_T10) -- { -- set_tok_reg (newtok[0], xr); -- set_tok_reg (newtok[1], AXP_REG_T10); -- assemble_tokens ("mov", newtok, 2, 1); -- } -- -- if (yr != AXP_REG_T10 && yr != AXP_REG_T11) -- { -- set_tok_reg (newtok[0], yr); -- set_tok_reg (newtok[1], AXP_REG_T11); -- assemble_tokens ("mov", newtok, 2, 1); -- } -- } -- -- /* Call the division routine. */ -- set_tok_reg (newtok[0], AXP_REG_T9); -- set_tok_sym (newtok[1], sym, 0); -- assemble_tokens ("call", newtok, 2, 1); -- -- /* Reload the GP register. */ --#ifdef OBJ_AOUT --FIXME --#endif --#if defined(OBJ_ECOFF) || defined(OBJ_ELF) -- set_tok_reg (newtok[0], sw_64_gp_register); -- set_tok_const (newtok[1], 0); -- set_tok_preg (newtok[2], AXP_REG_T9); -- assemble_tokens ("ldgp", newtok, 3, 1); --#endif -- -- /* Move the result to the right place. */ -- if (rr != AXP_REG_T12) -- { -- set_tok_reg (newtok[0], AXP_REG_T12); -- set_tok_reg (newtok[1], rr); -- assemble_tokens ("mov", newtok, 2, 1); -- } --} -- --#endif /* !OBJ_EVAX */ -- --/* The call and jmp macros differ from their instruction counterparts -- in that they can load the target address and default most -- everything. */ -- --static void --emit_jsrjmp (const expressionS *tok, -- int ntok, -- const void * vopname) --{ -- const char *opname = (const char *) vopname; -- struct sw_64_insn insn; -- expressionS newtok[3]; -- int r, tokidx = 0; -- long lituse = 0; -- -- if (tokidx < ntok && tok[tokidx].X_op == O_register) -- r = regno (tok[tokidx++].X_add_number); -- else -- r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA; -- -- set_tok_reg (newtok[0], r); -- -- if (tokidx < ntok && -- (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister)) -- r = regno (tok[tokidx++].X_add_number); --#ifdef OBJ_EVAX -- /* Keep register if call $n.. */ --#else -- else -- { -- int basereg = sw_64_gp_register; -- lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], -- &basereg, NULL, opname); -- } --#endif -- -- set_tok_cpreg (newtok[1], r); -- --#ifndef OBJ_EVAX -- if (tokidx < ntok) -- newtok[2] = tok[tokidx]; -- else --#endif -- set_tok_const (newtok[2], 0); -- -- assemble_tokens_to_insn (opname, newtok, 3, &insn); -- -- if (lituse) -- { -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_JSR; -- insn.fixups[insn.nfixups].exp.X_op = O_absent; -- insn.nfixups++; -- insn.sequence = lituse; -- } -- --#ifdef OBJ_EVAX -- if (sw_64_flag_replace -- && r == AXP_REG_RA -- && tok[tokidx].X_add_symbol -- && sw_64_linkage_symbol) -- { -- /* Create a BOH reloc for 'call $27,NAME'. */ -- const char *symname = S_GET_NAME (tok[tokidx].X_add_symbol); -- int symlen = strlen (symname); -- char *ensymname; -- -- /* Build the entry name as 'NAME..en'. */ -- ensymname = XNEWVEC (char, symlen + 5); -- memcpy (ensymname, symname, symlen); -- memcpy (ensymname + symlen, "..en", 5); -- -- gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -- if (insn.nfixups > 0) -- { -- memmove (&insn.fixups[1], &insn.fixups[0], -- sizeof(struct sw_64_fixup) * insn.nfixups); -- } -- -- /* The fixup must be the same as the BFD_RELOC_SW_64_NOP -- case in load_expression. See B.4.5.2 of the OpenVMS -- Linker Utility Manual. */ -- insn.fixups[0].reloc = BFD_RELOC_SW_64_BOH; -- insn.fixups[0].exp.X_op = O_symbol; -- insn.fixups[0].exp.X_add_symbol = symbol_find_or_make (ensymname); -- insn.fixups[0].exp.X_add_number = 0; -- insn.fixups[0].xtrasym = sw_64_linkage_symbol; -- insn.fixups[0].procsym = sw_64_evax_proc->symbol; -- insn.nfixups++; -- sw_64_linkage_symbol = 0; -- free (ensymname); -- } --#endif -- -- emit_insn (&insn); --} -- --/* The ret and jcr instructions differ from their instruction -- counterparts in that everything can be defaulted. */ -- --static void --emit_retjcr (const expressionS *tok, -- int ntok, -- const void * vopname) --{ -- const char *opname = (const char *) vopname; -- expressionS newtok[3]; -- int r, tokidx = 0; -- -- if (tokidx < ntok && tok[tokidx].X_op == O_register) -- r = regno (tok[tokidx++].X_add_number); -- else -- r = AXP_REG_ZERO; -- -- set_tok_reg (newtok[0], r); -- -- if (tokidx < ntok && -- (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister)) -- r = regno (tok[tokidx++].X_add_number); -- else -- r = AXP_REG_RA; -- -- set_tok_cpreg (newtok[1], r); -- -- if (tokidx < ntok) -- newtok[2] = tok[tokidx]; -- else -- set_tok_const (newtok[2], strcmp (opname, "ret") == 0); -- -- assemble_tokens (opname, newtok, 3, 0); --} -- --/* Implement the ldgp macro. */ -- --static void --emit_ldgp (const expressionS *tok ATTRIBUTE_UNUSED, -- int ntok ATTRIBUTE_UNUSED, -- const void * unused ATTRIBUTE_UNUSED) --{ --#ifdef OBJ_AOUT --FIXME --#endif --#if defined(OBJ_ECOFF) || defined(OBJ_ELF) -- /* from "ldgp r1,n(r2)", generate "ldih r1,X(R2); ldi r1,Y(r1)" -- with appropriate constants and relocations. */ -- struct sw_64_insn insn; -- expressionS newtok[3]; -- expressionS addend; -- --#ifdef OBJ_ECOFF -- if (regno (tok[2].X_add_number) == AXP_REG_PV) -- ecoff_set_gp_prolog_size (0); --#endif -- -- newtok[0] = tok[0]; -- set_tok_const (newtok[1], 0); -- newtok[2] = tok[2]; -- -- assemble_tokens_to_insn ("ldih", newtok, 3, &insn); -- -- addend = tok[1]; -- --#ifdef OBJ_ECOFF -- if (addend.X_op != O_constant) -- as_bad (_("can not resolve expression")); -- addend.X_op = O_symbol; -- addend.X_add_symbol = sw_64_gp_symbol; --#endif -- -- insn.nfixups = 1; -- insn.fixups[0].exp = addend; -- insn.fixups[0].reloc = BFD_RELOC_SW_64_GPDISP_HI16; -- insn.sequence = next_sequence_num; -- -- emit_insn (&insn); -- -- set_tok_preg (newtok[2], tok[0].X_add_number); -- -- assemble_tokens_to_insn ("ldi", newtok, 3, &insn); -- --#ifdef OBJ_ECOFF -- addend.X_add_number += 4; --#endif -- -- insn.nfixups = 1; -- insn.fixups[0].exp = addend; -- insn.fixups[0].reloc = BFD_RELOC_SW_64_GPDISP_LO16; -- insn.sequence = next_sequence_num--; -- -- emit_insn (&insn); --#endif /* OBJ_ECOFF || OBJ_ELF */ --} -- --/* The macro table. */ -- --static const struct sw_64_macro sw_64_macros[] = --{ -- { "vlog", emit_vlogx, NULL, -- { MACRO_FPR, MACRO_FPR, MACRO_FPR, MACRO_FPR, MACRO_EOA } }, --/* Load/Store macros. */ -- { "ldi", emit_ldi, NULL, -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldih", emit_ldih, NULL, -- { MACRO_IR, MACRO_EXP, MACRO_EOA } }, -- -- { "ldw", emit_ir_load, "ldw", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldl", emit_ir_load, "ldl", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldl_u", emit_ir_load, "ldl_u", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldw_inc", emit_ir_load, "ldw_inc", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldl_inc", emit_ir_load, "ldl_inc", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldw_dec", emit_ir_load, "ldw_dec", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldl_dec", emit_ir_load, "ldl_dec", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldw_set", emit_ir_load, "ldw_set", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldl_set", emit_ir_load, "ldl_set", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "flds", emit_loadstore, "flds", -- { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "fldd", emit_loadstore, "fldd", -- { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- -- { "ldb", emit_ldX, (void *) 0, -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "ldh", emit_ldX, (void *) 1, -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- -- { "ldgp", emit_ldgp, NULL, -- { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } }, -- { "stw", emit_loadstore, "stw", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "stl", emit_loadstore, "stl", -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "fsts", emit_loadstore, "fsts", -- { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "fstd", emit_loadstore, "fstd", -- { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- { "stb", emit_stX, (void *) 0, -- { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -- --/* Arithmetic macros. */ -- { "sextb", emit_sextX, (void *) 0, -- { MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EOA, -- /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, -- { "sexth", emit_sextX, (void *) 1, -- { MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EOA, -- /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, -- -- { "divw", emit_division, "__divw", -- { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_IR, MACRO_EOA, -- /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -- { "divwu", emit_division, "__divwu", -- { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_IR, MACRO_EOA, -- /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -- { "divl", emit_division, "__divl", -- { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_IR, MACRO_EOA, -- /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -- { "divlu", emit_division, "__divlu", -- { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_IR, MACRO_EOA, -- /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -- { "remw", emit_division, "__remw", -- { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_IR, MACRO_EOA, -- /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -- { "remwu", emit_division, "__remwu", -- { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_IR, MACRO_EOA, -- /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -- { "reml", emit_division, "__reml", -- { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_IR, MACRO_EOA, -- /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -- { "remlu", emit_division, "__remlu", -- { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_IR, MACRO_EOA, -- /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -- -- { "call", emit_jsrjmp, "call", -- { MACRO_PIR, MACRO_EXP, MACRO_EOA, -- MACRO_PIR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA, -- MACRO_EXP, MACRO_EOA } }, -- { "jmp", emit_jsrjmp, "jmp", -- { MACRO_PIR, MACRO_EXP, MACRO_EOA, -- MACRO_PIR, MACRO_EOA, -- MACRO_IR, MACRO_EXP, MACRO_EOA, -- MACRO_EXP, MACRO_EOA } }, -- { "ret", emit_retjcr, "ret", -- { MACRO_IR, MACRO_EXP, MACRO_EOA, -- MACRO_IR, MACRO_EOA, -- MACRO_PIR, MACRO_EXP, MACRO_EOA, -- MACRO_PIR, MACRO_EOA, -- MACRO_EXP, MACRO_EOA, -- MACRO_EOA } }, --}; -- --static const unsigned int sw_64_num_macros -- = sizeof (sw_64_macros) / sizeof (*sw_64_macros); -- --/* Search forward through all variants of a macro looking for a syntax -- match. */ -- --static const struct sw_64_macro * --find_macro_match (const struct sw_64_macro *first_macro, -- const expressionS *tok, -- int *pntok) -- --{ -- const struct sw_64_macro *macro = first_macro; -- int ntok = *pntok; -- -- do -- { -- const enum sw_64_macro_arg *arg = macro->argsets; -- int tokidx = 0; -- -- while (*arg) -- { -- switch (*arg) -- { -- case MACRO_EOA: -- if (tokidx == ntok) -- return macro; -- else -- tokidx = 0; -- break; -- -- /* Index register. */ -- case MACRO_IR: -- if (tokidx >= ntok || tok[tokidx].X_op != O_register -- || !is_ir_num (tok[tokidx].X_add_number)) -- goto match_failed; -- ++tokidx; -- break; -- -- /* Parenthesized index register. */ -- case MACRO_PIR: -- if (tokidx >= ntok || tok[tokidx].X_op != O_pregister -- || !is_ir_num (tok[tokidx].X_add_number)) -- goto match_failed; -- ++tokidx; -- break; -- -- /* Optional parenthesized index register. */ -- case MACRO_OPIR: -- if (tokidx < ntok && tok[tokidx].X_op == O_pregister -- && is_ir_num (tok[tokidx].X_add_number)) -- ++tokidx; -- break; -- -- /* Leading comma with a parenthesized index register. */ -- case MACRO_CPIR: -- if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister -- || !is_ir_num (tok[tokidx].X_add_number)) -- goto match_failed; -- ++tokidx; -- break; -- -- /* Floating point register. */ -- case MACRO_FPR: -- if (tokidx >= ntok || tok[tokidx].X_op != O_register -- || !is_fpr_num (tok[tokidx].X_add_number)) -- goto match_failed; -- ++tokidx; -- break; -- -- /* Normal expression. */ -- case MACRO_EXP: -- if (tokidx >= ntok) -- goto match_failed; -- switch (tok[tokidx].X_op) -- { -- case O_illegal: -- case O_absent: -- case O_register: -- case O_pregister: -- case O_cpregister: -- case O_literal: -- case O_lituse_base: -- case O_lituse_bytoff: -- case O_lituse_jsr: -- case O_gpdisp: -- case O_gprelhigh: -- case O_gprellow: -- case O_gprel: -- case O_samegp: -- goto match_failed; -- -- default: -- break; -- } -- ++tokidx; -- break; -- -- match_failed: -- while (*arg != MACRO_EOA) -- ++arg; -- tokidx = 0; -- break; -- } -- ++arg; -- } -- } -- while (++macro - sw_64_macros < (int) sw_64_num_macros -- && !strcmp (macro->name, first_macro->name)); -- -- return NULL; --} -- --/* Given an opcode name and a pre-tokenized set of arguments, take the -- opcode all the way through emission. */ -- --static void --assemble_tokens (const char *opname, -- const expressionS *tok, -- int ntok, -- int local_macros_on) --{ -- int found_something = 0; -- const struct sw_64_opcode *opcode; -- const struct sw_64_macro *macro; -- int cpumatch = 1; -- extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED; -- --#ifdef RELOC_OP_P -- /* If a user-specified relocation is present, this is not a macro. */ -- if (ntok && USER_RELOC_P (tok[ntok - 1].X_op)) -- { -- if (tok[ntok - 1].X_op == O_md3) -- { -- struct sw_64_insn insn; -- expressionS newtok[3]; -- newtok[0] = tok[0]; -- set_tok_const (newtok[1], 0); -- set_tok_preg (newtok[2], sw_64_gp_register); -- assemble_tokens_to_insn ("ldih", newtok, 3, &insn); -- insn.nfixups = 1; -- insn.fixups[0].reloc = BFD_RELOC_SW_64_ELF_LITERAL_GOT; -- emit_insn (&insn); -- } -- reloc = SW_64_RELOC_TABLE (tok[ntok - 1].X_op)->reloc; -- ntok--; -- } -- else --#endif -- if (local_macros_on) -- { -- macro = ((const struct sw_64_macro *) -- str_hash_find (sw_64_macro_hash, opname)); -- if (macro) -- { -- found_something = 1; -- macro = find_macro_match (macro, tok, &ntok); -- if (macro) -- { -- (*macro->emit) (tok, ntok, macro->arg); -- return; -- } -- } -- } -- -- if (memcmp (opname, "vlog", 4)==0) -- { -- unsigned long value; -- unsigned long length = strchr (opname,'g') - opname + 1; -- value=strtol (opname + length, NULL, 16); -- if (opname[length + 2] != '\0') -- as_bad (_("%s, wrong truth number!!"), opname); -- else if (value > 0xFF) -- as_bad (_("%s, wrong truth number!!"), opname); -- else if (value == 0 && (opname[length] != '0' || opname[length + 1] != '0')) -- as_bad (_("%s, wrong truth number!!"), opname); -- macro = ((const struct sw_64_macro *) -- str_hash_find (sw_64_macro_hash, "vlog")); -- if (macro) -- { -- found_something = 1; -- macro = find_macro_match (macro, tok, &ntok); -- if (macro) -- { -- -- expressionS newtok[5]; -- newtok[0] = tok[0]; -- newtok[1] = tok[1]; -- newtok[2] = tok[2]; -- newtok[3] = tok[3]; -- set_tok_const (newtok[4], value); -- (*macro->emit) (newtok, ntok+1, macro->arg); -- return; -- } -- } -- } -- -- /* Search opcodes. */ -- opcode = (const struct sw_64_opcode *) str_hash_find (sw_64_opcode_hash, opname); -- if (opcode) -- { -- found_something = 1; -- opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch); -- if (opcode) -- { -- struct sw_64_insn insn; -- assemble_insn (opcode, tok, ntok, &insn, reloc); -- -- /* Copy the sequence number for the reloc from the reloc token. */ -- if (reloc != BFD_RELOC_UNUSED) -- insn.sequence = tok[ntok].X_add_number; -- -- emit_insn (&insn); -- return; -- } -- } -- -- if (found_something) -- { -- if (cpumatch) -- as_bad (_("inappropriate arguments for opcode `%s'"), opname); -- else -- as_bad (_("opcode `%s' not supported for target %s"), opname, -- sw_64_target_name); -- } -- else -- as_bad (_("unknown opcode `%s'"), opname); --} -- --#ifdef OBJ_EVAX -- --/* Add sym+addend to link pool. -- Return offset from current procedure value (pv) to entry in link pool. -- -- Add new fixup only if offset isn't 16bit. */ -- --static symbolS * --add_to_link_pool (symbolS *sym, offsetT addend) --{ -- symbolS *basesym; -- segT current_section = now_seg; -- int current_subsec = now_subseg; -- char *p; -- segment_info_type *seginfo = seg_info (sw_64_link_section); -- fixS *fixp; -- symbolS *linksym, *expsym; -- expressionS e; -- -- basesym = sw_64_evax_proc->symbol; -- -- /* @@ This assumes all entries in a given section will be of the same -- size... Probably correct, but unwise to rely on. */ -- /* This must always be called with the same subsegment. */ -- -- if (seginfo->frchainP) -- for (fixp = seginfo->frchainP->fix_root; -- fixp != (fixS *) NULL; -- fixp = fixp->fx_next) -- { -- if (fixp->fx_addsy == sym -- && fixp->fx_offset == (valueT)addend -- && fixp->tc_fix_data.info -- && fixp->tc_fix_data.info->sym -- && symbol_symbolS (fixp->tc_fix_data.info->sym) -- && (symbol_get_value_expression (fixp->tc_fix_data.info->sym) -- ->X_op_symbol == basesym)) -- return fixp->tc_fix_data.info->sym; -- } -- -- /* Not found, add a new entry. */ -- subseg_set (sw_64_link_section, 0); -- linksym = symbol_new (FAKE_LABEL_NAME, now_seg, frag_now, frag_now_fix ()); -- p = frag_more (8); -- memset (p, 0, 8); -- -- /* Create a symbol for 'basesym - linksym' (offset of the added entry). */ -- e.X_op = O_subtract; -- e.X_add_symbol = linksym; -- e.X_op_symbol = basesym; -- e.X_add_number = 0; -- expsym = make_expr_symbol (&e); -- -- /* Create a fixup for the entry. */ -- fixp = fix_new -- (frag_now, p - frag_now->fr_literal, 8, sym, addend, 0, BFD_RELOC_64); -- fixp->tc_fix_data.info = get_sw_64_reloc_tag (next_sequence_num--); -- fixp->tc_fix_data.info->sym = expsym; -- -- subseg_set (current_section, current_subsec); -- -- /* Return the symbol. */ -- return expsym; --} --#endif /* OBJ_EVAX */ -- --/* Assembler directives. */ -- --/* Handle the .text pseudo-op. This is like the usual one, but it -- clears sw_64_insn_label and restores auto alignment. */ -- --static void --s_sw_64_text (int i) --{ --#ifdef OBJ_ELF -- obj_elf_text (i); --#else -- s_text (i); --#endif --#ifdef OBJ_EVAX -- { -- symbolS * symbolP; -- -- symbolP = symbol_find (".text"); -- if (symbolP == NULL) -- { -- symbolP = symbol_make (".text"); -- S_SET_SEGMENT (symbolP, text_section); -- symbol_table_insert (symbolP); -- } -- } --#endif -- sw_64_insn_label = NULL; -- sw_64_auto_align_on = 1; -- sw_64_current_align = 0; --} -- --/* Handle the .data pseudo-op. This is like the usual one, but it -- clears sw_64_insn_label and restores auto alignment. */ -- --static void --s_sw_64_data (int i) --{ --#ifdef OBJ_ELF -- obj_elf_data (i); --#else -- s_data (i); --#endif -- sw_64_insn_label = NULL; -- sw_64_auto_align_on = 1; -- sw_64_current_align = 0; --} -- --#if defined (OBJ_ECOFF) || defined (OBJ_EVAX) -- --/* Handle the OSF/1 and openVMS .comm pseudo quirks. */ -- --static void --s_sw_64_comm (int ignore ATTRIBUTE_UNUSED) --{ -- char *name; -- char c; -- char *p; -- offsetT size; -- symbolS *symbolP; --#ifdef OBJ_EVAX -- offsetT temp; -- int log_align = 0; --#endif -- -- c = get_symbol_name (&name); -- -- /* Just after name is now '\0'. */ -- p = input_line_pointer; -- *p = c; -- -- SKIP_WHITESPACE_AFTER_NAME (); -- -- /* Sw_64 OSF/1 compiler doesn't provide the comma, gcc does. */ -- if (*input_line_pointer == ',') -- { -- input_line_pointer++; -- SKIP_WHITESPACE (); -- } -- if ((size = get_absolute_expression ()) < 0) -- { -- as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size); -- ignore_rest_of_line (); -- return; -- } -- -- *p = 0; -- symbolP = symbol_find_or_make (name); -- *p = c; -- -- if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) -- { -- as_bad (_("Ignoring attempt to re-define symbol")); -- ignore_rest_of_line (); -- return; -- } -- --#ifdef OBJ_EVAX -- if (*input_line_pointer != ',') -- temp = 8; /* Default alignment. */ -- else -- { -- input_line_pointer++; -- SKIP_WHITESPACE (); -- temp = get_absolute_expression (); -- } -- -- /* ??? Unlike on OSF/1, the alignment factor is not in log units. */ -- while ((temp >>= 1) != 0) -- ++log_align; -- -- if (*input_line_pointer == ',') -- { -- /* Extended form of the directive -- -- .comm symbol, size, alignment, section -- -- where the "common" semantics is transferred to the section. -- The symbol is effectively an alias for the section name. */ -- -- segT sec; -- const char *sec_name; -- symbolS *sec_symbol; -- segT current_seg = now_seg; -- subsegT current_subseg = now_subseg; -- int cur_size; -- -- input_line_pointer++; -- SKIP_WHITESPACE (); -- sec_name = s_sw_64_section_name (); -- sec_symbol = symbol_find_or_make (sec_name); -- sec = subseg_new (sec_name, 0); -- S_SET_SEGMENT (sec_symbol, sec); -- symbol_get_bfdsym (sec_symbol)->flags |= BSF_SECTION_SYM; -- bfd_vms_set_section_flags (stdoutput, sec, 0, -- EGPS__V_OVR | EGPS__V_GBL | EGPS__V_NOMOD); -- record_alignment (sec, log_align); -- -- /* Reuse stab_string_size to store the size of the section. */ -- cur_size = seg_info (sec)->stabu.stab_string_size; -- if ((int) size > cur_size) -- { -- char *pfrag -- = frag_var (rs_fill, 1, 1, (relax_substateT)0, NULL, -- (valueT)size - (valueT)cur_size, NULL); -- *pfrag = 0; -- seg_info (sec)->stabu.stab_string_size = (int)size; -- } -- -- S_SET_SEGMENT (symbolP, sec); -- -- subseg_set (current_seg, current_subseg); -- } -- else -- { -- /* Regular form of the directive -- -- .comm symbol, size, alignment -- -- where the "common" semantics in on the symbol. -- These symbols are assembled in the .bss section. */ -- -- char *pfrag; -- segT current_seg = now_seg; -- subsegT current_subseg = now_subseg; -- -- subseg_set (bss_section, 1); -- frag_align (log_align, 0, 0); -- record_alignment (bss_section, log_align); -- -- symbol_set_frag (symbolP, frag_now); -- pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP, -- size, NULL); -- *pfrag = 0; -- -- S_SET_SEGMENT (symbolP, bss_section); -- -- subseg_set (current_seg, current_subseg); -- } --#endif -- -- if (S_GET_VALUE (symbolP)) -- { -- if (S_GET_VALUE (symbolP) != (valueT) size) -- as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."), -- S_GET_NAME (symbolP), -- (long) S_GET_VALUE (symbolP), -- (long) size); -- } -- else -- { --#ifndef OBJ_EVAX -- S_SET_VALUE (symbolP, (valueT) size); --#endif -- S_SET_EXTERNAL (symbolP); -- } -- --#ifndef OBJ_EVAX -- know (symbol_get_frag (symbolP) == &zero_address_frag); --#endif -- demand_empty_rest_of_line (); --} -- --#endif /* ! OBJ_ELF */ -- --#ifdef OBJ_ECOFF -- --/* Handle the .rdata pseudo-op. This is like the usual one, but it -- clears sw_64_insn_label and restores auto alignment. */ -- --static void --s_sw_64_rdata (int ignore ATTRIBUTE_UNUSED) --{ -- get_absolute_expression (); -- subseg_new (".rdata", 0); -- demand_empty_rest_of_line (); -- sw_64_insn_label = NULL; -- sw_64_auto_align_on = 1; -- sw_64_current_align = 0; --} -- --#endif -- --#ifdef OBJ_ECOFF -- --/* Handle the .sdata pseudo-op. This is like the usual one, but it -- clears sw_64_insn_label and restores auto alignment. */ -- --static void --s_sw_64_sdata (int ignore ATTRIBUTE_UNUSED) --{ -- get_absolute_expression (); -- subseg_new (".sdata", 0); -- demand_empty_rest_of_line (); -- sw_64_insn_label = NULL; -- sw_64_auto_align_on = 1; -- sw_64_current_align = 0; --} --#endif -- --#ifdef OBJ_ELF --struct sw_64_elf_frame_data --{ -- symbolS *func_sym; -- symbolS *func_end_sym; -- symbolS *prologue_sym; -- unsigned int mask; -- unsigned int fmask; -- int fp_regno; -- int ra_regno; -- offsetT frame_size; -- offsetT mask_offset; -- offsetT fmask_offset; -- -- struct sw_64_elf_frame_data *next; --}; -- --static struct sw_64_elf_frame_data *all_frame_data; --static struct sw_64_elf_frame_data **plast_frame_data = &all_frame_data; --static struct sw_64_elf_frame_data *cur_frame_data; -- --extern int all_cfi_sections; -- --/* Handle the .section pseudo-op. This is like the usual one, but it -- clears sw_64_insn_label and restores auto alignment. */ -- --static void --s_sw_64_section (int ignore ATTRIBUTE_UNUSED) --{ -- obj_elf_section (ignore); -- -- sw_64_insn_label = NULL; -- sw_64_auto_align_on = 1; -- sw_64_current_align = 0; --} -- --static void --s_sw_64_ent (int dummy ATTRIBUTE_UNUSED) --{ -- if (ECOFF_DEBUGGING) -- ecoff_directive_ent (0); -- else -- { -- char *name, name_end; -- -- name_end = get_symbol_name (&name); -- /* CFI_EMIT_eh_frame is the default. */ -- all_cfi_sections = CFI_EMIT_eh_frame; -- -- if (! is_name_beginner (*name)) -- { -- as_warn (_(".ent directive has no name")); -- (void) restore_line_pointer (name_end); -- } -- else -- { -- symbolS *sym; -- -- if (cur_frame_data) -- as_warn (_("nested .ent directives")); -- -- sym = symbol_find_or_make (name); -- symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION; -- -- cur_frame_data = XCNEW (struct sw_64_elf_frame_data); -- cur_frame_data->func_sym = sym; -- -- /* Provide sensible defaults. */ -- cur_frame_data->fp_regno = 30; /* sp */ -- cur_frame_data->ra_regno = 26; /* ra */ -- -- *plast_frame_data = cur_frame_data; -- plast_frame_data = &cur_frame_data->next; -- -- /* The .ent directive is sometimes followed by a number. Not sure -- what it really means, but ignore it. */ -- *input_line_pointer = name_end; -- SKIP_WHITESPACE_AFTER_NAME (); -- if (*input_line_pointer == ',') -- { -- input_line_pointer++; -- SKIP_WHITESPACE (); -- } -- if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') -- (void) get_absolute_expression (); -- } -- demand_empty_rest_of_line (); -- } --} -- --static void --s_sw_64_end (int dummy ATTRIBUTE_UNUSED) --{ -- if (ECOFF_DEBUGGING) -- ecoff_directive_end (0); -- else -- { -- char *name, name_end; -- -- name_end = get_symbol_name (&name); -- -- if (! is_name_beginner (*name)) -- { -- as_warn (_(".end directive has no name")); -- } -- else -- { -- symbolS *sym; -- -- sym = symbol_find (name); -- if (!cur_frame_data) -- as_warn (_(".end directive without matching .ent")); -- else if (sym != cur_frame_data->func_sym) -- as_warn (_(".end directive names different symbol than .ent")); -- -- /* Create an expression to calculate the size of the function. */ -- if (sym && cur_frame_data) -- { -- OBJ_SYMFIELD_TYPE *obj = symbol_get_obj (sym); -- expressionS *exp = XNEW (expressionS); -- -- obj->size = exp; -- exp->X_op = O_subtract; -- exp->X_add_symbol = symbol_temp_new_now (); -- exp->X_op_symbol = sym; -- exp->X_add_number = 0; -- -- cur_frame_data->func_end_sym = exp->X_add_symbol; -- } -- -- cur_frame_data = NULL; -- } -- -- (void) restore_line_pointer (name_end); -- demand_empty_rest_of_line (); -- } --} -- --static void --s_sw_64_mask (int fp) --{ -- if (ECOFF_DEBUGGING) -- { -- if (fp) -- ecoff_directive_fmask (0); -- else -- ecoff_directive_mask (0); -- } -- else -- { -- long val; -- offsetT offset; -- -- if (!cur_frame_data) -- { -- if (fp) -- as_warn (_(".fmask outside of .ent")); -- else -- as_warn (_(".mask outside of .ent")); -- discard_rest_of_line (); -- return; -- } -- -- if (get_absolute_expression_and_terminator (&val) != ',') -- { -- if (fp) -- as_warn (_("bad .fmask directive")); -- else -- as_warn (_("bad .mask directive")); -- --input_line_pointer; -- discard_rest_of_line (); -- return; -- } -- -- offset = get_absolute_expression (); -- demand_empty_rest_of_line (); -- -- if (fp) -- { -- cur_frame_data->fmask = val; -- cur_frame_data->fmask_offset = offset; -- } -- else -- { -- cur_frame_data->mask = val; -- cur_frame_data->mask_offset = offset; -- } -- } --} -- --static void --s_sw_64_frame (int dummy ATTRIBUTE_UNUSED) --{ -- if (ECOFF_DEBUGGING) -- ecoff_directive_frame (0); -- else -- { -- long val; -- -- if (!cur_frame_data) -- { -- as_warn (_(".frame outside of .ent")); -- discard_rest_of_line (); -- return; -- } -- -- cur_frame_data->fp_regno = tc_get_register (1); -- -- SKIP_WHITESPACE (); -- if (*input_line_pointer++ != ',' -- || get_absolute_expression_and_terminator (&val) != ',') -- { -- as_warn (_("bad .frame directive")); -- --input_line_pointer; -- discard_rest_of_line (); -- return; -- } -- cur_frame_data->frame_size = val; -- -- cur_frame_data->ra_regno = tc_get_register (0); -- -- /* Next comes the "offset of saved $a0 from $sp". In gcc terms -- this is current_function_pretend_args_size. There's no place -- to put this value, so ignore it. */ -- s_ignore (42); -- } --} -- --static void --s_sw_64_prologue (int ignore ATTRIBUTE_UNUSED) --{ -- symbolS *sym; -- int arg; -- -- arg = get_absolute_expression (); -- demand_empty_rest_of_line (); -- sw_64_prologue_label = symbol_new -- (FAKE_LABEL_NAME, now_seg, frag_now, frag_now_fix ()); -- -- if (ECOFF_DEBUGGING) -- sym = ecoff_get_cur_proc_sym (); -- else -- sym = cur_frame_data ? cur_frame_data->func_sym : NULL; -- -- if (sym == NULL) -- { -- as_bad (_(".prologue directive without a preceding .ent directive")); -- return; -- } -- -- switch (arg) -- { -- case 0: /* No PV required. */ -- S_SET_OTHER (sym, STO_SW_64_NOPV -- | (S_GET_OTHER (sym) & ~STO_SW_64_STD_GPLOAD)); -- break; -- case 1: /* Std GP load. */ -- S_SET_OTHER (sym, STO_SW_64_STD_GPLOAD -- | (S_GET_OTHER (sym) & ~STO_SW_64_STD_GPLOAD)); -- break; -- case 2: /* Non-std use of PV. */ -- break; -- -- default: -- as_bad (_("Invalid argument %d to .prologue."), arg); -- break; -- } -- -- if (cur_frame_data) -- cur_frame_data->prologue_sym = symbol_temp_new_now (); --} -- --static char *first_file_directive; -- --static void --s_sw_64_file (int ignore ATTRIBUTE_UNUSED) --{ -- /* Save the first .file directive we see, so that we can change our -- minds about whether ecoff debugging should or shouldn't be enabled. */ -- if (sw_64_flag_mdebug < 0 && ! first_file_directive) -- { -- char *start = input_line_pointer; -- size_t len; -- -- discard_rest_of_line (); -- -- len = input_line_pointer - start; -- first_file_directive = xmemdup0 (start, len); -- -- input_line_pointer = start; -- } -- -- if (ECOFF_DEBUGGING) -- ecoff_directive_file (0); -- else -- dwarf2_directive_file (0); --} -- --static void --s_sw_64_loc (int ignore ATTRIBUTE_UNUSED) --{ -- if (ECOFF_DEBUGGING) -- ecoff_directive_loc (0); -- else -- dwarf2_directive_loc (0); --} -- --static void --s_sw_64_stab (int n) --{ -- /* If we've been undecided about mdebug, make up our minds in favour. */ -- if (sw_64_flag_mdebug < 0) -- { -- segT sec = subseg_new (".mdebug", 0); -- bfd_set_section_flags (sec, SEC_HAS_CONTENTS | SEC_READONLY); -- bfd_set_section_alignment (sec, 3); -- ecoff_read_begin_hook (); -- -- if (first_file_directive) -- { -- char *save_ilp = input_line_pointer; -- input_line_pointer = first_file_directive; -- ecoff_directive_file (0); -- input_line_pointer = save_ilp; -- free (first_file_directive); -- } -- -- sw_64_flag_mdebug = 1; -- } -- s_stab (n); --} -- --static void --s_sw_64_coff_wrapper (int which) --{ -- static void (* const fns[]) (int) = { -- ecoff_directive_begin, -- ecoff_directive_bend, -- ecoff_directive_def, -- ecoff_directive_dim, -- ecoff_directive_endef, -- ecoff_directive_scl, -- ecoff_directive_tag, -- ecoff_directive_val, -- }; -- -- gas_assert (which >= 0 && which < (int) (sizeof (fns)/sizeof (*fns))); -- -- if (ECOFF_DEBUGGING) -- (*fns[which]) (0); -- else -- { -- as_bad (_("ECOFF debugging is disabled.")); -- ignore_rest_of_line (); -- } --} -- --/* Called at the end of assembly. Here we emit unwind info for frames -- unless the compiler has done it for us. */ -- --void --sw_64_elf_md_end (void) --{ -- struct sw_64_elf_frame_data *p; -- -- if (cur_frame_data) -- as_warn (_(".ent directive without matching .end")); -- -- /* If someone has generated the unwind info themselves, great. */ -- if (bfd_get_section_by_name (stdoutput, ".eh_frame") != NULL) -- return; -- -- /* ??? In theory we could look for functions for which we have -- generated unwind info via CFI directives, and those we have not. -- Those we have not could still get their unwind info from here. -- For now, do nothing if we've seen any CFI directives. Note that -- the above test will not trigger, as we've not emitted data yet. */ -- if (all_fde_data != NULL) -- return; -- -- /* Generate .eh_frame data for the unwind directives specified. */ -- for (p = all_frame_data; p ; p = p->next) -- if (p->prologue_sym) -- { -- /* Create a temporary symbol at the same location as our -- function symbol. This prevents problems with globals. */ -- cfi_new_fde (symbol_temp_new (S_GET_SEGMENT (p->func_sym), -- symbol_get_frag (p->func_sym), -- S_GET_VALUE (p->func_sym))); -- -- cfi_set_sections (); -- cfi_set_return_column (p->ra_regno); -- cfi_add_CFA_def_cfa_register (30); -- if (p->fp_regno != 30 || p->mask || p->fmask || p->frame_size) -- { -- unsigned int mask; -- offsetT offset; -- -- cfi_add_advance_loc (p->prologue_sym); -- -- if (p->fp_regno != 30) -- if (p->frame_size != 0) -- cfi_add_CFA_def_cfa (p->fp_regno, p->frame_size); -- else -- cfi_add_CFA_def_cfa_register (p->fp_regno); -- else if (p->frame_size != 0) -- cfi_add_CFA_def_cfa_offset (p->frame_size); -- -- mask = p->mask; -- offset = p->mask_offset; -- -- /* Recall that $26 is special-cased and stored first. */ -- if ((mask >> 26) & 1) -- { -- cfi_add_CFA_offset (26, offset); -- offset += 8; -- mask &= ~(1 << 26); -- } -- while (mask) -- { -- unsigned int i; -- i = mask & -mask; -- mask ^= i; -- i = ffs (i) - 1; -- -- cfi_add_CFA_offset (i, offset); -- offset += 8; -- } -- -- mask = p->fmask; -- offset = p->fmask_offset; -- while (mask) -- { -- unsigned int i; -- i = mask & -mask; -- mask ^= i; -- i = ffs (i) - 1; -- -- cfi_add_CFA_offset (i + 32, offset); -- offset += 8; -- } -- } -- -- cfi_end_fde (p->func_end_sym); -- } --} -- --static void --s_sw_64_usepv (int unused ATTRIBUTE_UNUSED) --{ -- char *name, name_end; -- char *which, which_end; -- symbolS *sym; -- int other; -- -- name_end = get_symbol_name (&name); -- -- if (! is_name_beginner (*name)) -- { -- as_bad (_(".usepv directive has no name")); -- (void) restore_line_pointer (name_end); -- ignore_rest_of_line (); -- return; -- } -- -- sym = symbol_find_or_make (name); -- name_end = restore_line_pointer (name_end); -- if (! is_end_of_line[(unsigned char) name_end]) -- input_line_pointer++; -- -- if (name_end != ',') -- { -- as_bad (_(".usepv directive has no type")); -- ignore_rest_of_line (); -- return; -- } -- -- SKIP_WHITESPACE (); -- -- which_end = get_symbol_name (&which); -- -- if (strcmp (which, "no") == 0) -- other = STO_SW_64_NOPV; -- else if (strcmp (which, "std") == 0) -- other = STO_SW_64_STD_GPLOAD; -- else -- { -- as_bad (_("unknown argument for .usepv")); -- other = 0; -- } -- -- (void) restore_line_pointer (which_end); -- demand_empty_rest_of_line (); -- -- S_SET_OTHER (sym, other | (S_GET_OTHER (sym) & ~STO_SW_64_STD_GPLOAD)); --} --#endif /* OBJ_ELF */ -- --/* Standard calling conventions leaves the CFA at $30 on entry. */ -- --void --sw_64_cfi_frame_initial_instructions (void) --{ -- cfi_add_CFA_def_cfa_register (30); --} -- --#ifdef OBJ_EVAX -- --/* Get name of section. */ --static const char * --s_sw_64_section_name (void) --{ -- char *name; -- -- SKIP_WHITESPACE (); -- if (*input_line_pointer == '"') -- { -- int dummy; -- -- name = demand_copy_C_string (&dummy); -- if (name == NULL) -- { -- ignore_rest_of_line (); -- return NULL; -- } -- } -- else -- { -- char *end = input_line_pointer; -- -- while (0 == strchr ("\n\t,; ", *end)) -- end++; -- if (end == input_line_pointer) -- { -- as_warn (_("missing name")); -- ignore_rest_of_line (); -- return NULL; -- } -- -- name = xmemdup0 (input_line_pointer, end - input_line_pointer); -- input_line_pointer = end; -- } -- SKIP_WHITESPACE (); -- return name; --} -- --/* Put clear/set flags in one flagword. The LSBs are flags to be set, -- the MSBs are the flags to be cleared. */ -- --#define EGPS__V_NO_SHIFT 16 --#define EGPS__V_MASK 0xffff -- --/* Parse one VMS section flag. */ -- --static flagword --s_sw_64_section_word (char *str, size_t len) --{ -- int no = 0; -- flagword flag = 0; -- -- if (len == 5 && strncmp (str, "NO", 2) == 0) -- { -- no = 1; -- str += 2; -- len -= 2; -- } -- -- if (len == 3) -- { -- if (strncmp (str, "PIC", 3) == 0) -- flag = EGPS__V_PIC; -- else if (strncmp (str, "LIB", 3) == 0) -- flag = EGPS__V_LIB; -- else if (strncmp (str, "OVR", 3) == 0) -- flag = EGPS__V_OVR; -- else if (strncmp (str, "REL", 3) == 0) -- flag = EGPS__V_REL; -- else if (strncmp (str, "GBL", 3) == 0) -- flag = EGPS__V_GBL; -- else if (strncmp (str, "SHR", 3) == 0) -- flag = EGPS__V_SHR; -- else if (strncmp (str, "EXE", 3) == 0) -- flag = EGPS__V_EXE; -- else if (strncmp (str, "WRT", 3) == 0) -- flag = EGPS__V_WRT; -- else if (strncmp (str, "VEC", 3) == 0) -- flag = EGPS__V_VEC; -- else if (strncmp (str, "MOD", 3) == 0) -- { -- flag = no ? EGPS__V_NOMOD : EGPS__V_NOMOD << EGPS__V_NO_SHIFT; -- no = 0; -- } -- else if (strncmp (str, "COM", 3) == 0) -- flag = EGPS__V_COM; -- } -- -- if (flag == 0) -- { -- char c = str[len]; -- str[len] = 0; -- as_warn (_("unknown section attribute %s"), str); -- str[len] = c; -- return 0; -- } -- -- if (no) -- return flag << EGPS__V_NO_SHIFT; -- else -- return flag; --} -- --/* Handle the section specific pseudo-op. */ -- --#define EVAX_SECTION_COUNT 5 -- --static const char *section_name[EVAX_SECTION_COUNT + 1] = -- { "NULL", ".rdata", ".comm", ".link", ".ctors", ".dtors" }; -- --static void --s_sw_64_section (int secid) --{ -- const char *name; -- char *beg; -- segT sec; -- flagword vms_flags = 0; -- symbolS *symbol; -- -- if (secid == 0) -- { -- name = s_sw_64_section_name (); -- if (name == NULL) -- return; -- sec = subseg_new (name, 0); -- if (*input_line_pointer == ',') -- { -- /* Skip the comma. */ -- ++input_line_pointer; -- SKIP_WHITESPACE (); -- -- do -- { -- char c; -- -- SKIP_WHITESPACE (); -- c = get_symbol_name (&beg); -- *input_line_pointer = c; -- -- vms_flags |= s_sw_64_section_word (beg, input_line_pointer - beg); -- -- SKIP_WHITESPACE_AFTER_NAME (); -- } -- while (*input_line_pointer++ == ','); -- -- --input_line_pointer; -- } -- -- symbol = symbol_find_or_make (name); -- S_SET_SEGMENT (symbol, sec); -- symbol_get_bfdsym (symbol)->flags |= BSF_SECTION_SYM; -- bfd_vms_set_section_flags -- (stdoutput, sec, -- (vms_flags >> EGPS__V_NO_SHIFT) & EGPS__V_MASK, -- vms_flags & EGPS__V_MASK); -- } -- else -- { -- get_absolute_expression (); -- subseg_new (section_name[secid], 0); -- } -- -- demand_empty_rest_of_line (); -- sw_64_insn_label = NULL; -- sw_64_auto_align_on = 1; -- sw_64_current_align = 0; --} -- --static void --s_sw_64_literals (int ignore ATTRIBUTE_UNUSED) --{ -- subseg_new (".literals", 0); -- demand_empty_rest_of_line (); -- sw_64_insn_label = NULL; -- sw_64_auto_align_on = 1; -- sw_64_current_align = 0; --} -- --/* Parse .ent directives. */ -- --static void --s_sw_64_ent (int ignore ATTRIBUTE_UNUSED) --{ -- symbolS *symbol; -- expressionS symexpr; -- -- if (sw_64_evax_proc != NULL) -- as_bad (_("previous .ent not closed by a .end")); -- -- sw_64_evax_proc = &sw_64_evax_proc_data; -- -- sw_64_evax_proc->pdsckind = 0; -- sw_64_evax_proc->framereg = -1; -- sw_64_evax_proc->framesize = 0; -- sw_64_evax_proc->rsa_offset = 0; -- sw_64_evax_proc->ra_save = AXP_REG_RA; -- sw_64_evax_proc->fp_save = -1; -- sw_64_evax_proc->imask = 0; -- sw_64_evax_proc->fmask = 0; -- sw_64_evax_proc->prologue = 0; -- sw_64_evax_proc->type = 0; -- sw_64_evax_proc->handler = 0; -- sw_64_evax_proc->handler_data = 0; -- -- expression (&symexpr); -- -- if (symexpr.X_op != O_symbol) -- { -- as_fatal (_(".ent directive has no symbol")); -- demand_empty_rest_of_line (); -- return; -- } -- -- symbol = make_expr_symbol (&symexpr); -- symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION; -- sw_64_evax_proc->symbol = symbol; -- -- demand_empty_rest_of_line (); --} -- --static void --s_sw_64_handler (int is_data) --{ -- if (is_data) -- sw_64_evax_proc->handler_data = get_absolute_expression (); -- else -- { -- char *name, name_end; -- -- name_end = get_symbol_name (&name); -- -- if (! is_name_beginner (*name)) -- { -- as_warn (_(".handler directive has no name")); -- } -- else -- { -- symbolS *sym; -- -- sym = symbol_find_or_make (name); -- symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION; -- sw_64_evax_proc->handler = sym; -- } -- -- (void) restore_line_pointer (name_end); -- } -- -- demand_empty_rest_of_line (); --} -- --/* Parse .frame ,,RA, directives. */ -- --static void --s_sw_64_frame (int ignore ATTRIBUTE_UNUSED) --{ -- long val; -- int ra; -- -- sw_64_evax_proc->framereg = tc_get_register (1); -- -- SKIP_WHITESPACE (); -- if (*input_line_pointer++ != ',' -- || get_absolute_expression_and_terminator (&val) != ',') -- { -- as_warn (_("Bad .frame directive 1./2. param")); -- --input_line_pointer; -- demand_empty_rest_of_line (); -- return; -- } -- -- sw_64_evax_proc->framesize = val; -- -- ra = tc_get_register (1); -- if (ra != AXP_REG_RA) -- as_warn (_("Bad RA (%d) register for .frame"), ra); -- -- SKIP_WHITESPACE (); -- if (*input_line_pointer++ != ',') -- { -- as_warn (_("Bad .frame directive 3./4. param")); -- --input_line_pointer; -- demand_empty_rest_of_line (); -- return; -- } -- sw_64_evax_proc->rsa_offset = get_absolute_expression (); --} -- --/* Parse .prologue. */ -- --static void --s_sw_64_prologue (int ignore ATTRIBUTE_UNUSED) --{ -- demand_empty_rest_of_line (); -- sw_64_prologue_label = symbol_new -- (FAKE_LABEL_NAME, now_seg, frag_now, frag_now_fix ()); --} -- --/* Parse .pdesc ,{null|stack|reg} -- Insert a procedure descriptor. */ -- --static void --s_sw_64_pdesc (int ignore ATTRIBUTE_UNUSED) --{ -- char *name; -- char name_end; -- char *p; -- expressionS exp; -- symbolS *entry_sym; -- const char *entry_sym_name; -- const char *pdesc_sym_name; -- fixS *fixp; -- size_t len; -- -- if (now_seg != sw_64_link_section) -- { -- as_bad (_(".pdesc directive not in link (.link) section")); -- return; -- } -- -- expression (&exp); -- if (exp.X_op != O_symbol) -- { -- as_bad (_(".pdesc directive has no entry symbol")); -- return; -- } -- -- entry_sym = make_expr_symbol (&exp); -- entry_sym_name = S_GET_NAME (entry_sym); -- -- /* Strip "..en". */ -- len = strlen (entry_sym_name); -- if (len < 4 || strcmp (entry_sym_name + len - 4, "..en") != 0) -- { -- as_bad (_(".pdesc has a bad entry symbol")); -- return; -- } -- len -= 4; -- pdesc_sym_name = S_GET_NAME (sw_64_evax_proc->symbol); -- -- if (!sw_64_evax_proc -- || !S_IS_DEFINED (sw_64_evax_proc->symbol) -- || strlen (pdesc_sym_name) != len -- || memcmp (entry_sym_name, pdesc_sym_name, len) != 0) -- { -- as_fatal (_(".pdesc doesn't match with last .ent")); -- return; -- } -- -- /* Define pdesc symbol. */ -- symbol_set_value_now (sw_64_evax_proc->symbol); -- -- /* Save bfd symbol of proc entry in function symbol. */ -- ((struct evax_private_udata_struct *) -- symbol_get_bfdsym (sw_64_evax_proc->symbol)->udata.p)->enbsym -- = symbol_get_bfdsym (entry_sym); -- -- SKIP_WHITESPACE (); -- if (*input_line_pointer++ != ',') -- { -- as_warn (_("No comma after .pdesc ")); -- demand_empty_rest_of_line (); -- return; -- } -- -- SKIP_WHITESPACE (); -- name_end = get_symbol_name (&name); -- -- if (strncmp (name, "stack", 5) == 0) -- sw_64_evax_proc->pdsckind = PDSC_S_K_KIND_FP_STACK; -- -- else if (strncmp (name, "reg", 3) == 0) -- sw_64_evax_proc->pdsckind = PDSC_S_K_KIND_FP_REGISTER; -- -- else if (strncmp (name, "null", 4) == 0) -- sw_64_evax_proc->pdsckind = PDSC_S_K_KIND_NULL; -- -- else -- { -- (void) restore_line_pointer (name_end); -- as_fatal (_("unknown procedure kind")); -- demand_empty_rest_of_line (); -- return; -- } -- -- (void) restore_line_pointer (name_end); -- demand_empty_rest_of_line (); -- --#ifdef md_flush_pending_output -- md_flush_pending_output (); --#endif -- -- frag_align (3, 0, 0); -- p = frag_more (16); -- fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0); -- fixp->fx_done = 1; -- -- *p = sw_64_evax_proc->pdsckind -- | ((sw_64_evax_proc->framereg == 29) ? PDSC_S_M_BASE_REG_IS_FP : 0) -- | ((sw_64_evax_proc->handler) ? PDSC_S_M_HANDLER_VALID : 0) -- | ((sw_64_evax_proc->handler_data) ? PDSC_S_M_HANDLER_DATA_VALID : 0); -- *(p + 1) = PDSC_S_M_NATIVE | PDSC_S_M_NO_JACKET; -- -- switch (sw_64_evax_proc->pdsckind) -- { -- case PDSC_S_K_KIND_NULL: -- *(p + 2) = 0; -- *(p + 3) = 0; -- break; -- case PDSC_S_K_KIND_FP_REGISTER: -- *(p + 2) = sw_64_evax_proc->fp_save; -- *(p + 3) = sw_64_evax_proc->ra_save; -- break; -- case PDSC_S_K_KIND_FP_STACK: -- md_number_to_chars (p + 2, (valueT) sw_64_evax_proc->rsa_offset, 2); -- break; -- default: /* impossible */ -- break; -- } -- -- *(p + 4) = 0; -- *(p + 5) = sw_64_evax_proc->type & 0x0f; -- -- /* Signature offset. */ -- md_number_to_chars (p + 6, (valueT) 0, 2); -- -- fix_new_exp (frag_now, p - frag_now->fr_literal + 8, -- 8, &exp, 0, BFD_RELOC_64); -- -- if (sw_64_evax_proc->pdsckind == PDSC_S_K_KIND_NULL) -- return; -- -- /* pdesc+16: Size. */ -- p = frag_more (6); -- md_number_to_chars (p, (valueT) sw_64_evax_proc->framesize, 4); -- md_number_to_chars (p + 4, (valueT) 0, 2); -- -- /* Entry length. */ -- exp.X_op = O_subtract; -- exp.X_add_symbol = sw_64_prologue_label; -- exp.X_op_symbol = entry_sym; -- emit_expr (&exp, 2); -- -- if (sw_64_evax_proc->pdsckind == PDSC_S_K_KIND_FP_REGISTER) -- return; -- -- /* pdesc+24: register masks. */ -- p = frag_more (8); -- md_number_to_chars (p, sw_64_evax_proc->imask, 4); -- md_number_to_chars (p + 4, sw_64_evax_proc->fmask, 4); -- -- if (sw_64_evax_proc->handler) -- { -- p = frag_more (8); -- fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, -- sw_64_evax_proc->handler, 0, 0, BFD_RELOC_64); -- } -- -- if (sw_64_evax_proc->handler_data) -- { -- p = frag_more (8); -- md_number_to_chars (p, sw_64_evax_proc->handler_data, 8); -- } --} -- --/* Support for crash debug on vms. */ -- --static void --s_sw_64_name (int ignore ATTRIBUTE_UNUSED) --{ -- char *p; -- expressionS exp; -- -- if (now_seg != sw_64_link_section) -- { -- as_bad (_(".name directive not in link (.link) section")); -- demand_empty_rest_of_line (); -- return; -- } -- -- expression (&exp); -- if (exp.X_op != O_symbol) -- { -- as_warn (_(".name directive has no symbol")); -- demand_empty_rest_of_line (); -- return; -- } -- -- demand_empty_rest_of_line (); -- --#ifdef md_flush_pending_output -- md_flush_pending_output (); --#endif -- -- frag_align (3, 0, 0); -- p = frag_more (8); -- -- fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0, BFD_RELOC_64); --} -- --/* Parse .linkage . -- Create a linkage pair relocation. */ -- --static void --s_sw_64_linkage (int ignore ATTRIBUTE_UNUSED) --{ -- expressionS exp; -- char *p; -- fixS *fixp; -- --#ifdef md_flush_pending_output -- md_flush_pending_output (); --#endif -- -- expression (&exp); -- if (exp.X_op != O_symbol) -- { -- as_fatal (_("No symbol after .linkage")); -- } -- else -- { -- struct sw_64_linkage_fixups *linkage_fixup; -- -- p = frag_more (LKP_S_K_SIZE); -- memset (p, 0, LKP_S_K_SIZE); -- fixp = fix_new_exp -- (frag_now, p - frag_now->fr_literal, LKP_S_K_SIZE, &exp, 0, -- BFD_RELOC_SW_64_LINKAGE); -- -- if (sw_64_insn_label == NULL) -- sw_64_insn_label = symbol_new -- (FAKE_LABEL_NAME, now_seg, frag_now, frag_now_fix ()); -- -- /* Create a linkage element. */ -- linkage_fixup = XNEW (struct sw_64_linkage_fixups); -- linkage_fixup->fixp = fixp; -- linkage_fixup->next = NULL; -- linkage_fixup->label = sw_64_insn_label; -- -- /* Append it to the list. */ -- if (sw_64_linkage_fixup_root == NULL) -- sw_64_linkage_fixup_root = linkage_fixup; -- else -- sw_64_linkage_fixup_tail->next = linkage_fixup; -- sw_64_linkage_fixup_tail = linkage_fixup; -- } -- demand_empty_rest_of_line (); --} -- --/* Parse .code_address . -- Create a code address relocation. */ -- --static void --s_sw_64_code_address (int ignore ATTRIBUTE_UNUSED) --{ -- expressionS exp; -- char *p; -- --#ifdef md_flush_pending_output -- md_flush_pending_output (); --#endif -- -- expression (&exp); -- if (exp.X_op != O_symbol) -- as_fatal (_("No symbol after .code_address")); -- else -- { -- p = frag_more (8); -- memset (p, 0, 8); -- fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0,\ -- BFD_RELOC_SW_64_CODEADDR); -- } -- demand_empty_rest_of_line (); --} -- --static void --s_sw_64_fp_save (int ignore ATTRIBUTE_UNUSED) --{ -- sw_64_evax_proc->fp_save = tc_get_register (1); -- -- demand_empty_rest_of_line (); --} -- --static void --s_sw_64_mask (int ignore ATTRIBUTE_UNUSED) --{ -- long val; -- -- if (get_absolute_expression_and_terminator (&val) != ',') -- { -- as_warn (_("Bad .mask directive")); -- --input_line_pointer; -- } -- else -- { -- sw_64_evax_proc->imask = val; -- (void) get_absolute_expression (); -- } -- demand_empty_rest_of_line (); --} -- --static void --s_sw_64_fmask (int ignore ATTRIBUTE_UNUSED) --{ -- long val; -- -- if (get_absolute_expression_and_terminator (&val) != ',') -- { -- as_warn (_("Bad .fmask directive")); -- --input_line_pointer; -- } -- else -- { -- sw_64_evax_proc->fmask = val; -- (void) get_absolute_expression (); -- } -- demand_empty_rest_of_line (); --} -- --static void --s_sw_64_end (int ignore ATTRIBUTE_UNUSED) --{ -- char *name; -- char c; -- -- c = get_symbol_name (&name); -- (void) restore_line_pointer (c); -- demand_empty_rest_of_line (); -- sw_64_evax_proc = NULL; --} -- --static void --s_sw_64_file (int ignore ATTRIBUTE_UNUSED) --{ -- symbolS *s; -- int length; -- static char case_hack[32]; -- -- sprintf (case_hack, "", -- sw_64_flag_hash_long_names, sw_64_flag_show_after_trunc); -- -- s = symbol_find_or_make (case_hack); -- symbol_get_bfdsym (s)->flags |= BSF_FILE; -- -- get_absolute_expression (); -- s = symbol_find_or_make (demand_copy_string (&length)); -- symbol_get_bfdsym (s)->flags |= BSF_FILE; -- demand_empty_rest_of_line (); --} --#endif /* OBJ_EVAX */ -- --/* Handle the .gprel32 pseudo op. */ -- --static void --s_sw_64_gprel32 (int ignore ATTRIBUTE_UNUSED) --{ -- expressionS e; -- char *p; -- -- SKIP_WHITESPACE (); -- expression (&e); -- --#ifdef OBJ_ELF -- switch (e.X_op) -- { -- case O_constant: -- e.X_add_symbol = section_symbol (absolute_section); -- e.X_op = O_symbol; -- /* FALLTHRU */ -- case O_symbol: -- break; -- default: -- abort (); -- } --#else --#ifdef OBJ_ECOFF -- 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 = sw_64_gp_symbol; -- break; -- default: -- abort (); -- } --#endif --#endif -- -- if (sw_64_auto_align_on && sw_64_current_align < 2) -- sw_64_align (2, (char *) NULL, sw_64_insn_label, 0); -- if (sw_64_current_align > 2) -- sw_64_current_align = 2; -- sw_64_insn_label = NULL; -- -- p = frag_more (4); -- memset (p, 0, 4); -- fix_new_exp (frag_now, p - frag_now->fr_literal, 4, -- &e, 0, BFD_RELOC_GPREL32); --} -- --/* Handle floating point allocation pseudo-ops. This is like the -- generic version, but it makes sure the current label, if any, is -- correctly aligned. */ -- --static void --s_sw_64_float_cons (int type) --{ -- 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; -- } -- -- if (sw_64_auto_align_on && sw_64_current_align < log_size) -- sw_64_align (log_size, (char *) NULL, sw_64_insn_label, 0); -- if (sw_64_current_align > log_size) -- sw_64_current_align = log_size; -- sw_64_insn_label = NULL; -- -- float_cons (type); --} -- --/* Handle the .proc pseudo op. We don't really do much with it except -- parse it. */ -- --static void --s_sw_64_proc (int is_static ATTRIBUTE_UNUSED) --{ -- char *name; -- char c; -- char *p; -- symbolS *symbolP; -- int temp; -- -- /* Takes ".proc name,nargs". */ -- SKIP_WHITESPACE (); -- c = get_symbol_name (&name); -- p = input_line_pointer; -- symbolP = symbol_find_or_make (name); -- *p = c; -- SKIP_WHITESPACE_AFTER_NAME (); -- 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 (); -- } -- /* *symbol_get_obj (symbolP) = (signed char) temp; */ -- (void) symbolP; -- as_warn (_("unhandled: .proc %s,%d"), name, temp); -- demand_empty_rest_of_line (); --} -- --/* Handle the .set pseudo op. This is used to turn on and off most of -- the assembler features. */ -- --static void --s_sw_64_set (int x ATTRIBUTE_UNUSED) --{ -- char *name, ch, *s; -- int yesno = 1; -- -- SKIP_WHITESPACE (); -- -- ch = get_symbol_name (&name); -- s = name; -- if (s[0] == 'n' && s[1] == 'o') -- { -- yesno = 0; -- s += 2; -- } -- if (!strcmp ("reorder", s)) -- /* ignore */ ; -- else if (!strcmp ("at", s)) -- sw_64_noat_on = !yesno; -- else if (!strcmp ("macro", s)) -- sw_64_macros_on = yesno; -- else if (!strcmp ("move", s)) -- /* ignore */ ; -- else if (!strcmp ("volatile", s)) -- /* ignore */ ; -- else -- as_warn (_("Tried to .set unrecognized mode `%s'"), name); -- -- (void) restore_line_pointer (ch); -- demand_empty_rest_of_line (); --} -- --/* Handle the .base pseudo op. This changes the assembler's notion of -- the $gp register. */ -- --static void --s_sw_64_base (int ignore ATTRIBUTE_UNUSED) --{ -- SKIP_WHITESPACE (); -- -- if (*input_line_pointer == '$') -- { -- /* $rNN form. */ -- input_line_pointer++; -- if (*input_line_pointer == 'r') -- input_line_pointer++; -- } -- -- sw_64_gp_register = get_absolute_expression (); -- if (sw_64_gp_register < 0 || sw_64_gp_register > 31) -- { -- sw_64_gp_register = AXP_REG_GP; -- as_warn (_("Bad base register, using $%d."), sw_64_gp_register); -- } -- -- demand_empty_rest_of_line (); --} -- --/* 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_sw_64_align (int ignore ATTRIBUTE_UNUSED) --{ -- int align; -- char fill, *pfill; -- long max_alignment = 16; -- -- align = get_absolute_expression (); -- if (align > max_alignment) -- { -- align = max_alignment; -- as_bad (_("Alignment too large: %d. assumed"), align); -- } -- else if (align < 0) -- { -- as_warn (_("Alignment negative: 0 assumed")); -- align = 0; -- } -- -- if (*input_line_pointer == ',') -- { -- input_line_pointer++; -- fill = get_absolute_expression (); -- pfill = &fill; -- } -- else -- pfill = NULL; -- -- if (align != 0) -- { -- sw_64_auto_align_on = 1; -- sw_64_align (align, pfill, NULL, 1); -- } -- else -- { -- sw_64_auto_align_on = 0; -- } -- sw_64_insn_label = NULL; -- -- demand_empty_rest_of_line (); --} -- --/* Hook the normal string processor to reset known alignment. */ -- --static void --s_sw_64_stringer (int terminate) --{ -- sw_64_current_align = 0; -- sw_64_insn_label = NULL; -- stringer (8 + terminate); --} -- --/* Hook the normal space processing to reset known alignment. */ -- --static void --s_sw_64_space (int ignore) --{ -- sw_64_current_align = 0; -- sw_64_insn_label = NULL; -- s_space (ignore); --} -- --/* Hook into cons for auto-alignment. */ -- --void --sw_64_cons_align (int size) --{ -- int log_size; -- -- log_size = 0; -- while ((size >>= 1) != 0) -- ++log_size; -- -- if (sw_64_auto_align_on && sw_64_current_align < log_size) -- sw_64_align (log_size, (char *) NULL, sw_64_insn_label, 0); -- if (sw_64_current_align > log_size) -- sw_64_current_align = log_size; -- sw_64_insn_label = NULL; --} -- --/* Here come the .uword, .ulong, and .uquad explicitly unaligned -- pseudos. We just turn off auto-alignment and call down to cons. */ -- --static void --s_sw_64_ucons (int bytes) --{ -- int hold = sw_64_auto_align_on; -- sw_64_auto_align_on = 0; -- cons (bytes); -- sw_64_auto_align_on = hold; --} -- --/* Switch the working cpu type. */ -- --static void --s_sw_64_arch (int ignored ATTRIBUTE_UNUSED) --{ -- char *name, ch; -- const struct cpu_type *p; -- -- SKIP_WHITESPACE (); -- -- ch = get_symbol_name (&name); -- -- for (p = cpu_types; p->name; ++p) -- if (strcmp (name, p->name) == 0) -- { -- sw_64_target_name = p->name, sw_64_target = p->flags; -- goto found; -- } -- as_warn (_("Unknown CPU identifier `%s'"), name); -- --found: -- (void) restore_line_pointer (ch); -- demand_empty_rest_of_line (); --} -- --#ifdef DEBUG1 --/* print token expression with sw_64 specific extension. */ -- --static void --sw_64_print_token (FILE *f, const expressionS *exp) --{ -- switch (exp->X_op) -- { -- case O_cpregister: -- putc (',', f); -- /* FALLTHRU */ -- case O_pregister: -- putc ('(', f); -- { -- expressionS nexp = *exp; -- nexp.X_op = O_register; -- print_expr_1 (f, &nexp); -- } -- putc (')', f); -- break; -- default: -- print_expr_1 (f, exp); -- break; -- } --} --#endif -- --/* The target specific pseudo-ops which we support. */ -- --const pseudo_typeS md_pseudo_table[] = --{ --#ifdef OBJ_ECOFF -- {"comm", s_sw_64_comm, 0}, /* OSF1 compiler does this. */ -- {"rdata", s_sw_64_rdata, 0}, --#endif -- {"text", s_sw_64_text, 0}, -- {"data", s_sw_64_data, 0}, --#ifdef OBJ_ECOFF -- {"sdata", s_sw_64_sdata, 0}, --#endif --#ifdef OBJ_ELF -- {"section", s_sw_64_section, 0}, -- {"section.s", s_sw_64_section, 0}, -- {"sect", s_sw_64_section, 0}, -- {"sect.s", s_sw_64_section, 0}, --#endif --#ifdef OBJ_EVAX -- {"section", s_sw_64_section, 0}, -- {"literals", s_sw_64_literals, 0}, -- {"pdesc", s_sw_64_pdesc, 0}, -- {"name", s_sw_64_name, 0}, -- {"linkage", s_sw_64_linkage, 0}, -- {"code_address", s_sw_64_code_address, 0}, -- {"ent", s_sw_64_ent, 0}, -- {"frame", s_sw_64_frame, 0}, -- {"fp_save", s_sw_64_fp_save, 0}, -- {"mask", s_sw_64_mask, 0}, -- {"fmask", s_sw_64_fmask, 0}, -- {"end", s_sw_64_end, 0}, -- {"file", s_sw_64_file, 0}, -- {"rdata", s_sw_64_section, 1}, -- {"comm", s_sw_64_comm, 0}, -- {"link", s_sw_64_section, 3}, -- {"ctors", s_sw_64_section, 4}, -- {"dtors", s_sw_64_section, 5}, -- {"handler", s_sw_64_handler, 0}, -- {"handler_data", s_sw_64_handler, 1}, --#endif --#ifdef OBJ_ELF -- /* Frame related pseudos. */ -- {"ent", s_sw_64_ent, 0}, -- {"end", s_sw_64_end, 0}, -- {"mask", s_sw_64_mask, 0}, -- {"fmask", s_sw_64_mask, 1}, -- {"frame", s_sw_64_frame, 0}, -- {"prologue", s_sw_64_prologue, 0}, -- {"file", s_sw_64_file, 5}, -- {"loc", s_sw_64_loc, 9}, -- {"stabs", s_sw_64_stab, 's'}, -- {"stabn", s_sw_64_stab, 'n'}, -- {"usepv", s_sw_64_usepv, 0}, -- /* COFF debugging related pseudos. */ -- {"begin", s_sw_64_coff_wrapper, 0}, -- {"bend", s_sw_64_coff_wrapper, 1}, -- {"def", s_sw_64_coff_wrapper, 2}, -- {"dim", s_sw_64_coff_wrapper, 3}, -- {"endef", s_sw_64_coff_wrapper, 4}, -- {"scl", s_sw_64_coff_wrapper, 5}, -- {"tag", s_sw_64_coff_wrapper, 6}, -- {"val", s_sw_64_coff_wrapper, 7}, --#else --#ifdef OBJ_EVAX -- {"prologue", s_sw_64_prologue, 0}, --#else -- {"prologue", s_ignore, 0}, --#endif --#endif -- {"gprel32", s_sw_64_gprel32, 0}, -- {"t_floating", s_sw_64_float_cons, 'd'}, -- {"s_floating", s_sw_64_float_cons, 'f'}, -- {"f_floating", s_sw_64_float_cons, 'F'}, -- {"g_floating", s_sw_64_float_cons, 'G'}, -- {"d_floating", s_sw_64_float_cons, 'D'}, -- -- {"proc", s_sw_64_proc, 0}, -- {"aproc", s_sw_64_proc, 1}, -- {"set", s_sw_64_set, 0}, -- {"reguse", s_ignore, 0}, -- {"livereg", s_ignore, 0}, -- {"base", s_sw_64_base, 0}, /*??*/ -- {"option", s_ignore, 0}, -- {"aent", s_ignore, 0}, -- {"ugen", s_ignore, 0}, -- {"eflag", s_ignore, 0}, -- -- {"align", s_sw_64_align, 0}, -- {"double", s_sw_64_float_cons, 'd'}, -- {"float", s_sw_64_float_cons, 'f'}, -- {"single", s_sw_64_float_cons, 'f'}, -- {"ascii", s_sw_64_stringer, 0}, -- {"asciz", s_sw_64_stringer, 1}, -- {"string", s_sw_64_stringer, 1}, -- {"space", s_sw_64_space, 0}, -- {"skip", s_sw_64_space, 0}, -- {"zero", s_sw_64_space, 0}, -- --/* Unaligned data pseudos. */ -- {"uword", s_sw_64_ucons, 2}, -- {"ulong", s_sw_64_ucons, 4}, -- {"uquad", s_sw_64_ucons, 8}, -- --#ifdef OBJ_ELF --/* Dwarf wants these versions of unaligned. */ -- {"2byte", s_sw_64_ucons, 2}, -- {"4byte", s_sw_64_ucons, 4}, -- {"8byte", s_sw_64_ucons, 8}, --#endif -- --/* We don't do any optimizing, so we can safely ignore these. */ -- {"noalias", s_ignore, 0}, -- {"alias", s_ignore, 0}, -- -- {"arch", s_sw_64_arch, 0}, -- -- {NULL, 0, 0}, --}; -- --#ifdef OBJ_ECOFF -- --/* @@@ GP selection voodoo. All of this seems overly complicated and -- unnecessary; which is the primary reason it's for ECOFF only. */ -- --static inline void --maybe_set_gp (asection *sec) --{ -- bfd_vma vma; -- -- if (!sec) -- return; -- vma = bfd_section_vma (sec); -- if (vma && vma < sw_64_gp_value) -- sw_64_gp_value = vma; --} -- --static void --select_gp_value (void) --{ -- gas_assert (sw_64_gp_value == 0); -- -- /* Get minus-one in whatever width... */ -- sw_64_gp_value = 0; -- sw_64_gp_value--; -- -- /* Select the smallest VMA of these existing sections. */ -- maybe_set_gp (sw_64_lita_section); -- --/* @@ Will a simple 0x8000 work here? If not, why not? */ --#define GP_ADJUSTMENT (0x8000 - 0x10) -- -- sw_64_gp_value += GP_ADJUSTMENT; -- -- S_SET_VALUE (sw_64_gp_symbol, sw_64_gp_value); -- --#ifdef DEBUG1 -- printf (_("Chose GP value of %lx\n"), sw_64_gp_value); --#endif --} --#endif /* OBJ_ECOFF */ -- --#ifdef OBJ_ELF --/* Map 's' to SHF_SW_64_GPREL. */ -- --bfd_vma --sw_64_elf_section_letter (int letter, const char **ptr_msg) --{ -- if (letter == 's') -- return SHF_SW_64_GPREL; -- -- *ptr_msg = _("bad .section directive: want a,s,w,x,M,S,G,T in string"); -- return -1; --} -- --/* Map SHF_SW_64_GPREL to SEC_SMALL_DATA. */ -- --flagword --sw_64_elf_section_flags (flagword flags, bfd_vma attr, int type ATTRIBUTE_UNUSED) --{ -- if (attr & SHF_SW_64_GPREL) -- flags |= SEC_SMALL_DATA; -- return flags; --} --#endif /* OBJ_ELF */ -- --/* This is called from HANDLE_ALIGN in write.c. Fill in the contents -- of an rs_align_code fragment. */ -- --void --sw_64_handle_align (fragS *fragp) --{ -- static unsigned char const unop[4] = { 0x00, 0x00, 0xfe, 0xff }; -- static unsigned char const nopunop[8] = -- { -- 0x00, 0x00, 0xfe, 0xff, -- 0x00, 0x00, 0xfe, 0xff -- }; -- -- int bytes, fix; -- char *p; -- -- if (fragp->fr_type != rs_align_code) -- return; -- -- bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; -- p = fragp->fr_literal + fragp->fr_fix; -- fix = 0; -- -- if (bytes & 3) -- { -- fix = bytes & 3; -- memset (p, 0, fix); -- p += fix; -- bytes -= fix; -- } -- -- if (bytes & 4) -- { -- memcpy (p, unop, 4); -- p += 4; -- bytes -= 4; -- fix += 4; -- } -- -- memcpy (p, nopunop, 8); -- -- fragp->fr_fix += fix; -- fragp->fr_var = 8; --} -- --/* Public interface functions. */ -- --/* This function is called once, at assembler startup time. It sets -- 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 (void) --{ -- unsigned int i; -- -- /* Verify that X_op field is wide enough. */ -- { -- expressionS e; -- -- e.X_op = O_max; -- gas_assert (e.X_op == O_max); -- } -- -- if (! bfd_set_arch_mach (stdoutput, bfd_arch_sw_64, file_sw_64_arch)) -- as_warn (_("could not set architecture and machine")); -- -- /* Create the opcode hash table. */ -- sw_64_opcode_hash = str_htab_create (); -- -- for (i = 0; i < sw_64_num_opcodes;) -- { -- const char *name, *slash; -- -- name = sw_64_opcodes[i].name; -- if(str_hash_insert (sw_64_opcode_hash, name, &sw_64_opcodes[i], 0)) -- as_fatal (_("internal error: can't hash opcode `%s': %s"),name); -- -- /* Some opcodes include modifiers of various sorts with a "/mod" -- syntax, like the architecture manual suggests. However, for -- use with gcc at least, we also need access to those same opcodes -- without the "/". */ -- -- if ((slash = strchr (name, '/')) != NULL) -- { -- char *p = XNEWVEC (char, strlen (name)); -- -- memcpy (p, name, slash - name); -- strcpy (p + (slash - name), slash + 1); -- -- (void) str_hash_insert (sw_64_opcode_hash, p, &sw_64_opcodes[i], 0); -- /* Ignore failures -- the opcode table does duplicate some -- variants in different forms, like "hw_stq" and "hw_st/q". */ -- } -- -- while (++i < sw_64_num_opcodes -- && (sw_64_opcodes[i].name == name -- || !strcmp (sw_64_opcodes[i].name, name))) -- continue; -- } -- -- /* Create the macro hash table. */ -- sw_64_macro_hash = str_htab_create (); -- -- for (i = 0; i < sw_64_num_macros;) -- { -- const char *name, *retval; -- -- name = sw_64_macros[i].name; -- if(str_hash_insert (sw_64_macro_hash, name, &sw_64_macros[i], 0)) -- as_fatal (_("internal error: can't hash macro `%s': %s"), -- name); -- -- while (++i < sw_64_num_macros -- && (sw_64_macros[i].name == name -- || !strcmp (sw_64_macros[i].name, name))) -- continue; -- } -- -- /* Construct symbols for each of the registers. */ -- for (i = 0; i < 32; ++i) -- { -- char name[4]; -- -- sprintf (name, "$%d", i); -- sw_64_register_table[i] = symbol_create (name, reg_section, -- &zero_address_frag, i); -- } -- -- for (; i < 64; ++i) -- { -- char name[5]; -- -- sprintf (name, "$f%d", i - 32); -- sw_64_register_table[i] = symbol_create (name, reg_section, -- &zero_address_frag, i); -- } -- -- /* Create the special symbols and sections we'll be using. */ -- -- /* So .sbss will get used for tiny objects. */ -- bfd_set_gp_size (stdoutput, g_switch_value); -- --#ifdef OBJ_ECOFF -- create_literal_section (".lita", &sw_64_lita_section, &sw_64_lita_symbol); -- -- /* For handling the GP, create a symbol that won't be output in the -- symbol table. We'll edit it out of relocs later. */ -- sw_64_gp_symbol = symbol_create ("", sw_64_lita_section, -- &zero_address_frag, 0x8000); --#endif -- --#ifdef OBJ_EVAX -- create_literal_section (".link", &sw_64_link_section, &sw_64_link_symbol); --#endif -- --#ifdef OBJ_ELF -- if (ECOFF_DEBUGGING) -- { -- segT sec = subseg_new (".mdebug", (subsegT) 0); -- bfd_set_section_flags (sec, SEC_HAS_CONTENTS | SEC_READONLY); -- bfd_set_section_alignment (sec, 3); -- } --#endif -- -- /* Create literal lookup hash table. */ -- sw_64_literal_hash = str_htab_create (); -- -- subseg_set (text_section, 0); --} -- --/* The public interface to the instruction assembler. */ -- --void --md_assemble (char *str) --{ -- /* Current maximum is 13. */ -- char opname[32]; -- expressionS tok[MAX_INSN_ARGS]; -- int ntok, trunclen; -- size_t opnamelen; -- -- /* Split off the opcode. */ -- opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/0123456789"); -- trunclen = (opnamelen < sizeof (opname) - 1 -- ? opnamelen -- : sizeof (opname) - 1); -- memcpy (opname, str, trunclen); -- opname[trunclen] = '\0'; -- --if (!strcmp (opname, "ldw_inc") || !strcmp (opname, "ldl_inc") -- || !strcmp (opname, "ldw_dec") || !strcmp (opname, "ldl_dec") -- || !strcmp (opname, "ldw_set") || !strcmp (opname, "ldl_set")) -- { -- if (!strcmp (sw_64_target_name, "sw6a")) -- as_warn (_("The %s is only 6A instruction, you better change it!"), opname); -- if (!strcmp (sw_64_target_name, "sw6b")) -- as_bad (_("sw6b don't have \"%s\" !!"),(char *)opname); -- } -- -- /* Tokenize the rest of the line. */ -- if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0) -- { -- if (ntok != TOKENIZE_ERROR_REPORT) -- as_bad (_("syntax error")); -- -- return; -- } -- --#define REG_NUM 64 -- int i, j; -- char float_insn[REG_NUM][REG_NUM] = -- { "fadds", "faddd", "fsubs", "fsubd", "fmuls", "fmuld", -- "fdivs", "fdivd", "fsqrts", "fsqrtd", "fcmpeq", -- "fcmple", "fcmplt", "fcmpun", "fcvtsd", "fcvtds", -- "fcvtdl_g", "fcvtdl_p", "fcvtdl_z", "fcvtdl_n", -- "fcvtdl", "fcvtlw", "fcvtls", "fcvtld", -- "fmas","fmad","fmss","fmsd","fnmas","fnmad","fnmss","fnmsd", -- "vadds","vaddd","vsubs","vsubd","vmuls","vmuld","vdivs","vdivd", -- "vsqrts","vsqrtd","vmas","vmad","vmss","vmsd","vnmas","vnmad", -- "vnmss","vnmsd","vfcmpeq","vfcmple", "vfcmplt", "vfcmpun" -- }; -- if (!sw_64_flag_nocheck_samereg) -- { -- for (i = 0; i < REG_NUM; i++) -- { -- if (strcmp (opname, float_insn[i]) == 0) -- { -- for (j = 0; j < ntok-1; j++) -- { -- if (tok[j].X_add_number == tok[ntok-1].X_add_number ) -- as_bad (_("SRC and DST register of '%s' must be different!"), opname); -- } -- } -- } -- } -- -- /* Finish it off. */ -- assemble_tokens (opname, tok, ntok, sw_64_macros_on); --} -- --/* Round up a section's size to the appropriate boundary. */ -- --valueT --md_section_align (segT seg, valueT size) --{ -- int align = bfd_section_alignment (seg); -- valueT mask = ((valueT) 1 << align) - 1; -- -- return (size + mask) & ~mask; --} -- --/* 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. */ -- --const char * --md_atof (int type, char *litP, int *sizeP) --{ -- extern const char *vax_md_atof (int, char *, int *); -- -- switch (type) -- { -- /* VAX floats. */ -- case 'G': -- /* vax_md_atof() doesn't like "G" for some reason. */ -- type = 'g'; -- /* Fall through. */ -- case 'F': -- case 'D': -- return vax_md_atof (type, litP, sizeP); -- -- default: -- return ieee_md_atof (type, litP, sizeP, FALSE); -- } --} -- --/* Take care of the target-specific command-line options. */ -- --int --md_parse_option (int c, const char *arg) --{ -- switch (c) -- { -- case 'F': -- sw_64_nofloats_on = 1; -- break; -- -- case OPTION_32ADDR: -- sw_64_addr32_on = 1; -- break; -- -- case 'g': -- sw_64_debug = 1; -- break; -- -- case 'G': -- g_switch_value = atoi (arg); -- break; -- -- case 'm': -- { -- const struct cpu_type *p; -- -- for (p = cpu_types; p->name; ++p) -- if (strcmp (arg, p->name) == 0) -- { -- sw_64_target_name = p->name, sw_64_target = p->flags; -- goto found; -- } -- as_warn (_("Unknown CPU identifier `%s'"), arg); -- found:; -- } -- break; -- --#ifdef OBJ_EVAX -- case '+': /* For g++. Hash any name > 63 chars long. */ -- sw_64_flag_hash_long_names = 1; -- break; -- -- case 'H': /* Show new symbol after hash truncation. */ -- sw_64_flag_show_after_trunc = 1; -- break; -- -- case 'h': /* For gnu-c/vax compatibility. */ -- break; -- -- case OPTION_REPLACE: -- sw_64_flag_replace = 1; -- break; -- -- case OPTION_NOREPLACE: -- sw_64_flag_replace = 0; -- break; --#endif -- -- case OPTION_RELAX: -- sw_64_flag_relax = 1; -- break; -- --#ifdef OBJ_ELF -- case OPTION_MDEBUG: -- sw_64_flag_mdebug = 1; -- break; -- case OPTION_NO_MDEBUG: -- sw_64_flag_mdebug = 0; -- break; --#endif -- -- case OPTION_NOCHECK_SAMEREG: -- sw_64_flag_nocheck_samereg = 1; -- break; -- -- default: -- return 0; -- } -- -- return 1; --} -- --/* Print a description of the command-line options that we accept. */ -- --void --md_show_usage (FILE *stream) --{ -- fputs (_("\ --Sw_64 options:\n\ ---32addr treat addresses as 32-bit values\n\ ---F lack floating point instructions support\n\ ---msw6a | -msw6b\n\ -- these variants include PALcode opcodes\n"), -- stream); --#ifdef OBJ_EVAX -- fputs (_("\ --VMS options:\n\ ---+ encode (don't truncate) names longer than 64 characters\n\ ---H show new symbol after hash truncation\n\ ---replace/-noreplace enable or disable the optimization of procedure calls\n"), -- stream); --#endif --} -- --/* Decide from what point a pc-relative relocation is relative to, -- relative to the pc-relative fixup. Er, relatively speaking. */ -- --long --md_pcrel_from (fixS *fixP) --{ -- valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; -- -- switch (fixP->fx_r_type) -- { -- case BFD_RELOC_23_PCREL_S2: -- case BFD_RELOC_SW_64_HINT: -- case BFD_RELOC_SW_64_BRSGP: -- return addr + 4; -- default: -- return addr; -- } --} -- --/* Attempt to simplify or even eliminate a fixup. The return value is -- ignored; perhaps it was once meaningful, but now it is historical. -- To indicate that a fixup has been eliminated, set fixP->fx_done. -- -- For ELF, here it is that we transform the GPDISP_HI16 reloc we used -- internally into the GPDISP reloc used externally. We had to do -- this so that we'd have the GPDISP_LO16 reloc as a tag to compute -- the distance to the "ldi" instruction for setting the addend to -- GPDISP. */ -- --void --md_apply_fix (fixS *fixP, valueT * valP, segT seg) --{ -- char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where; -- valueT value = * valP; -- unsigned image, size; -- -- switch (fixP->fx_r_type) -- { -- /* The GPDISP relocations are processed internally with a symbol -- referring to the current function's section; 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_SW_64_GPDISP_HI16: -- { -- fixS *next = fixP->fx_next; -- -- /* With user-specified !gpdisp relocations, we can be missing -- the matching LO16 reloc. We will have already issued an -- error message. */ -- if (next) -- fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where -- - fixP->fx_frag->fr_address - fixP->fx_where); -- -- value = (value - sign_extend_16 (value)) >> 16; -- } --#ifdef OBJ_ELF -- fixP->fx_r_type = BFD_RELOC_SW_64_GPDISP; --#endif -- goto do_reloc_gp; -- -- case BFD_RELOC_SW_64_GPDISP_LO16: -- value = sign_extend_16 (value); -- fixP->fx_offset = 0; --#ifdef OBJ_ELF -- fixP->fx_done = 1; --#endif -- -- do_reloc_gp: -- fixP->fx_addsy = section_symbol (seg); -- md_number_to_chars (fixpos, value, 2); -- break; -- case BFD_RELOC_8: -- if (fixP->fx_pcrel) -- fixP->fx_r_type = BFD_RELOC_8_PCREL; -- size = 1; -- goto do_reloc_xx; -- case BFD_RELOC_16: -- if (fixP->fx_pcrel) -- fixP->fx_r_type = BFD_RELOC_16_PCREL; -- size = 2; -- goto do_reloc_xx; -- -- case BFD_RELOC_32: -- if (fixP->fx_pcrel) -- fixP->fx_r_type = BFD_RELOC_32_PCREL; -- size = 4; -- goto do_reloc_xx; -- -- case BFD_RELOC_64: -- if (fixP->fx_pcrel) -- fixP->fx_r_type = BFD_RELOC_64_PCREL; -- size = 8; -- -- do_reloc_xx: -- if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) -- { -- md_number_to_chars (fixpos, value, size); -- goto done; -- } -- return; -- --#ifdef OBJ_ECOFF -- case BFD_RELOC_GPREL32: -- gas_assert (fixP->fx_subsy == sw_64_gp_symbol); -- fixP->fx_subsy = 0; -- /* FIXME: inherited this obliviousness of `value' -- why? */ -- md_number_to_chars (fixpos, -sw_64_gp_value, 4); -- break; --#else -- case BFD_RELOC_GPREL32: --#endif -- case BFD_RELOC_GPREL16: -- case BFD_RELOC_SW_64_GPREL_HI16: -- case BFD_RELOC_SW_64_GPREL_LO16: -- return; -- -- case BFD_RELOC_23_PCREL_S2: -- if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) -- { -- image = bfd_getl32 (fixpos); -- image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF); -- goto write_done; -- } -- return; -- -- case BFD_RELOC_SW_64_HINT: -- if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) -- { -- image = bfd_getl32 (fixpos); -- /* SW6 use 16 bit hint disp,not 14. */ -- image = (image & ~0xFFFF) | ((value >> 2) & 0xFFFF); -- goto write_done; -- } -- return; -- --#ifdef OBJ_ELF -- case BFD_RELOC_SW_64_BRSGP: -- return; -- -- case BFD_RELOC_SW_64_TLSGD: -- case BFD_RELOC_SW_64_TLSLDM: -- case BFD_RELOC_SW_64_GOTDTPREL16: -- case BFD_RELOC_SW_64_DTPREL_HI16: -- case BFD_RELOC_SW_64_DTPREL_LO16: -- case BFD_RELOC_SW_64_DTPREL16: -- case BFD_RELOC_SW_64_GOTTPREL16: -- case BFD_RELOC_SW_64_TPREL_HI16: -- case BFD_RELOC_SW_64_TPREL_LO16: -- case BFD_RELOC_SW_64_TPREL16: -- if (fixP->fx_addsy) -- S_SET_THREAD_LOCAL (fixP->fx_addsy); -- return; --#endif -- --#ifdef OBJ_ECOFF -- case BFD_RELOC_SW_64_LITERAL: -- md_number_to_chars (fixpos, value, 2); -- return; --#endif -- case BFD_RELOC_SW_64_ELF_LITERAL: -- case BFD_RELOC_SW_64_ELF_LITERAL_GOT: -- case BFD_RELOC_SW_64_LITUSE: -- case BFD_RELOC_SW_64_LINKAGE: -- case BFD_RELOC_SW_64_CODEADDR: -- return; -- --#ifdef OBJ_EVAX -- case BFD_RELOC_SW_64_NOP: -- value -= (8 + 4); /* PC-relative, base is call+4. */ -- -- /* From B.4.5.2 of the OpenVMS Linker Utility Manual: -- "Finally, the ETIR$C_STC_BSR command passes the same address -- as ETIR$C_STC_NOP (so that they will fail or succeed together), -- and the same test is done again." */ -- if (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) -- { -- fixP->fx_addnumber = -value; -- return; -- } -- if (value + (1u << 22) >= (1u << 23)) -- goto done; -- else -- { -- /* Change to a nop. */ -- image = 0x47FF041F; -- goto write_done; -- } -- -- case BFD_RELOC_SW_64_LDA: -- /* fixup_segment sets fixP->fx_addsy to NULL when it can pre-compute -- the value for an O_subtract. */ -- if (fixP->fx_addsy -- && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) -- { -- fixP->fx_addnumber = symbol_get_bfdsym (fixP->fx_subsy)->value; -- return; -- } -- if (value + (1u << 15) >= (1u << 16)) -- goto done; -- else -- { -- /* Change to an ldi. */ -- image = 0x237B0000 | (value & 0xFFFF); -- goto write_done; -- } -- -- case BFD_RELOC_SW_64_BSR: -- case BFD_RELOC_SW_64_BOH: -- value -= 4; /* PC-relative, base is call+4. */ -- -- /* See comment in the BFD_RELOC_SW_64_NOP case above. */ -- if (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) -- { -- fixP->fx_addnumber = -value; -- return; -- } -- if (value + (1u << 22) >= (1u << 23)) -- { -- /* Out of range. */ -- if (fixP->fx_r_type == BFD_RELOC_SW_64_BOH) -- { -- /* Add a hint. */ -- image = bfd_getl32(fixpos); -- image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF); -- goto write_done; -- } -- goto done; -- } -- else -- { -- /* Change to a branch. */ -- image = 0xD3400000 | ((value >> 2) & 0x1FFFFF); -- goto write_done; -- } --#endif -- -- case BFD_RELOC_VTABLE_INHERIT: -- case BFD_RELOC_VTABLE_ENTRY: -- return; -- -- default: -- { -- const struct sw_64_operand *operand; -- -- if ((int) fixP->fx_r_type >= 0) -- as_fatal (_("unhandled relocation type %s"), -- bfd_get_reloc_code_name (fixP->fx_r_type)); -- -- gas_assert (-(int) fixP->fx_r_type < (int) sw_64_num_operands); -- operand = &sw_64_operands[-(int) fixP->fx_r_type]; -- -- /* The rest of these fixups only exist internally during symbol -- resolution and have no representation in the object file. -- Therefore they must be completely resolved as constants. */ -- -- if (fixP->fx_addsy != 0 -- && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section) -- as_bad_where (fixP->fx_file, fixP->fx_line, -- _("non-absolute expression in constant field")); -- -- image = bfd_getl32 (fixpos); -- image = insert_operand (image, operand, (offsetT) value, -- fixP->fx_file, fixP->fx_line); -- } -- goto write_done; -- } -- -- if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0) -- return; -- else -- { -- as_warn_where (fixP->fx_file, fixP->fx_line, -- _("type %d reloc done?\n"), (int) fixP->fx_r_type); -- goto done; -- } -- --write_done: -- md_number_to_chars (fixpos, image, 4); -- --done: -- fixP->fx_done = 1; --} -- --/* Look for a register name in the given symbol. */ -- --symbolS * --md_undefined_symbol (char *name) --{ -- if (*name == '$') -- { -- int is_float = 0, num; -- -- switch (*++name) -- { -- case 'f': -- if (name[1] == 'p' && name[2] == '\0') -- return sw_64_register_table[AXP_REG_FP]; -- is_float = 32; -- /* Fall through. */ -- -- case 'r': -- if (!ISDIGIT (*++name)) -- break; -- /* Fall through. */ -- -- case '0': case '1': case '2': case '3': case '4': -- case '5': case '6': case '7': case '8': case '9': -- if (name[1] == '\0') -- num = name[0] - '0'; -- else if (name[0] != '0' && ISDIGIT (name[1]) && name[2] == '\0') -- { -- num = (name[0] - '0') * 10 + name[1] - '0'; -- if (num >= 32) -- break; -- } -- else -- break; -- -- if (!sw_64_noat_on && (num + is_float) == AXP_REG_AT) -- as_warn (_("Used $at without \".set noat\"")); -- return sw_64_register_table[num + is_float]; -- -- case 'a': -- if (name[1] == 't' && name[2] == '\0') -- { -- if (!sw_64_noat_on) -- as_warn (_("Used $at without \".set noat\"")); -- return sw_64_register_table[AXP_REG_AT]; -- } -- break; -- -- case 'g': -- if (name[1] == 'p' && name[2] == '\0') -- return sw_64_register_table[sw_64_gp_register]; -- break; -- -- case 's': -- if (name[1] == 'p' && name[2] == '\0') -- return sw_64_register_table[AXP_REG_SP]; -- break; -- } -- } -- return NULL; --} -- --#ifdef OBJ_ECOFF --/* @@@ Magic ECOFF bits. */ -- --void --sw_64_frob_ecoff_data (void) --{ -- select_gp_value (); -- /* $zero and $f31 are read-only. */ -- sw_64_gprmask &= ~1; -- sw_64_fprmask &= ~1; --} --#endif -- --/* Hook to remember a recently defined label so that the auto-align -- code can adjust the symbol after we know what alignment will be -- required. */ -- --void --sw_64_define_label (symbolS *sym) --{ -- sw_64_insn_label = sym; --#ifdef OBJ_ELF -- dwarf2_emit_label (sym); --#endif --} -- --/* Return true if we must always emit a reloc for a type and false if -- there is some hope of resolving it at assembly time. */ -- --int --sw_64_force_relocation (fixS *f) --{ -- if (sw_64_flag_relax) -- return 1; -- -- switch (f->fx_r_type) -- { -- case BFD_RELOC_SW_64_GPDISP_HI16: -- case BFD_RELOC_SW_64_GPDISP_LO16: -- case BFD_RELOC_SW_64_GPDISP: -- case BFD_RELOC_SW_64_LITERAL: -- case BFD_RELOC_SW_64_ELF_LITERAL: -- case BFD_RELOC_SW_64_ELF_LITERAL_GOT: -- case BFD_RELOC_SW_64_LITUSE: -- case BFD_RELOC_GPREL16: -- case BFD_RELOC_GPREL32: -- case BFD_RELOC_SW_64_GPREL_HI16: -- case BFD_RELOC_SW_64_GPREL_LO16: -- case BFD_RELOC_SW_64_LINKAGE: -- case BFD_RELOC_SW_64_CODEADDR: -- case BFD_RELOC_SW_64_BRSGP: -- case BFD_RELOC_SW_64_TLSGD: -- case BFD_RELOC_SW_64_TLSLDM: -- case BFD_RELOC_SW_64_GOTDTPREL16: -- case BFD_RELOC_SW_64_DTPREL_HI16: -- case BFD_RELOC_SW_64_DTPREL_LO16: -- case BFD_RELOC_SW_64_DTPREL16: -- case BFD_RELOC_SW_64_GOTTPREL16: -- case BFD_RELOC_SW_64_TPREL_HI16: -- case BFD_RELOC_SW_64_TPREL_LO16: -- case BFD_RELOC_SW_64_TPREL16: --#ifdef OBJ_EVAX -- case BFD_RELOC_SW_64_NOP: -- case BFD_RELOC_SW_64_BSR: -- case BFD_RELOC_SW_64_LDA: -- case BFD_RELOC_SW_64_BOH: --#endif -- return 1; -- -- default: -- break; -- } -- -- return generic_force_reloc (f); --} -- --/* Return true if we can partially resolve a relocation now. */ -- --int --sw_64_fix_adjustable (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_SW_64_GPDISP_HI16: -- case BFD_RELOC_SW_64_GPDISP_LO16: -- case BFD_RELOC_SW_64_GPDISP: -- return 0; -- -- case BFD_RELOC_SW_64_LITERAL: -- case BFD_RELOC_SW_64_ELF_LITERAL: -- case BFD_RELOC_SW_64_ELF_LITERAL_GOT: -- case BFD_RELOC_SW_64_LITUSE: -- case BFD_RELOC_SW_64_LINKAGE: -- case BFD_RELOC_SW_64_CODEADDR: -- return 1; -- -- case BFD_RELOC_VTABLE_ENTRY: -- case BFD_RELOC_VTABLE_INHERIT: -- return 0; -- -- case BFD_RELOC_GPREL16: -- case BFD_RELOC_GPREL32: -- case BFD_RELOC_SW_64_GPREL_HI16: -- case BFD_RELOC_SW_64_GPREL_LO16: -- case BFD_RELOC_23_PCREL_S2: -- case BFD_RELOC_16: -- case BFD_RELOC_32: -- case BFD_RELOC_64: -- case BFD_RELOC_SW_64_HINT: -- return 1; -- -- case BFD_RELOC_SW_64_TLSGD: -- case BFD_RELOC_SW_64_TLSLDM: -- case BFD_RELOC_SW_64_GOTDTPREL16: -- case BFD_RELOC_SW_64_DTPREL_HI16: -- case BFD_RELOC_SW_64_DTPREL_LO16: -- case BFD_RELOC_SW_64_DTPREL16: -- case BFD_RELOC_SW_64_GOTTPREL16: -- case BFD_RELOC_SW_64_TPREL_HI16: -- case BFD_RELOC_SW_64_TPREL_LO16: -- case BFD_RELOC_SW_64_TPREL16: -- /* ??? No idea why we can't return a reference to .tbss+10, but -- we're preventing this in the other assemblers. Follow for now. */ -- return 0; -- --#ifdef OBJ_ELF -- case BFD_RELOC_SW_64_BRSGP: -- /* If we have a BRSGP reloc to a local symbol, adjust it to BRADDR and -- let it get resolved at assembly time. */ -- { -- symbolS *sym = f->fx_addsy; -- const char *name; -- int offset = 0; -- -- if (generic_force_reloc (f)) -- return 0; -- -- switch (S_GET_OTHER (sym) & STO_SW_64_STD_GPLOAD) -- { -- case STO_SW_64_NOPV: -- break; -- case STO_SW_64_STD_GPLOAD: -- offset = 8; -- break; -- default: -- if (S_IS_LOCAL (sym)) -- name = ""; -- else -- name = S_GET_NAME (sym); -- as_bad_where (f->fx_file, f->fx_line, -- _("!samegp reloc against symbol without .prologue: %s"), -- name); -- break; -- } -- f->fx_r_type = BFD_RELOC_23_PCREL_S2; -- f->fx_offset += offset; -- return 1; -- } --#endif --#ifdef OBJ_EVAX -- case BFD_RELOC_SW_64_NOP: -- case BFD_RELOC_SW_64_BSR: -- case BFD_RELOC_SW_64_LDA: -- case BFD_RELOC_SW_64_BOH: -- return 1; --#endif -- -- default: -- return 1; -- } --} -- --/* Generate the BFD reloc to be stuck in the object file from the -- fixup used internally in the assembler. */ -- --arelent * --tc_gen_reloc (asection *sec ATTRIBUTE_UNUSED, -- fixS *fixp) --{ -- arelent *reloc; -- -- reloc = XNEW (arelent); -- reloc->sym_ptr_ptr = XNEW (asymbol *); -- *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); -- reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; -- -- /* Make sure none of our internal relocations make it this far. -- They'd better have been fully resolved by this point. */ -- gas_assert ((int) fixp->fx_r_type > 0); -- -- reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); -- if (reloc->howto == NULL) -- { -- as_bad_where (fixp->fx_file, fixp->fx_line, -- _("cannot represent `%s' relocation in object file"), -- bfd_get_reloc_code_name (fixp->fx_r_type)); -- return NULL; -- } -- -- 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)); -- -- gas_assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); -- -- reloc->addend = fixp->fx_offset; -- --#ifdef OBJ_ECOFF -- /* Fake out bfd_perform_relocation. sigh. */ -- /* ??? Better would be to use the special_function hook. */ -- if (fixp->fx_r_type == BFD_RELOC_SW_64_LITERAL) -- reloc->addend = -sw_64_gp_value; --#endif -- --#ifdef OBJ_EVAX -- switch (fixp->fx_r_type) -- { -- struct evax_private_udata_struct *udata; -- const char *pname; -- int pname_len; -- -- case BFD_RELOC_SW_64_LINKAGE: -- /* Copy the linkage index. */ -- reloc->addend = fixp->fx_addnumber; -- break; -- -- case BFD_RELOC_SW_64_NOP: -- case BFD_RELOC_SW_64_BSR: -- case BFD_RELOC_SW_64_LDA: -- case BFD_RELOC_SW_64_BOH: -- pname = symbol_get_bfdsym (fixp->fx_addsy)->name; -- -- /* We need the non-suffixed name of the procedure. Beware that -- the main symbol might be equated so look it up and take its name. */ -- pname_len = strlen (pname); -- if (pname_len > 4 && strcmp (pname + pname_len - 4, "..en") == 0) -- { -- symbolS *sym; -- char *my_pname = xmemdup0 (pname, pname_len - 4); -- sym = symbol_find (my_pname); -- free (my_pname); -- if (sym == NULL) -- abort (); -- -- while (symbol_equated_reloc_p (sym)) -- { -- symbolS *n = symbol_get_value_expression (sym)->X_add_symbol; -- -- /* We must avoid looping, as that can occur with a badly -- written program. */ -- if (n == sym) -- break; -- sym = n; -- } -- pname = symbol_get_bfdsym (sym)->name; -- } -- -- udata = XNEW (struct evax_private_udata_struct); -- udata->enbsym = symbol_get_bfdsym (fixp->fx_addsy); -- udata->bsym = symbol_get_bfdsym (fixp->tc_fix_data.info->psym); -- udata->origname = (char *)pname; -- udata->lkindex = ((struct evax_private_udata_struct *) -- symbol_get_bfdsym (fixp->tc_fix_data.info->sym)->udata.p)->lkindex; -- reloc->sym_ptr_ptr = (void *)udata; -- reloc->addend = fixp->fx_addnumber; -- -- default: -- break; -- } --#endif -- -- return reloc; --} -- --/* Parse a register name off of the input_line and return a register -- number. Gets md_undefined_symbol above to do the register name -- matching for us. -- -- Only called as a part of processing the ECOFF .frame directive. */ -- --int --tc_get_register (int frame ATTRIBUTE_UNUSED) --{ -- int framereg = AXP_REG_SP; -- -- SKIP_WHITESPACE (); -- if (*input_line_pointer == '$') -- { -- char *s; -- char c = get_symbol_name (&s); -- symbolS *sym = md_undefined_symbol (s); -- -- *strchr (s, '\0') = c; -- if (sym && (framereg = S_GET_VALUE (sym)) <= 31) -- goto found; -- } -- as_warn (_("frame reg expected, using $%d."), framereg); -- --found: -- note_gpreg (framereg); -- return framereg; --} -- --/* This is called before the symbol table is processed. In order to -- work with gcc when using mips-tfile, we must keep all local labels. -- However, in other cases, we want to discard them. If we were -- called with -g, but we didn't see any debugging information, it may -- mean that gcc is smuggling debugging information through to -- mips-tfile, in which case we must generate all local labels. */ -- --#ifdef OBJ_ECOFF -- --void --sw_64_frob_file_before_adjust (void) --{ -- if (sw_64_debug != 0 -- && ! ecoff_debugging_seen) -- flag_keep_locals = 1; --} -- --#endif /* OBJ_ECOFF */ -- --static const struct sw_64_cpu_info * --sw_64_parse_cpu (const char *option, const char *cpu_string) --{ -- if (strcasecmp (cpu_string, "sw6a") == 0) -- return sw_64_cpu_info_from_isa (ISA_SW6A); -- -- if (strcasecmp (cpu_string, "sw6b") == 0) -- return sw_64_cpu_info_from_isa (ISA_SW6B); -- -- if (strcasecmp (cpu_string, "default") == 0) -- return 0; --} -- --/* Set up globals to generate code for the ISA or processor -- * described by INFO. */ -- --static void --sw_64_set_architecture (const struct sw_64_cpu_info *info) --{ -- if (info != 0) -- { -- file_sw_64_arch = info->cpu; -- sw_64_opts.arch = info->cpu; -- sw_64_opts.isa = info->isa; -- } --} -- --void --sw_64_after_parse_args (void) --{ -- const struct sw_64_cpu_info *arch_info = 0; -- const struct sw_64_cpu_info *tune_info = 0; -- -- const struct cpu_type *p; -- if (sw_64_target_name == NULL) -- { -- for (p = cpu_types; p->name; ++p) -- if (strcmp (SW_CPU_STRING_DEFAULT, p->name) == 0) -- { -- sw_64_target_name = p->name, sw_64_target = p->flags; -- goto found; -- } -- as_bad (_("Unknown CPU default name `%s'"), SW_CPU_STRING_DEFAULT); --found: -- arch_info = sw_64_parse_cpu ("default CPU", SW_CPU_STRING_DEFAULT); -- gas_assert (arch_info); -- } -- -- if (strcmp (sw_64_target_name, "sw6a") == 0) -- arch_info = sw_64_parse_cpu ("default CPU", "sw6a"); -- else if (strcmp (sw_64_target_name, "sw6b") == 0) -- arch_info = sw_64_parse_cpu ("default CPU", "sw6b"); -- else -- as_bad (_("Unkonwn CPU target name: `%s'"), sw_64_target_name); -- sw_64_set_architecture (arch_info); --} -- --static const struct sw_64_cpu_info sw_64_cpu_info_table[] = --{ -- /* Entries for generic ISAs */ -- { "sw6a", SW_64_CPU_IS_ISA, 0, ISA_SW6A, CPU_SW6A }, -- { "sw6b", SW_64_CPU_IS_ISA, 0, ISA_SW6B, CPU_SW6B }, -- { NULL, 0, 0, 0, 0 } --}; -- --/* Return the canonical processor information for ISA (a member of the -- * ISA_SW_64* enumeration). */ -- --static const struct sw_64_cpu_info * --sw_64_cpu_info_from_isa (int isa) --{ -- int i; -- -- for (i = 0; sw_64_cpu_info_table[i].name != NULL; i++) -- if ((sw_64_cpu_info_table[i].flags & SW_64_CPU_IS_ISA) -- && isa == sw_64_cpu_info_table[i].isa) -- return (&sw_64_cpu_info_table[i]); -- -- return NULL; --} -- --/* Some special processing for a SW_64 ELF file. */ -- --void --sw_64_elf_final_processing (void) --{ --#ifdef GIT_REVISION -- elf_elfheader (stdoutput)->e_flags |= GIT_REVISION; --#else -- if (file_sw_64_arch == 4) -- elf_elfheader (stdoutput)->e_flags |= EF_SW6A_FLGAS; -- else if (file_sw_64_arch == 8) -- elf_elfheader (stdoutput)->e_flags |= EF_SW6B_FLGAS; -- else -- elf_elfheader (stdoutput)->e_flags |= 0; --#endif --} -- -- --/* The Sw_64 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. */ --#include "config/atof-vax.c" ---- b/gas/config/tc-sw_64.h -+++ /dev/null -@@ -1,197 +0,0 @@ --/* This file is tc-sw_64.h -- Copyright (C) 1994-2018 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA -- 02110-1301, USA. */ -- --#define TC_SW_64 -- --#define TARGET_BYTES_BIG_ENDIAN 0 -- --#define WORKING_DOT_WORD -- --#define TARGET_ARCH bfd_arch_sw_64 -- --#ifdef TE_FreeBSD --#define ELF_TARGET_FORMAT "elf64-sw_64-freebsd" --#endif --#ifndef ELF_TARGET_FORMAT --#define ELF_TARGET_FORMAT "elf64-sw_64" --#endif -- --#define TARGET_FORMAT (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ -- ? "ecoff-littlesw_64" \ -- : OUTPUT_FLAVOR == bfd_target_elf_flavour \ -- ? ELF_TARGET_FORMAT \ -- : OUTPUT_FLAVOR == bfd_target_evax_flavour \ -- ? "vms-sw_64" \ -- : "unknown-format") -- --#define NEED_LITERAL_POOL --#define REPEAT_CONS_EXPRESSIONS -- --struct fix; --struct sw_64_reloc_tag; -- --extern int sw_64_force_relocation (struct fix *); --extern int sw_64_fix_adjustable (struct fix *); -- --extern unsigned long sw_64_gprmask, sw_64_fprmask; --extern valueT sw_64_gp_value; -- --#define TC_FORCE_RELOCATION(FIX) sw_64_force_relocation (FIX) --#define tc_fix_adjustable(FIX) sw_64_fix_adjustable (FIX) --#define RELOC_REQUIRES_SYMBOL -- --/* Values passed to md_apply_fix don't include the symbol value. */ --#define MD_APPLY_SYM_VALUE(FIX) 0 -- --#define md_convert_frag(b,s,f) as_fatal ("sw_64 convert_frag\n") --#define md_estimate_size_before_relax(f,s) \ -- (as_fatal ("estimate_size_before_relax called"),1) --#define md_operand(x) -- --#ifdef OBJ_EVAX --#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1 -- --#define tc_canonicalize_symbol_name evax_shorten_name -- --#define TC_CONS_FIX_NEW(FRAG,OFF,LEN,EXP,RELOC) \ -- (void) RELOC, \ -- fix_new_exp (FRAG, OFF, (int)LEN, EXP, 0, \ -- LEN == 2 ? BFD_RELOC_16 \ -- : LEN == 4 ? BFD_RELOC_32 \ -- : LEN == 8 ? BFD_RELOC_64 \ -- : BFD_RELOC_SW_64_LINKAGE); --#endif -- --#ifdef OBJ_EVAX --#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) (P2VAR) = 3 --#else --#define TC_IMPLICIT_LCOMM_ALIGNMENT(size, align) \ -- do \ -- { \ -- align = 0; \ -- if (size > 1) \ -- { \ -- addressT temp = 1; \ -- while ((size & temp) == 0) \ -- ++align, temp <<= 1; \ -- } \ -- } \ -- while (0) --#endif -- --#define md_number_to_chars number_to_chars_littleendian -- --extern int tc_get_register (int); --extern void sw_64_frob_ecoff_data (void); -- --#define tc_frob_label(sym) sw_64_define_label (sym) --extern void sw_64_define_label (symbolS *); -- --#define md_cons_align(nbytes) sw_64_cons_align (nbytes) --extern void sw_64_cons_align (int); -- --#define HANDLE_ALIGN(fragp) sw_64_handle_align (fragp) --extern void sw_64_handle_align (struct frag *); -- --#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4 + 8) -- --#ifdef OBJ_ECOFF --#define tc_frob_file_before_adjust() sw_64_frob_file_before_adjust () --extern void sw_64_frob_file_before_adjust (void); -- --#define TC_VALIDATE_FIX_SUB(FIX, SEG) \ -- ((md_register_arithmetic || (SEG) != reg_section) \ -- && ((FIX)->fx_r_type == BFD_RELOC_GPREL32 \ -- || (FIX)->fx_r_type == BFD_RELOC_GPREL16)) --#endif -- --#define md_after_parse_args() sw_64_after_parse_args() --extern void sw_64_after_parse_args (void); -- --#define elf_tc_final_processing sw_64_elf_final_processing --extern void sw_64_elf_final_processing (void); -- --#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs. */ -- --#ifdef OBJ_ELF --#define md_elf_section_letter sw_64_elf_section_letter --extern bfd_vma sw_64_elf_section_letter (int, const char **); --#define md_elf_section_flags sw_64_elf_section_flags --extern flagword sw_64_elf_section_flags (flagword, bfd_vma, int); --#endif -- --/* Whether to add support for explicit !relocation_op!sequence_number. At the -- moment, only do this for ELF, though ECOFF could use it as well. */ -- --#ifdef OBJ_ELF --#define RELOC_OP_P --#endif -- --#ifndef OBJ_EVAX --/* Before the relocations are written, reorder them, so that user -- supplied !lituse relocations follow the appropriate !literal -- relocations. Also convert the gas-internal relocations to the -- appropriate linker relocations. */ --#define tc_frob_file_before_fix() sw_64_before_fix () --extern void sw_64_before_fix (void); --#endif -- --#ifdef OBJ_ELF --#define md_end sw_64_elf_md_end --extern void sw_64_elf_md_end (void); --#endif -- --/* New fields for supporting explicit relocations (such as !literal to mark -- where a pointer is loaded from the global table, and !lituse_base to track -- all of the normal uses of that pointer). */ -- --#define TC_FIX_TYPE struct sw_64_fix_tag -- --struct sw_64_fix_tag --{ -- struct fix *next_reloc; /* Next !lituse or !gpdisp. */ -- struct sw_64_reloc_tag *info; /* Other members with same sequence. */ --}; -- --/* Initialize the TC_FIX_TYPE field. */ --#define TC_INIT_FIX_DATA(FIX) \ --do { \ -- FIX->tc_fix_data.next_reloc = NULL; \ -- FIX->tc_fix_data.info = NULL; \ --} while (0) -- --/* Work with DEBUG5 to print fields in tc_fix_type. */ --#define TC_FIX_DATA_PRINT(STREAM, FIX) \ --do { \ -- if (FIX->tc_fix_data.info) \ -- fprintf (STREAM, "\tinfo = 0x%lx, next_reloc = 0x%lx\n", \ -- (long) FIX->tc_fix_data.info, \ -- (long) FIX->tc_fix_data.next_reloc); \ --} while (0) -- --#define TARGET_USE_CFIPOP 1 -- --#define tc_cfi_frame_initial_instructions sw_64_cfi_frame_initial_instructions --extern void sw_64_cfi_frame_initial_instructions (void); -- --#define DWARF2_LINE_MIN_INSN_LENGTH 4 --#define DWARF2_DEFAULT_RETURN_COLUMN 26 --#define DWARF2_CIE_DATA_ALIGNMENT (-8) ---- b/gas/test -+++ /dev/null -@@ -1,350 +0,0 @@ --# Copyright (C) 2012-2021 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 3 of the License, or --# (at your option) any later version. --# --# This program is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --# GNU General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. -- --# --# elf tests --# -- --proc run_elf_list_test { name suffix opts readelf_opts readelf_pipe } { -- global READELF -- global srcdir subdir -- set testname "elf $name list" -- set file $srcdir/$subdir/$name -- gas_run ${name}.s "$opts -o dump.o" ">&dump.out" -- if { ![string match "" $opts] -- && [regexp_diff "dump.out" "${file}.l"] } then { -- fail $testname -- verbose "output is [file_contents "dump.out"]" 2 -- return -- } -- send_log "$READELF $readelf_opts dump.o $readelf_pipe > dump.out\n" -- set status [gas_host_run "$READELF $readelf_opts dump.o" ">readelf.out"] -- if { [lindex $status 0] != 0 || ![string match "" [lindex $status 1]] } then { -- send_log "[lindex $status 1]\n" -- fail $testname -- return -- } -- catch "exec cat readelf.out $readelf_pipe > dump.out\n" comp_output -- if ![string match "" $comp_output] then { -- send_log "$comp_output\n" -- fail $testname -- return -- } -- verbose_eval {[file_contents "dump.out"]} 3 -- if { [regexp_diff "dump.out" "${file}.e${suffix}"] } then { -- fail $testname -- verbose "output is [file_contents "dump.out"]" 2 -- return -- } -- pass $testname --} -- --# We're testing bits in obj-elf -- don't run on anything else. --if { [is_elf_format] } then { -- if { [is_elf_unused_section_symbols ] } { -- set target_machine -unused -- } else { -- set target_machine "" -- } -- set dump_opts "" -- if {[istarget "arc*-*-*"]} { -- set target_machine -arc -- } -- if {[istarget "arm*-*-*"]} { -- set target_machine -arm -- } -- if {[istarget "avr*-*-*"]} { -- set dump_opts {{as -mno-link-relax}} -- } -- if {[istarget "csky*-*-*"]} { -- set target_machine -csky -- } -- if {[istarget "m32r*-*-*"]} then { -- set target_machine -m32r -- } -- if {[istarget "mips*-*-*"]} then { -- set target_machine -mips -- } -- if {[istarget "msp430-*-*"]} then { -- set target_machine -msp430 -- } -- if {[istarget "pru-*-*"]} { -- set dump_opts {{as -mno-link-relax}} -- } -- if {[istarget "riscv*-*-*"]} then { -- set target_machine -riscv -- set dump_opts {{as -mno-relax}} -- } -- if {[istarget "rl78-*-*"]} then { -- set target_machine -rl78 -- } -- if {[istarget "rx-*-*"]} then { -- set target_machine -rx -- } -- if {[istarget "score-*-*"]} then { -- set target_machine -score -- } -- if {[istarget "tic6x-*-*"]} then { -- set target_machine -tic6x -- } -- if {[istarget "v850*-*-*"]} then { -- set target_machine -v850 -- } -- if {[istarget "xtensa*-*-*"]} then { -- set target_machine -xtensa -- set dump_opts {{as --no-link-relax}} -- } -- -- # The MN10300 and Xtensa ports disable the assembler's call frame -- # optimization because it interfers with link-time relaxation of -- # function prologues. -- if {![istarget "mn10300-*-*"] -- && ![istarget "am3*-*-*"] -- && ![istarget "xtensa*-*-*"] -- && ![istarget "msp430*-*-*"] -- && ![istarget "nds32*-*-*"] -- && ![istarget "am3*-*-*"]} then { -- run_dump_test "ehopt0" -- } -- switch -glob $target_triplet { -- m68k-*-* - -- m68[03]??-*-* { -- run_dump_test "file" { { as "--defsym m68k=1" } } -- } -- mmix-*-* { -- run_dump_test "file" { { as "--defsym mmix=1" } } -- } -- xtensa*-*-* { -- run_dump_test "file" { { as "--rename-section file.s=file.c" } } -- } -- default { -- run_dump_test "file" -- } -- } -- run_dump_test "file-2" -- setup_xfail "nds32*-*-*" -- run_dump_test "group0a" -- run_dump_test "group0b" -- run_dump_test "group0c" -- run_dump_test "group1a" -- run_dump_test "group1b" -- run_dump_test "group2" -- run_dump_test "group3" -- -- run_dump_test "attach-1" -- run_dump_test "attach-err" -- -- switch -glob $target_triplet { -- hppa64*-*-hpux* { } -- riscv*-*-* { } -- default { -- run_dump_test "groupautoa" -- } -- } -- switch -glob $target_triplet { -- hppa64*-*-hpux* { } -- riscv*-*-* { } -- xtensa*-*-* { } -- default { -- run_dump_test "groupautob" -- } -- } -- switch -glob $target_triplet { -- alpha*-*-* { } -- am3*-*-* { } -- *c54x*-*-* { } -- cr16*-*-* { } -- crx*-*-* { } -- h8300-*-* { } -- hppa*-*-* { } -- iq2000*-*-* { } -- mips*-*-* { } -- mn10200-*-* { } -- mn10300-*-* { } -- msp43*-*-* { } -- rl78-*-* { } -- riscv*-*-* { } -- rx-*-* { } -- loongarch*-*-* { } -- default { -- # The next test can fail if the target does not convert fixups -- # against ordinary symbols into relocations against section symbols. -- # This is usually revealed by the error message: -- # symbol `sym' required but not present -- setup_xfail "m681*-*-*" "m68hc*-*-*" "xgate-*-*" "vax-*-*" "sw_64*-*-*" -- run_dump_test redef -- setup_xfail "sw_64*-*-*" -- run_dump_test equ-reloc -- } -- } -- run_dump_test "pseudo" -- run_dump_test "section0" -- run_dump_test "section1" -- # The h8300 port issues a warning message for -- # new sections created without atrributes. -- if {! [istarget "h8300-*-*"]} then { -- set as_flags "-al --generate-missing-build-notes=no" -- switch -glob $target_triplet { -- i*86-*-* - -- x86_64-*-* { -- set as_flags "$as_flags -mx86-used-note=no" -- } -- riscv*-*-* { -- set as_flags "$as_flags -march-attr" -- } -- } -- run_elf_list_test "section2" "$target_machine" "$as_flags" "-s" "" -- } -- run_dump_test "section3" -- run_dump_test "section4" -- if {! [istarget "h8300-*-*"] && ! [istarget "rx-*-*"]} then { -- # The h8300 port issues a warning message for -- # new sections created without atrributes. -- # The RX port does not complain about changing the attributes of the -- # .data and .bss sections since it does not use those names. -- run_elf_list_test "section5" "" "-al -Z" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\"" -- } -- run_dump_test "struct" -- if {! [istarget "alpha*-*-*"] && ! [istarget "sw_64*-*-*"]} then { -- # The alpha port uses .set for state, e.g. nomacro. -- run_dump_test "symtab" -- } -- run_dump_test "symver" -- run_dump_test "pr21661" -- run_dump_test "pr14891" -- -- # No indirect functions on non-GNU targets. -- # The Visium and MSP set the ELF header's OSABI field to ELFOSABI_STANDALONE. -- # The non-eabi ARM ports sets it to ELFOSABI_ARM. -- # So for these targets we cannot include an IFUNC symbol type -- # in the symbol type test. -- # We also need to exclude targets that do not support unique objects. -- if { [istarget "*-*-hpux*"] -- || [istarget "arm*-*-*"] -- || [istarget "mips*-*-*"] -- || [istarget "msp*-*-*"] -- || [istarget "visium-*-*"] -- || ![supports_gnu_unique] -- } then { -- # hppa64 has a non-standard common directive -- if { ![istarget "hppa64*-*-hpux*"] } then { -- run_elf_list_test "type-noifunc" "" "" "-s" "| grep \"1 *\\\[FONTC\\\]\"" -- } -- } else { -- if {! [istarget "sw_64*-*-*"] } then { -- run_dump_test ifunc-1 -- } -- run_elf_list_test "type" "" "" "-s" "| grep \"1 *\\\[FIONTCU\\\]\"" -- run_elf_list_test "type-2" "" "--warn" "-s" "| grep \"0 *\\\[FIONT\\\]\"" -- } -- -- run_dump_test "section6" -- run_dump_test "section7" -- run_dump_test "section8" -- run_dump_test "section9" -- run_dump_test "section10" -- run_dump_test "section11" -- run_dump_test "section12a" -- run_dump_test "section12b" -- run_dump_test "section13" -- run_dump_test "section14" -- run_dump_test "section15" -- run_dump_test "section16a" -- run_dump_test "section16b" -- run_dump_test "section17" -- run_dump_test "section18" -- run_dump_test "section19" -- run_dump_test "section20" -- run_dump_test "section21" -- run_dump_test "section22" -- run_dump_test "section23a" -- run_dump_test "section23b" -- run_dump_test "section24a" -- run_dump_test "section24b" -- run_dump_test "section25" -- run_dump_test "section26" -- run_dump_test "section27" -- run_dump_test "section28" -- run_dump_test "section29" -- run_dump_test "sh-link-zero" -- run_dump_test "dwarf2-1" $dump_opts -- run_dump_test "dwarf2-2" $dump_opts -- run_dump_test "dwarf2-3" $dump_opts -- run_dump_test "dwarf2-4" $dump_opts -- run_dump_test "dwarf2-5" $dump_opts -- run_dump_test "dwarf2-6" $dump_opts -- run_dump_test "dwarf2-7" $dump_opts -- run_dump_test "dwarf2-8" $dump_opts -- run_dump_test "dwarf2-9" $dump_opts -- run_dump_test "dwarf2-10" $dump_opts -- run_dump_test "dwarf2-11" $dump_opts -- run_dump_test "dwarf2-12" $dump_opts -- run_dump_test "dwarf2-13" $dump_opts -- run_dump_test "dwarf2-14" $dump_opts -- run_dump_test "dwarf2-15" $dump_opts -- run_dump_test "dwarf2-16" $dump_opts -- run_dump_test "dwarf2-17" $dump_opts -- run_dump_test "dwarf2-18" $dump_opts -- run_dump_test "dwarf2-19" $dump_opts -- run_dump_test "dwarf2-20" $dump_opts -- run_dump_test "dwarf2-21" $dump_opts -- run_dump_test "dwarf-5-file0" $dump_opts -- run_dump_test "dwarf-5-file0-2" $dump_opts -- run_dump_test "dwarf-5-file0-3" $dump_opts -- run_dump_test "dwarf-5-dir0" $dump_opts -- run_dump_test "dwarf-5-loc0" $dump_opts -- run_dump_test "dwarf-4-cu" $dump_opts -- run_dump_test "dwarf-5-cu" $dump_opts -- run_dump_test "dwarf-5-nop-for-line-table" $dump_opts -- run_dump_test "pr25917" -- run_dump_test "bss" -- run_dump_test "bad-bss" -- run_dump_test "bad-section-flag" -- run_dump_test "bad-size" -- run_dump_test "bad-group" -- run_dump_test "pr27355" -- -- if { ![istarget "sw_64*-*-*"]} then { -- run_dump_test "syms" -- } -- run_dump_test "startof" -- -- run_dump_test "missing-build-notes" -- -- run_dump_test "common1" -- run_dump_test "common2" -- -- # hpux has a non-standard common directive. -- if { ![istarget "*-*-hpux*"] } then { -- run_dump_test "common3a" -- run_dump_test "common3b" -- run_dump_test "common4a" -- run_dump_test "common4b" -- } -- -- if { ![istarget "sw_64*-*-*"] && ![istarget "*-*-hpux*"]} then { -- run_dump_test "common5a" -- run_dump_test "common5b" -- run_dump_test "common5c" -- run_dump_test "common5d" -- } -- -- run_dump_test "strtab" -- -- run_dump_test "bignums" -- run_dump_test "section-symbol-redef" -- run_dump_test "pr27228" --} ---- b/gas/testsuite/gas/elf/elf.exp.2.37 -+++ /dev/null -@@ -1,344 +0,0 @@ --# Copyright (C) 2012-2021 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 3 of the License, or --# (at your option) any later version. --# --# This program is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --# GNU General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. -- --# --# elf tests --# -- --proc run_elf_list_test { name suffix opts readelf_opts readelf_pipe } { -- global READELF -- global srcdir subdir -- set testname "elf $name list" -- set file $srcdir/$subdir/$name -- gas_run ${name}.s "$opts -o dump.o" ">&dump.out" -- if { ![string match "" $opts] -- && [regexp_diff "dump.out" "${file}.l"] } then { -- fail $testname -- verbose "output is [file_contents "dump.out"]" 2 -- return -- } -- send_log "$READELF $readelf_opts dump.o $readelf_pipe > dump.out\n" -- set status [gas_host_run "$READELF $readelf_opts dump.o" ">readelf.out"] -- if { [lindex $status 0] != 0 || ![string match "" [lindex $status 1]] } then { -- send_log "[lindex $status 1]\n" -- fail $testname -- return -- } -- catch "exec cat readelf.out $readelf_pipe > dump.out\n" comp_output -- if ![string match "" $comp_output] then { -- send_log "$comp_output\n" -- fail $testname -- return -- } -- verbose_eval {[file_contents "dump.out"]} 3 -- if { [regexp_diff "dump.out" "${file}.e${suffix}"] } then { -- fail $testname -- verbose "output is [file_contents "dump.out"]" 2 -- return -- } -- pass $testname --} -- --# We're testing bits in obj-elf -- don't run on anything else. --if { [is_elf_format] } then { -- if { [is_elf_unused_section_symbols ] } { -- set target_machine -unused -- } else { -- set target_machine "" -- } -- set dump_opts "" -- if {[istarget "arc*-*-*"]} { -- set target_machine -arc -- } -- if {[istarget "arm*-*-*"]} { -- set target_machine -arm -- } -- if {[istarget "avr*-*-*"]} { -- set dump_opts {{as -mno-link-relax}} -- } -- if {[istarget "csky*-*-*"]} { -- set target_machine -csky -- } -- if {[istarget "m32r*-*-*"]} then { -- set target_machine -m32r -- } -- if {[istarget "mips*-*-*"]} then { -- set target_machine -mips -- } -- if {[istarget "msp430-*-*"]} then { -- set target_machine -msp430 -- } -- if {[istarget "pru-*-*"]} { -- set dump_opts {{as -mno-link-relax}} -- } -- if {[istarget "riscv*-*-*"]} then { -- set target_machine -riscv -- set dump_opts {{as -mno-relax}} -- } -- if {[istarget "rl78-*-*"]} then { -- set target_machine -rl78 -- } -- if {[istarget "rx-*-*"]} then { -- set target_machine -rx -- } -- if {[istarget "score-*-*"]} then { -- set target_machine -score -- } -- if {[istarget "tic6x-*-*"]} then { -- set target_machine -tic6x -- } -- if {[istarget "v850*-*-*"]} then { -- set target_machine -v850 -- } -- if {[istarget "xtensa*-*-*"]} then { -- set target_machine -xtensa -- set dump_opts {{as --no-link-relax}} -- } -- -- # The MN10300 and Xtensa ports disable the assembler's call frame -- # optimization because it interfers with link-time relaxation of -- # function prologues. -- if {![istarget "mn10300-*-*"] -- && ![istarget "am3*-*-*"] -- && ![istarget "xtensa*-*-*"] -- && ![istarget "msp430*-*-*"] -- && ![istarget "nds32*-*-*"] -- && ![istarget "am3*-*-*"]} then { -- run_dump_test "ehopt0" -- } -- switch -glob $target_triplet { -- m68k-*-* - -- m68[03]??-*-* { -- run_dump_test "file" { { as "--defsym m68k=1" } } -- } -- mmix-*-* { -- run_dump_test "file" { { as "--defsym mmix=1" } } -- } -- xtensa*-*-* { -- run_dump_test "file" { { as "--rename-section file.s=file.c" } } -- } -- default { -- run_dump_test "file" -- } -- } -- run_dump_test "file-2" -- setup_xfail "nds32*-*-*" -- run_dump_test "group0a" -- run_dump_test "group0b" -- run_dump_test "group0c" -- run_dump_test "group1a" -- run_dump_test "group1b" -- run_dump_test "group2" -- run_dump_test "group3" -- -- run_dump_test "attach-1" -- run_dump_test "attach-err" -- -- switch -glob $target_triplet { -- hppa64*-*-hpux* { } -- riscv*-*-* { } -- default { -- run_dump_test "groupautoa" -- } -- } -- switch -glob $target_triplet { -- hppa64*-*-hpux* { } -- riscv*-*-* { } -- xtensa*-*-* { } -- default { -- run_dump_test "groupautob" -- } -- } -- switch -glob $target_triplet { -- alpha*-*-* { } -- am3*-*-* { } -- *c54x*-*-* { } -- cr16*-*-* { } -- crx*-*-* { } -- h8300-*-* { } -- hppa*-*-* { } -- iq2000*-*-* { } -- mips*-*-* { } -- mn10200-*-* { } -- mn10300-*-* { } -- msp43*-*-* { } -- rl78-*-* { } -- riscv*-*-* { } -- rx-*-* { } -- default { -- # The next test can fail if the target does not convert fixups -- # against ordinary symbols into relocations against section symbols. -- # This is usually revealed by the error message: -- # symbol `sym' required but not present -- setup_xfail "m681*-*-*" "m68hc*-*-*" "xgate-*-*" "vax-*-*" "sw_64*-*-*" -- run_dump_test redef -- setup_xfail "sw_64*-*-*" -- run_dump_test equ-reloc -- } -- } -- run_dump_test "pseudo" -- run_dump_test "section0" -- run_dump_test "section1" -- # The h8300 port issues a warning message for -- # new sections created without atrributes. -- if {! [istarget "h8300-*-*"]} then { -- set as_flags "-al --generate-missing-build-notes=no" -- switch -glob $target_triplet { -- i*86-*-* - -- x86_64-*-* { -- set as_flags "$as_flags -mx86-used-note=no" -- } -- riscv*-*-* { -- set as_flags "$as_flags -march-attr" -- } -- } -- run_elf_list_test "section2" "$target_machine" "$as_flags" "-s" "" -- } -- run_dump_test "section3" -- run_dump_test "section4" -- if {! [istarget "h8300-*-*"] && ! [istarget "rx-*-*"]} then { -- # The h8300 port issues a warning message for -- # new sections created without atrributes. -- # The RX port does not complain about changing the attributes of the -- # .data and .bss sections since it does not use those names. -- run_elf_list_test "section5" "" "-al -Z" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\"" -- } -- run_dump_test "struct" -- if {! [istarget "alpha*-*-*"] && ! [istarget "sw_64*-*-*"]} then { -- # The alpha port uses .set for state, e.g. nomacro. -- run_dump_test "symtab" -- } -- run_dump_test "symver" -- run_dump_test "pr21661" -- run_dump_test "pr14891" -- -- # No indirect functions on non-GNU targets. -- # The Visium and MSP set the ELF header's OSABI field to ELFOSABI_STANDALONE. -- # The non-eabi ARM ports sets it to ELFOSABI_ARM. -- # So for these targets we cannot include an IFUNC symbol type -- # in the symbol type test. -- # We also need to exclude targets that do not support unique objects. -- if { [istarget "*-*-hpux*"] -- || [istarget "arm*-*-*"] -- || [istarget "mips*-*-*"] -- || [istarget "msp*-*-*"] -- || [istarget "visium-*-*"] -- || ![supports_gnu_unique] -- } then { -- # hppa64 has a non-standard common directive -- if { ![istarget "hppa64*-*-hpux*"] } then { -- run_elf_list_test "type-noifunc" "" "" "-s" "| grep \"1 *\\\[FONTC\\\]\"" -- } -- } else { -- if {! [istarget "sw_64*-*-*"] } then { -- run_dump_test ifunc-1 -- } -- run_elf_list_test "type" "" "" "-s" "| grep \"1 *\\\[FIONTCU\\\]\"" -- run_elf_list_test "type-2" "" "--warn" "-s" "| grep \"0 *\\\[FIONT\\\]\"" -- } -- -- run_dump_test "section6" -- run_dump_test "section7" -- run_dump_test "section8" -- run_dump_test "section9" -- run_dump_test "section10" -- run_dump_test "section11" -- run_dump_test "section12a" -- run_dump_test "section12b" -- run_dump_test "section13" -- run_dump_test "section14" -- run_dump_test "section15" -- run_dump_test "section16a" -- run_dump_test "section16b" -- run_dump_test "section17" -- run_dump_test "section18" -- run_dump_test "section19" -- run_dump_test "section20" -- run_dump_test "section21" -- run_dump_test "section22" -- run_dump_test "section23a" -- run_dump_test "section23b" -- run_dump_test "section24a" -- run_dump_test "section24b" -- run_dump_test "section25" -- run_dump_test "section26" -- run_dump_test "section27" -- run_dump_test "section28" -- run_dump_test "section29" -- run_dump_test "sh-link-zero" -- run_dump_test "dwarf2-1" $dump_opts -- run_dump_test "dwarf2-2" $dump_opts -- run_dump_test "dwarf2-3" $dump_opts -- run_dump_test "dwarf2-4" $dump_opts -- run_dump_test "dwarf2-5" $dump_opts -- run_dump_test "dwarf2-6" $dump_opts -- run_dump_test "dwarf2-7" $dump_opts -- run_dump_test "dwarf2-8" $dump_opts -- run_dump_test "dwarf2-9" $dump_opts -- run_dump_test "dwarf2-10" $dump_opts -- run_dump_test "dwarf2-11" $dump_opts -- run_dump_test "dwarf2-12" $dump_opts -- run_dump_test "dwarf2-13" $dump_opts -- run_dump_test "dwarf2-14" $dump_opts -- run_dump_test "dwarf2-15" $dump_opts -- run_dump_test "dwarf2-16" $dump_opts -- run_dump_test "dwarf2-17" $dump_opts -- run_dump_test "dwarf2-18" $dump_opts -- run_dump_test "dwarf2-19" $dump_opts -- run_dump_test "dwarf2-20" $dump_opts -- run_dump_test "dwarf-5-file0" $dump_opts -- run_dump_test "dwarf-4-cu" $dump_opts -- run_dump_test "dwarf-5-cu" $dump_opts -- run_dump_test "dwarf-5-nop-for-line-table" $dump_opts -- run_dump_test "pr25917" -- run_dump_test "bss" -- run_dump_test "bad-bss" -- run_dump_test "bad-section-flag" -- run_dump_test "bad-size" -- run_dump_test "bad-group" -- run_dump_test "pr27355" -- -- if { ![istarget "sw_64*-*-*"]} then { -- run_dump_test "syms" -- } -- run_dump_test "startof" -- -- run_dump_test "missing-build-notes" -- -- run_dump_test "common1" -- run_dump_test "common2" -- -- # hpux has a non-standard common directive. -- if { ![istarget "*-*-hpux*"] } then { -- run_dump_test "common3a" -- run_dump_test "common3b" -- run_dump_test "common4a" -- run_dump_test "common4b" -- } -- -- if { ![istarget "sw_64*-*-*"] && ![istarget "*-*-hpux*"]} then { -- run_dump_test "common5a" -- run_dump_test "common5b" -- run_dump_test "common5c" -- run_dump_test "common5d" -- } -- -- run_dump_test "strtab" -- -- run_dump_test "bignums" -- run_dump_test "section-symbol-redef" -- run_dump_test "pr27228" --} ---- b/gas/testsuite/gas/elf/elf.exp.ok -+++ /dev/null -@@ -1,350 +0,0 @@ --# Copyright (C) 2012-2021 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 3 of the License, or --# (at your option) any later version. --# --# This program is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --# GNU General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. -- --# --# elf tests --# -- --proc run_elf_list_test { name suffix opts readelf_opts readelf_pipe } { -- global READELF -- global srcdir subdir -- set testname "elf $name list" -- set file $srcdir/$subdir/$name -- gas_run ${name}.s "$opts -o dump.o" ">&dump.out" -- if { ![string match "" $opts] -- && [regexp_diff "dump.out" "${file}.l"] } then { -- fail $testname -- verbose "output is [file_contents "dump.out"]" 2 -- return -- } -- send_log "$READELF $readelf_opts dump.o $readelf_pipe > dump.out\n" -- set status [gas_host_run "$READELF $readelf_opts dump.o" ">readelf.out"] -- if { [lindex $status 0] != 0 || ![string match "" [lindex $status 1]] } then { -- send_log "[lindex $status 1]\n" -- fail $testname -- return -- } -- catch "exec cat readelf.out $readelf_pipe > dump.out\n" comp_output -- if ![string match "" $comp_output] then { -- send_log "$comp_output\n" -- fail $testname -- return -- } -- verbose_eval {[file_contents "dump.out"]} 3 -- if { [regexp_diff "dump.out" "${file}.e${suffix}"] } then { -- fail $testname -- verbose "output is [file_contents "dump.out"]" 2 -- return -- } -- pass $testname --} -- --# We're testing bits in obj-elf -- don't run on anything else. --if { [is_elf_format] } then { -- if { [is_elf_unused_section_symbols ] } { -- set target_machine -unused -- } else { -- set target_machine "" -- } -- set dump_opts "" -- if {[istarget "arc*-*-*"]} { -- set target_machine -arc -- } -- if {[istarget "arm*-*-*"]} { -- set target_machine -arm -- } -- if {[istarget "avr*-*-*"]} { -- set dump_opts {{as -mno-link-relax}} -- } -- if {[istarget "csky*-*-*"]} { -- set target_machine -csky -- } -- if {[istarget "m32r*-*-*"]} then { -- set target_machine -m32r -- } -- if {[istarget "mips*-*-*"]} then { -- set target_machine -mips -- } -- if {[istarget "msp430-*-*"]} then { -- set target_machine -msp430 -- } -- if {[istarget "pru-*-*"]} { -- set dump_opts {{as -mno-link-relax}} -- } -- if {[istarget "riscv*-*-*"]} then { -- set target_machine -riscv -- set dump_opts {{as -mno-relax}} -- } -- if {[istarget "rl78-*-*"]} then { -- set target_machine -rl78 -- } -- if {[istarget "rx-*-*"]} then { -- set target_machine -rx -- } -- if {[istarget "score-*-*"]} then { -- set target_machine -score -- } -- if {[istarget "tic6x-*-*"]} then { -- set target_machine -tic6x -- } -- if {[istarget "v850*-*-*"]} then { -- set target_machine -v850 -- } -- if {[istarget "xtensa*-*-*"]} then { -- set target_machine -xtensa -- set dump_opts {{as --no-link-relax}} -- } -- -- # The MN10300 and Xtensa ports disable the assembler's call frame -- # optimization because it interfers with link-time relaxation of -- # function prologues. -- if {![istarget "mn10300-*-*"] -- && ![istarget "am3*-*-*"] -- && ![istarget "xtensa*-*-*"] -- && ![istarget "msp430*-*-*"] -- && ![istarget "nds32*-*-*"] -- && ![istarget "am3*-*-*"]} then { -- run_dump_test "ehopt0" -- } -- switch -glob $target_triplet { -- m68k-*-* - -- m68[03]??-*-* { -- run_dump_test "file" { { as "--defsym m68k=1" } } -- } -- mmix-*-* { -- run_dump_test "file" { { as "--defsym mmix=1" } } -- } -- xtensa*-*-* { -- run_dump_test "file" { { as "--rename-section file.s=file.c" } } -- } -- default { -- run_dump_test "file" -- } -- } -- run_dump_test "file-2" -- setup_xfail "nds32*-*-*" -- run_dump_test "group0a" -- run_dump_test "group0b" -- run_dump_test "group0c" -- run_dump_test "group1a" -- run_dump_test "group1b" -- run_dump_test "group2" -- run_dump_test "group3" -- -- run_dump_test "attach-1" -- run_dump_test "attach-err" -- -- switch -glob $target_triplet { -- hppa64*-*-hpux* { } -- riscv*-*-* { } -- default { -- run_dump_test "groupautoa" -- } -- } -- switch -glob $target_triplet { -- hppa64*-*-hpux* { } -- riscv*-*-* { } -- xtensa*-*-* { } -- default { -- run_dump_test "groupautob" -- } -- } -- switch -glob $target_triplet { -- alpha*-*-* { } -- am3*-*-* { } -- *c54x*-*-* { } -- cr16*-*-* { } -- crx*-*-* { } -- h8300-*-* { } -- hppa*-*-* { } -- iq2000*-*-* { } -- mips*-*-* { } -- mn10200-*-* { } -- mn10300-*-* { } -- msp43*-*-* { } -- rl78-*-* { } -- riscv*-*-* { } -- rx-*-* { } -- loongarch*-*-* { } -- default { -- # The next test can fail if the target does not convert fixups -- # against ordinary symbols into relocations against section symbols. -- # This is usually revealed by the error message: -- # symbol `sym' required but not present -- setup_xfail "m681*-*-*" "m68hc*-*-*" "xgate-*-*" "vax-*-*" "sw_64*-*-*" -- run_dump_test redef -- setup_xfail "sw_64*-*-*" -- run_dump_test equ-reloc -- } -- } -- run_dump_test "pseudo" -- run_dump_test "section0" -- run_dump_test "section1" -- # The h8300 port issues a warning message for -- # new sections created without atrributes. -- if {! [istarget "h8300-*-*"]} then { -- set as_flags "-al --generate-missing-build-notes=no" -- switch -glob $target_triplet { -- i*86-*-* - -- x86_64-*-* { -- set as_flags "$as_flags -mx86-used-note=no" -- } -- riscv*-*-* { -- set as_flags "$as_flags -march-attr" -- } -- } -- run_elf_list_test "section2" "$target_machine" "$as_flags" "-s" "" -- } -- run_dump_test "section3" -- run_dump_test "section4" -- if {! [istarget "h8300-*-*"] && ! [istarget "rx-*-*"]} then { -- # The h8300 port issues a warning message for -- # new sections created without atrributes. -- # The RX port does not complain about changing the attributes of the -- # .data and .bss sections since it does not use those names. -- run_elf_list_test "section5" "" "-al -Z" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\"" -- } -- run_dump_test "struct" -- if {! [istarget "alpha*-*-*"] && ! [istarget "sw_64*-*-*"]} then { -- # The alpha port uses .set for state, e.g. nomacro. -- run_dump_test "symtab" -- } -- run_dump_test "symver" -- run_dump_test "pr21661" -- run_dump_test "pr14891" -- -- # No indirect functions on non-GNU targets. -- # The Visium and MSP set the ELF header's OSABI field to ELFOSABI_STANDALONE. -- # The non-eabi ARM ports sets it to ELFOSABI_ARM. -- # So for these targets we cannot include an IFUNC symbol type -- # in the symbol type test. -- # We also need to exclude targets that do not support unique objects. -- if { [istarget "*-*-hpux*"] -- || [istarget "arm*-*-*"] -- || [istarget "mips*-*-*"] -- || [istarget "msp*-*-*"] -- || [istarget "visium-*-*"] -- || ![supports_gnu_unique] -- } then { -- # hppa64 has a non-standard common directive -- if { ![istarget "hppa64*-*-hpux*"] } then { -- run_elf_list_test "type-noifunc" "" "" "-s" "| grep \"1 *\\\[FONTC\\\]\"" -- } -- } else { -- if {! [istarget "sw_64*-*-*"] } then { -- run_dump_test ifunc-1 -- } -- run_elf_list_test "type" "" "" "-s" "| grep \"1 *\\\[FIONTCU\\\]\"" -- run_elf_list_test "type-2" "" "--warn" "-s" "| grep \"0 *\\\[FIONT\\\]\"" -- } -- -- run_dump_test "section6" -- run_dump_test "section7" -- run_dump_test "section8" -- run_dump_test "section9" -- run_dump_test "section10" -- run_dump_test "section11" -- run_dump_test "section12a" -- run_dump_test "section12b" -- run_dump_test "section13" -- run_dump_test "section14" -- run_dump_test "section15" -- run_dump_test "section16a" -- run_dump_test "section16b" -- run_dump_test "section17" -- run_dump_test "section18" -- run_dump_test "section19" -- run_dump_test "section20" -- run_dump_test "section21" -- run_dump_test "section22" -- run_dump_test "section23a" -- run_dump_test "section23b" -- run_dump_test "section24a" -- run_dump_test "section24b" -- run_dump_test "section25" -- run_dump_test "section26" -- run_dump_test "section27" -- run_dump_test "section28" -- run_dump_test "section29" -- run_dump_test "sh-link-zero" -- run_dump_test "dwarf2-1" $dump_opts -- run_dump_test "dwarf2-2" $dump_opts -- run_dump_test "dwarf2-3" $dump_opts -- run_dump_test "dwarf2-4" $dump_opts -- run_dump_test "dwarf2-5" $dump_opts -- run_dump_test "dwarf2-6" $dump_opts -- run_dump_test "dwarf2-7" $dump_opts -- run_dump_test "dwarf2-8" $dump_opts -- run_dump_test "dwarf2-9" $dump_opts -- run_dump_test "dwarf2-10" $dump_opts -- run_dump_test "dwarf2-11" $dump_opts -- run_dump_test "dwarf2-12" $dump_opts -- run_dump_test "dwarf2-13" $dump_opts -- run_dump_test "dwarf2-14" $dump_opts -- run_dump_test "dwarf2-15" $dump_opts -- run_dump_test "dwarf2-16" $dump_opts -- run_dump_test "dwarf2-17" $dump_opts -- run_dump_test "dwarf2-18" $dump_opts -- run_dump_test "dwarf2-19" $dump_opts -- run_dump_test "dwarf2-20" $dump_opts -- run_dump_test "dwarf2-21" $dump_opts -- run_dump_test "dwarf-5-file0" $dump_opts -- run_dump_test "dwarf-5-file0-2" $dump_opts -- run_dump_test "dwarf-5-file0-3" $dump_opts -- run_dump_test "dwarf-5-dir0" $dump_opts -- run_dump_test "dwarf-5-loc0" $dump_opts -- run_dump_test "dwarf-4-cu" $dump_opts -- run_dump_test "dwarf-5-cu" $dump_opts -- run_dump_test "dwarf-5-nop-for-line-table" $dump_opts -- run_dump_test "pr25917" -- run_dump_test "bss" -- run_dump_test "bad-bss" -- run_dump_test "bad-section-flag" -- run_dump_test "bad-size" -- run_dump_test "bad-group" -- run_dump_test "pr27355" -- -- if { ![istarget "sw_64*-*-*"]} then { -- run_dump_test "syms" -- } -- run_dump_test "startof" -- -- run_dump_test "missing-build-notes" -- -- run_dump_test "common1" -- run_dump_test "common2" -- -- # hpux has a non-standard common directive. -- if { ![istarget "*-*-hpux*"] } then { -- run_dump_test "common3a" -- run_dump_test "common3b" -- run_dump_test "common4a" -- run_dump_test "common4b" -- } -- -- if { ![istarget "sw_64*-*-*"] && ![istarget "*-*-hpux*"]} then { -- run_dump_test "common5a" -- run_dump_test "common5b" -- run_dump_test "common5c" -- run_dump_test "common5d" -- } -- -- run_dump_test "strtab" -- -- run_dump_test "bignums" -- run_dump_test "section-symbol-redef" -- run_dump_test "pr27228" --} ---- b/gold/sw_64.cc -+++ /dev/null -@@ -1,1787 +0,0 @@ --// sw_64.cc -- sw_64 target support for gold. -- --// Copyright (C) 2021-2021 LiNaKeSi Ltd. --// Written by Kid Lee . -- --#include "gold.h" -- --#include --#include --#include --#include --#include --#include -- --#include "elfcpp.h" --#include "gc.h" --#include "object.h" --#include "output.h" --#include "sw_64.h" --#include "target.h" --#include "target-reloc.h" --#include "target-select.h" -- --namespace --{ --using namespace gold; -- --template --class Elf{ -- public: -- static constexpr int size = _size; -- static constexpr bool big_endian = _big_endian; --}; -- --typedef Elf<64, false> Elf64le; -- --const char* get_relocation_name(unsigned int r_type){ -- switch(r_type){ --# define ELF_RELOC(name, value) \ -- case elfcpp::name: return #name; \ -- /* end of ELF_RELOC. */ --# include "sw_64.def.h" --# undef ELF_RELOC -- default: { -- static __thread char str[32]; -- str[0] = '\0'; -- snprintf(str, sizeof(str), "Unknown(%d)", r_type); -- return str; -- }break; -- } --} -- --// set_union(A, B) - Compute A := A u B, return whether A changed. --template --bool set_union(S1Ty &S1, const S2Ty &S2) { -- bool Changed = false; -- -- for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); -- SI != SE; ++SI) -- if (S1.insert(*SI).second) -- Changed = true; -- -- return Changed; --} -- --template --struct X{ -- using ClassifyReloc = gold::Default_classify_reloc; -- using EmitRelocsStrategy = gold::Default_emit_relocs_strategy; -- using SizedRel = Sized_relobj_file; -- using Address = typename elfcpp::Elf_types::Elf_Addr; -- using RelInfo = Relocate_info; -- using Offset = typename elfcpp::Elf_types::Elf_Off; -- using Sym = elfcpp::Sym; -- using Rela = elfcpp::Rela; -- using Addend = typename elfcpp::Elf_types::Elf_Addr; -- using RelType = elfcpp::SwRelType; -- using LocalIndex = unsigned int; -- using GSymbol = const Symbol*; -- using LSymbol = std::pair; -- using Shndx = unsigned int; -- -- class Target_sw_64; -- class Target_selector_sw_64; -- class Output_data_got_sw_64; -- class Output_data_plt_sw_64; -- class Output_data_reloc_sw_64; -- -- struct USymbol{ -- union{ -- GSymbol gsym_; -- SizedRel* object_; -- }; -- LocalIndex index_; -- -- USymbol(GSymbol gsym) -- : gsym_(gsym) -- , index_(GLOBAL_INDEX) -- {} -- -- USymbol(LSymbol lsym) -- : object_(std::get<0>(lsym)) -- , index_(std::get<1>(lsym)) -- {} -- -- USymbol(GSymbol gsym, SizedRel* object, LocalIndex index){ -- if(nullptr != gsym){ -- gsym_ = gsym; -- index_ = GLOBAL_INDEX; -- }else{ -- object_ = object; -- index_ = index; -- } -- } -- -- bool is_local()const{ -- return GLOBAL_INDEX != index_; -- } -- -- const GSymbol& as_global()const{ -- return gsym_; -- } -- -- const LSymbol& as_local()const{ -- static_assert(sizeof(LSymbol) == sizeof(*this)); -- return *reinterpret_cast(this); -- } -- -- bool operator<(const USymbol &rhs)const{ -- return object_ < rhs.object_ || (object_ == rhs.object_ && index_ < rhs.index_); -- } -- -- static constexpr LocalIndex GLOBAL_INDEX = -1U; -- }; -- -- static bool is_static_link_time_constant(const GSymbol gsym){ -- return gsym->final_value_is_known(); -- } -- -- static bool is_static_link_time_constant(const LSymbol &){ -- return !parameters->options().output_is_position_independent(); -- } -- -- static bool is_preemptible(const GSymbol gsym){ -- if(parameters->options().is_static())return false; -- return gsym->is_from_dynobj() || gsym->is_undefined()|| gsym->is_preemptible(); -- } -- -- static bool is_preemptible(const LSymbol &){ -- return false; -- } -- -- static bool is_tls(const GSymbol &gsym){ -- return elfcpp::STT_TLS == gsym->type(); -- } -- -- static bool is_tls(const LSymbol &lsym){ -- return std::get<0>(lsym)->local_is_tls(std::get<1>(lsym)); -- } -- -- static bool is_undef(const GSymbol &gsym){ -- return nullptr == gsym; -- } -- -- static bool is_undef(const LSymbol &lsym){ -- return 0 == std::get<1>(lsym); -- } -- -- static bool is_func(const GSymbol &gsym){ -- return gsym->is_func(); -- } -- -- static bool is_func(const LSymbol &lsym){ -- // FIXME: This implement is totally wrong, but the current only user -- // do not care about local symbol. -- return false; -- } -- -- class ScanRelocatableRelocs: public gold::Default_scan_relocatable_relocs{ -- public: -- // Return the strategy to use for a local symbol which is a section -- // symbol, given the relocation type. -- inline Relocatable_relocs::Reloc_strategy -- local_section_strategy(unsigned int r_type, Relobj*) -- { -- gold_assert(ClassifyReloc::sh_type == elfcpp::SHT_RELA); -- switch(r_type){ -- case elfcpp::R_SW_64_GPDISP: -- case elfcpp::R_SW_64_LITUSE: -- return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA_0; -- default: -- break; -- } -- return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; -- } -- }; --}; -- --template --class X::Target_sw_64: public Sized_target --{ -- public: -- using super = Sized_target; -- using Reloc_section = Output_data_reloc; -- static constexpr Offset INVALID_OFFSET = static_cast(0) - 1; -- static constexpr auto ORDER_GOT = ORDER_LARGE_DATA; -- // Get access to `Relocate::do_gpdisp` class. -- friend class Output_data_plt_sw_64; -- -- Target_sw_64(): super(&sw64_info) -- {} -- -- void -- gc_process_relocs(Symbol_table* symtab, -- Layout *layout, -- SizedRel *object, -- unsigned int data_shndx, -- unsigned int sh_type, -- const unsigned char* prelocs, -- size_t reloc_count, -- Output_section* output_section, -- bool needs_special_offset_handling, -- size_t local_symbol_count, -- const unsigned char* plocal_symbols -- )override; -- -- void -- scan_relocs(Symbol_table* symtab, -- Layout *layout, -- SizedRel *object, -- unsigned int data_shndx, -- unsigned int sh_type, -- const unsigned char* prelocs, -- size_t reloc_count, -- Output_section* output_section, -- bool needs_special_offset_handling, -- size_t local_symbol_count, -- const unsigned char* plocal_symbols -- )override; -- -- void -- relocate_section(const RelInfo *, -- unsigned int sh_type, -- const unsigned char* prelocs, -- size_t reloc_count, -- Output_section* output_section, -- bool needs_special_offset_handling, -- unsigned char* view, -- Address view_address, -- section_size_type view_size, -- const Reloc_symbol_changes* -- )override; -- -- void -- scan_relocatable_relocs(Symbol_table* symtab, -- Layout *layout, -- SizedRel *object, -- unsigned int data_shndx, -- unsigned int sh_type, -- const unsigned char* prelocs, -- size_t reloc_count, -- Output_section* output_section, -- bool needs_special_offset_handling, -- size_t local_symbol_count, -- const unsigned char* plocal_symbols, -- Relocatable_relocs* -- )override; -- -- void -- emit_relocs_scan( -- Symbol_table* symtab -- , Layout* layout -- , SizedRel *object -- , unsigned int data_shndx -- , unsigned int sh_type -- , const unsigned char *prelocs -- , size_t reloc_count -- , Output_section *output_section -- , bool needs_special_offset_handling -- , size_t local_symbol_count -- , const unsigned char *plocal_syms -- , Relocatable_relocs *rr -- )override; -- -- void -- relocate_relocs(const RelInfo *relinfo, -- unsigned int sh_type, -- const unsigned char* prelocs, -- size_t reloc_count, -- Output_section* output_section, -- Offset offset_in_output_section, -- unsigned char* view, -- Address view_address, -- section_size_type view_size, -- unsigned char* reloc_view, -- section_size_type reloc_view_size -- )override; -- -- unsigned int -- got_entry_count() const override{ -- gold_assert(nullptr != got_); -- return got_->entries_num(); -- } -- -- unsigned int -- plt_entry_count() const override{ -- gold_assert(nullptr != plt_); -- return plt_->entries_num(); -- } -- -- unsigned int -- first_plt_entry_offset() const override{ -- gold_assert(nullptr != plt_); -- return plt_->first_entry_offset(); -- } -- -- unsigned int -- plt_entry_size() const override{ -- gold_assert(nullptr != plt_); -- return plt_->entry_size(); -- } -- -- void -- do_new_output_section(Output_section *os) const override{ -- gold_assert(nullptr != os); -- if(0 != strcmp(".sdata", os->name()))return; -- static_assert(ORDER_GOT < ORDER_SMALL_DATA); -- os->set_order(ORDER_SMALL_DATA); -- } -- -- // Get the GOT section. -- Output_data_got_sw_64* -- got_section()const{ return this->got_; } -- -- // Get the dynamic reloc section. -- Output_data_reloc_sw_64* -- rela_dyn_section()const{ return rela_dyn_; } -- -- Reloc_section* -- rela_plt_section()const{ return rela_plt_; }; -- -- Output_data_plt_sw_64* -- plt_section()const{ return this->plt_; } -- -- void add_jsr_user(const SizedRel *f, unsigned int shndx, unsigned int relnum){ -- jsrs_.insert({f, shndx, relnum}); -- } -- -- bool is_jsr_user(const SizedRel *f, unsigned int shndx, unsigned int relnum){ -- return std::end(jsrs_) != jsrs_.find({f, shndx, relnum}); -- } -- -- Offset tls_offset()const{ return tls_offset_; } -- -- protected: -- virtual void -- do_select_as_default_target(); -- -- virtual void -- do_finalize_sections(Layout*, const Input_objects*, Symbol_table*); -- -- private: -- class Scan{ -- public: -- void -- local( -- Symbol_table * -- , Layout * -- , Target_sw_64* target -- , SizedRel *object -- , unsigned int data_shndx -- , Output_section* output_section -- , const Rela &reloc -- , unsigned int r_type -- , const Sym &sym -- , bool is_discarded -- ){ -- ++next_; -- if(is_discarded)return; -- --#ifdef GOLD_EH_FRAME_OPTIMIZATION_BUG -- if(elfcpp::R_SW_64_GPRELHIGH == r_type -- && object->is_output_section_offset_invalid(sym.get_st_shndx()) -- && elfcpp::STT_SECTION == sym.get_st_type() -- && 0 == reloc.get_r_addend() -- && ".eh_frame" == object->section_name(sym.get_st_shndx()) -- ){ -- // Make the offset valid forcibly, so this symbol will have the -- // correct final value. -- object->set_section_offset(sym.get_st_shndx(), 0); -- } --#endif -- -- auto r_sym = elfcpp::elf_r_sym(reloc.get_r_info()); -- static constexpr std::bitset<64> REL_TLS( -- 1ULL << elfcpp::R_SW_64_GOTTPREL -- ); -- if(REL_TLS[r_type]){ -- // Normally the same is done in `count_local_symbols`, just after -- // `Target::finalize_sections`. But we need the TLS information in -- // the `do_finalize_sections` function, apparently the normal situation -- // is a little bit too late for us, so hack it here. -- auto lv = const_cast *>(object->local_symbol(r_sym)); -- if(elfcpp::STT_TLS == sym.get_st_type())lv->set_is_tls_symbol(); -- } -- -- return scan( -- target -- , object -- , data_shndx -- , output_section -- , reloc -- , r_type -- , std::move(std::make_pair(object, r_sym)) -- ); -- } -- -- void -- global( -- Symbol_table * -- , Layout * -- , Target_sw_64 *target -- , SizedRel *object -- , unsigned int data_shndx -- , Output_section* output_section -- , const Rela &reloc -- , unsigned int r_type -- , Symbol *gsym -- ){ -- ++next_; -- return scan( -- target -- , object -- , data_shndx -- , output_section -- , reloc -- , r_type -- , std::move(gsym) -- ); -- } -- -- inline bool -- local_reloc_may_be_function_pointer( -- Symbol_table * -- , Layout * -- , Target_sw_64 * -- , SizedRel * -- , unsigned int -- , Output_section* -- , const Rela & -- , unsigned int r_type -- , const Sym &); -- -- inline bool -- global_reloc_may_be_function_pointer( -- Symbol_table * -- , Layout * -- , Target_sw_64 * -- , SizedRel * -- , unsigned int -- , Output_section* -- , const Rela & -- , unsigned int r_type -- , Symbol* gsym); -- -- template -- inline void -- scan( -- Target_sw_64 * -- , SizedRel * -- , unsigned int data_shndx -- , Output_section* output_section -- , const Rela & -- , unsigned int r_type -- , const Symbol_type &&sym -- ); -- -- private: -- size_t next_ = 0; -- -- static constexpr int32_t LITUSE_JSR = 3; -- }; -- -- class Relocate{ -- public: -- using Bit32 = typename elfcpp::Swap<32, E::big_endian>; -- using Bit16 = typename elfcpp::Swap<16, E::big_endian>; -- using Bit32_v = typename Bit32::Valtype; -- using Bit16_v = typename Bit16::Valtype; -- using Inst = Bit32; -- using Inst_v = typename Inst::Valtype; -- using Rf = Relocate_functions; -- -- Relocate() -- {} -- -- inline bool -- relocate( -- const RelInfo * -- , unsigned int -- , Target_sw_64 * -- , Output_section * -- , size_t relnum -- , const unsigned char* -- , const Sized_symbol* -- , const Symbol_value* -- , unsigned char* -- , Address -- , section_size_type); -- -- static void do_gpdisp( -- unsigned char *view_hi -- , unsigned char *view_lo -- , uint64_t disp -- ){ -- auto i_hi = Inst::readval(view_hi); -- auto i_lo = Inst::readval(view_lo); -- // TODO: check the instructions. -- uint64_t addend; -- addend = ((i_hi & 0xffff) << 16) | (i_lo & 0xffff); -- addend = (addend ^ 0x80008000) - 0x80008000; -- disp += addend; -- -- if(static_cast(0x7fff8000) <= static_cast(disp) -- || static_cast(disp) < -static_cast(0x7fff8000) -- ){ -- // TODO: overflow. -- } -- -- i_hi = bit_select32( i_hi , high(disp) , 0xffff); -- i_lo = bit_select32( i_lo , disp & 0xffff , 0xffff); -- Inst::writeval(view_hi, i_hi); -- Inst::writeval(view_lo, i_lo); -- } -- -- private: -- static inline uint32_t bit_select32(uint32_t a, uint32_t b, uint32_t mask){ -- return Bits<32>::bit_select32(a, b, mask); -- } -- -- static inline uint32_t high(uint32_t value){ -- return (value >> 16) + (0 != (value & 0x8000)); -- } -- -- static constexpr uintptr_t RA_SHIFT = 21; -- static constexpr uintptr_t RB_SHIFT = 16; -- static constexpr uintptr_t RC_MASK = 31; -- static constexpr uintptr_t RA_MASK = RC_MASK << RA_SHIFT; -- static constexpr uintptr_t RB_MASK = RC_MASK << RB_SHIFT; -- -- Offset literal_got_offset = INVALID_OFFSET; -- }; -- -- // Track the relocs being scanned. -- // This is going to work is base on the fact the scanning can **NOT** be paralleled. -- const unsigned char *prelocs_; -- // Track the total number of relocs being scanned. -- size_t reloc_count_; -- std::set> jsrs_; -- -- Output_data_got_sw_64 *got_ = nullptr; -- Output_data_reloc_sw_64* rela_dyn_ = nullptr; -- Reloc_section* rela_plt_ = nullptr; -- Output_data_plt_sw_64* plt_ = nullptr; -- Offset tls_offset_ = 0; -- -- static Target::Target_info sw64_info; -- static constexpr uintptr_t TCB_SIZE = 16; --}; -- --template --class X::Output_data_got_sw_64: public Output_data_got_base{ -- public: -- static constexpr size_t ENTRY_SIZE = E::size / 8; -- using Index = size_t; -- using Valtype = Address; -- -- Output_data_got_sw_64() -- : Output_data_got_base(ENTRY_SIZE) -- { -- } -- -- // Return gp value for particular input file. -- int64_t gp_offset(const SizedRel *f = nullptr)const{ -- int64_t offset = GP_OFFSET; -- if(has_got_index(f)){ -- offset += gots_[got_index(f)].start_index * ENTRY_SIZE; -- } -- return offset; -- } -- -- void add_entry( -- SizedRel *f -- , const LSymbol &&lsym -- , int64_t addend -- , bool -- ){ -- auto &got = file_got(f); -- got.locals.insert({{std::move(lsym), addend}, 0}); -- } -- -- void add_entry( -- SizedRel *f -- , const GSymbol sym -- , int64_t addend -- , bool is_plt -- ){ -- auto &got = file_got(f); -- auto &entries = is_plt && sym->in_dyn() ? got.plts : got.globals; -- entries.insert({{sym, addend}, 0}); -- } -- -- int64_t sym_entry_offset( -- SizedRel *f -- , const Symbol *sym -- , LocalIndex index -- , int64_t addend -- , bool is_plt -- ){ -- auto const &got = file_got(reinterpret_cast(f)); -- if(nullptr == sym){ -- return got_offset(got.locals, {{f, index}, addend}); -- } -- auto &entries = is_plt && sym->in_dyn() ? got.plts : got.globals; -- return got_offset(entries, {sym, addend}); -- } -- -- template -- void add_tls_entry( -- SizedRel *f -- , const ST &&sym -- ){ -- file_got(f).tlss.insert({{sym}, 0}); -- } -- -- int64_t sym_tls_offset( -- SizedRel *f -- , const USymbol &sym -- ){ -- auto const &got = file_got(reinterpret_cast(f)); -- return got_offset(got.tlss, sym); -- } -- -- void add_tls_index(SizedRel *f){ -- file_got(f).tlss.insert({{{f, 0}}, 0}); -- } -- -- void build(Target_sw_64 *target){ -- for(auto i = std::begin(gots_); i < std::end(gots_); ++i){ -- if(nullptr == i->file)continue; -- for(auto j = std::next(i); j < std::end(gots_); ++j){ -- if(nullptr == j->file)continue; -- merge_gots(*i, *j); -- if(MAX_GOTS <= i->entries_num())break; -- } -- } -- -- size_t index = 0; -- auto rela_dyn = target->rela_dyn_section(); -- auto rela_plt = target->rela_plt_section(); -- auto plt = target->plt_section(); -- auto is_pic = parameters->options().output_is_position_independent(); -- auto shared = parameters->options().shared(); -- for(auto &got: gots_){ -- if(nullptr == got.file)continue; -- got.start_index = index; -- -- for(auto &p: got.globals){ -- p.second = index++; -- -- auto sym = const_cast(p.first.first); -- auto addend = p.first.second; -- int64_t offset = p.second * ENTRY_SIZE; -- -- relocations_.push_back({p.second, sym, addend, is_tls(sym)}); -- -- if(is_preemptible(sym) -- || (shared && sym->is_defined() && sym->binding() == elfcpp::STB_WEAK)){ -- rela_dyn->add_entry(is_tls(sym) ? elfcpp::R_SW_64_TPREL64 : elfcpp::R_SW_64_GLOB_DAT, this, offset, sym, addend); -- }else if(is_pic && !is_tls(sym)){ -- rela_dyn->add_entry(elfcpp::R_SW_64_RELATIVE, this, offset, sym, addend); -- } -- } -- -- for(auto &p: got.plts){ -- p.second = index++; -- -- auto sym = const_cast(p.first.first); -- auto addend = p.first.second; -- int64_t offset = p.second * ENTRY_SIZE; -- gold_assert(0 == addend); -- -- rela_plt->add_global(sym, elfcpp::R_SW_64_JMP_SLOT, this, offset, addend); -- // This is the bfd behavior. -- sym->set_nonvis(0); -- auto plt_offset = plt->add_entry(sym); -- relocations_.push_back({p.second, sym, 0, plt_offset}); -- } -- -- for(auto &p: got.locals){ -- p.second = index++; -- -- auto &sym = p.first.first; -- auto addend = p.first.second; -- int64_t offset = p.second * ENTRY_SIZE; -- -- relocations_.push_back({p.second, sym, addend, is_tls(sym)}); -- -- // TODO: Check whether the symbol is an absolute value. -- if(is_pic && !is_tls(sym)){ -- rela_dyn->add_entry(elfcpp::R_SW_64_RELATIVE, this, offset, sym, addend); -- } -- } -- -- for(auto &p: got.tlss){ -- p.second = index; -- index += DYNAMIC_TLS_GOT_COUNT; -- -- auto &usym = p.first; -- if(usym.is_local()){ -- build_dyn_tls(rela_dyn, shared, p.second, usym.as_local()); -- }else{ -- build_dyn_tls(rela_dyn, shared, p.second, usym.as_global()); -- } -- } -- } -- set_data_size(index * ENTRY_SIZE); -- } -- -- size_t entries_num()const{ -- size_t count = 0; -- for(auto &got: gots_){ -- if(nullptr == got.file)continue; -- count += got.entries_num(); -- } -- return count; -- } -- -- void -- do_print_to_mapfile(Mapfile*) const override{ -- } -- -- protected: -- virtual void -- do_write(Output_file *of){ -- const off_t off = this->offset(); -- const off_t oview_size = this->data_size(); -- unsigned char* const oview = of->get_output_view(off, oview_size); -- -- for(const auto &reloc: relocations_){ -- reloc.write(oview); -- } -- of->write_output_view(off, oview_size, oview); -- } -- -- // Reserve the slot at index I in the GOT. -- virtual void -- do_reserve_slot(unsigned int){ -- } -- -- private: -- class Got_reloc{ -- public: -- // Create a global symbol entry. -- Got_reloc(Index index, const Symbol *gsym, Addend addend, Offset plt_offset=0) -- : index_(index) -- , local_sym_index_(GSYM) -- , gsym_(gsym) -- , addend_(addend) -- , plt_offset_(plt_offset) -- {} -- -- // Create a local symbol entry. -- Got_reloc(Index index -- , const LSymbol &lsym -- , Addend addend -- , bool use_tls_offset=false -- ) -- : index_(index) -- , local_sym_index_(std::get<1>(lsym)) -- , object_(std::get<0>(lsym)) -- , addend_(addend) -- , plt_offset_(use_tls_offset) -- { -- } -- -- // Create a constant entry. The constant is a host value--it will -- // be swapped, if necessary, when it is written out. -- Got_reloc(Index index, Valtype constant) -- : index_(index) -- , local_sym_index_(CONSTANT) -- , constant_(constant) -- , addend_(0) -- , plt_offset_(0) -- {} -- -- // Write the GOT entry to an output view. -- void write(unsigned char* pov)const{ -- Valtype val = 0; -- auto &target = reinterpret_cast(parameters->target()); -- -- switch(this->local_sym_index_){ -- case GSYM: { -- // If the symbol is resolved locally, we need to write out the -- // link-time value, which will be relocated dynamically by a -- // RELATIVE relocation. -- if(Output_data_plt_sw_64::is_plt_offset(plt_offset_)){ -- val = target.plt_section()->address() + plt_offset_; -- }else{ -- switch(parameters->size_and_endianness()){ --#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) -- case Parameters::TARGET_32_LITTLE: -- case Parameters::TARGET_32_BIG: -- { -- // This cast is ugly. We don't want to put a -- // virtual method in Symbol, because we want Symbol -- // to be as small as possible. -- Sized_symbol<32>::Value_type v; -- v = static_cast*>(gsym_)->value(); -- val = convert_types::Value_type>(v); -- }break; --#endif --#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) -- case Parameters::TARGET_64_LITTLE: -- case Parameters::TARGET_64_BIG: -- { -- Sized_symbol<64>::Value_type v; -- v = static_cast*>(gsym_)->value(); -- val = convert_types::Value_type>(v); -- }break; --#endif -- default: -- gold_unreachable(); -- } -- if(this->plt_offset_ && is_tls(gsym_)){ -- val += target.tls_offset(); -- } -- } -- }break; -- -- case CONSTANT: -- val = this->constant_; -- break; -- -- default: { -- const unsigned int lsi = this->local_sym_index_; -- bool is_tls = object_->local_is_tls(lsi); -- if(this->plt_offset_ && !is_tls){ -- val = parameters->target().plt_address_for_local(object_, lsi); -- }else{ -- uint64_t lval = object_->local_symbol_value(lsi, 0); -- val = convert_types(lval); -- if(this->plt_offset_ && is_tls){ -- val += target.tls_offset(); -- } -- } -- }break; -- } // end of switch(this->local_sym_index_). -- -- pov += index_ * ENTRY_SIZE; -- elfcpp::Swap::writeval(pov, val + addend_); -- }; -- -- private: -- static constexpr LocalIndex GSYM = 0x7fffffff; -- static constexpr LocalIndex CONSTANT = 0x7ffffffe; -- -- Index index_; -- // For a local symbol, the local symbol index. This is GSYM_CODE -- // for a global symbol, or CONSTANT_CODE for a constant. -- LocalIndex local_sym_index_; -- union{ -- // For a local symbol, the object. -- const Relobj* object_; -- // For a global symbol, the symbol. -- const Symbol* gsym_; -- // For a constant, the constant. -- Valtype constant_; -- }; -- Addend addend_; -- // For TLS symbols, whether to offset the symbol value. -- Offset plt_offset_; -- }; -- std::vector relocations_; -- template using Got_entry = std::pair; -- template using Got_map = std::map; -- -- struct File_got{ -- SizedRel *file = nullptr; -- size_t start_index = 0; -- -- Got_map, size_t> locals; -- Got_map, size_t> globals; -- Got_map, size_t> plts; -- Got_map tlss; -- -- size_t entries_num()const{ -- return locals.size() -- + globals.size() -- + plts.size() -- + tlss.size() * DYNAMIC_TLS_GOT_COUNT -- ; -- } -- }; -- -- // Return `File_got`. -- const File_got& file_got(const SizedRel *f)const{ -- gold_assert(nullptr != f && has_got_index(f)); -- return gots_.at(got_index(f)); -- } -- -- // Return (and create if necessary) `File_got`. -- File_got& file_got(SizedRel *f){ -- gold_assert(nullptr != f); -- if(!has_got_index(f)){ -- gots_.emplace_back(); -- gots_.back().file = f; -- set_got_index(f, gots_.size() - 1); -- } -- return gots_[got_index(f)]; -- } -- -- // Container of GOT created for each input file. -- std::vector gots_; -- -- template -- inline void build_dyn_tls(Output_data_reloc_sw_64 *rela_dyn, bool shared, size_t index, const ST &sym){ -- int64_t offset = index * ENTRY_SIZE; -- int64_t offset2 = offset + ENTRY_SIZE; -- -- if(shared || is_undef(sym) || is_preemptible(sym)){ -- rela_dyn->add_entry(elfcpp::R_SW_64_DTPMOD64, this, offset, sym, 0); -- if(is_undef(sym))return; -- } -- if(is_preemptible(sym)){ -- rela_dyn->add_entry(elfcpp::R_SW_64_DTPREL64, this, offset2, sym, 0); -- }else{ -- if(!shared){ -- relocations_.push_back({index, 1}); -- } -- relocations_.push_back({index + 1, sym, 0, false}); -- } -- } -- -- bool merge_gots(File_got &dst, File_got &src){ -- gold_assert(nullptr != dst.file); -- -- // TODO: Do an optimistic merge. -- if(MAX_GOTS < dst.entries_num() + src.entries_num())return false; -- -- set_union(dst.locals, src.locals); -- set_union(dst.globals, src.globals); -- set_union(dst.plts, src.plts); -- set_union(dst.tlss, src.tlss); -- set_got_index(src.file, got_index(dst.file)); -- src.file = nullptr; -- -- gold_assert(dst.entries_num() <= MAX_GOTS); -- return true; -- } -- -- static constexpr int64_t GP_OFFSET = 0x8000; -- static constexpr unsigned int GOT_INDEX_TYPE = static_cast(-1); -- static constexpr size_t DYNAMIC_TLS_GOT_COUNT = 2; -- static constexpr size_t MAX_GOTS = 1 << 13; -- -- static bool has_got_index(const SizedRel *f){ -- return nullptr != f && f->local_has_got_offset(0, GOT_INDEX_TYPE); -- } -- -- static intptr_t got_index(const SizedRel *f){ -- gold_assert(nullptr != f); -- return f->local_got_offset(0, GOT_INDEX_TYPE); -- } -- -- static void set_got_index(SizedRel *f, size_t index){ -- f->set_local_got_offset(0, GOT_INDEX_TYPE, index); -- } -- -- template -- static int64_t got_offset(const Got_map &entries, const T &key){ -- const auto it = entries.find(key); -- return (std::end(entries) == it ? -1 : it->second * ENTRY_SIZE); -- } --}; -- --template --class X::Output_data_plt_sw_64: public Output_section_data{ -- public: -- Output_data_plt_sw_64() -- : Output_section_data(0x10) -- , got_plt_(nullptr) -- { -- } -- -- void set_got_plt(const Output_section_data* got_plt){ -- got_plt_ = got_plt; -- } -- -- Offset add_entry(Symbol* sym){ -- entries_.push_back(sym); -- return HEADER_SIZE + ENTRY_SIZE * (entries_.size() - 1); -- } -- -- unsigned int -- entries_num()const{ -- return entries_.size(); -- } -- -- unsigned int -- first_entry_offset()const{ -- return HEADER_SIZE; -- } -- -- unsigned int -- entry_size()const{ -- return ENTRY_SIZE; -- } -- -- void -- do_print_to_mapfile(Mapfile*) const override{ -- } -- -- static bool is_plt_offset(Offset offset){ -- return HEADER_SIZE <= offset; -- } -- -- protected: -- virtual void -- do_write(Output_file *of){ -- const off_t off = this->offset(); -- const off_t oview_size = this->data_size(); -- unsigned char* const oview = of->get_output_view(off, oview_size); -- -- const uint8_t plt_data[] = { -- 0x39, 0x01, 0x7c, 0x43, // subl $r27,$r28,$r25 -- 0x00, 0x00, 0x9c, 0xff, // ldih $r28,0($r28) <--- needs relocation. -- 0x79, 0x01, 0x39, 0x43, // s4subl $r25,$r25,$r25 -- 0x00, 0x00, 0x9c, 0xfb, // ldi $r28,0($r28) <--- needs relocation. -- 0x00, 0x00, 0x7c, 0x8f, // ldl $r27,0($r28) -- 0x19, 0x01, 0x39, 0x43, // addl $r25,$r25,$r25 -- 0x08, 0x00, 0x9c, 0x8f, // ldl $r28,8($r28) -- 0x00, 0x00, 0xfb, 0x0f, // jmp $r31,($r27),1200020, 0x<_PROCEDURE_LINKAGE_TABLE_+0x20> -- 0xf7, 0xff, 0x9f, 0x13, // br $r28,1200000, 0x<_PROCEDURE_LINKAGE_TABLE_> -- }; -- static_assert(HEADER_SIZE == sizeof(plt_data)); -- memcpy(oview, plt_data, sizeof(plt_data)); -- // $28 point to PLT[0], need to be relocated to the beginning of .got.plt section. -- auto disp = got_plt_->address() - address() - HEADER_SIZE; -- Target_sw_64::Relocate::do_gpdisp(oview + 4, oview + 12, disp); -- -- auto buf = reinterpret_cast(oview + HEADER_SIZE); -- for(size_t i = 0; i < entries_.size(); ++i){ -- buf[i] = 0x13fffffe - i; -- } -- -- of->write_output_view(off, oview_size, oview); -- } -- -- virtual void -- set_final_data_size(){ -- set_data_size(HEADER_SIZE + ENTRY_SIZE * entries_.size()); -- } -- -- private: -- const Output_section_data *got_plt_; -- std::vector entries_; -- -- static constexpr size_t HEADER_SIZE = 0x24; -- static constexpr size_t ENTRY_SIZE = 4; --}; -- --template --class X::Output_data_reloc_sw_64: public Output_data_reloc{ -- public: -- using super = Output_data_reloc; -- using super::super; -- -- void add_entry( -- RelType rel -- , Output_data *od -- , SizedRel *obj -- , Shndx shndx -- , Address offset -- , const USymbol &sym -- , Addend addend -- ){ -- auto is_relative = elfcpp::R_SW_64_RELATIVE == rel; -- if(sym.is_local()){ -- const LSymbol &lsym = sym.as_local(); -- gold_assert(nullptr == obj || obj == std::get<0>(lsym)); -- this->add(od, {obj, std::get<1>(lsym), rel, shndx, offset, addend, is_relative, is_relative, false, false}); -- }else{ -- this->add(od, {const_cast(sym.as_global()), rel, obj, shndx, offset, addend, is_relative, is_relative, false}); -- } -- } -- -- void add_entry( -- RelType rel -- , Output_data *od -- , Address offset -- , const GSymbol &sym -- , Addend addend -- ){ -- auto is_relative = elfcpp::R_SW_64_RELATIVE == rel; -- this->add(od, { -- const_cast(sym), -- rel, -- od, -- offset, -- addend, -- is_relative, // is_relative -- is_relative, // is_symbolless -- false, // use_plt_offset -- }); -- } -- -- void add_entry( -- RelType rel -- , Output_data *od -- , Address offset -- , const LSymbol &lsym -- , Addend addend -- ){ -- auto is_relative = elfcpp::R_SW_64_RELATIVE == rel; -- this->add(od, { -- std::get<0>(lsym), -- elfcpp::R_SW_64_DTPMOD64 == rel ? 0 : std::get<1>(lsym), -- rel, -- od, -- offset, -- addend, -- is_relative, // is_relative -- is_relative, // is_symbolless -- false, // is_section_symbol -- false, // use_plt_offset -- }); -- } --}; -- --template --void --X::Target_sw_64::gc_process_relocs(Symbol_table* symtab, -- Layout *layout, -- SizedRel *object, -- unsigned int data_shndx, -- unsigned int sh_type, -- const unsigned char* prelocs, -- size_t reloc_count, -- Output_section* output_section, -- bool needs_special_offset_handling, -- size_t local_symbol_count, -- const unsigned char* plocal_symbols) --{ -- if(elfcpp::SHT_RELA != sh_type)return; -- gold::gc_process_relocs( -- symtab -- , layout -- , this -- , object -- , data_shndx -- , prelocs -- , reloc_count -- , output_section -- , needs_special_offset_handling -- , local_symbol_count -- , plocal_symbols -- ); --} -- --template --void --X::Target_sw_64::scan_relocs(Symbol_table* symtab, -- Layout *layout, -- SizedRel *object, -- unsigned int data_shndx, -- unsigned int sh_type, -- const unsigned char* prelocs, -- size_t reloc_count, -- Output_section* output_section, -- bool needs_special_offset_handling, -- size_t local_symbol_count, -- const unsigned char* plocal_symbols) --{ -- if(elfcpp::SHT_RELA != sh_type){ -- gold_error(_("%s: unsupported reloc type %d section.") -- , object->name().c_str(), sh_type); -- return; -- } -- prelocs_ = prelocs; -- reloc_count_ = reloc_count; -- gold::scan_relocs( -- symtab -- , layout -- , this -- , object -- , data_shndx -- , prelocs -- , reloc_count -- , output_section -- , needs_special_offset_handling -- , local_symbol_count -- , plocal_symbols); --} -- --template --void --X::Target_sw_64::relocate_section( -- const RelInfo *relinfo -- , unsigned int sh_type -- , const unsigned char* prelocs -- , size_t reloc_count -- , Output_section* output_section -- , bool needs_special_offset_handling -- , unsigned char* view -- , Address view_address -- , section_size_type view_size -- , const Reloc_symbol_changes* reloc_symbol_changes --){ -- gold_assert(elfcpp::SHT_RELA == sh_type); -- gold::relocate_section( -- relinfo -- , this -- , prelocs -- , reloc_count -- , output_section -- , needs_special_offset_handling -- , view -- , view_address -- , view_size -- , reloc_symbol_changes -- ); --} -- --template --void --X::Target_sw_64::scan_relocatable_relocs( -- Symbol_table *symtab -- , Layout *layout -- , SizedRel *object -- , unsigned int data_shndx -- , unsigned int sh_type -- , const unsigned char* prelocs -- , size_t reloc_count -- , Output_section* output_section -- , bool needs_special_offset_handling -- , size_t local_symbol_count -- , const unsigned char* plocal_symbols -- , Relocatable_relocs* rr --){ -- gold_assert(sh_type == elfcpp::SHT_RELA); -- gold::scan_relocatable_relocs( -- symtab, -- layout, -- object, -- data_shndx, -- prelocs, -- reloc_count, -- output_section, -- needs_special_offset_handling, -- local_symbol_count, -- plocal_symbols, -- rr); --} -- --template --void --X::Target_sw_64::emit_relocs_scan( -- Symbol_table *symtab -- , Layout *layout -- , SizedRel *object -- , unsigned int data_shndx -- , unsigned int sh_type -- , const unsigned char *prelocs -- , size_t reloc_count -- , Output_section *output_section -- , bool needs_special_offset_handling -- , size_t local_symbol_count -- , const unsigned char *plocal_syms -- , Relocatable_relocs *rr --){ -- gold_assert(sh_type == elfcpp::SHT_RELA); -- gold::scan_relocatable_relocs( -- symtab, -- layout, -- object, -- data_shndx, -- prelocs, -- reloc_count, -- output_section, -- needs_special_offset_handling, -- local_symbol_count, -- plocal_syms, -- rr); --} -- --template --void --X::Target_sw_64::relocate_relocs(const RelInfo *relinfo, -- unsigned int sh_type, -- const unsigned char* prelocs, -- size_t reloc_count, -- Output_section* output_section, -- Offset offset_in_output_section, -- unsigned char* view, -- Address view_address, -- section_size_type view_size, -- unsigned char* reloc_view, -- section_size_type reloc_view_size) --{ -- gold_assert(sh_type == elfcpp::SHT_RELA); -- -- gold::relocate_relocs( -- relinfo, -- prelocs, -- reloc_count, -- output_section, -- offset_in_output_section, -- view, -- view_address, -- view_size, -- reloc_view, -- reloc_view_size); --} -- --template --void --X::Target_sw_64::do_select_as_default_target(){ -- got_ = new Output_data_got_sw_64; -- rela_dyn_ = new Output_data_reloc_sw_64(!parameters->options_valid() || parameters->options().combreloc()); -- rela_plt_ = new Reloc_section(false); -- plt_ = new Output_data_plt_sw_64; --} -- --template --void --X::Target_sw_64::do_finalize_sections( -- Layout* layout -- , const Input_objects* -- , Symbol_table *symtab --){ -- Output_section_data* got_plt = nullptr; -- if(auto tls_segment = layout->tls_segment()){ -- tls_offset_ = align_address(TCB_SIZE, tls_segment->maximum_alignment()); -- } -- -- got_->build(this); -- -- if(0 < rela_dyn_->current_data_size()){ -- layout->add_output_section_data( -- ".rela.dyn" -- , elfcpp::SHT_RELA -- , elfcpp::SHF_ALLOC -- , rela_dyn_ -- , ORDER_DYNAMIC_RELOCS -- , false // is_relro -- ); -- }else{ -- rela_dyn_ = nullptr; -- } -- -- if(0 < rela_plt_->current_data_size()){ -- layout->add_output_section_data( -- ".rela.plt" -- , elfcpp::SHT_RELA -- , elfcpp::SHF_ALLOC -- , rela_plt_ -- , ORDER_DYNAMIC_PLT_RELOCS -- , false // is_relro -- ); -- -- layout->add_output_section_data( -- ".plt" -- , elfcpp::SHT_PROGBITS -- , (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR) -- , plt_ -- , ORDER_PLT -- , false // is_relro -- ); -- // Make it compatible with bfd. -- symtab->define_in_output_data( -- "_PROCEDURE_LINKAGE_TABLE_" -- , NULL -- , Symbol_table::PREDEFINED -- , plt_ -- , 0 -- , 0 -- , elfcpp::STT_OBJECT -- , elfcpp::STB_LOCAL -- , elfcpp::STV_DEFAULT -- , 0 -- , false -- , false -- ); -- -- static std::string got_plt_data(E::size / 8 * 2, '\0'); -- got_plt = new Output_data_const(got_plt_data, E::size / 8); -- layout->add_output_section_data( -- ".got.plt" -- , elfcpp::SHT_PROGBITS -- , (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE) -- , got_plt -- , ORDER_RELRO -- , true // is_relro -- ); -- plt_->set_got_plt(got_plt); -- }else{ -- rela_plt_ = nullptr; -- } -- -- layout->add_target_dynamic_tags( -- false // use_rel -- , got_plt -- , rela_plt_ -- , rela_dyn_ -- , true // add_debug -- , false // dynrel_includes_plt -- ); -- auto dyn = layout->dynamic_data(); -- if(nullptr != dyn){ -- dyn->add_constant(elfcpp::DT_SW_64_PLTRO, 1); -- } -- -- layout->add_output_section_data( -- ".got" -- , elfcpp::SHT_PROGBITS -- , elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE -- , got_ -- , ORDER_GOT -- , false // is_relro -- ); --} -- --template --template --inline void --X::Target_sw_64::Scan::scan( -- Target_sw_64 *target -- , SizedRel *object -- , unsigned int data_shndx -- , Output_section* output_section -- , const Rela &reloc -- , unsigned int r_type -- , const Symbol_type &&sym --){ -- auto r_addend = reloc.get_r_addend(); -- -- switch(r_type){ -- case elfcpp::R_SW_64_NONE: -- case elfcpp::R_SW_64_GPREL32: -- case elfcpp::R_SW_64_GPREL16: -- case elfcpp::R_SW_64_GPDISP: -- case elfcpp::R_SW_64_LITUSE: -- case elfcpp::R_SW_64_REFLONG: -- case elfcpp::R_SW_64_HINT: -- case elfcpp::R_SW_64_SREL16: -- case elfcpp::R_SW_64_SREL32: -- case elfcpp::R_SW_64_SREL64: -- case elfcpp::R_SW_64_GPRELHIGH: -- case elfcpp::R_SW_64_GPRELLOW: -- case elfcpp::R_SW_64_GLOB_DAT: -- case elfcpp::R_SW_64_JMP_SLOT: -- case elfcpp::R_SW_64_RELATIVE: -- case elfcpp::R_SW_64_LITERAL_GOT: -- case elfcpp::R_SW_64_DTPRELHI: -- case elfcpp::R_SW_64_DTPRELLO: -- case elfcpp::R_SW_64_TPREL64: -- case elfcpp::R_SW_64_TPRELHI: -- case elfcpp::R_SW_64_TPRELLO: -- case elfcpp::R_SW_64_TPREL16: -- case elfcpp::R_SW_64_BRADDR: -- // TODO: Check target's .prologue and merge GOTs. -- case elfcpp::R_SW_64_BRSGP: -- // Nothing to do. -- break; -- case elfcpp::R_SW_64_REFQUAD: -- { -- if(!is_static_link_time_constant(sym)){ -- auto rel = is_preemptible(sym) ? static_cast(r_type) : elfcpp::R_SW_64_RELATIVE; -- target->rela_dyn_section()->add_entry( -- rel -- , output_section -- , object -- , data_shndx -- , reloc.get_r_offset() -- , sym -- , r_addend -- ); -- } -- }break; -- case elfcpp::R_SW_64_LITERAL: { -- bool use_plt = false; -- if(next_ < target->reloc_count_){ -- Rela next_reloc(target->prelocs_ -- + next_ * Reloc_types::reloc_size); -- auto next_info = next_reloc.get_r_info(); -- auto next_type = elfcpp::elf_r_type(next_info); -- if(elfcpp::R_SW_64_LITUSE == next_type){ -- use_plt = is_func(sym) && LITUSE_JSR == next_reloc.get_r_addend(); -- if(use_plt)target->add_jsr_user(object, data_shndx, next_ - 1); -- } -- } -- target->got_section()->add_entry(object, std::move(sym), r_addend, use_plt); -- }break; -- case elfcpp::R_SW_64_TLSGD: { -- target->got_section()->add_tls_entry(object, std::move(sym)); -- }break; -- case elfcpp::R_SW_64_TLS_LDM: { -- if(parameters->options().shared() || !parameters->options().relax()){ -- target->got_section()->add_tls_index(object); -- }else{ -- gold_error(_("TODO: relax from LD to LE is not implemented yet.")); -- } -- }break; -- case elfcpp::R_SW_64_GOTTPREL: { -- target->got_section()->add_entry(object, std::move(sym), r_addend, false); -- }break; -- default: -- gold_error(_("%s: unsupported relocation '%s' at offset %#lx.") -- , object->name().c_str() -- , get_relocation_name(r_type) -- , reloc.get_r_offset() -- ); -- } --} -- --template --inline bool --X::Target_sw_64::Scan::local_reloc_may_be_function_pointer( -- Symbol_table* -- , Layout* -- , Target_sw_64* -- , SizedRel * -- , unsigned int -- , Output_section* -- , const Rela & -- , unsigned int r_type -- , const Sym &) --{ -- // TODO -- return true; --} -- --template --inline bool --X::Target_sw_64::Scan::global_reloc_may_be_function_pointer( -- Symbol_table * -- , Layout * -- , Target_sw_64 * -- , SizedRel * -- , unsigned int -- , Output_section * -- , const Rela & -- , unsigned int r_type -- , Symbol* gsym) --{ -- // TODO -- return true; --} -- --template --inline bool --X::Target_sw_64::Relocate::relocate( -- const RelInfo *relinfo -- , unsigned int -- , Target_sw_64 *target -- , Output_section * -- , size_t relnum -- , const unsigned char *preloc -- , const Sized_symbol* gsym -- , const Symbol_value* symval -- , unsigned char* view -- , Address address -- , section_size_type --){ -- const Rela rela(preloc); -- auto r_type = elfcpp::elf_r_type(rela.get_r_info()); -- auto r_offset = rela.get_r_offset(); -- auto r_addend = rela.get_r_addend(); -- auto r_info = rela.get_r_info(); -- auto r_sym = elfcpp::elf_r_sym(r_info); -- auto object = relinfo->object; -- -- switch(r_type){ -- case elfcpp::R_SW_64_NONE: -- // This reloc only immediately follows a R_SW_64_LITERAL reloc, and it -- // does not do any real relocation. -- case elfcpp::R_SW_64_LITUSE: -- case elfcpp::R_SW_64_GLOB_DAT: -- case elfcpp::R_SW_64_JMP_SLOT: -- case elfcpp::R_SW_64_RELATIVE: -- // Nothing to do. -- break; -- case elfcpp::R_SW_64_REFLONG: { -- auto val = symval->value(object, r_addend); -- Rf::rel32(view, val); -- }break; -- case elfcpp::R_SW_64_REFQUAD: { -- auto val = symval->value(object, r_addend); -- Rf::rel64(view, val); -- }break; -- case elfcpp::R_SW_64_GPREL32: { -- auto got = target->got_section(); -- auto disp = symval->value(object, r_addend) - got->address() - got->gp_offset(object); -- disp += Inst::readval(view); -- Inst::writeval(view, disp); -- }break; -- case elfcpp::R_SW_64_GOTTPREL: -- case elfcpp::R_SW_64_LITERAL: { -- auto got = target->got_section(); -- auto use_plt = target->is_jsr_user(object, relinfo->data_shndx, relnum); -- auto offset = got->sym_entry_offset(object, gsym, r_sym, r_addend, use_plt) -- - got->gp_offset(object); -- auto literal_inst = Inst::readval(view); -- -- if(INVALID_OFFSET != literal_got_offset){ -- auto hi_view = view - r_offset + literal_got_offset; -- auto hi_inst = Inst::readval(hi_view); -- // TODO: Check the protocol is correct. -- -- // Change previous instruction with R_SW_64_LITERAL_GOT to load the high part of GOT. -- Inst::writeval(hi_view, bit_select32(hi_inst, high(offset), 0xffff)); -- // Change the base register of low load to the destination register of the high load. -- literal_inst = bit_select32( -- literal_inst -- , (hi_inst & RA_MASK) >> (RA_SHIFT - RB_SHIFT) -- , RC_MASK << RB_SHIFT -- ); -- }else if(static_cast(offset) < INT16_MIN || INT16_MAX < static_cast(offset)){ -- gold_error("%s: relocation '%s' at offset %#lx overflowed %#lx." -- , relinfo->object->name().data() -- , get_relocation_name(r_type) -- , r_offset -- , offset -- ); -- } -- Inst::writeval(view, bit_select32(literal_inst, offset, 0xffff)); -- }break; -- case elfcpp::R_SW_64_GPDISP: { -- auto got = target->got_section(); -- auto disp = got->address() + got->gp_offset(object) - address; -- do_gpdisp(view, view + r_addend, disp); -- }break; -- case elfcpp::R_SW_64_BRADDR: -- case elfcpp::R_SW_64_BRSGP: -- { -- auto inst = Inst::readval(view); -- auto val = (symval->value(object, r_addend) - address) / 4 - 1; -- Inst::writeval(view, bit_select32(inst, val, 0x1fffff)); -- }break; -- case elfcpp::R_SW_64_HINT: { -- auto inst = Inst::readval(view); -- auto disp = (symval->value(object, r_addend) ?: address +4) - address; -- disp = (disp >> 2) - 1; -- Inst::writeval(view, bit_select32(inst, disp, 0xffff)); -- }break; -- case elfcpp::R_SW_64_SREL16: { -- auto disp = symval->value(object, r_addend) - address; -- Rf::rel16(view, disp); -- }break; -- case elfcpp::R_SW_64_SREL32: { -- auto disp = symval->value(object, r_addend) - address; -- Rf::rel32(view, disp); -- }break; -- case elfcpp::R_SW_64_SREL64: { -- auto disp = symval->value(object, r_addend) - address; -- Rf::rel64(view, disp); -- }break; -- case elfcpp::R_SW_64_GPRELHIGH: { -- auto got = target->got_section(); -- auto disp = symval->value(object, r_addend) - got->address() - got->gp_offset(object); -- auto inst = Inst::readval(view); -- Inst::writeval(view, bit_select32(inst, high(disp), 0xffff)); -- }break; -- case elfcpp::R_SW_64_GPREL16: -- case elfcpp::R_SW_64_GPRELLOW: { -- auto got = target->got_section(); -- auto disp = symval->value(object, r_addend) - got->address() - got->gp_offset(object); -- auto inst = Inst::readval(view); -- Inst::writeval(view, bit_select32(inst, disp, 0xffff)); -- }break; -- case elfcpp::R_SW_64_TLSGD: { -- auto got = target->got_section(); -- auto disp = got->sym_tls_offset(object, {gsym, object, r_sym}) - got->gp_offset(object); -- auto inst = Inst::readval(view); -- Inst::writeval(view, bit_select32(inst, disp, 0xffff)); -- }break; -- case elfcpp::R_SW_64_TLS_LDM: { -- auto got = target->got_section(); -- auto disp = got->sym_tls_offset(object, {nullptr, object, 0}) - got->gp_offset(object); -- auto inst = Inst::readval(view); -- Inst::writeval(view, bit_select32(inst, disp, 0xffff)); -- }break; -- case elfcpp::R_SW_64_DTPRELHI: { -- auto inst = Inst::readval(view); -- auto val = symval->value(object, r_addend); -- Inst::writeval(view, bit_select32(inst, high(val), 0xffff)); -- }break; -- case elfcpp::R_SW_64_DTPRELLO: { -- auto inst = Inst::readval(view); -- auto val = symval->value(object, r_addend); -- Inst::writeval(view, bit_select32(inst, val, 0xffff)); -- }break; -- case elfcpp::R_SW_64_TPREL64: { -- auto val = symval->value(object, r_addend) + target->tls_offset(); -- Rf::rel64(view, val); -- }break; -- case elfcpp::R_SW_64_TPRELHI: { -- auto inst = Inst::readval(view); -- auto val = symval->value(object, r_addend) + target->tls_offset(); -- Inst::writeval(view, bit_select32(inst, high(val), 0xffff)); -- }break; -- case elfcpp::R_SW_64_TPRELLO: { -- auto inst = Inst::readval(view); -- auto val = symval->value(object, r_addend) + target->tls_offset(); -- Inst::writeval(view, bit_select32(inst, val, 0xffff)); -- }break; -- case elfcpp::R_SW_64_TPREL16: { -- auto val = symval->value(object, r_addend) + target->tls_offset(); -- Rf::rel16(view, val); -- }break; -- case elfcpp::R_SW_64_LITERAL_GOT: -- literal_got_offset = r_offset; -- return true; -- default: -- gold_error_at_location( -- relinfo -- , relnum -- , r_offset -- , _("can't handle relocation '%s'.") -- , get_relocation_name(r_type) -- ); -- break; -- } -- -- literal_got_offset = INVALID_OFFSET; -- return true; --} -- --template --Target::Target_info X::Target_sw_64::sw64_info = { -- E::size, // size -- E::big_endian, // is_big_endian -- elfcpp::EM_SW_64, // machine_code -- false, // has_make_symbol -- false, // has_resolve -- false, // has_code_fill -- false, // is_default_stack_executable -- false, // can_icf_inline_merge_sections -- '\0', // wrap_char -- "/lib/ld-linux.so.2", // dynamic_linker -- 0x120000000, // default_text_segment_address -- 64 * 1024, // abi_pagesize -- 64 * 1024, // common_pagesize -- false, // isolate_execinstr -- 0, // rosegment_gap -- elfcpp::SHN_UNDEF, // small_common_shndx -- elfcpp::SHN_UNDEF, // large_common_shndx -- 0, // small_common_section_flags -- 0, // large_common_section_flags -- NULL, // attributes_section -- NULL, // attributes_vendor -- "_start", // entry_symbol_name -- 64, // hash_entry_size -- elfcpp::SHT_PROGBITS, // unwind_section_type --}; -- --template --class X::Target_selector_sw_64: public Target_selector --{ -- public: -- Target_selector_sw_64(); -- -- virtual Target* -- do_instantiate_target() -- { return new Target_sw_64(); } --}; -- --template<> --X::Target_selector_sw_64::Target_selector_sw_64() -- : Target_selector(elfcpp::EM_SW_64, 64, false, "elf64-sw_64", "elf64sw_64") --{} -- --X::Target_selector_sw_64 target_selector_elf64_sw_64; --} // End anonymous namespace. ---- b/gprof/sw_64.c -+++ /dev/null -@@ -1,176 +0,0 @@ --/* -- * Copyright (c) 1983, 1993, 1998 -- * The Regents of the University of California. All rights reserved. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions -- * are met: -- * 1. Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * 2. Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * 3. Neither the name of the University nor the names of its contributors -- * may be used to endorse or promote products derived from this software -- * without specific prior written permission. -- * -- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -- * SUCH DAMAGE. -- */ --#include "gprof.h" --#include "search_list.h" --#include "source.h" --#include "symtab.h" --#include "cg_arcs.h" --#include "corefile.h" --#include "hist.h" -- --/* -- * Opcodes of the call instructions: -- */ --#define OP_Jxx 0x1aU --#define OP_BSR 0x34U -- --#define Jxx_FUNC_JMP 0U --#define Jxx_FUNC_JSR 1U --#define Jxx_FUNC_RET 2U --#define Jxx_FUNC_JSR_COROUTINE 3U -- --/* *INDENT-OFF* */ --/* Here to document only. We can't use this when cross compiling as -- the bitfield layout might not be the same as native. -- -- typedef union -- { -- struct -- { -- unsigned other:26; -- unsigned op_code:6; -- } -- a; -- any format -- struct -- { -- int disp:21; -- unsigned ra:5; -- unsigned op_code:6; -- } -- b; -- branch format -- struct -- { -- int hint:14; -- unsigned func:2; -- unsigned rb:5; -- unsigned ra:5; -- unsigned op_code:6; -- } -- j; -- jump format -- } -- sw_64_Instruction; --*/ --/* *INDENT-ON* */ -- --static Sym indirect_child; -- --void sw_64_find_call (Sym *, bfd_vma, bfd_vma); -- --/* -- * On the Alpha we can only detect PC relative calls, which are -- * usually generated for calls to functions within the same -- * object file only. This is still better than nothing, however. -- * (In particular it should be possible to find functions that -- * potentially call integer division routines, for example.) -- */ --void --sw_64_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc) --{ -- bfd_vma pc, dest_pc; -- unsigned int insn; -- Sym *child; -- -- if (indirect_child.name == NULL) -- { -- sym_init (&indirect_child); -- indirect_child.name = _(""); -- indirect_child.cg.prop.fract = 1.0; -- indirect_child.cg.cyc.head = &indirect_child; -- } -- -- DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"), -- parent->name, (unsigned long) p_lowpc, -- (unsigned long) p_highpc)); -- for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4) -- { -- insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space -- + pc - core_text_sect->vma)); -- switch (insn & (0x3fU << 26)) -- { -- case OP_Jxx << 26: -- /* -- * There is no simple and reliable way to determine the -- * target of a jsr (the hint bits help, but there aren't -- * enough bits to get a satisfactory hit rate). Instead, -- * for any indirect jump we simply add an arc from PARENT -- * to INDIRECT_CHILD---that way the user it at least able -- * to see that there are other calls as well. -- */ -- if ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14 -- || (insn & (3 << 14)) == Jxx_FUNC_JSR_COROUTINE << 14) -- { -- DBG (CALLDEBUG, -- printf (_("[find_call] 0x%lx: jsr%s \n"), -- (unsigned long) pc, -- ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14 -- ? "" : "_coroutine"))); -- arc_add (parent, &indirect_child, (unsigned long) 0); -- } -- break; -- -- case OP_BSR << 26: -- DBG (CALLDEBUG, -- printf (_("[find_call] 0x%lx: bsr"), (unsigned long) pc)); -- /* -- * Regular PC relative addressing. Check that this is the -- * address of a function. The linker sometimes redirects -- * the entry point by 8 bytes to skip loading the global -- * pointer, so we allow for either address: -- */ -- dest_pc = pc + 4 + (((bfd_signed_vma) (insn & 0x1fffff) -- ^ 0x100000) - 0x100000); -- if (hist_check_address (dest_pc)) -- { -- child = sym_lookup (&symtab, dest_pc); -- if (child) -- { -- DBG (CALLDEBUG, -- printf (" 0x%lx\t; name=%s, addr=0x%lx", -- (unsigned long) dest_pc, child->name, -- (unsigned long) child->addr)); -- if (child->addr == dest_pc || child->addr == dest_pc - 8) -- { -- DBG (CALLDEBUG, printf ("\n")); -- /* a hit: */ -- arc_add (parent, child, (unsigned long) 0); -- continue; -- } -- } -- } -- /* -- * Something funny going on. -- */ -- DBG (CALLDEBUG, printf ("\tbut it's a botch\n")); -- break; -- -- default: -- break; -- } -- } --} ---- b/include/coff/sw_64.h -+++ /dev/null -@@ -1,386 +0,0 @@ --/* ECOFF support on Sw_64 machines. -- coff/ecoff.h must be included before this file. -- -- Copyright (C) 2001-2018 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 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. */ -- --/********************** FILE HEADER **********************/ -- --struct external_filehdr --{ -- unsigned char f_magic[2]; /* magic number */ -- unsigned char f_nscns[2]; /* number of sections */ -- unsigned char f_timdat[4]; /* time & date stamp */ -- unsigned char f_symptr[8]; /* file pointer to symtab */ -- unsigned char f_nsyms[4]; /* number of symtab entries */ -- unsigned char f_opthdr[2]; /* sizeof(optional hdr) */ -- unsigned char f_flags[2]; /* flags */ --}; -- --/* Magic numbers are defined in coff/ecoff.h. */ --#define SW_64_ECOFF_BADMAG(x) \ -- ((x).f_magic != SW_64_MAGIC && (x).f_magic != SW_64_MAGIC_BSD) -- --#define SW_64_ECOFF_COMPRESSEDMAG(x) \ -- ((x).f_magic == SW_64_MAGIC_COMPRESSED) -- --/* The object type is encoded in the f_flags. */ --#define F_SW_64_OBJECT_TYPE_MASK 0x3000 --#define F_SW_64_NO_SHARED 0x1000 --#define F_SW_64_SHARABLE 0x2000 --#define F_SW_64_CALL_SHARED 0x3000 -- --#define FILHDR struct external_filehdr --#define FILHSZ 24 -- --/********************** AOUT "OPTIONAL HEADER" **********************/ -- --typedef struct external_aouthdr --{ -- unsigned char magic[2]; /* type of file */ -- unsigned char vstamp[2]; /* version stamp */ -- unsigned char bldrev[2]; /* ?? */ -- unsigned char padding[2]; /* pad to quadword boundary */ -- unsigned char tsize[8]; /* text size in bytes */ -- unsigned char dsize[8]; /* initialized data " " */ -- unsigned char bsize[8]; /* uninitialized data " " */ -- unsigned char entry[8]; /* entry pt. */ -- unsigned char text_start[8]; /* base of text used for this file */ -- unsigned char data_start[8]; /* base of data used for this file */ -- unsigned char bss_start[8]; /* base of bss used for this file */ -- unsigned char gprmask[4]; /* bitmask of general registers used */ -- unsigned char fprmask[4]; /* bitmask of floating point registers used */ -- unsigned char gp_value[8]; /* value for gp register */ --} AOUTHDR; -- --/* compute size of a header */ -- --#define AOUTSZ 80 --#define AOUTHDRSZ 80 -- --/********************** SECTION HEADER **********************/ -- --struct external_scnhdr --{ -- unsigned char s_name[8]; /* section name */ -- unsigned char s_paddr[8]; /* physical address, aliased s_nlib */ -- unsigned char s_vaddr[8]; /* virtual address */ -- unsigned char s_size[8]; /* section size */ -- unsigned char s_scnptr[8]; /* file ptr to raw data for section */ -- unsigned char s_relptr[8]; /* file ptr to relocation */ -- unsigned char s_lnnoptr[8]; /* file ptr to line numbers */ -- unsigned char s_nreloc[2]; /* number of relocation entries */ -- unsigned char s_nlnno[2]; /* number of line number entries*/ -- unsigned char s_flags[4]; /* flags */ --}; -- --#define SCNHDR struct external_scnhdr --#define SCNHSZ 64 -- --/********************** RELOCATION DIRECTIVES **********************/ -- --struct external_reloc --{ -- unsigned char r_vaddr[8]; -- unsigned char r_symndx[4]; -- unsigned char r_bits[4]; --}; -- --#define RELOC struct external_reloc --#define RELSZ 16 -- --/* Constants to unpack the r_bits field. The Sw_64 seems to always be -- little endian, so I haven't bothered to define big endian variants -- of these. */ -- --#define RELOC_BITS0_TYPE_LITTLE 0xff --#define RELOC_BITS0_TYPE_SH_LITTLE 0 -- --#define RELOC_BITS1_EXTERN_LITTLE 0x01 -- --#define RELOC_BITS1_OFFSET_LITTLE 0x7e --#define RELOC_BITS1_OFFSET_SH_LITTLE 1 -- --#define RELOC_BITS1_RESERVED_LITTLE 0x80 --#define RELOC_BITS1_RESERVED_SH_LITTLE 7 --#define RELOC_BITS2_RESERVED_LITTLE 0xff --#define RELOC_BITS2_RESERVED_SH_LEFT_LITTLE 1 --#define RELOC_BITS3_RESERVED_LITTLE 0x03 --#define RELOC_BITS3_RESERVED_SH_LEFT_LITTLE 9 -- --#define RELOC_BITS3_SIZE_LITTLE 0xfc --#define RELOC_BITS3_SIZE_SH_LITTLE 2 -- --/* The r_type field in a reloc is one of the following values. */ --#define SW_64_R_IGNORE 0 --#define SW_64_R_REFLONG 1 --#define SW_64_R_REFQUAD 2 --#define SW_64_R_GPREL32 3 --#define SW_64_R_LITERAL 4 --#define SW_64_R_LITUSE 5 --#define SW_64_R_GPDISP 6 --#define SW_64_R_BRADDR 7 --#define SW_64_R_HINT 8 --#define SW_64_R_SREL16 9 --#define SW_64_R_SREL32 10 --#define SW_64_R_SREL64 11 --#define SW_64_R_OP_PUSH 12 --#define SW_64_R_OP_STORE 13 --#define SW_64_R_OP_PSUB 14 --#define SW_64_R_OP_PRSHIFT 15 --#define SW_64_R_GPVALUE 16 --#define SW_64_R_GPRELHIGH 17 --#define SW_64_R_GPRELLOW 18 --#define SW_64_R_IMMED 19 -- --/* Overloaded reloc value used by Net- and OpenBSD. */ --#define SW_64_R_LITERALSLEAZY 17 -- --/* With SW_64_R_LITUSE, the r_size field is one of the following values. */ --#define SW_64_R_LU_BASE 1 --#define SW_64_R_LU_BYTOFF 2 --#define SW_64_R_LU_JSR 3 -- --/* With SW_64_R_IMMED, the r_size field is one of the following values. */ --#define SW_64_R_IMMED_GP_16 1 --#define SW_64_R_IMMED_GP_HI32 2 --#define SW_64_R_IMMED_SCN_HI32 3 --#define SW_64_R_IMMED_BR_HI32 4 --#define SW_64_R_IMMED_LO32 5 -- --/********************** SYMBOLIC INFORMATION **********************/ -- --/* Written by John Gilmore. */ -- --/* ECOFF uses COFF-like section structures, but its own symbol format. -- This file defines the symbol format in fields whose size and alignment -- will not vary on different host systems. */ -- --/* File header as a set of bytes */ -- --struct hdr_ext --{ -- unsigned char h_magic[2]; -- unsigned char h_vstamp[2]; -- unsigned char h_ilineMax[4]; -- unsigned char h_idnMax[4]; -- unsigned char h_ipdMax[4]; -- unsigned char h_isymMax[4]; -- unsigned char h_ioptMax[4]; -- unsigned char h_iauxMax[4]; -- unsigned char h_issMax[4]; -- unsigned char h_issExtMax[4]; -- unsigned char h_ifdMax[4]; -- unsigned char h_crfd[4]; -- unsigned char h_iextMax[4]; -- unsigned char h_cbLine[8]; -- unsigned char h_cbLineOffset[8]; -- unsigned char h_cbDnOffset[8]; -- unsigned char h_cbPdOffset[8]; -- unsigned char h_cbSymOffset[8]; -- unsigned char h_cbOptOffset[8]; -- unsigned char h_cbAuxOffset[8]; -- unsigned char h_cbSsOffset[8]; -- unsigned char h_cbSsExtOffset[8]; -- unsigned char h_cbFdOffset[8]; -- unsigned char h_cbRfdOffset[8]; -- unsigned char h_cbExtOffset[8]; --}; -- --/* File descriptor external record */ -- --struct fdr_ext --{ -- unsigned char f_adr[8]; -- unsigned char f_cbLineOffset[8]; -- unsigned char f_cbLine[8]; -- unsigned char f_cbSs[8]; -- unsigned char f_rss[4]; -- unsigned char f_issBase[4]; -- unsigned char f_isymBase[4]; -- unsigned char f_csym[4]; -- unsigned char f_ilineBase[4]; -- unsigned char f_cline[4]; -- unsigned char f_ioptBase[4]; -- unsigned char f_copt[4]; -- unsigned char f_ipdFirst[4]; -- unsigned char f_cpd[4]; -- unsigned char f_iauxBase[4]; -- unsigned char f_caux[4]; -- unsigned char f_rfdBase[4]; -- unsigned char f_crfd[4]; -- unsigned char f_bits1[1]; -- unsigned char f_bits2[3]; -- unsigned char f_padding[4]; --}; -- --#define FDR_BITS1_LANG_BIG 0xF8 --#define FDR_BITS1_LANG_SH_BIG 3 --#define FDR_BITS1_LANG_LITTLE 0x1F --#define FDR_BITS1_LANG_SH_LITTLE 0 -- --#define FDR_BITS1_FMERGE_BIG 0x04 --#define FDR_BITS1_FMERGE_LITTLE 0x20 -- --#define FDR_BITS1_FREADIN_BIG 0x02 --#define FDR_BITS1_FREADIN_LITTLE 0x40 -- --#define FDR_BITS1_FBIGENDIAN_BIG 0x01 --#define FDR_BITS1_FBIGENDIAN_LITTLE 0x80 -- --#define FDR_BITS2_GLEVEL_BIG 0xC0 --#define FDR_BITS2_GLEVEL_SH_BIG 6 --#define FDR_BITS2_GLEVEL_LITTLE 0x03 --#define FDR_BITS2_GLEVEL_SH_LITTLE 0 -- --/* We ignore the `reserved' field in bits2. */ -- --/* Procedure descriptor external record */ -- --struct pdr_ext { -- unsigned char p_adr[8]; -- unsigned char p_cbLineOffset[8]; -- unsigned char p_isym[4]; -- unsigned char p_iline[4]; -- unsigned char p_regmask[4]; -- unsigned char p_regoffset[4]; -- unsigned char p_iopt[4]; -- unsigned char p_fregmask[4]; -- unsigned char p_fregoffset[4]; -- unsigned char p_frameoffset[4]; -- unsigned char p_lnLow[4]; -- unsigned char p_lnHigh[4]; -- unsigned char p_gp_prologue[1]; -- unsigned char p_bits1[1]; -- unsigned char p_bits2[1]; -- unsigned char p_localoff[1]; -- unsigned char p_framereg[2]; -- unsigned char p_pcreg[2]; --}; -- --#define PDR_BITS1_GP_USED_BIG 0x80 --#define PDR_BITS1_REG_FRAME_BIG 0x40 --#define PDR_BITS1_PROF_BIG 0x20 --#define PDR_BITS1_RESERVED_BIG 0x1f --#define PDR_BITS1_RESERVED_SH_LEFT_BIG 8 --#define PDR_BITS2_RESERVED_BIG 0xff --#define PDR_BITS2_RESERVED_SH_BIG 0 -- --#define PDR_BITS1_GP_USED_LITTLE 0x01 --#define PDR_BITS1_REG_FRAME_LITTLE 0x02 --#define PDR_BITS1_PROF_LITTLE 0x04 --#define PDR_BITS1_RESERVED_LITTLE 0xf8 --#define PDR_BITS1_RESERVED_SH_LITTLE 3 --#define PDR_BITS2_RESERVED_LITTLE 0xff --#define PDR_BITS2_RESERVED_SH_LEFT_LITTLE 5 -- --/* Line numbers */ -- --struct line_ext { -- unsigned char l_line[4]; --}; -- --/* Symbol external record */ -- --struct sym_ext { -- unsigned char s_value[8]; -- unsigned char s_iss[4]; -- unsigned char s_bits1[1]; -- unsigned char s_bits2[1]; -- unsigned char s_bits3[1]; -- unsigned char s_bits4[1]; --}; -- --#define SYM_BITS1_ST_BIG 0xFC --#define SYM_BITS1_ST_SH_BIG 2 --#define SYM_BITS1_ST_LITTLE 0x3F --#define SYM_BITS1_ST_SH_LITTLE 0 -- --#define SYM_BITS1_SC_BIG 0x03 --#define SYM_BITS1_SC_SH_LEFT_BIG 3 --#define SYM_BITS1_SC_LITTLE 0xC0 --#define SYM_BITS1_SC_SH_LITTLE 6 -- --#define SYM_BITS2_SC_BIG 0xE0 --#define SYM_BITS2_SC_SH_BIG 5 --#define SYM_BITS2_SC_LITTLE 0x07 --#define SYM_BITS2_SC_SH_LEFT_LITTLE 2 -- --#define SYM_BITS2_RESERVED_BIG 0x10 --#define SYM_BITS2_RESERVED_LITTLE 0x08 -- --#define SYM_BITS2_INDEX_BIG 0x0F --#define SYM_BITS2_INDEX_SH_LEFT_BIG 16 --#define SYM_BITS2_INDEX_LITTLE 0xF0 --#define SYM_BITS2_INDEX_SH_LITTLE 4 -- --#define SYM_BITS3_INDEX_SH_LEFT_BIG 8 --#define SYM_BITS3_INDEX_SH_LEFT_LITTLE 4 -- --#define SYM_BITS4_INDEX_SH_LEFT_BIG 0 --#define SYM_BITS4_INDEX_SH_LEFT_LITTLE 12 -- --/* External symbol external record */ -- --struct ext_ext { -- struct sym_ext es_asym; -- unsigned char es_bits1[1]; -- unsigned char es_bits2[3]; -- unsigned char es_ifd[4]; --}; -- --#define EXT_BITS1_JMPTBL_BIG 0x80 --#define EXT_BITS1_JMPTBL_LITTLE 0x01 -- --#define EXT_BITS1_COBOL_MAIN_BIG 0x40 --#define EXT_BITS1_COBOL_MAIN_LITTLE 0x02 -- --#define EXT_BITS1_WEAKEXT_BIG 0x20 --#define EXT_BITS1_WEAKEXT_LITTLE 0x04 -- --/* Dense numbers external record */ -- --struct dnr_ext { -- unsigned char d_rfd[4]; -- unsigned char d_index[4]; --}; -- --/* Relative file descriptor */ -- --struct rfd_ext { -- unsigned char rfd[4]; --}; -- --/* Optimizer symbol external record */ -- --struct opt_ext { -- unsigned char o_bits1[1]; -- unsigned char o_bits2[1]; -- unsigned char o_bits3[1]; -- unsigned char o_bits4[1]; -- struct rndx_ext o_rndx; -- unsigned char o_offset[4]; --}; -- --#define OPT_BITS2_VALUE_SH_LEFT_BIG 16 --#define OPT_BITS2_VALUE_SH_LEFT_LITTLE 0 -- --#define OPT_BITS3_VALUE_SH_LEFT_BIG 8 --#define OPT_BITS3_VALUE_SH_LEFT_LITTLE 8 -- --#define OPT_BITS4_VALUE_SH_LEFT_BIG 0 --#define OPT_BITS4_VALUE_SH_LEFT_LITTLE 16 ---- b/include/elf/sw_64.h -+++ /dev/null -@@ -1,136 +0,0 @@ --/* SW_64 ELF support for BFD. -- Copyright (C) 1996-2018 Free Software Foundation, Inc. -- -- By Eric Youngdale, . No processor supplement available -- for this platform. -- -- This file is part of BFD, the Binary File Descriptor library. -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. */ -- --/* This file holds definitions specific to the SW_64 ELF ABI. Note -- that most of this is not actually implemented by BFD. */ -- --#ifndef _ELF_SW_64_H --#define _ELF_SW_64_H -- --/* Processor specific flags for the ELF header e_flags field. */ -- --/* All addresses must be below 2GB. */ --#define EF_SW_64_32BIT 0x00000001 -- --/* All relocations needed for relaxation with code movement are present. */ --#define EF_SW_64_CANRELAX 0x00000002 -- --/* Processor specific section flags. */ -- --/* This section must be in the global data area. */ --#define SHF_SW_64_GPREL 0x10000000 -- --/* Section contains some sort of debugging information. The exact -- format is unspecified. It's probably ECOFF symbols. */ --#define SHT_SW_64_DEBUG 0x70000001 -- --/* Section contains register usage information. */ --#define SHT_SW_64_REGINFO 0x70000002 -- -- --/* Special values for the st_other field in the symbol table. */ -- --#define STO_SW_64_NOPV 0x80 --#define STO_SW_64_STD_GPLOAD 0x88 -- --/* Special values for Elf64_Dyn tag. */ --#define DT_SW_64_PLTRO DT_LOPROC -- --#include "elf/reloc-macros.h" -- -- --unsigned long bfd_elf_sw_64_mach (flagword flags); -- --enum --{ -- E_SW_64_MACH_SW6A = 4, -- E_SW_64_MACH_SW6B = 8, --}; -- --#define EF_SW_64_MACH ~(0x3) -- --#define E_SW_64_MACH_SW6A 4 --#define E_SW_64_MACH_SW6B 8 -- --/* Sw_64 relocs. */ --START_RELOC_NUMBERS (elf_sw_64_reloc_type) -- RELOC_NUMBER (R_SW_64_NONE, 0) /* No reloc */ -- RELOC_NUMBER (R_SW_64_REFLONG, 1) /* Direct 32 bit */ -- RELOC_NUMBER (R_SW_64_REFQUAD, 2) /* Direct 64 bit */ -- RELOC_NUMBER (R_SW_64_GPREL32, 3) /* GP relative 32 bit */ -- RELOC_NUMBER (R_SW_64_LITERAL, 4) /* GP relative 16 bit w/optimization */ -- RELOC_NUMBER (R_SW_64_LITUSE, 5) /* Optimization hint for LITERAL */ -- RELOC_NUMBER (R_SW_64_GPDISP, 6) /* Add displacement to GP */ -- RELOC_NUMBER (R_SW_64_BRADDR, 7) /* PC+4 relative 23 bit shifted */ -- RELOC_NUMBER (R_SW_64_HINT, 8) /* PC+4 relative 16 bit shifted */ -- RELOC_NUMBER (R_SW_64_SREL16, 9) /* PC relative 16 bit */ -- RELOC_NUMBER (R_SW_64_SREL32, 10) /* PC relative 32 bit */ -- RELOC_NUMBER (R_SW_64_SREL64, 11) /* PC relative 64 bit */ -- -- /* Skip 12 - 16; deprecated ECOFF relocs. */ -- -- RELOC_NUMBER (R_SW_64_GPRELHIGH, 17) /* GP relative 32 bit, high 16 bits */ -- RELOC_NUMBER (R_SW_64_GPRELLOW, 18) /* GP relative 32 bit, low 16 bits */ -- RELOC_NUMBER (R_SW_64_GPREL16, 19) /* GP relative 16 bit */ -- -- /* Skip 20 - 23; deprecated ECOFF relocs. */ -- -- /* These relocations are specific to shared libraries. */ -- RELOC_NUMBER (R_SW_64_COPY, 24) /* Copy symbol at runtime */ -- RELOC_NUMBER (R_SW_64_GLOB_DAT, 25) /* Create GOT entry */ -- RELOC_NUMBER (R_SW_64_JMP_SLOT, 26) /* Create PLT entry */ -- RELOC_NUMBER (R_SW_64_RELATIVE, 27) /* Adjust by program base */ -- -- /* Like BRADDR, but assert that the source and target object file -- share the same GP value, and adjust the target address for -- STO_SW_64_STD_GPLOAD. */ -- RELOC_NUMBER (R_SW_64_BRSGP, 28) -- -- /* Thread-Local Storage. */ -- RELOC_NUMBER (R_SW_64_TLSGD, 29) -- RELOC_NUMBER (R_SW_64_TLSLDM, 30) -- RELOC_NUMBER (R_SW_64_DTPMOD64, 31) -- RELOC_NUMBER (R_SW_64_GOTDTPREL, 32) -- RELOC_NUMBER (R_SW_64_DTPREL64, 33) -- RELOC_NUMBER (R_SW_64_DTPRELHI, 34) -- RELOC_NUMBER (R_SW_64_DTPRELLO, 35) -- RELOC_NUMBER (R_SW_64_DTPREL16, 36) -- RELOC_NUMBER (R_SW_64_GOTTPREL, 37) -- RELOC_NUMBER (R_SW_64_TPREL64, 38) -- RELOC_NUMBER (R_SW_64_TPRELHI, 39) -- RELOC_NUMBER (R_SW_64_TPRELLO, 40) -- RELOC_NUMBER (R_SW_64_TPREL16, 41) -- RELOC_NUMBER (R_SW_64_BR26ADDR, 42) -- RELOC_NUMBER (R_SW_64_LITERAL_GOT, 43) /* GP relative 16 bit */ -- --END_RELOC_NUMBERS (R_SW_64_max) -- --#define LITUSE_SW_64_ADDR 0 --#define LITUSE_SW_64_BASE 1 --#define LITUSE_SW_64_BYTOFF 2 --#define LITUSE_SW_64_JSR 3 --#define LITUSE_SW_64_TLSGD 4 --#define LITUSE_SW_64_TLSLDM 5 --#define LITUSE_SW_64_JSRDIRECT 6 -- --#endif /* _ELF_SW_64_H */ ---- b/include/opcode/pe.h -+++ /dev/null -@@ -1,605 +0,0 @@ --/* pe.h - PE COFF header information -- -- Copyright (C) 1999-2018 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 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software Foundation, -- Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ --#ifndef _PE_H --#define _PE_H -- --#include "msdos.h" -- --/* NT specific file attributes. */ --#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 --#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 --#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 --#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 --#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 --#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 --#define IMAGE_FILE_16BIT_MACHINE 0x0040 --#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 --#define IMAGE_FILE_32BIT_MACHINE 0x0100 --#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 --#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 --#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 --#define IMAGE_FILE_SYSTEM 0x1000 --#define IMAGE_FILE_DLL 0x2000 --#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 --#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 -- --/* DllCharacteristics flag bits. The inconsistent naming may seem -- odd, but that is how they are defined in the PE specification. */ --#define IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 --#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040 --#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080 --#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100 --#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 --#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 --#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 --#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 --#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 -- --/* Additional flags to be set for section headers to allow the NT loader to -- read and write to the section data (to replace the addresses of data in -- dlls for one thing); also to execute the section in .text's case. */ --#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 --#define IMAGE_SCN_MEM_EXECUTE 0x20000000 --#define IMAGE_SCN_MEM_READ 0x40000000 --#define IMAGE_SCN_MEM_WRITE 0x80000000 -- --/* Section characteristics added for ppc-nt. */ -- --#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */ -- --#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */ --#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */ --#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */ -- --#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */ --#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */ --#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */ --#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */ -- --#define IMAGE_SCN_MEM_FARDATA 0x00008000 -- --#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 --#define IMAGE_SCN_MEM_16BIT 0x00020000 --#define IMAGE_SCN_MEM_LOCKED 0x00040000 --#define IMAGE_SCN_MEM_PRELOAD 0x00080000 -- --/* Bit position in the s_flags field where the alignment values start. */ --#define IMAGE_SCN_ALIGN_POWER_BIT_POS 20 --#define IMAGE_SCN_ALIGN_POWER_BIT_MASK 0x00f00000 --#define IMAGE_SCN_ALIGN_POWER_NUM(val) \ -- (((val) >> IMAGE_SCN_ALIGN_POWER_BIT_POS) - 1) --#define IMAGE_SCN_ALIGN_POWER_CONST(val) \ -- (((val) + 1) << IMAGE_SCN_ALIGN_POWER_BIT_POS) -- --#define IMAGE_SCN_ALIGN_1BYTES IMAGE_SCN_ALIGN_POWER_CONST (0) --#define IMAGE_SCN_ALIGN_2BYTES IMAGE_SCN_ALIGN_POWER_CONST (1) --#define IMAGE_SCN_ALIGN_4BYTES IMAGE_SCN_ALIGN_POWER_CONST (2) --#define IMAGE_SCN_ALIGN_8BYTES IMAGE_SCN_ALIGN_POWER_CONST (3) --/* Default alignment if no others are specified. */ --#define IMAGE_SCN_ALIGN_16BYTES IMAGE_SCN_ALIGN_POWER_CONST (4) --#define IMAGE_SCN_ALIGN_32BYTES IMAGE_SCN_ALIGN_POWER_CONST (5) --#define IMAGE_SCN_ALIGN_64BYTES IMAGE_SCN_ALIGN_POWER_CONST (6) --#define IMAGE_SCN_ALIGN_128BYTES IMAGE_SCN_ALIGN_POWER_CONST (7) --#define IMAGE_SCN_ALIGN_256BYTES IMAGE_SCN_ALIGN_POWER_CONST (8) --#define IMAGE_SCN_ALIGN_512BYTES IMAGE_SCN_ALIGN_POWER_CONST (9) --#define IMAGE_SCN_ALIGN_1024BYTES IMAGE_SCN_ALIGN_POWER_CONST (10) --#define IMAGE_SCN_ALIGN_2048BYTES IMAGE_SCN_ALIGN_POWER_CONST (11) --#define IMAGE_SCN_ALIGN_4096BYTES IMAGE_SCN_ALIGN_POWER_CONST (12) --#define IMAGE_SCN_ALIGN_8192BYTES IMAGE_SCN_ALIGN_POWER_CONST (13) -- --/* Encode alignment power into IMAGE_SCN_ALIGN bits of s_flags. */ --#define COFF_ENCODE_ALIGNMENT(SECTION, ALIGNMENT_POWER) \ -- ((SECTION).s_flags |= IMAGE_SCN_ALIGN_POWER_CONST ((ALIGNMENT_POWER) <= 13 \ -- ? (ALIGNMENT_POWER) : 13)) --#define COFF_DECODE_ALIGNMENT(X) \ -- IMAGE_SCN_ALIGN_POWER_NUM ((X) & IMAGE_SCN_ALIGN_POWER_BIT_MASK) -- --#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */ --#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */ --#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */ --#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */ -- --/* COMDAT selection codes. */ -- --#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */ --#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */ --#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */ --#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */ --#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */ -- --/* Machine numbers. */ -- --#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 --#define IMAGE_FILE_MACHINE_ALPHA 0x0184 --#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 --#define IMAGE_FILE_MACHINE_SW_64 0x0184 --#define IMAGE_FILE_MACHINE_SW_6464 0x0284 --#define IMAGE_FILE_MACHINE_AM33 0x01d3 --#define IMAGE_FILE_MACHINE_AMD64 0x8664 --#define IMAGE_FILE_MACHINE_ARM 0x01c0 --#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 --#define IMAGE_FILE_MACHINE_CEE 0xc0ee --#define IMAGE_FILE_MACHINE_CEF 0x0cef --#define IMAGE_FILE_MACHINE_EBC 0x0ebc --#define IMAGE_FILE_MACHINE_I386 0x014c --#define IMAGE_FILE_MACHINE_IA64 0x0200 --#define IMAGE_FILE_MACHINE_M32R 0x9041 --#define IMAGE_FILE_MACHINE_M68K 0x0268 --#define IMAGE_FILE_MACHINE_MIPS16 0x0266 --#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 --#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 --#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 --#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 --#define IMAGE_FILE_MACHINE_R10000 0x0168 --#define IMAGE_FILE_MACHINE_R3000 0x0162 --#define IMAGE_FILE_MACHINE_R4000 0x0166 --#define IMAGE_FILE_MACHINE_SH3 0x01a2 --#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 --#define IMAGE_FILE_MACHINE_SH3E 0x01a4 --#define IMAGE_FILE_MACHINE_SH4 0x01a6 --#define IMAGE_FILE_MACHINE_SH5 0x01a8 --#define IMAGE_FILE_MACHINE_THUMB 0x01c2 --#define IMAGE_FILE_MACHINE_TRICORE 0x0520 --#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 --#define IMAGE_FILE_MACHINE_AMD64 0x8664 -- --#define IMAGE_SUBSYSTEM_UNKNOWN 0 --#define IMAGE_SUBSYSTEM_NATIVE 1 --#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 --#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 --#define IMAGE_SUBSYSTEM_POSIX_CUI 7 --#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 --#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 --#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 --#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 --#define IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 --#define IMAGE_SUBSYSTEM_XBOX 14 -- --/* NT allows long filenames, we want to accommodate this. -- This may break some of the bfd functions. */ --#undef FILNMLEN --#define FILNMLEN 18 /* # characters in a file name. */ -- --struct external_PEI_IMAGE_hdr --{ -- char nt_signature[4]; /* Required NT signature, 0x4550. */ -- -- /* From standard header. */ -- char f_magic[2]; /* Magic number. */ -- char f_nscns[2]; /* Number of sections. */ -- char f_timdat[4]; /* Time & date stamp. */ -- char f_symptr[4]; /* File pointer to symtab. */ -- char f_nsyms[4]; /* Number of symtab entries. */ -- char f_opthdr[2]; /* Sizeof(optional hdr). */ -- char f_flags[2]; /* Flags. */ --}; -- --struct external_PEI_filehdr --{ -- /* DOS header fields - always at offset zero in the EXE file. */ -- char e_magic[2]; /* Magic number, 0x5a4d. */ -- char e_cblp[2]; /* Bytes on last page of file, 0x90. */ -- char e_cp[2]; /* Pages in file, 0x3. */ -- char e_crlc[2]; /* Relocations, 0x0. */ -- char e_cparhdr[2]; /* Size of header in paragraphs, 0x4. */ -- char e_minalloc[2]; /* Minimum extra paragraphs needed, 0x0. */ -- char e_maxalloc[2]; /* Maximum extra paragraphs needed, 0xFFFF. */ -- char e_ss[2]; /* Initial (relative) SS value, 0x0. */ -- char e_sp[2]; /* Initial SP value, 0xb8. */ -- char e_csum[2]; /* Checksum, 0x0. */ -- char e_ip[2]; /* Initial IP value, 0x0. */ -- char e_cs[2]; /* Initial (relative) CS value, 0x0. */ -- char e_lfarlc[2]; /* File address of relocation table, 0x40. */ -- char e_ovno[2]; /* Overlay number, 0x0. */ -- char e_res[4][2]; /* Reserved words, all 0x0. */ -- char e_oemid[2]; /* OEM identifier (for e_oeminfo), 0x0. */ -- char e_oeminfo[2]; /* OEM information; e_oemid specific, 0x0. */ -- char e_res2[10][2]; /* Reserved words, all 0x0. */ -- char e_lfanew[4]; /* File address of new exe header, usually 0x80. */ -- char dos_message[16][4]; /* Other stuff, always follow DOS header. */ -- -- /* Note: additional bytes may be inserted before the signature. Use -- the e_lfanew field to find the actual location of the NT signature. */ -- -- char nt_signature[4]; /* Required NT signature, 0x4550. */ -- -- /* From standard header. */ -- char f_magic[2]; /* Magic number. */ -- char f_nscns[2]; /* Number of sections. */ -- char f_timdat[4]; /* Time & date stamp. */ -- char f_symptr[4]; /* File pointer to symtab. */ -- char f_nsyms[4]; /* Number of symtab entries. */ -- char f_opthdr[2]; /* Sizeof(optional hdr). */ -- char f_flags[2]; /* Flags. */ --}; -- --#ifdef COFF_IMAGE_WITH_PE -- --/* The filehdr is only weird in images. */ -- --#undef FILHDR --#define FILHDR struct external_PEI_filehdr --#undef FILHSZ --#define FILHSZ 152 -- --#endif /* COFF_IMAGE_WITH_PE */ -- --/* 32-bit PE a.out header: */ -- --typedef struct --{ -- AOUTHDR standard; -- -- /* NT extra fields; see internal.h for descriptions. */ -- char ImageBase[4]; -- char SectionAlignment[4]; -- char FileAlignment[4]; -- char MajorOperatingSystemVersion[2]; -- char MinorOperatingSystemVersion[2]; -- char MajorImageVersion[2]; -- char MinorImageVersion[2]; -- char MajorSubsystemVersion[2]; -- char MinorSubsystemVersion[2]; -- char Reserved1[4]; -- char SizeOfImage[4]; -- char SizeOfHeaders[4]; -- char CheckSum[4]; -- char Subsystem[2]; -- char DllCharacteristics[2]; -- char SizeOfStackReserve[4]; -- char SizeOfStackCommit[4]; -- char SizeOfHeapReserve[4]; -- char SizeOfHeapCommit[4]; -- char LoaderFlags[4]; -- char NumberOfRvaAndSizes[4]; -- /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */ -- char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars. */ --} PEAOUTHDR; -- --#undef AOUTSZ --#define AOUTSZ (AOUTHDRSZ + 196) -- --/* Like PEAOUTHDR, except that the "standard" member has no BaseOfData -- (aka data_start) member and that some of the members are 8 instead -- of just 4 bytes long. */ --typedef struct --{ --#ifdef AOUTHDRSZ64 -- AOUTHDR64 standard; --#else -- AOUTHDR standard; --#endif -- /* NT extra fields; see internal.h for descriptions. */ -- char ImageBase[8]; -- char SectionAlignment[4]; -- char FileAlignment[4]; -- char MajorOperatingSystemVersion[2]; -- char MinorOperatingSystemVersion[2]; -- char MajorImageVersion[2]; -- char MinorImageVersion[2]; -- char MajorSubsystemVersion[2]; -- char MinorSubsystemVersion[2]; -- char Reserved1[4]; -- char SizeOfImage[4]; -- char SizeOfHeaders[4]; -- char CheckSum[4]; -- char Subsystem[2]; -- char DllCharacteristics[2]; -- char SizeOfStackReserve[8]; -- char SizeOfStackCommit[8]; -- char SizeOfHeapReserve[8]; -- char SizeOfHeapCommit[8]; -- char LoaderFlags[4]; -- char NumberOfRvaAndSizes[4]; -- /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */ -- char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars. */ --} PEPAOUTHDR; -- --#ifdef AOUTHDRSZ64 --#define PEPAOUTSZ (AOUTHDRSZ64 + 196 + 5 * 4) /* = 240 */ --#else --#define PEPAOUTSZ 240 --#endif -- --#undef E_FILNMLEN --#define E_FILNMLEN 18 /* # characters in a file name. */ -- --/* Import Tyoes fot ILF format object files.. */ --#define IMPORT_CODE 0 --#define IMPORT_DATA 1 --#define IMPORT_CONST 2 -- --/* Import Name Tyoes for ILF format object files. */ --#define IMPORT_ORDINAL 0 --#define IMPORT_NAME 1 --#define IMPORT_NAME_NOPREFIX 2 --#define IMPORT_NAME_UNDECORATE 3 -- --/* Weak external characteristics. */ --#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 --#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 --#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 -- --/* Bigobj header. */ --struct external_ANON_OBJECT_HEADER_BIGOBJ --{ -- /* ANON_OBJECT_HEADER_V2 header. */ -- char Sig1[2]; -- char Sig2[2]; -- char Version[2]; -- char Machine[2]; -- char TimeDateStamp[4]; -- char ClassID[16]; -- char SizeOfData[4]; -- char Flags[4]; -- char MetaDataSize[4]; -- char MetaDataOffset[4]; -- -- /* BIGOBJ specific. */ -- char NumberOfSections[4]; -- char PointerToSymbolTable[4]; -- char NumberOfSymbols[4]; --}; -- --#define FILHSZ_BIGOBJ (14 * 4) -- --struct external_SYMBOL_EX --{ -- union -- { -- char e_name[E_SYMNMLEN]; -- -- struct -- { -- char e_zeroes[4]; -- char e_offset[4]; -- } e; -- } e; -- -- char e_value[4]; -- char e_scnum[4]; -- char e_type[2]; -- char e_sclass[1]; -- char e_numaux[1]; --} ATTRIBUTE_PACKED ; -- --#define SYMENT_BIGOBJ struct external_SYMBOL_EX --#define SYMESZ_BIGOBJ 20 -- --#define FILNMLEN_BIGOBJ 20 -- --union external_AUX_SYMBOL_EX --{ -- struct -- { -- char WeakDefaultSymIndex[4]; -- char WeakSearchType[4]; -- char rgbReserved[12]; -- } Sym; -- -- struct -- { -- char Name[FILNMLEN_BIGOBJ]; -- } File; -- -- struct -- { -- char Length[4]; /* Section length. */ -- char NumberOfRelocations[2];/* # relocation entries. */ -- char NumberOfLinenumbers[2];/* # line numbers. */ -- char Checksum[4]; /* Section COMDAT checksum. */ -- char Number[2]; /* COMDAT associated section index. */ -- char Selection[1]; /* COMDAT selection number. */ -- char bReserved[1]; -- char HighNumber[2]; /* High bits of COMDAT associated sec. */ -- char rgbReserved[2]; -- } Section; --} ATTRIBUTE_PACKED; -- --#define AUXENT_BIGOBJ union external_AUX_SYMBOL_EX --#define AUXESZ_BIGOBJ 20 -- --/* .pdata/.xdata defines and structures for x64 PE+ for exception handling. */ -- --/* .pdata in exception directory. */ -- --struct pex64_runtime_function --{ -- bfd_vma rva_BeginAddress; -- bfd_vma rva_EndAddress; -- bfd_vma rva_UnwindData; --}; -- --struct external_pex64_runtime_function --{ -- bfd_byte rva_BeginAddress[4]; -- bfd_byte rva_EndAddress[4]; -- bfd_byte rva_UnwindData[4]; --}; -- --/* If the lowest significant bit is set for rva_UnwindData RVA, it -- means that the unified RVA points to another pex64_runtime_function -- that this entry shares the unwind_info block with. */ --#define PEX64_IS_RUNTIME_FUNCTION_CHAINED(PTR_RTF) \ -- (((PTR_RTF)->rva_UnwindData & 1) != 0) --#define PEX64_GET_UNWINDDATA_UNIFIED_RVA(PTR_RTF) \ -- ((PTR_RTF)->rva_UnwindData & ~1) -- --/* The unwind codes. */ --#define UWOP_PUSH_NONVOL 0 --#define UWOP_ALLOC_LARGE 1 --#define UWOP_ALLOC_SMALL 2 --#define UWOP_SET_FPREG 3 --#define UWOP_SAVE_NONVOL 4 --#define UWOP_SAVE_NONVOL_FAR 5 --#define UWOP_SAVE_XMM 6 /* For version 1. */ --#define UWOP_EPILOG 6 /* For version 2. */ --#define UWOP_SAVE_XMM_FAR 7 /* For version 1 (deprecated). */ --#define UWOP_SPARE 7 /* For version 2. */ --#define UWOP_SAVE_XMM128 8 --#define UWOP_SAVE_XMM128_FAR 9 --#define UWOP_PUSH_MACHFRAME 10 -- --struct pex64_unwind_code --{ -- bfd_vma prologue_offset; -- /* Contains Frame offset, or frame allocation size. */ -- bfd_vma frame_addr; -- unsigned int uwop_code : 4; -- /* xmm, mm, or standard register from 0 - 15. */ -- unsigned int reg : 4; -- /* Used for UWOP_PUSH_MACHFRAME to indicate optional errorcode stack -- argument. */ -- unsigned int has_errorcode : 1; --}; -- --struct external_pex64_unwind_code --{ -- bfd_byte dta[2]; --}; -- --#define PEX64_UNWCODE_CODE(VAL) ((VAL) & 0xf) --#define PEX64_UNWCODE_INFO(VAL) (((VAL) >> 4) & 0xf) -- --/* The unwind info. */ --#define UNW_FLAG_NHANDLER 0 --#define UNW_FLAG_EHANDLER 1 --#define UNW_FLAG_UHANDLER 2 --#define UNW_FLAG_FHANDLER 3 --#define UNW_FLAG_CHAININFO 4 -- --#define UNW_FLAG_MASK 0x1f -- --struct pex64_unwind_info --{ -- bfd_vma SizeOfBlock; -- bfd_byte Version; /* Values from 0 up to 7 are possible. */ -- bfd_byte Flags; /* Values from 0 up to 31 are possible. */ -- bfd_vma SizeOfPrologue; -- bfd_vma CountOfCodes; /* Amount of pex64_unwind_code elements. */ -- /* 0 = CFA, 1..15 are index of integer registers. */ -- unsigned int FrameRegister : 4; -- bfd_vma FrameOffset; -- bfd_vma sizeofUnwindCodes; -- bfd_byte *rawUnwindCodes; -- bfd_byte *rawUnwindCodesEnd; -- bfd_vma rva_ExceptionHandler; /* UNW_EHANDLER or UNW_FLAG_UHANDLER. */ -- bfd_vma rva_BeginAddress; /* UNW_FLAG_CHAININFO. */ -- bfd_vma rva_EndAddress; /* UNW_FLAG_CHAININFO. */ -- bfd_vma rva_UnwindData; /* UNW_FLAG_CHAININFO. */ --}; -- --struct external_pex64_unwind_info --{ -- bfd_byte Version_Flags; -- bfd_byte SizeOfPrologue; -- bfd_byte CountOfCodes; -- bfd_byte FrameRegisterOffset; -- /* external_pex64_unwind_code array. */ -- /* bfd_byte handler[4]; */ -- /* Optional language specific data. */ --}; -- --struct external_pex64_scope --{ -- bfd_vma Count; --}; -- --struct pex64_scope --{ -- bfd_byte Count[4]; --}; -- --struct pex64_scope_entry --{ -- bfd_vma rva_BeginAddress; -- bfd_vma rva_EndAddress; -- bfd_vma rva_HandlerAddress; -- bfd_vma rva_JumpAddress; --}; --#define PEX64_SCOPE_ENTRY_SIZE 16 -- --struct external_pex64_scope_entry --{ -- bfd_byte rva_BeginAddress[4]; -- bfd_byte rva_EndAddress[4]; -- bfd_byte rva_HandlerAddress[4]; -- bfd_byte rva_JumpAddress[4]; --}; -- --#define PEX64_UWI_VERSION(VAL) ((VAL) & 7) --#define PEX64_UWI_FLAGS(VAL) (((VAL) >> 3) & 0x1f) --#define PEX64_UWI_FRAMEREG(VAL) ((VAL) & 0xf) --#define PEX64_UWI_FRAMEOFF(VAL) (((VAL) >> 4) & 0xf) --#define PEX64_UWI_SIZEOF_UWCODE_ARRAY(VAL) \ -- ((((VAL) + 1) & ~1) * 2) -- --#define PEX64_OFFSET_TO_UNWIND_CODE 0x4 -- --#define PEX64_OFFSET_TO_HANDLER_RVA (COUNTOFUNWINDCODES) \ -- (PEX64_OFFSET_TO_UNWIND_CODE + \ -- PEX64_UWI_SIZEOF_UWCODE_ARRAY(COUNTOFUNWINDCODES)) -- --#define PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) \ -- (PEX64_OFFSET_TO_HANDLER_RVA(COUNTOFUNWINDCODES) + 4) -- --#define PEX64_SCOPE_ENTRY(COUNTOFUNWINDCODES, IDX) \ -- (PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) + \ -- PEX64_SCOPE_ENTRY_SIZE * (IDX)) -- --/* Extra structure used in debug directory. */ --struct external_IMAGE_DEBUG_DIRECTORY --{ -- char Characteristics[4]; -- char TimeDateStamp[4]; -- char MajorVersion[2]; -- char MinorVersion[2]; -- char Type[4]; -- char SizeOfData[4]; -- char AddressOfRawData[4]; -- char PointerToRawData[4]; --}; -- --/* Extra structures used in codeview debug record. */ --/* This is not part of the PE specification. */ -- --#define CVINFO_PDB70_CVSIGNATURE 0x53445352 // "RSDS" --#define CVINFO_PDB20_CVSIGNATURE 0x3031424e // "NB10" --#define CVINFO_CV50_CVSIGNATURE 0x3131424e // "NB11" --#define CVINFO_CV41_CVSIGNATURE 0x3930424e // "NB09" -- --typedef struct _CV_INFO_PDB70 --{ -- char CvSignature[4]; -- char Signature[16]; -- char Age[4]; -- char PdbFileName[]; --} CV_INFO_PDB70; -- --typedef struct _CV_INFO_PDB20 --{ -- char CvHeader[4]; -- char Offset[4]; -- char Signature[4]; -- char Age[4]; -- char PdbFileName[]; --} CV_INFO_PDB20; -- --#endif /* _PE_H */ ---- b/include/opcode/sw_64.h -+++ /dev/null -@@ -1,255 +0,0 @@ --/* sw_64.h -- Header file for Sw_64 opcode table -- Copyright (C) 1996-2018 Free Software Foundation, Inc. -- Contributed by Richard Henderson , -- patterned after the PPC opcode table written by Ian Lance Taylor. -- -- This file is part of GDB, GAS, and the GNU binutils. -- -- GDB, GAS, and the GNU binutils are free software; you can redistribute -- them and/or modify them under the terms of the GNU General Public -- License as published by the Free Software Foundation; either version 3, -- or (at your option) any later version. -- -- GDB, GAS, and the GNU binutils are distributed in the hope that they -- will be useful, but WITHOUT ANY WARRANTY; without even the implied -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -- the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this file; see the file COPYING3. If not, write to the Free -- Software Foundation, 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. */ -- --#ifndef OPCODE_SW_64_H --#define OPCODE_SW_64_H -- --/* The opcode table is an array of struct sw_64_opcode. */ -- --struct sw_64_opcode --{ -- /* The opcode name. */ -- const char *name; -- -- /* The opcode itself. Those bits which will be filled in with -- operands are zeroes. */ -- unsigned opcode; -- -- /* The opcode mask. This is used by the disassembler. This is a -- mask containing ones indicating those bits which must match the -- opcode field, and zeroes indicating those bits which need not -- match (and are presumably filled in by operands). */ -- unsigned mask; -- -- /* One bit flags for the opcode. These are primarily used to -- indicate specific processors and environments support the -- instructions. The defined values are listed below. */ -- unsigned flags; -- -- /* An array of operand codes. Each code is an index into the -- operand table. They appear in the order which the operands must -- appear in assembly code, and are terminated by a zero. */ -- -- unsigned char operands[5]; --}; -- --/* The table itself is sorted by major opcode number, and is otherwise -- in the order in which the disassembler should consider -- instructions. */ --extern const struct sw_64_opcode sw_64_opcodes[]; --extern const unsigned sw_64_num_opcodes; -- --/* Values defined for the flags field of a struct sw_64_opcode. */ -- --/* CPU Availability */ --#define AXP_OPCODE_SW6 0x0800 /* SW6 insns. */ --#define AXP_OPCODE_SW6A 0x1000 /* SW6A insns. */ --#define AXP_OPCODE_SW6B 0x2000 /* SW6B insns. */ -- -- --#define AXP_OPCODE_NOPAL ((AXP_OPCODE_SW6|AXP_OPCODE_SW6A|AXP_OPCODE_SW6B)) -- --/* A macro to extract the major opcode from an instruction. */ --#define AXP_OP(i) (((i) >> 26) & 0x3F) -- --#define AXP_LITOP(i) (((i) >> 26) & 0x3D) -- --/* The total number of major opcodes. */ --#define AXP_NOPS 0x40 -- -- --/* The operands table is an array of struct sw_64_operand. */ -- --struct sw_64_operand --{ -- /* The number of bits in the operand. */ -- unsigned int bits : 5; -- -- /* How far the operand is left shifted in the instruction. */ -- unsigned int shift : 5; -- -- /* The default relocation type for this operand. */ -- signed int default_reloc : 16; -- -- /* One bit syntax flags. */ -- unsigned int flags : 16; -- -- /* Insertion function. This is used by the assembler. To insert an -- operand value into an instruction, check this field. -- -- If it is NULL, execute -- i |= (op & ((1 << o->bits) - 1)) << o->shift; -- (i is the instruction which we are filling in, o is a pointer to -- this structure, and op is the opcode value; this assumes twos -- complement arithmetic). -- -- If this field is not NULL, then simply call it with the -- instruction and the operand value. It will return the new value -- of the instruction. If the ERRMSG argument is not NULL, then if -- the operand value is illegal, *ERRMSG will be set to a warning -- string (the operand will be inserted in any case). If the -- operand value is legal, *ERRMSG will be unchanged (most operands -- can accept any value). */ -- unsigned (*insert) (unsigned instruction, int op, const char **errmsg); -- -- /* Extraction function. This is used by the disassembler. To -- extract this operand type from an instruction, check this field. -- -- If it is NULL, compute -- op = ((i) >> o->shift) & ((1 << o->bits) - 1); -- if ((o->flags & AXP_OPERAND_SIGNED) != 0 -- && (op & (1 << (o->bits - 1))) != 0) -- op -= 1 << o->bits; -- (i is the instruction, o is a pointer to this structure, and op -- is the result; this assumes twos complement arithmetic). -- -- If this field is not NULL, then simply call it with the -- instruction value. It will return the value of the operand. If -- the INVALID argument is not NULL, *INVALID will be set to -- non-zero if this operand type can not actually be extracted from -- this operand (i.e., the instruction does not match). If the -- operand is valid, *INVALID will not be changed. */ -- int (*extract) (unsigned instruction, int *invalid); --}; -- -- --#define ISA_UNKNOWN 0 /* Gas internal use. */ --#define ISA_SW6A 4 --#define ISA_SW6B 8 -- --#define CPU_UNKNOWN 0 /* Gas internal use. */ --#define CPU_SW6A 4 --#define CPU_SW6B 8 -- --#define EF_SW6A_FLGAS 4 /* Low 2-bit is '0'. */ --#define EF_SW6B_FLGAS 8 -- -- --/* Elements in the table are retrieved by indexing with values from -- the operands field of the sw_64_opcodes table. */ -- --extern const struct sw_64_operand sw_64_operands[]; --extern const unsigned sw_64_num_operands; -- --/* Values defined for the flags field of a struct sw_64_operand. */ -- --/* Mask for selecting the type for typecheck purposes */ --#define AXP_OPERAND_TYPECHECK_MASK \ -- (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA | AXP_OPERAND_IR | \ -- AXP_OPERAND_FPR | AXP_OPERAND_RELATIVE | AXP_OPERAND_SIGNED | \ -- AXP_OPERAND_UNSIGNED) -- --/* This operand does not actually exist in the assembler input. This -- is used to support extended mnemonics, for which two operands fields -- are identical. The assembler should call the insert function with -- any op value. The disassembler should call the extract function, -- ignore the return value, and check the value placed in the invalid -- argument. */ --#define AXP_OPERAND_FAKE 01 -- --/* The operand should be wrapped in parentheses rather than separated -- from the previous by a comma. This is used for the load and store -- instructions which want their operands to look like "Ra,disp(Rb)". */ --#define AXP_OPERAND_PARENS 02 -- --/* Used in combination with PARENS, this supresses the supression of -- the comma. This is used for "jmp Ra,(Rb),hint". */ --#define AXP_OPERAND_COMMA 04 -- --/* This operand names an integer register. */ --#define AXP_OPERAND_IR 010 -- --/* This operand names a floating point register. */ --#define AXP_OPERAND_FPR 020 -- --/* This operand is a relative branch displacement. The disassembler -- prints these symbolically if possible. */ --#define AXP_OPERAND_RELATIVE 040 -- --/* This operand takes signed values. */ --#define AXP_OPERAND_SIGNED 0100 -- --/* This operand takes unsigned values. This exists primarily so that -- a flags value of 0 can be treated as end-of-arguments. */ --#define AXP_OPERAND_UNSIGNED 0200 -- --/* Supress overflow detection on this field. This is used for hints. */ --#define AXP_OPERAND_NOOVERFLOW 0400 -- --/* Mask for optional argument default value. */ --#define AXP_OPERAND_OPTIONAL_MASK 07000 -- --/* This operand defaults to zero. This is used for jump hints. */ --#define AXP_OPERAND_DEFAULT_ZERO 01000 -- --/* This operand should default to the first (real) operand and is used -- in conjunction with AXP_OPERAND_OPTIONAL. This allows -- "and $0,3,$0" to be written as "and $0,3", etc. I don't like -- it, but it's what DEC does. */ --#define AXP_OPERAND_DEFAULT_FIRST 02000 -- --/* Similarly, this operand should default to the second (real) operand. -- This allows "negl $0" instead of "negl $0,$0". */ --#define AXP_OPERAND_DEFAULT_SECOND 04000 -- --/* Similarly, this operand should default to the third (real) operand. -- * This allows "selne $0,$1,$2,$2" to be written as "selne $0,$1,$2" */ --#define AXP_OPERAND_DEFAULT_THIRD 0xa00 -- -- --/* Register common names */ -- --#define AXP_REG_V0 0 --#define AXP_REG_T0 1 --#define AXP_REG_T1 2 --#define AXP_REG_T2 3 --#define AXP_REG_T3 4 --#define AXP_REG_T4 5 --#define AXP_REG_T5 6 --#define AXP_REG_T6 7 --#define AXP_REG_T7 8 --#define AXP_REG_S0 9 --#define AXP_REG_S1 10 --#define AXP_REG_S2 11 --#define AXP_REG_S3 12 --#define AXP_REG_S4 13 --#define AXP_REG_S5 14 --#define AXP_REG_FP 15 --#define AXP_REG_A0 16 --#define AXP_REG_A1 17 --#define AXP_REG_A2 18 --#define AXP_REG_A3 19 --#define AXP_REG_A4 20 --#define AXP_REG_A5 21 --#define AXP_REG_T8 22 --#define AXP_REG_T9 23 --#define AXP_REG_T10 24 --#define AXP_REG_T11 25 --#define AXP_REG_RA 26 --#define AXP_REG_PV 27 --#define AXP_REG_T12 27 --#define AXP_REG_AT 28 --#define AXP_REG_GP 29 --#define AXP_REG_SP 30 --#define AXP_REG_ZERO 31 -- --#endif /* OPCODE_SW_64_H */ ---- b/ld/emulparams/elf64sw_64.sh -+++ /dev/null -@@ -1,36 +0,0 @@ --ENTRY=_start --SCRIPT_NAME=elf --ELFSIZE=64 --TEMPLATE_NAME=elf --EXTRA_EM_FILE=sw_64elf --OUTPUT_FORMAT="elf64-sw_64" --NO_REL_RELOCS=yes --TEXT_START_ADDR="0x120000000" --MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" --COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)" -- --# for flags of elf file header --if [ "$sw_cpu_type" = "sw_64sw6a" ]; then -- ARCH=sw_64:4 --elif [ "$sw_cpu_type" = "sw_64sw6b" ]; then -- ARCH=sw_64:8 --else -- ARCH=sw_64 --fi -- --MACHINE= --GENERATE_SHLIB_SCRIPT=yes --GENERATE_PIE_SCRIPT=yes -- --# Yes, we want duplicate .plt sections. The linker chooses the --# appropriate one magically in sw_64_after_open. --PLT=".plt ${RELOCATING-0} : SPECIAL { *(.plt) }" --DATA_PLT=yes --TEXT_PLT=yes -- --# Note that the number is always big-endian, thus we have to --# reverse the digit string. --NOP=0x5f07ff435f07ff43 -- --OTHER_READONLY_SECTIONS=" -- .reginfo ${RELOCATING-0} : { *(.reginfo) }" ---- b/ld/emulparams/elf64sw_64_fbsd.sh -+++ /dev/null -@@ -1,3 +0,0 @@ --source_sh ${srcdir}/emulparams/elf64sw_64.sh --source_sh ${srcdir}/emulparams/elf_fbsd.sh --OUTPUT_FORMAT="elf64-sw_64-freebsd" ---- b/ld/emulparams/elf64sw_64_nbsd.sh -+++ /dev/null -@@ -1,2 +0,0 @@ --source_sh ${srcdir}/emulparams/elf64sw_64.sh --ENTRY=__start ---- b/ld/emulparams/sw_64.sh -+++ /dev/null -@@ -1,3 +0,0 @@ --SCRIPT_NAME=sw_64 --OUTPUT_FORMAT="ecoff-littlesw_64" --ARCH=sw_64 ---- b/ld/emulparams/sw_64vms.sh -+++ /dev/null -@@ -1,7 +0,0 @@ --SCRIPT_NAME=sw_64vms -- --OUTPUT_FORMAT="vms-sw_64" --ARCH=sw_64 -- --COMPILE_IN=yes --EXTRA_EM_FILE=vms -\ No newline at end of file ---- b/ld/emultempl/sw_64elf.em -+++ /dev/null -@@ -1,152 +0,0 @@ --# This shell script emits a C file. -*- C -*- --# Copyright (C) 2003-2015 Free Software Foundation, Inc. --# --# This file is part of the 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 3 of the License, or --# (at your option) any later version. --# --# This program is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --# GNU General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, --# MA 02110-1301, USA. --# -- --# This file is sourced from elf.em, and defines extra sw_64 --# specific routines. --# --fragment <next) -- { -- if (os->constraint == SPECIAL && strcmp (os->name, ".plt") == 0) -- { -- if (num_plt < 2) -- plt_os[num_plt] = os; -- ++num_plt; -- } -- } -- -- if (num_plt == 2) -- { -- plt_os[0]->constraint = elf64_sw_64_use_secureplt ? 0 : -1; -- plt_os[1]->constraint = elf64_sw_64_use_secureplt ? -1 : 0; -- } -- } -- -- gld${EMULATION_NAME}_after_open (); --} -- --static void --sw_64_after_parse (void) --{ -- link_info.relax_pass = 2; -- if (limit_32bit -- && !bfd_link_pic (&link_info) -- && !bfd_link_relocatable (&link_info)) -- lang_section_start (".interp", -- exp_binop ('+', -- exp_intop (SW_64_TEXT_START_32BIT), -- exp_nameop (SIZEOF_HEADERS, NULL)), -- NULL); -- -- ldelf_after_parse (); --} -- --static void --sw_64_before_allocation (void) --{ -- /* Call main function; we're just extending it. */ -- gld${EMULATION_NAME}_before_allocation (); -- -- /* Add -relax if -O, not -r, and not explicitly disabled. */ -- if (link_info.optimize -- && !bfd_link_relocatable (&link_info) -- && ! RELAXATION_DISABLED_BY_USER) -- ENABLE_RELAXATION; --} -- --static void --sw_64_finish (void) --{ -- if (limit_32bit) -- elf_elfheader (link_info.output_bfd)->e_flags |= EF_SW_64_32BIT; -- -- finish_default (); --} --EOF -- --# Define some shell vars to insert bits of code into the standard elf --# parse_args and list_options functions. --# --PARSE_AND_LIST_PROLOGUE=' --#define OPTION_TASO 300 --#define OPTION_SECUREPLT (OPTION_TASO + 1) --#define OPTION_NO_SECUREPLT (OPTION_SECUREPLT + 1) --' -- --PARSE_AND_LIST_LONGOPTS=' -- { "taso", no_argument, NULL, OPTION_TASO }, -- { "secureplt", no_argument, NULL, OPTION_SECUREPLT }, -- { "no-secureplt", no_argument, NULL, OPTION_NO_SECUREPLT }, --' -- --PARSE_AND_LIST_OPTIONS=' -- fprintf (file, _("\ -- --taso Load executable in the lower 31-bit addressable\n\ -- virtual address range.\n\ -- --secureplt Force PLT in text segment.\n\ -- --no-secureplt Force PLT in data segment.\n\ --")); --' -- --PARSE_AND_LIST_ARGS_CASES=' -- case OPTION_TASO: -- limit_32bit = 1; -- break; -- case OPTION_SECUREPLT: -- elf64_sw_64_use_secureplt = true; -- break; -- case OPTION_NO_SECUREPLT: -- elf64_sw_64_use_secureplt = false; -- break; --' -- --# Put these extra sw_64 routines in ld_${EMULATION_NAME}_emulation --# --LDEMUL_AFTER_OPEN=sw_64_after_open --LDEMUL_AFTER_PARSE=sw_64_after_parse --LDEMUL_BEFORE_ALLOCATION=sw_64_before_allocation --LDEMUL_FINISH=sw_64_finish ---- b/ld/scripttempl/sw_64.sc -+++ /dev/null -@@ -1,87 +0,0 @@ --# Linker script for Sw_64 systems. --# Ian Lance Taylor . --# These variables may be overridden by the emulation file. The --# defaults are appropriate for an Sw_64 running OSF/1. --# --# Copyright (C) 2014-2020 Free Software Foundation, Inc. --# --# Copying and distribution of this file, with or without modification, --# are permitted in any medium without royalty provided the copyright --# notice and this notice are preserved. -- --test -z "$ENTRY" && ENTRY=__start --test -z "$TEXT_START_ADDR" && TEXT_START_ADDR="0x120000000 + SIZEOF_HEADERS" --if test "x$LD_FLAG" = "xn" -o "x$LD_FLAG" = "xN"; then -- DATA_ADDR=. --else -- test -z "$DATA_ADDR" && DATA_ADDR=0x140000000 --fi --cat <. --# --# Copyright (C) 2014-2020 Free Software Foundation, Inc. --# --# Copying and distribution of this file, with or without modification, --# are permitted in any medium without royalty provided the copyright --# notice and this notice are preserved. -- --PAGESIZE=0x10000 -- --cat <, -- patterned after the PPC opcode handling written by Ian Lance Taylor. -- -- This file is part of libopcodes. -- -- This library is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3, or (at your option) -- any later version. -- -- It is distributed in the hope that it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this file; see the file COPYING. If not, write to the Free -- Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA -- 02110-1301, USA. */ -- --#include "sysdep.h" --#include --#include "disassemble.h" --#include "opcode/sw_64.h" -- --/* OSF register names. */ -- --static const char * const osf_regnames[64] = { -- "$r0", "$r1", "$r2", "$r3" , "$r4", "$r5", "$r6", "$r7", -- "$r8", "$r9", "$r10", "$r11" , "$r12", "$r13", "$r14", "fp", -- "$r16", "$r17", "$r18", "$r19" , "$r20", "$r21", "$r22", "$r23", -- "$r24", "$r25", "ra", "$r27" , "$r28", "$r29", "sp", "$r31", -- "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", -- "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", -- "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", -- "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" --}; -- --/* VMS register names. */ -- --static const char * const vms_regnames[64] = { -- "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", -- "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", -- "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23", -- "R24", "AI", "RA", "PV", "AT", "FP", "SP", "RZ", -- "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", -- "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", -- "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", -- "F24", "F25", "F26", "F27", "F28", "F29", "F30", "FZ" --}; -- --/* Disassemble Sw_64 instructions. */ -- --int --print_insn_sw_64 (bfd_vma memaddr, struct disassemble_info *info) --{ -- static const struct sw_64_opcode *opcode_index[AXP_NOPS+1]; -- const char * const * regnames; -- const struct sw_64_opcode *opcode, *opcode_end; -- const unsigned char *opindex; -- unsigned insn, op, isa_mask; -- int need_comma; -- -- /* Initialize the majorop table the first time through */ -- if (!opcode_index[0]) -- { -- opcode = sw_64_opcodes; -- opcode_end = opcode + sw_64_num_opcodes; -- -- for (op = 0; op < AXP_NOPS; ++op) -- { -- opcode_index[op] = opcode; -- if ((AXP_LITOP (opcode->opcode) != 0x10) -- && (AXP_LITOP (opcode->opcode) != 0x11)) -- { -- while (opcode < opcode_end && op == AXP_OP (opcode->opcode)) -- ++opcode; -- } -- else -- { -- while (opcode < opcode_end && op == AXP_LITOP (opcode->opcode)) -- ++opcode; -- } -- } -- opcode_index[op] = opcode; -- } -- -- if (info->flavour == bfd_target_evax_flavour) -- regnames = vms_regnames; -- else -- regnames = osf_regnames; -- -- isa_mask = AXP_OPCODE_NOPAL; -- switch (info->mach) -- { -- case bfd_mach_sw_64_sw6a: -- isa_mask |= AXP_OPCODE_SW6 | AXP_OPCODE_SW6A; -- break; -- case bfd_mach_sw_64_sw6b: -- isa_mask |= AXP_OPCODE_SW6 | AXP_OPCODE_SW6B; -- break; -- } -- -- /* Read the insn into a host word */ -- { -- bfd_byte buffer[4]; -- int status = (*info->read_memory_func) (memaddr, buffer, 4, info); -- if (status != 0) -- { -- (*info->memory_error_func) (status, memaddr, info); -- return -1; -- } -- insn = bfd_getl32 (buffer); -- } -- -- /* Get the major opcode of the instruction. */ -- -- if((AXP_LITOP (insn)==0x10) || (AXP_LITOP (insn)==0x11)) -- op = AXP_LITOP (insn); -- else if((AXP_OP(insn) & 0x3C) == 0x14 ) //logx -- op=0x14; -- else -- op = AXP_OP (insn); -- -- /* Find the first match in the opcode table. */ -- opcode_end = opcode_index[op + 1]; -- for (opcode = opcode_index[op]; opcode < opcode_end; ++opcode) -- { -- if ((insn ^ opcode->opcode) & opcode->mask) -- continue; -- -- if (!(opcode->flags & isa_mask)) -- continue; -- -- /* Make two passes over the operands. First see if any of them -- have extraction functions, and, if they do, make sure the -- instruction is valid. */ -- { -- int invalid = 0; -- for (opindex = opcode->operands; *opindex != 0; opindex++) -- { -- const struct sw_64_operand *operand = sw_64_operands + *opindex; -- if (operand->extract) -- (*operand->extract) (insn, &invalid); -- } -- if (invalid) -- continue; -- } -- -- /* The instruction is valid. */ -- goto found; -- } -- -- /* No instruction found */ -- (*info->fprintf_func) (info->stream, ".long %#08x", insn); -- -- return 4; -- --found: -- if (!strncmp ("sys_call", opcode->name,8)) -- { -- if (insn & (0x1 << 25)) -- (*info->fprintf_func) (info->stream, "%s", "sys_call"); -- else -- (*info->fprintf_func) (info->stream, "%s", "sys_call/b"); -- } -- else -- (*info->fprintf_func) (info->stream, "%s", opcode->name); -- --/* get zz[7:6] and zz[5:0] to form truth for vlog */ -- if (!strcmp(opcode->name,"vlog")) -- { -- unsigned int truth; -- char tr[4]; -- truth = (AXP_OP (insn) & 3) << 6; -- truth = truth | ((insn & 0xFC00) >> 10); -- sprintf (tr,"%x",truth); -- (*info->fprintf_func) (info->stream, "%s", tr); -- } -- if (opcode->operands[0] != 0) -- (*info->fprintf_func) (info->stream, "\t"); -- -- /* Now extract and print the operands. */ -- need_comma = 0; -- for (opindex = opcode->operands; *opindex != 0; opindex++) -- { -- const struct sw_64_operand *operand = sw_64_operands + *opindex; -- int value; -- -- /* Operands that are marked FAKE are simply ignored. We -- already made sure that the extract function considered -- the instruction to be valid. */ -- if ((operand->flags & AXP_OPERAND_FAKE) != 0) -- continue; -- -- /* Extract the value from the instruction. */ -- if (operand->extract) -- value = (*operand->extract) (insn, (int *) NULL); -- else -- { -- value = (insn >> operand->shift) & ((1 << operand->bits) - 1); -- if (operand->flags & AXP_OPERAND_SIGNED) -- { -- int signbit = 1 << (operand->bits - 1); -- value = (value ^ signbit) - signbit; -- } -- } -- -- if (need_comma && -- ((operand->flags & (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA)) -- != AXP_OPERAND_PARENS)) -- { -- (*info->fprintf_func) (info->stream, ","); -- } -- if (operand->flags & AXP_OPERAND_PARENS) -- (*info->fprintf_func) (info->stream, "("); -- -- /* Print the operand as directed by the flags. */ -- if (operand->flags & AXP_OPERAND_IR) -- (*info->fprintf_func) (info->stream, "%s", regnames[value]); -- else if (operand->flags & AXP_OPERAND_FPR) -- (*info->fprintf_func) (info->stream, "%s", regnames[value + 32]); -- else if (operand->flags & AXP_OPERAND_RELATIVE) -- (*info->print_address_func) (memaddr + 4 + value, info); -- else if (operand->flags & AXP_OPERAND_SIGNED) -- (*info->fprintf_func) (info->stream, "%d", value); -- else -- (*info->fprintf_func) (info->stream, "%#x", value); -- -- if (operand->flags & AXP_OPERAND_PARENS) -- (*info->fprintf_func) (info->stream, ")"); -- need_comma = 1; -- } -- -- return 4; --} ---- b/opcodes/sw_64-opc.c -+++ /dev/null -@@ -1,1055 +0,0 @@ --/* sw_64-opc.c -- Sw_64 AXP opcode list -- Copyright (C) 1996-2018 Free Software Foundation, Inc. -- Contributed by Richard Henderson , -- patterned after the PPC opcode handling written by Ian Lance Taylor. -- -- This file is part of libopcodes. -- -- This library is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3, or (at your option) -- any later version. -- -- It is distributed in the hope that it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this file; see the file COPYING. If not, write to the -- Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA -- 02110-1301, USA. */ -- --#include "sysdep.h" --#include --#include "opcode/sw_64.h" --#include "bfd.h" --#include "opintl.h" -- --/* This file holds the Sw_64 AXP opcode table. The opcode table includes -- almost all of the extended instruction mnemonics. This permits the -- disassembler to use them, and simplifies the assembler logic, at the -- cost of increasing the table size. The table is strictly constant -- data, so the compiler should be able to put it in the text segment. -- -- This file also holds the operand table. All knowledge about inserting -- and extracting operands from instructions is kept in this file. -- -- The information for the base instruction set was compiled from the -- _Sw_64 Architecture Handbook_, Digital Order Number EC-QD2KB-TE, -- version 2. -- */ -- --/* The RB field when it is the same as the RA field in the same insn. -- This operand is marked fake. The insertion function just copies -- the RA field into the RB field, and the extraction function just -- checks that the fields are the same. */ -- --static unsigned --insert_rba (unsigned insn, -- int value ATTRIBUTE_UNUSED, -- const char **errmsg ATTRIBUTE_UNUSED) --{ -- return insn | (((insn >> 21) & 0x1f) << 16); --} -- --static int --extract_rba (unsigned insn, int *invalid) --{ -- if (invalid != (int *) NULL -- && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f)) -- *invalid = 1; -- return 0; --} -- --/* The same for the RC field. */ -- --static unsigned --insert_rca (unsigned insn, -- int value ATTRIBUTE_UNUSED, -- const char **errmsg ATTRIBUTE_UNUSED) --{ -- return insn | ((insn >> 21) & 0x1f); --} -- --static int --extract_rca (unsigned insn, int *invalid) --{ -- if (invalid != (int *) NULL -- && ((insn >> 21) & 0x1f) != (insn & 0x1f)) -- *invalid = 1; -- return 0; --} -- --static unsigned --insert_rdc (unsigned insn, -- int value ATTRIBUTE_UNUSED, -- const char **errmsg ATTRIBUTE_UNUSED) --{ -- return insn | ((insn >> 5) & 0x1f); --} -- --static int --extract_rdc (unsigned insn, int *invalid) --{ -- if (invalid != (int *) NULL -- && ((insn >> 5) & 0x1f) != (insn & 0x1f)) -- *invalid = 1; -- return 0; --} -- --/* Fake arguments in which the registers must be set to ZERO. */ -- --static unsigned --insert_za (unsigned insn, -- int value ATTRIBUTE_UNUSED, -- const char **errmsg ATTRIBUTE_UNUSED) --{ -- return insn | (31 << 21); --} -- --static int --extract_za (unsigned insn, int *invalid) --{ -- if (invalid != (int *) NULL && ((insn >> 21) & 0x1f) != 31) -- *invalid = 1; -- return 0; --} -- --static unsigned --insert_zb (unsigned insn, -- int value ATTRIBUTE_UNUSED, -- const char **errmsg ATTRIBUTE_UNUSED) --{ -- return insn | (31 << 16); --} -- --static int --extract_zb (unsigned insn, int *invalid) --{ -- if (invalid != (int *) NULL && ((insn >> 16) & 0x1f) != 31) -- *invalid = 1; -- return 0; --} -- --static unsigned --insert_zc (unsigned insn, -- int value ATTRIBUTE_UNUSED, -- const char **errmsg ATTRIBUTE_UNUSED) --{ -- return insn | 31; --} -- --static int --extract_zc (unsigned insn, int *invalid) --{ -- if (invalid != (int *) NULL && (insn & 0x1f) != 31) -- *invalid = 1; -- return 0; --} -- -- --/* The displacement field of a Branch format insn. */ -- --static unsigned --insert_bdisp (unsigned insn, int value, const char **errmsg) --{ -- if (errmsg != (const char **)NULL && (value & 3)) -- *errmsg = _("branch operand unaligned"); -- return insn | ((value / 4) & 0x1FFFFF); --} -- --static int --extract_bdisp (unsigned insn, int *invalid ATTRIBUTE_UNUSED) --{ -- return 4 * (((insn & 0x1FFFFF) ^ 0x100000) - 0x100000); --} -- --/* The hint field of a JMP/JSR insn. */ -- --/* sw use 16 bits hint disp. */ --static unsigned --insert_jhint (unsigned insn, int value, const char **errmsg) --{ -- if (errmsg != (const char **)NULL && (value & 3)) -- *errmsg = _("jump hint unaligned"); -- return insn | ((value / 4) & 0xFFFF); --} -- --static int --extract_jhint (unsigned insn, int *invalid ATTRIBUTE_UNUSED) --{ -- return 4 * (((insn & 0xFFFF) ^ 0x8000) - 0x8000); --} -- --/* The hint field of an SW6 HW_JMP/JSR insn. */ -- --static unsigned --insert_sw6hwjhint (unsigned insn, int value, const char **errmsg) --{ -- if (errmsg != (const char **)NULL && (value & 3)) -- *errmsg = _("jump hint unaligned"); -- return insn | ((value / 4) & 0x1FFF); --} -- --static int --extract_sw6hwjhint (unsigned insn, int *invalid ATTRIBUTE_UNUSED) --{ -- return 4 * (((insn & 0x1FFF) ^ 0x1000) - 0x1000); --} -- --/* The operands table. */ -- --const struct sw_64_operand sw_64_operands[] = --{ -- /* The fields are bits, shift, insert, extract, flags */ -- /* The zero index is used to indicate end-of-list */ --#define UNUSED 0 -- { 0, 0, 0, 0, 0, 0 }, -- -- /* The plain integer register fields. */ --#define RA (UNUSED + 1) -- { 5, 21, 0, AXP_OPERAND_IR, 0, 0 }, --#define RB (RA + 1) -- { 5, 16, 0, AXP_OPERAND_IR, 0, 0 }, --#define RC (RB + 1) -- { 5, 0, 0, AXP_OPERAND_IR, 0, 0 }, -- -- /* The plain fp register fields. */ --#define FA (RC + 1) -- { 5, 21, 0, AXP_OPERAND_FPR, 0, 0 }, --#define FB (FA + 1) -- { 5, 16, 0, AXP_OPERAND_FPR, 0, 0 }, --#define FC (FB + 1) -- { 5, 0, 0, AXP_OPERAND_FPR, 0, 0 }, -- -- /* The integer registers when they are ZERO. */ --#define ZA (FC + 1) -- { 5, 21, 0, AXP_OPERAND_FAKE, insert_za, extract_za }, --#define ZB (ZA + 1) -- { 5, 16, 0, AXP_OPERAND_FAKE, insert_zb, extract_zb }, --#define ZC (ZB + 1) -- { 5, 0, 0, AXP_OPERAND_FAKE, insert_zc, extract_zc }, -- -- /* The RB field when it needs parentheses. */ --#define PRB (ZC + 1) -- { 5, 16, 0, AXP_OPERAND_IR|AXP_OPERAND_PARENS, 0, 0 }, -- -- /* The RB field when it needs parentheses _and_ a preceding comma. */ --#define CPRB (PRB + 1) -- { 5, 16, 0, -- AXP_OPERAND_IR|AXP_OPERAND_PARENS|AXP_OPERAND_COMMA, 0, 0 }, -- -- /* The RB field when it must be the same as the RA field. */ --#define RBA (CPRB + 1) -- { 5, 16, 0, AXP_OPERAND_FAKE, insert_rba, extract_rba }, -- -- /* The RC field when it must be the same as the RB field. */ --#define RCA (RBA + 1) -- { 5, 0, 0, AXP_OPERAND_FAKE, insert_rca, extract_rca }, -- --#define RDC (RCA + 1) -- { 5, 0, 0, AXP_OPERAND_FAKE, insert_rdc, extract_rdc }, -- -- /* The RC field when it can *default* to RA. */ --#define DRC1 (RDC + 1) -- { 5, 0, 0, -- AXP_OPERAND_IR|AXP_OPERAND_DEFAULT_FIRST, 0, 0 }, -- -- /* The RC field when it can *default* to RB. */ --#define DRC2 (DRC1 + 1) -- { 5, 0, 0, -- AXP_OPERAND_IR|AXP_OPERAND_DEFAULT_SECOND, 0, 0 }, -- -- /* The RD field when it can *default* to RC. */ --#define DRC3 (DRC2 + 1) -- { 5, 0, 0, -- AXP_OPERAND_IR|AXP_OPERAND_DEFAULT_THIRD, 0, 0 }, -- -- /* The FC field when it can *default* to RA. */ --#define DFC1 (DRC3 + 1) -- { 5, 0, 0, -- AXP_OPERAND_FPR|AXP_OPERAND_DEFAULT_FIRST, 0, 0 }, -- -- /* The FC field when it can *default* to RB. */ --#define DFC2 (DFC1 + 1) -- { 5, 0, 0, -- AXP_OPERAND_FPR|AXP_OPERAND_DEFAULT_SECOND, 0, 0 }, -- -- /* The FD field when it can *default* to FC. */ --#define DFC3 (DFC2 + 1) -- { 5, 0, 0, -- AXP_OPERAND_FPR|AXP_OPERAND_DEFAULT_THIRD, 0, 0 }, -- -- /* The unsigned 8-bit literal of Operate format insns. */ --#define LIT (DFC3 + 1) -- { 8, 13, -LIT, AXP_OPERAND_UNSIGNED, 0, 0 }, -- -- /* The signed 16-bit displacement of Memory format insns. From here -- we can't tell what relocation should be used, so don't use a default. */ --#define MDISP (LIT + 1) -- { 16, 0, -MDISP, AXP_OPERAND_SIGNED, 0, 0 }, -- -- /* The signed "23-bit" aligned displacement of Branch format insns. */ --#define BDISP (MDISP + 1) -- { 21, 0, BFD_RELOC_23_PCREL_S2, -- AXP_OPERAND_RELATIVE, insert_bdisp, extract_bdisp }, -- -- /* The 25-bit PALcode function. */ --#define PALFN (BDISP + 1) -- { 25, 0, -PALFN, AXP_OPERAND_UNSIGNED, 0, 0 }, -- -- /* sw jsr/ret insntructions has no function bits. */ -- /* The optional signed "16-bit" aligned displacement of the JMP/JSR hint. */ --#define JMPHINT (PALFN + 1) -- { 16, 0, BFD_RELOC_SW_64_HINT, -- AXP_OPERAND_RELATIVE|AXP_OPERAND_DEFAULT_ZERO|AXP_OPERAND_NOOVERFLOW, -- insert_jhint, extract_jhint }, -- -- /* The optional hint to RET/JSR_COROUTINE. */ --#define RETHINT (JMPHINT + 1) -- { 16, 0, -RETHINT, -- AXP_OPERAND_UNSIGNED|AXP_OPERAND_DEFAULT_ZERO, 0, 0 }, -- --#define SW6HWDISP (RETHINT + 1) -- {12, 0, -SW6HWDISP, AXP_OPERAND_SIGNED, 0, 0 }, -- -- /* The 16-bit combined index/scoreboard mask for the sw6 -- hw_m[ft]pr (pal19/pal1d) insns. */ --#define SW6HWINDEX (SW6HWDISP + 1) -- { 16, 0, -SW6HWINDEX, AXP_OPERAND_UNSIGNED, 0, 0 }, -- -- /* The 13-bit branch hint for the sw6 hw_jmp/jsr (pal1e) insn. */ --#define SW6HWJMPHINT (SW6HWINDEX+ 1) -- { 8, 0, -SW6HWJMPHINT, -- AXP_OPERAND_RELATIVE|AXP_OPERAND_DEFAULT_ZERO|AXP_OPERAND_NOOVERFLOW, -- insert_sw6hwjhint, extract_sw6hwjhint }, -- -- /* for the third operand of ternary operands integer insn. */ --#define R3 (SW6HWJMPHINT + 1) -- { 5, 5, 0, AXP_OPERAND_IR, 0, 0 }, -- -- /* The plain fp register fields */ --#define F3 (R3 + 1) -- { 5, 5, 0, AXP_OPERAND_FPR, 0, 0 }, -- --/* sw simd settle instruction lit */ --#define FMALIT (F3 + 1) -- { 5, 5, -FMALIT, AXP_OPERAND_UNSIGNED, 0, 0 },//V1.1 -- --/*for pal to check disp which must be plus sign and less than 0x8000,WCH20080901*/ --#define LMDISP (FMALIT + 1) -- { 15, 0, -LMDISP, AXP_OPERAND_UNSIGNED, 0, 0 }, -- --#define RPIINDEX (LMDISP + 1) -- { 8, 0, -RPIINDEX, AXP_OPERAND_UNSIGNED, 0, 0 }, -- --#define ATMDISP (RPIINDEX + 1) -- { 12, 0, -ATMDISP, AXP_OPERAND_SIGNED, 0, 0 }, --}; -- --const unsigned sw_64_num_operands = sizeof(sw_64_operands)/sizeof(*sw_64_operands); -- -- --/* Macros used to form opcodes. */ -- --/* The main opcode. */ --#define OP(x) (((x) & 0x3Fu) << 26) --#define OP_MASK 0xFC000000 -- --/* Branch format instructions. */ --#define BRA_(oo) OP(oo) --#define BRA_MASK OP_MASK --#define BRA(oo) BRA_(oo), BRA_MASK -- --/* Floating point format instructions. */ --#define FP_(oo,fff) (OP(oo) | (((fff) & 0xFF) << 5)) --#define FP_MASK (OP_MASK | 0x1FE0) --#define FP(oo,fff) FP_(oo,fff), FP_MASK -- --#define FMA_(oo,fff) (OP(oo) | (((fff) & 0x3F) << 10 )) --#define FMA_MASK (OP_MASK | 0xFC00) --#define FMA(oo,fff) FMA_(oo,fff), FMA_MASK -- --/* Memory format instructions. */ --#define MEM_(oo) OP(oo) --#define MEM_MASK OP_MASK --#define MEM(oo) MEM_(oo), MEM_MASK -- --/* Memory/Func Code format instructions. */ --#define MFC_(oo,ffff) (OP(oo) | ((ffff) & 0xFFFF)) --#define MFC_MASK (OP_MASK | 0xFFFF) --#define MFC(oo,ffff) MFC_(oo,ffff), MFC_MASK -- --/* Memory/Branch format instructions. */ --#define MBR_(oo,h) (OP(oo) | (((h) & 3) << 14)) --#define MBR_MASK (OP_MASK | 0xC000) --#define MBR(oo,h) MBR_(oo,h), MBR_MASK -- --/* Operate format instructions. The OPRL variant specifies a -- literal second argument. */ --#define OPR_(oo,ff) (OP(oo) | (((ff) & 0xFF) << 5)) --#define OPRL_(oo,ff) (OPR_((oo),(ff)) ) --#define OPR_MASK (OP_MASK | 0x1FE0) --#define OPR(oo,ff) OPR_(oo,ff), OPR_MASK --#define OPRL(oo,ff) OPRL_(oo,ff), OPR_MASK -- --/* sw ternary operands Operate format instructions. */ --#define TOPR_(oo,ff) (OP(oo) | (((ff) & 0x07) << 10)) --#define TOPRL_(oo,ff) (TOPR_((oo),(ff))) --#define TOPR_MASK (OP_MASK | 0x1C00) --#define TOPR(oo,ff) TOPR_(oo,ff), TOPR_MASK --#define TOPRL(oo,ff) TOPRL_(oo,ff), TOPR_MASK -- --/* sw atom instructions. */ --#define ATMEM_(oo,h) (OP(oo) | (((h) & 0xF) << 12)) --#define ATMEM_MASK (OP_MASK | 0xF000) --#define ATMEM(oo,h) ATMEM_(oo,h), ATMEM_MASK -- --/* sw privilege instructions. */ --#define PRIRET_(oo,h) (OP(oo) | (((h) & 0x1) << 20)) --#define PRIRET_MASK (OP_MASK | 0x100000) --#define PRIRET(oo,h) PRIRET_(oo,h), PRIRET_MASK -- --/* sw rpi_rcsr,rpi_wcsr. */ --#define CSR_(oo,ff) (OP(oo) | (((ff) & 0xFF) << 8)) --#define CSR_MASK (OP_MASK | 0xFF00) --#define CSR(oo,ff) CSR_(oo,ff), CSR_MASK -- --/* Generic PALcode format instructions. */ --#define PCD_(oo,ff) (OP(oo) | (ff << 25)) --#define PCD_MASK OP_MASK --#define PCD(oo,ff) PCD_(oo,ff), PCD_MASK -- --/* Specific PALcode instructions. */ --#define SPCD_(oo,ffff) (OP(oo) | ((ffff) & 0x3FFFFFF)) --#define SPCD_MASK 0xFFFFFFFF --#define SPCD(oo,ffff) SPCD_(oo,ffff), SPCD_MASK -- --/* Hardware memory (hw_{ld,st}) instructions. */ --#define SW6HWMEM_(oo,f) (OP(oo) | (((f) & 0xF) << 12)) --#define SW6HWMEM_MASK (OP_MASK | 0xF000) --#define SW6HWMEM(oo,f) SW6HWMEM_(oo,f), SW6HWMEM_MASK -- --#define SW6HWMBR_(oo,h) (OP(oo) | (((h) & 7) << 13)) --#define SW6HWMBR_MASK (OP_MASK | 0xE000) --#define SW6HWMBR(oo,h) SW6HWMBR_(oo,h), SW6HWMBR_MASK -- --#define LOGX_(oo,ff) (OP(oo) | (((ff) & 0x3F) << 10)) --#define LOGX_MASK (0xF0000000) --#define LOGX(oo,ff) LOGX_(oo,ff), LOGX_MASK -- --#define PSE_LOGX_(oo,ff) (OP(oo) | (((ff) & 0x3F) << 10) | (((ff) >> 0x6) << 26 ) | 0x3E0 ) --#define PSE_LOGX(oo,ff) PSE_LOGX_(oo,ff), LOGX_MASK -- --/* Abbreviations for instruction subsets. */ --#define SW6 AXP_OPCODE_SW6 --#define SW6A AXP_OPCODE_SW6A --#define SW6B AXP_OPCODE_SW6B -- --/* Common combinations of arguments. */ --#define ARG_NONE { 0 } --#define ARG_BRA { RA, BDISP } --#define ARG_FBRA { FA, BDISP } --#define ARG_FP { FA, FB, DFC1 } --#define ARG_FPZ1 { ZA, FB, DFC1 } --#define ARG_MEM { RA, MDISP, PRB } --#define ARG_FMEM { FA, MDISP, PRB } --#define ARG_OPR { RA, RB, DRC1 } --#define ARG_OPRL { RA, LIT, DRC1 } --#define ARG_OPRZ1 { ZA, RB, DRC1 } --#define ARG_OPRLZ1 { ZA, LIT, RC } --#define ARG_PCD { PALFN } --#define ARG_SW6HWMEM { RA, SW6HWDISP, PRB } -- --#define ARG_FPL { FA,LIT, DFC1 } --#define ARG_FMA { FA,FB,F3, DFC1 } --#define ARG_PREFETCH { ZA, MDISP, PRB } --#define ARG_FCMOV { FA,FB,F3, DFC3 } --#define ARG_TOPR { RA, RB,R3, DRC3 } --#define ARG_TOPRL { RA, LIT, R3,DRC3 } -- --/* for cmov** instruction. */ --#define ARG_TOPC { RA, RB, R3, RDC } --#define ARG_TOPCL { RA, LIT, R3, RDC } --#define ARG_TOPFC { FA, FB, F3, RDC } --#define ARG_TOPFCL { FA, LIT, F3, RDC } -- --/* sw settle instruction. */ --#define ARG_FMAL { FA,FB,FMALIT, DFC1 } --/* sw atom insitruction. */ --#define ARG_ATMEM { RA, ATMDISP, PRB } -- --#define ARG_VUAMEM { FA, ATMDISP, PRB } --#define ARG_OPRLZ3 { RA, LIT, ZC } -- --/* The opcode table. -- -- The format of the opcode table is: -- -- NAME OPCODE MASK { OPERANDS } -- -- NAME is the name of the instruction. -- -- OPCODE is the instruction opcode. -- -- MASK is the opcode mask; this is used to tell the disassembler -- which bits in the actual opcode must match OPCODE. -- -- OPERANDS is the list of operands. -- -- The preceding macros merge the text of the OPCODE and MASK fields. -- -- The disassembler reads the table in order and prints the first -- instruction which matches, so this table is sorted to put more -- specific instructions before more general instructions. -- -- Otherwise, it is sorted by major opcode and minor function code. -- -- There are three classes of not-really-instructions in this table: -- -- ALIAS is another name for another instruction. Some of -- these come from the Architecture Handbook, some -- come from the original gas opcode tables. In all -- cases, the functionality of the opcode is unchanged. -- -- PSEUDO a stylized code form endorsed by Chapter A.4 of the -- Architecture Handbook. -- -- EXTRA a stylized code form found in the original gas tables. -- */ -- --const struct sw_64_opcode sw_64_opcodes[] = --{ -- { "sys_call/b", PCD(0x00,0x00), SW6, ARG_PCD }, -- { "sys_call", PCD(0x00,0x01), SW6, ARG_PCD }, -- { "draina", SPCD(0x00,0x0002), SW6, ARG_NONE }, -- { "bpt", SPCD(0x00,0x0080), SW6, ARG_NONE }, -- { "bugchk", SPCD(0x00,0x0081), SW6, ARG_NONE }, -- { "callsys", SPCD(0x00,0x0083), SW6, ARG_NONE }, -- { "chmk", SPCD(0x00,0x0083), SW6, ARG_NONE }, -- { "imb", SPCD(0x00,0x0086), SW6, ARG_NONE }, -- { "rduniq", SPCD(0x00,0x009e), SW6, ARG_NONE }, -- { "wruniq", SPCD(0x00,0x009f), SW6, ARG_NONE }, -- { "gentrap", SPCD(0x00,0x00aa), SW6, ARG_NONE }, -- { "call", MEM(0x01), SW6, { RA, CPRB, JMPHINT } }, -- { "ret", MEM(0x02), SW6, { RA, CPRB, RETHINT } }, -- { "ret", MEM_(0x02)| (31 << 21) | (26 << 16) | 1,0xFFFFFFFF, SW6, { 0 } }, /*pseudo*/ -- { "jmp", MEM(0x03), SW6, { RA, CPRB, JMPHINT } }, -- { "br", BRA(0x04), SW6, { ZA, BDISP } }, /* pseudo */ -- { "br", BRA(0x04), SW6, ARG_BRA }, -- { "bsr", BRA(0x05), SW6, ARG_BRA }, -- { "memb", MFC(0x06,0x0000), SW6, ARG_NONE }, -- { "imemb", MFC(0x06,0x0001), SW6, ARG_NONE }, -- { "rtc", MFC(0x06,0x0020), SW6, { RA, ZB } }, -- { "rtc", MFC(0x06,0x0020), SW6, { RA, RB } }, -- { "rcid", MFC(0x06,0x0040), SW6, { RA , ZB} }, -- { "halt", MFC(0x06,0x0080), SW6, { ZA, ZB } }, -- { "rd_f", MFC(0x06,0x1000), SW6, { RA, ZB } }, -- { "wr_f", MFC(0x06,0x1020), SW6, { RA, ZB } }, -- { "rtid", MFC(0x06,0x1040), SW6, { RA } }, -- { "pri_rcsr", CSR(0x06,0xFE), SW6, { RA, RPIINDEX ,ZB } }, -- { "pri_wcsr", CSR(0x06,0xFF), SW6, { RA, RPIINDEX ,ZB } }, -- { "pri_ret", PRIRET(0x07,0x0), SW6, { RA } }, -- { "pri_ret/b", PRIRET(0x07,0x1), SW6, { RA } }, -- { "lldw", ATMEM(0x08,0x0), SW6, ARG_ATMEM }, -- { "lldl", ATMEM(0x08,0x1), SW6, ARG_ATMEM }, -- { "ldw_inc", ATMEM(0x08,0x2), SW6, ARG_ATMEM }, -- { "ldl_inc", ATMEM(0x08,0x3), SW6, ARG_ATMEM }, -- { "ldw_dec", ATMEM(0x08,0x4), SW6, ARG_ATMEM }, -- { "ldl_dec", ATMEM(0x08,0x5), SW6, ARG_ATMEM }, -- { "ldw_set", ATMEM(0x08,0x6), SW6, ARG_ATMEM }, -- { "ldl_set", ATMEM(0x08,0x7), SW6, ARG_ATMEM }, -- { "lstw", ATMEM(0x08,0x8), SW6, ARG_ATMEM }, -- { "lstl", ATMEM(0x08,0x9), SW6, ARG_ATMEM }, -- { "ldw_nc", ATMEM(0x08,0xA), SW6, ARG_ATMEM }, -- { "ldl_nc", ATMEM(0x08,0xB), SW6, ARG_ATMEM }, -- { "ldd_nc", ATMEM(0x08,0xC), SW6, ARG_VUAMEM }, -- { "stw_nc", ATMEM(0x08,0xD), SW6, ARG_ATMEM }, -- { "stl_nc", ATMEM(0x08,0xE), SW6, ARG_ATMEM }, -- { "std_nc", ATMEM(0x08,0xF), SW6, ARG_VUAMEM }, -- { "fillcs", MEM(0x09), SW6, ARG_PREFETCH }, -- { "ldwe", MEM(0x09), SW6, ARG_FMEM }, //sw6 v0.2a -- { "e_fillcs", MEM(0x0A), SW6, ARG_PREFETCH }, -- { "ldse", MEM(0x0A), SW6, ARG_FMEM }, -- { "lds4e", MEM(0x0A), SW6, ARG_FMEM },/* pseudo SW6 SIMD WCH20081028*/ -- { "fillcs_e", MEM(0x0B), SW6, ARG_PREFETCH }, -- { "ldde", MEM(0x0B), SW6, ARG_FMEM }, -- { "ldd4e", MEM(0x0B), SW6, ARG_FMEM },/* pseudo SW6 SIMD WCH20081028*/ -- { "e_fillde", MEM(0x0C), SW6, ARG_PREFETCH }, -- { "vlds", MEM(0x0C), SW6, ARG_FMEM }, -- { "v4lds", MEM(0x0C), SW6, ARG_FMEM }, -- { "vldd", MEM(0x0D), SW6, ARG_FMEM }, -- { "v4ldd", MEM(0x0D), SW6, ARG_FMEM }, -- { "vsts", MEM(0x0E), SW6, ARG_FMEM }, -- { "v4sts", MEM(0x0E), SW6, ARG_FMEM }, -- { "vstd", MEM(0x0F), SW6, ARG_FMEM }, -- { "v4std", MEM(0x0F), SW6, ARG_FMEM }, -- { "addw", OPR(0x10,0x00), SW6, ARG_OPR }, -- { "addw", OPRL(0x12,0x00), SW6, ARG_OPRL }, -- { "sextl", OPR(0x10,0x00), SW6, ARG_OPRZ1 }, /* pseudo */ -- { "sextl", OPRL(0x12,0x00), SW6, ARG_OPRLZ1 }, /* pseudo */ -- { "subw", OPR(0x10,0x01), SW6, ARG_OPR }, -- { "subw", OPRL(0x12,0x01), SW6, ARG_OPRL }, -- { "negw", OPR(0x10,0x01), SW6, ARG_OPRZ1 }, /* pseudo swgcc */ -- { "negw", OPRL(0x12,0x01), SW6, ARG_OPRLZ1 }, /* pseudo swgcc */ -- { "s4addw", OPR(0x10,0x02), SW6, ARG_OPR }, -- { "s4addw", OPRL(0x12,0x02), SW6, ARG_OPRL }, -- { "s4subw", OPR(0x10,0x03), SW6, ARG_OPR }, -- { "s4subw", OPRL(0x12,0x03), SW6, ARG_OPRL }, -- { "s8addw", OPR(0x10,0x04), SW6, ARG_OPR }, -- { "s8addw", OPRL(0x12,0x04), SW6, ARG_OPRL }, -- { "s8subw", OPR(0x10,0x05), SW6, ARG_OPR }, -- { "s8subw", OPRL(0x12,0x05), SW6, ARG_OPRL }, -- { "addl", OPR(0x10,0x08), SW6, ARG_OPR }, -- { "addl", OPRL(0x12,0x08), SW6, ARG_OPRL }, -- { "subl", OPR(0x10,0x09), SW6, ARG_OPR }, -- { "subl", OPRL(0x12,0x09), SW6, ARG_OPRL }, -- { "negl", OPR(0x10,0x09), SW6, ARG_OPRZ1 }, /* pseudo swgcc */ -- { "negl", OPRL(0x12,0x09), SW6, ARG_OPRLZ1 }, /* pseudo swgcc */ -- { "neglv", OPR(0x10,0x09), SW6, ARG_OPRZ1 }, /* pseudo swgcc */ -- { "neglv", OPRL(0x12,0x09), SW6, ARG_OPRLZ1 }, /* pseudo swgcc */ -- { "s4addl", OPR(0x10,0x0A), SW6, ARG_OPR }, -- { "s4addl", OPRL(0x12,0x0A), SW6, ARG_OPRL }, -- { "s4subl", OPR(0x10,0x0B), SW6, ARG_OPR }, -- { "s4subl", OPRL(0x12,0x0B), SW6, ARG_OPRL }, -- { "s8addl", OPR(0x10,0x0C), SW6, ARG_OPR }, -- { "s8addl", OPRL(0x12,0x0C), SW6, ARG_OPRL }, -- { "s8subl", OPR(0x10,0x0D), SW6, ARG_OPR }, -- { "s8subl", OPRL(0x12,0x0D), SW6, ARG_OPRL }, -- { "mulw", OPR(0x10,0x10), SW6, ARG_OPR }, -- { "mulw", OPRL(0x12,0x10), SW6, ARG_OPRL }, -- { "divw", OPR(0x10,0x11), SW6B, ARG_OPR }, -- { "udivw", OPR(0x10,0x12), SW6B, ARG_OPR }, -- { "remw", OPR(0x10,0x13), SW6B, ARG_OPR }, -- { "uremw", OPR(0x10,0x14), SW6B, ARG_OPR }, -- { "mull", OPR(0x10,0x18), SW6, ARG_OPR }, -- { "mull", OPRL(0x12,0x18), SW6, ARG_OPRL }, -- { "umulh", OPR(0x10,0x19), SW6, ARG_OPR }, -- { "umulh", OPRL(0x12,0x19), SW6, ARG_OPRL }, -- { "cmpeq", OPR(0x10,0x28), SW6, ARG_OPR }, -- { "cmpeq", OPRL(0x12,0x28), SW6, ARG_OPRL }, -- { "cmplt", OPR(0x10,0x29), SW6, ARG_OPR }, -- { "cmplt", OPRL(0x12,0x29), SW6, ARG_OPRL }, -- { "cmple", OPR(0x10,0x2A), SW6, ARG_OPR }, -- { "cmple", OPRL(0x12,0x2A), SW6, ARG_OPRL }, -- { "cmpult", OPR(0x10,0x2B), SW6, ARG_OPR }, -- { "cmpult", OPRL(0x12,0x2B), SW6, ARG_OPRL }, -- { "cmpule", OPR(0x10,0x2C), SW6, ARG_OPR }, -- { "cmpule", OPRL(0x12,0x2C), SW6, ARG_OPRL }, -- { "and", OPR(0x10,0x38), SW6, ARG_OPR }, -- { "and", OPRL(0x12,0x38),SW6, ARG_OPRL }, -- { "bic", OPR(0x10,0x39), SW6, ARG_OPR }, -- { "bic", OPRL(0x12,0x39),SW6, ARG_OPRL }, -- { "andnot", OPR(0x10,0x39), SW6, ARG_OPR },/* pseudo */ -- { "andnot", OPRL(0x12,0x39),SW6, ARG_OPRL },/* pseudo */ -- { "nop", OPR(0x10,0x3A), SW6, { ZA, ZB, ZC } }, /* now unop has a new expression */ -- { "excb", OPR(0x10,0x3A), SW6, { ZA, ZB, ZC } }, /* pseudo */ -- { "clr", OPR(0x10,0x3A),SW6, { ZA, ZB, RC } }, /* pseudo swgcc */ -- { "mov", OPR(0x10,0x3A), SW6, { ZA, RB, RC } }, /* pseudo */ -- { "mov", OPRL(0x12,0x3A),SW6, { ZA, LIT, RC } }, /* pseudo */ -- { "implver", OPRL_(0x12,0x3A)|2<<13,0xFFFFFFE0,SW6, {ZA,RC } }, /* pseudo swgcc */ -- { "amask", OPR_(0x10,0x3A)|31<<16,OPR_MASK, SW6, { ZA, RB, RC } }, /* pseudo */ -- { "amask", OPRL(0x12,0x3A), SW6, { ZA, LIT, RC } }, /* pseudo */ -- { "or", OPR(0x10,0x3A), SW6, ARG_OPR }, -- { "or", OPRL(0x12,0x3A),SW6, ARG_OPRL }, -- { "bis", OPR(0x10,0x3A), SW6, ARG_OPR }, -- { "bis", OPRL(0x12,0x3A),SW6, ARG_OPRL }, -- { "not", OPR(0x10,0x3B), SW6, ARG_OPRZ1 }, /* pseudo swgcc */ -- { "not", OPRL(0x12,0x3B),SW6, ARG_OPRLZ1 }, /* pseudo swgcc */ -- { "ornot", OPR(0x10,0x3B), SW6, ARG_OPR }, -- { "ornot", OPRL(0x12,0x3B),SW6, ARG_OPRL }, -- { "xor", OPR(0x10,0x3C), SW6, ARG_OPR }, -- { "xor", OPRL(0x12,0x3C),SW6, ARG_OPRL }, -- { "eqv", OPR(0x10,0x3D), SW6, ARG_OPR }, -- { "eqv", OPRL(0x12,0x3D),SW6, ARG_OPRL }, -- { "xornot", OPR(0x10,0x3D), SW6, ARG_OPR }, /* pseudo swgcc */ -- { "xornot", OPRL(0x12,0x3D),SW6, ARG_OPRL },/* pseudo swgcc */ -- { "inslb", OPR(0x10,0x40), SW6, ARG_OPR }, -- { "inslb", OPRL(0x12,0x40),SW6, ARG_OPRL }, -- { "ins0b", OPR(0x10,0x40), SW6, ARG_OPR }, -- { "ins0b", OPRL(0x12,0x40),SW6, ARG_OPRL }, -- { "inslh", OPR(0x10,0x41), SW6, ARG_OPR }, -- { "inslh", OPRL(0x12,0x41),SW6, ARG_OPRL }, -- { "ins1b", OPR(0x10,0x41), SW6, ARG_OPR }, -- { "ins1b", OPRL(0x12,0x41),SW6, ARG_OPRL }, -- { "inslw", OPR(0x10,0x42), SW6, ARG_OPR }, -- { "inslw", OPRL(0x12,0x42),SW6, ARG_OPRL }, -- { "ins2b", OPR(0x10,0x42), SW6, ARG_OPR }, -- { "ins2b", OPRL(0x12,0x42),SW6, ARG_OPRL }, -- { "insll", OPR(0x10,0x43), SW6, ARG_OPR }, -- { "insll", OPRL(0x12,0x43),SW6, ARG_OPRL }, -- { "ins3b", OPR(0x10,0x43), SW6, ARG_OPR }, -- { "ins3b", OPRL(0x12,0x43),SW6, ARG_OPRL }, -- { "inshb", OPR(0x10,0x44), SW6, ARG_OPR }, -- { "inshb", OPRL(0x12,0x44),SW6, ARG_OPRL }, -- { "ins4b", OPR(0x10,0x44), SW6, ARG_OPR }, -- { "ins4b", OPRL(0x12,0x44),SW6, ARG_OPRL }, -- { "inshh", OPR(0x10,0x45), SW6, ARG_OPR }, -- { "inshh", OPRL(0x12,0x45),SW6, ARG_OPRL }, -- { "ins5b", OPR(0x10,0x45), SW6, ARG_OPR }, -- { "ins5b", OPRL(0x12,0x45),SW6, ARG_OPRL }, -- { "inshw", OPR(0x10,0x46), SW6, ARG_OPR }, -- { "inshw", OPRL(0x12,0x46),SW6, ARG_OPRL }, -- { "ins6b", OPR(0x10,0x46), SW6, ARG_OPR }, -- { "ins6b", OPRL(0x12,0x46),SW6, ARG_OPRL }, -- { "inshl", OPR(0x10,0x47), SW6, ARG_OPR }, -- { "inshl", OPRL(0x12,0x47),SW6, ARG_OPRL }, -- { "ins7b", OPR(0x10,0x47), SW6, ARG_OPR }, -- { "ins7b", OPRL(0x12,0x47),SW6, ARG_OPRL }, -- { "sll", OPR(0x10,0x48), SW6, ARG_OPR }, -- { "sll", OPRL(0x12,0x48),SW6, ARG_OPRL }, -- { "srl", OPR(0x10,0x49), SW6, ARG_OPR }, -- { "srl", OPRL(0x12,0x49),SW6, ARG_OPRL }, -- { "sra", OPR(0x10,0x4A), SW6, ARG_OPR }, -- { "sra", OPRL(0x12,0x4A),SW6, ARG_OPRL }, -- { "sllw2", OPR(0x10,0x4C), SW6, ARG_OPR }, //sw6 v0.2a -- { "sllw2", OPRL(0x12,0x4C),SW6, ARG_OPRL },//sw6 v0.2a -- { "srlw2", OPR(0x10,0x4D), SW6, ARG_OPR }, //sw6 v0.2a -- { "srlw2", OPRL(0x12,0x4D),SW6, ARG_OPRL },//sw6 v0.2a -- { "sraw2", OPR(0x10,0x4E), SW6, ARG_OPR }, //sw6 v0.2a -- { "sraw2", OPRL(0x12,0x4E),SW6, ARG_OPRL },//sw6 v0.2a -- { "extlb", OPR(0x10,0x50), SW6, ARG_OPR }, -- { "extlb", OPRL(0x12,0x50),SW6, ARG_OPRL }, -- { "ext0b", OPR(0x10,0x50), SW6, ARG_OPR }, -- { "ext0b", OPRL(0x12,0x50),SW6, ARG_OPRL }, -- { "extlh", OPR(0x10,0x51), SW6, ARG_OPR }, -- { "extlh", OPRL(0x12,0x51),SW6, ARG_OPRL }, -- { "ext1b", OPR(0x10,0x51), SW6, ARG_OPR }, -- { "ext1b", OPRL(0x12,0x51),SW6, ARG_OPRL }, -- { "extlw", OPR(0x10,0x52), SW6, ARG_OPR }, -- { "extlw", OPRL(0x12,0x52),SW6, ARG_OPRL }, -- { "ext2b", OPR(0x10,0x52), SW6, ARG_OPR }, -- { "ext2b", OPRL(0x12,0x52),SW6, ARG_OPRL }, -- { "extll", OPR(0x10,0x53), SW6, ARG_OPR }, -- { "extll", OPRL(0x12,0x53),SW6, ARG_OPRL }, -- { "ext3b", OPR(0x10,0x53), SW6, ARG_OPR }, -- { "ext3b", OPRL(0x12,0x53),SW6, ARG_OPRL }, -- { "exthb", OPR(0x10,0x54), SW6, ARG_OPR }, -- { "exthb", OPRL(0x12,0x54),SW6, ARG_OPRL }, -- { "ext4b", OPR(0x10,0x54), SW6, ARG_OPR }, -- { "ext4b", OPRL(0x12,0x54),SW6, ARG_OPRL }, -- { "exthh", OPR(0x10,0x55), SW6, ARG_OPR }, -- { "exthh", OPRL(0x12,0x55),SW6, ARG_OPRL }, -- { "ext5b", OPR(0x10,0x55), SW6, ARG_OPR }, -- { "ext5b", OPRL(0x12,0x55),SW6, ARG_OPRL }, -- { "exthw", OPR(0x10,0x56), SW6, ARG_OPR }, -- { "exthw", OPRL(0x12,0x56),SW6, ARG_OPRL }, -- { "ext6b", OPR(0x10,0x56), SW6, ARG_OPR }, -- { "ext6b", OPRL(0x12,0x56),SW6, ARG_OPRL }, -- { "exthl", OPR(0x10,0x57), SW6, ARG_OPR }, -- { "exthl", OPRL(0x12,0x57),SW6, ARG_OPRL }, -- { "ext7b", OPR(0x10,0x57), SW6, ARG_OPR }, -- { "ext7b", OPRL(0x12,0x57),SW6, ARG_OPRL }, -- { "ctpop", OPR(0x10,0x58), SW6, ARG_OPRZ1 }, -- { "ctlz", OPR(0x10,0x59), SW6, ARG_OPRZ1 }, -- { "cttz", OPR(0x10,0x5A), SW6, ARG_OPRZ1 }, -- { "masklb", OPR(0x10,0x60), SW6, ARG_OPR }, -- { "masklb", OPRL(0x12,0x60),SW6, ARG_OPRL }, -- { "mask0b", OPR(0x10,0x60), SW6, ARG_OPR }, -- { "mask0b", OPRL(0x12,0x60),SW6, ARG_OPRL }, -- { "masklh", OPR(0x10,0x61), SW6, ARG_OPR }, -- { "masklh", OPRL(0x12,0x61),SW6, ARG_OPRL }, -- { "mask1b", OPR(0x10,0x61), SW6, ARG_OPR }, -- { "mask1b", OPRL(0x12,0x61),SW6, ARG_OPRL }, -- { "masklw", OPR(0x10,0x62), SW6, ARG_OPR }, -- { "masklw", OPRL(0x12,0x62),SW6, ARG_OPRL }, -- { "mask2b", OPR(0x10,0x62), SW6, ARG_OPR }, -- { "mask2b", OPRL(0x12,0x62),SW6, ARG_OPRL }, -- { "maskll", OPR(0x10,0x63), SW6, ARG_OPR }, -- { "maskll", OPRL(0x12,0x63),SW6, ARG_OPRL }, -- { "mask3b", OPR(0x10,0x63), SW6, ARG_OPR }, -- { "mask3b", OPRL(0x12,0x63),SW6, ARG_OPRL }, -- { "maskhb", OPR(0x10,0x64), SW6, ARG_OPR }, -- { "maskhb", OPRL(0x12,0x64),SW6, ARG_OPRL }, -- { "mask4b", OPR(0x10,0x64), SW6, ARG_OPR }, -- { "mask4b", OPRL(0x12,0x64),SW6, ARG_OPRL }, -- { "maskhh", OPR(0x10,0x65), SW6, ARG_OPR }, -- { "maskhh", OPRL(0x12,0x65),SW6, ARG_OPRL }, -- { "mask5b", OPR(0x10,0x65), SW6, ARG_OPR }, -- { "mask5b", OPRL(0x12,0x65),SW6, ARG_OPRL }, -- { "maskhw", OPR(0x10,0x66), SW6, ARG_OPR }, -- { "maskhw", OPRL(0x12,0x66),SW6, ARG_OPRL }, -- { "mask6b", OPR(0x10,0x66), SW6, ARG_OPR }, -- { "mask6b", OPRL(0x12,0x66),SW6, ARG_OPRL }, -- { "maskhl", OPR(0x10,0x67), SW6, ARG_OPR }, -- { "maskhl", OPRL(0x12,0x67),SW6, ARG_OPRL }, -- { "mask7b", OPR(0x10,0x67), SW6, ARG_OPR }, -- { "mask7b", OPRL(0x12,0x67),SW6, ARG_OPRL }, -- { "zap", OPR(0x10,0x68), SW6, ARG_OPR }, -- { "zap", OPRL(0x12,0x68),SW6, ARG_OPRL }, -- { "zapnot", OPR(0x10,0x69), SW6, ARG_OPR }, -- { "zapnot", OPRL(0x12,0x69),SW6, ARG_OPRL }, -- { "sextb", OPR(0x10,0x6A), SW6, ARG_OPRZ1}, -- { "sextb", OPRL(0x12,0x6A),SW6, ARG_OPRLZ1 }, -- { "sexth", OPR(0x10,0x6B), SW6, ARG_OPRZ1 }, -- { "sexth", OPRL(0x12,0x6B),SW6, ARG_OPRLZ1 }, -- { "cmpgeb", OPR(0x10,0x6C), SW6, ARG_OPR }, -- { "cmpgeb", OPRL(0x12,0x6C),SW6, ARG_OPRL }, -- { "fimovs", OPR(0x10,0x70), SW6, { FA, ZB, RC } }, -- { "fimovd", OPR(0x10,0x78), SW6, { FA, ZB, RC } }, -- { "ftoid", OPR(0x10,0x78), SW6, { FA, ZB, RC } }, -- { "seleq", TOPR(0x11,0x0), SW6, ARG_TOPR }, -- { "seleq", TOPRL(0x13,0x0),SW6, ARG_TOPRL }, -- { "selge", TOPR(0x11,0x1), SW6, ARG_TOPR }, -- { "selge", TOPRL(0x13,0x1),SW6, ARG_TOPRL }, -- { "selgt", TOPR(0x11,0x2), SW6, ARG_TOPR }, -- { "selgt", TOPRL(0x13,0x2),SW6, ARG_TOPRL }, -- { "selle", TOPR(0x11,0x3), SW6, ARG_TOPR }, -- { "selle", TOPRL(0x13,0x3),SW6, ARG_TOPRL }, -- { "sellt", TOPR(0x11,0x4), SW6, ARG_TOPR }, -- { "sellt", TOPRL(0x13,0x4),SW6, ARG_TOPRL }, -- { "selne", TOPR(0x11,0x5), SW6, ARG_TOPR }, -- { "selne", TOPRL(0x13,0x5),SW6, ARG_TOPRL }, -- { "sellbc", TOPR(0x11,0x6), SW6, ARG_TOPR }, -- { "sellbc", TOPRL(0x13,0x6),SW6, ARG_TOPRL }, -- { "sellbs", TOPR(0x11,0x7), SW6, ARG_TOPR }, -- { "sellbs", TOPRL(0x13,0x7),SW6, ARG_TOPRL }, -- { "vlog", LOGX(0x14,0x00), SW6, ARG_FMA }, -- -- { "vbicw", PSE_LOGX(0x14,0x30), SW6, { FA , FB , DFC1 } }, -- { "vxorw", PSE_LOGX(0x14,0x3c), SW6, { FA , FB , DFC1 } }, -- { "vandw", PSE_LOGX(0x14,0xc0), SW6, { FA , FB , DFC1 } }, -- { "veqvw", PSE_LOGX(0x14,0xc3), SW6, { FA , FB , DFC1 } }, -- { "vornotw", PSE_LOGX(0x14,0xf3), SW6, { FA , FB , DFC1 } }, -- { "vbisw", PSE_LOGX(0x14,0xfc), SW6, { FA , FB , DFC1 } }, -- -- { "fadds", FP(0x18,0x00), SW6, ARG_FP }, -- { "faddd", FP(0x18,0x01), SW6, ARG_FP }, -- { "fsubs", FP(0x18,0x02), SW6, ARG_FP }, -- { "fsubd", FP(0x18,0x03), SW6, ARG_FP }, -- { "fmuls", FP(0x18,0x04), SW6, ARG_FP }, -- { "fmuld", FP(0x18,0x05), SW6, ARG_FP }, -- { "fdivs", FP(0x18,0x06), SW6, ARG_FP }, -- { "fdivd", FP(0x18,0x07), SW6, ARG_FP }, -- { "fsqrts", FP(0x18,0x08), SW6, ARG_FPZ1 }, -- { "fsqrtd", FP(0x18,0x09), SW6, ARG_FPZ1 }, -- { "fcmpeq", FP(0x18,0x10), SW6, ARG_FP }, -- { "fcmple", FP(0x18,0x11), SW6, ARG_FP }, -- { "fcmplt", FP(0x18,0x12), SW6, ARG_FP }, -- { "fcmpun", FP(0x18,0x13), SW6, ARG_FP }, -- -- { "fcvtsd", FP(0x18,0x20), SW6, ARG_FPZ1 }, -- { "fcvtds", FP(0x18,0x21), SW6, ARG_FPZ1 }, -- { "fcvtdl_g", FP(0x18,0x22), SW6, ARG_FPZ1 }, -- { "fcvtdl_p", FP(0x18,0x23), SW6, ARG_FPZ1 }, -- { "fcvtdl_z", FP(0x18,0x24), SW6, ARG_FPZ1 }, -- { "fcvtdl_n", FP(0x18,0x25), SW6, ARG_FPZ1 }, -- { "fcvtdl", FP(0x18,0x27), SW6, ARG_FPZ1 }, -- { "fcvtwl", FP(0x18,0x28), SW6, ARG_FPZ1 }, -- { "fcvtlw", FP(0x18,0x29), SW6, ARG_FPZ1 }, -- { "fcvtls", FP(0x18,0x2d), SW6, ARG_FPZ1 }, -- { "fcvtld", FP(0x18,0x2f), SW6, ARG_FPZ1 }, -- -- { "fnop", FP(0x18,0x030), SW6, { ZA, ZB, ZC } }, -- { "fclr", FP(0x18,0x030), SW6, { ZA, ZB, FC } }, -- { "fabs", FP(0x18,0x030), SW6, ARG_FPZ1 }, -- { "fcpys", FP(0x18,0x30), SW6, ARG_FP }, -- { "fmov", FP(0x18,0x30), SW6, { FA, RBA, FC } }, -- { "fcpyse", FP(0x18,0x31), SW6, ARG_FP }, -- { "fneg", FP(0x18,0x32), SW6, { FA, RBA, FC } }, -- { "fcpysn", FP(0x18,0x32), SW6, ARG_FP }, -- -- { "ifmovs", FP(0x18,0x40), SW6, { RA, ZB, FC } }, -- { "ifmovd", FP(0x18,0x41), SW6, { RA, ZB, FC } }, -- { "itofd", FP(0x18,0x41), SW6, { RA, ZB, FC } }, -- -- { "rfpcr", FP(0x18,0x50), SW6, { FA, RBA, RCA } }, -- { "wfpcr", FP(0x18,0x51), SW6, { FA, RBA, RCA } }, -- { "setfpec0", FP(0x18,0x54), SW6, ARG_NONE }, -- { "setfpec1", FP(0x18,0x55), SW6, ARG_NONE }, -- { "setfpec2", FP(0x18,0x56), SW6, ARG_NONE }, -- { "setfpec3", FP(0x18,0x57), SW6, ARG_NONE }, -- { "fmas", FMA(0x19,0x00), SW6, ARG_FMA }, -- { "fmad", FMA(0x19,0x01), SW6, ARG_FMA }, -- { "fmss", FMA(0x19,0x02), SW6, ARG_FMA }, -- { "fmsd", FMA(0x19,0x03), SW6, ARG_FMA }, -- { "fnmas", FMA(0x19,0x04), SW6, ARG_FMA }, -- { "fnmad", FMA(0x19,0x05), SW6, ARG_FMA }, -- { "fnmss", FMA(0x19,0x06), SW6, ARG_FMA }, -- { "fnmsd", FMA(0x19,0x07), SW6, ARG_FMA }, -- --//fcmov*(SW6) to fcmov*(SW6) for fcmov* no need in sw64, and fsel*->fcmov* has difference in operands number,so it should not repalce directly. The default FD should be the same FC but not FA -- { "fseleq", FMA(0x19,0x10), SW6, ARG_FCMOV }, -- { "fselne", FMA(0x19,0x11), SW6, ARG_FCMOV }, -- { "fsellt", FMA(0x19,0x12), SW6, ARG_FCMOV }, -- { "fselle", FMA(0x19,0x13), SW6, ARG_FCMOV }, -- { "fselgt", FMA(0x19,0x14), SW6, ARG_FCMOV }, -- { "fselge", FMA(0x19,0x15), SW6, ARG_FCMOV }, -- -- { "vaddw", FP(0x1A,0x00), SW6, ARG_FP }, -- { "vaddw", FP(0x1A,0x20), SW6, ARG_FPL }, -- { "vsubw", FP(0x1A,0x01), SW6, ARG_FP }, -- { "vsubw", FP(0x1A,0x21), SW6, ARG_FPL }, -- { "vcmpgew", FP(0x1A,0x02), SW6, ARG_FP }, -- { "vcmpgew", FP(0x1A,0x22), SW6, ARG_FPL }, -- { "vcmpeqw", FP(0x1A,0x03), SW6, ARG_FP }, -- { "vcmpeqw", FP(0x1A,0x23), SW6, ARG_FPL }, -- { "vcmplew", FP(0x1A,0x04), SW6, ARG_FP }, -- { "vcmplew", FP(0x1A,0x24), SW6, ARG_FPL }, -- { "vcmpltw", FP(0x1A,0x05), SW6, ARG_FP }, -- { "vcmpltw", FP(0x1A,0x25), SW6, ARG_FPL }, -- { "vcmpulew", FP(0x1A,0x06), SW6, ARG_FP }, -- { "vcmpulew", FP(0x1A,0x26), SW6, ARG_FPL }, -- { "vcmpultw", FP(0x1A,0x07), SW6, ARG_FP }, -- { "vcmpultw", FP(0x1A,0x27), SW6, ARG_FPL }, -- -- { "vsllw", FP(0x1A,0x08), SW6, ARG_FP }, -- { "vsllw", FP(0x1A,0x28), SW6, ARG_FPL }, -- { "vsrlw", FP(0x1A,0x09), SW6, ARG_FP }, -- { "vsrlw", FP(0x1A,0x29), SW6, ARG_FPL }, -- { "vsraw", FP(0x1A,0x0A), SW6, ARG_FP }, -- { "vsraw", FP(0x1A,0x2A), SW6, ARG_FPL }, -- { "vrolw", FP(0x1A,0x0B), SW6, ARG_FP }, -- { "vrolw", FP(0x1A,0x2B), SW6, ARG_FPL }, -- { "sllow", FP(0x1A,0x0C), SW6, ARG_FP }, -- { "sllow", FP(0x1A,0x2C), SW6, ARG_FPL }, -- { "srlow", FP(0x1A,0x0D), SW6, ARG_FP }, -- { "srlow", FP(0x1A,0x2D), SW6, ARG_FPL }, -- { "vaddl", FP(0x1A,0x0E), SW6, ARG_FP }, -- { "vaddl", FP(0x1A,0x2E), SW6, ARG_FPL }, -- { "vsubl", FP(0x1A,0x0F), SW6, ARG_FP }, -- { "vsubl", FP(0x1A,0x2F), SW6, ARG_FPL }, -- { "ctpopow", FP(0x1A,0x18), SW6, { FA, ZB, DFC1 } }, -- { "ctlzow", FP(0x1A,0x19), SW6, { FA, ZB, DFC1 } }, -- { "vucaddw", FP(0x1A,0x40), SW6, ARG_FP }, -- { "vucaddw", FP(0x1A,0x60), SW6, ARG_FPL }, -- { "vucsubw", FP(0x1A,0x41), SW6, ARG_FP }, -- { "vucsubw", FP(0x1A,0x61), SW6, ARG_FPL }, -- { "vucaddh", FP(0x1A,0x42), SW6, ARG_FP }, -- { "vucaddh", FP(0x1A,0x62), SW6, ARG_FPL }, -- { "vucsubh", FP(0x1A,0x43), SW6, ARG_FP }, -- { "vucsubh", FP(0x1A,0x63), SW6, ARG_FPL }, -- { "vucaddb", FP(0x1A,0x44), SW6, ARG_FP }, -- { "vucaddb", FP(0x1A,0x64), SW6, ARG_FPL }, -- { "vucsubb", FP(0x1A,0x45), SW6, ARG_FP }, -- { "vucsubb", FP(0x1A,0x65), SW6, ARG_FPL }, -- { "vadds", FP(0x1A,0x80), SW6, ARG_FP }, -- { "v4adds", FP(0x1A,0x80), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -- { "vaddd", FP(0x1A,0x81), SW6, ARG_FP }, -- { "v4addd", FP(0x1A,0x81), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -- { "vsubs", FP(0x1A,0x82), SW6, ARG_FP }, -- { "v4subs", FP(0x1A,0x82), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -- { "vsubd", FP(0x1A,0x83), SW6, ARG_FP }, -- { "v4subd", FP(0x1A,0x83), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -- { "vmuls", FP(0x1A,0x84), SW6, ARG_FP }, -- { "v4muls", FP(0x1A,0x84), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -- { "vmuld", FP(0x1A,0x85), SW6, ARG_FP }, -- { "v4muld", FP(0x1A,0x85), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -- { "vdivs", FP(0x1A,0x86), SW6, ARG_FP }, -- { "vdivd", FP(0x1A,0x87), SW6, ARG_FP }, -- { "vsqrts", FP(0x1A,0x88), SW6, ARG_FPZ1 }, -- { "vsqrtd", FP(0x1A,0x89), SW6, ARG_FPZ1 }, -- { "vfcmpeq", FP(0x1A,0x8C), SW6, ARG_FP }, -- { "vfcmple", FP(0x1A,0x8D), SW6, ARG_FP }, -- { "vfcmplt", FP(0x1A,0x8E), SW6, ARG_FP }, -- { "vfcmpun", FP(0x1A,0x8F), SW6, ARG_FP }, -- { "vcpys", FP(0x1A,0x90), SW6, ARG_FP }, -- { "vfmov", FP(0x1A,0x90), SW6, { FA, RBA, FC } }, //V1.1 -- { "vcpyse", FP(0x1A,0x91), SW6, ARG_FP }, // SW6 1.0 -- { "vcpysn", FP(0x1A,0x92), SW6, ARG_FP }, // SW6 1.0 -- { "vmas", FMA(0x1B,0x00), SW6, ARG_FMA }, -- { "vmad", FMA(0x1B,0x01), SW6, ARG_FMA }, -- { "vmss", FMA(0x1B,0x02), SW6, ARG_FMA }, -- { "vmsd", FMA(0x1B,0x03), SW6, ARG_FMA }, -- { "vnmas", FMA(0x1B,0x04), SW6, ARG_FMA }, -- { "vnmad", FMA(0x1B,0x05), SW6, ARG_FMA }, -- { "vnmss", FMA(0x1B,0x06), SW6, ARG_FMA }, -- { "vnmsd", FMA(0x1B,0x07), SW6, ARG_FMA }, -- { "vfseleq", FMA(0x1B,0x10), SW6, ARG_FMA }, -- { "vfsellt", FMA(0x1B,0x12), SW6, ARG_FMA }, -- { "vfselle", FMA(0x1B,0x13), SW6, ARG_FMA }, -- { "vseleqw", FMA(0x1B,0x18), SW6, ARG_FMA }, -- { "vseleqw", FMA(0x1B,0x38), SW6, ARG_FMAL }, -- { "vsellbcw", FMA(0x1B,0x19), SW6, ARG_FMA }, -- { "vsellbcw", FMA(0x1B,0x39), SW6, ARG_FMAL }, -- { "vselltw", FMA(0x1B,0x1A), SW6, ARG_FMA }, -- { "vselltw", FMA(0x1B,0x3A), SW6, ARG_FMAL }, -- { "vsellew", FMA(0x1B,0x1B), SW6, ARG_FMA }, -- { "vsellew", FMA(0x1B,0x3B), SW6, ARG_FMAL }, -- { "vinsw", FMA(0x1B,0x20), SW6, ARG_FMAL }, -- { "vinsf", FMA(0x1B,0x21), SW6, ARG_FMAL }, -- { "vextw", FMA(0x1B,0x22), SW6, { FA, FMALIT, DFC1 }}, -- { "vextf", FMA(0x1B,0x23), SW6, { FA, FMALIT, DFC1 }}, -- { "vcpyw", FMA(0x1B,0x24), SW6, { FA, DFC1 }}, -- { "vcpyf", FMA(0x1B,0x25), SW6, { FA, DFC1 }}, -- { "vconw", FMA(0x1B,0x26), SW6, ARG_FMA }, -- { "vshfw", FMA(0x1B,0x27), SW6, ARG_FMA }, -- { "vcons", FMA(0x1B,0x28), SW6, ARG_FMA }, -- { "vcond", FMA(0x1B,0x29), SW6, ARG_FMA }, -- { "vldw_u", ATMEM(0x1C,0x0), SW6, ARG_VUAMEM }, -- { "vstw_u", ATMEM(0x1C,0x1), SW6, ARG_VUAMEM }, -- { "vlds_u", ATMEM(0x1C,0x2), SW6, ARG_VUAMEM }, -- { "vsts_u", ATMEM(0x1C,0x3), SW6, ARG_VUAMEM }, -- { "vldd_u", ATMEM(0x1C,0x4), SW6, ARG_VUAMEM }, -- { "vstd_u", ATMEM(0x1C,0x5), SW6, ARG_VUAMEM }, -- { "vstw_ul", ATMEM(0x1C,0x8), SW6, ARG_VUAMEM }, -- { "vstw_uh", ATMEM(0x1C,0x9), SW6, ARG_VUAMEM }, -- { "vsts_ul", ATMEM(0x1C,0xA), SW6, ARG_VUAMEM }, -- { "vsts_uh", ATMEM(0x1C,0xB), SW6, ARG_VUAMEM }, -- { "vstd_ul", ATMEM(0x1C,0xC), SW6, ARG_VUAMEM }, -- { "vstd_uh", ATMEM(0x1C,0xD), SW6, ARG_VUAMEM }, -- { "vldd_nc", ATMEM(0x1C,0xE), SW6, ARG_VUAMEM }, -- { "vstd_nc", ATMEM(0x1C,0xF), SW6, ARG_VUAMEM }, -- { "flushd", MEM(0x20), SW6, ARG_PREFETCH }, -- { "ldbu", MEM(0x20), SW6, ARG_MEM }, -- { "evictdg", MEM(0x21), SW6, ARG_PREFETCH }, -- { "ldhu", MEM(0x21), SW6, ARG_MEM }, -- { "s_fillcs", MEM(0x22), SW6, ARG_PREFETCH }, -- { "ldw", MEM(0x22), SW6, ARG_MEM }, -- { "wh64", MFC(0x22,0xF800), SW6, { ZA, PRB } }, -- { "s_fillde", MEM(0x23), SW6, ARG_PREFETCH }, -- { "ldl", MEM(0x23), SW6, ARG_MEM }, -- { "evictdl", MEM(0x24), SW6, ARG_PREFETCH }, -- { "ldl_u", MEM(0x24), SW6, ARG_MEM }, -- { "pri_ldw/p", SW6HWMEM(0x25,0x0), SW6, ARG_SW6HWMEM }, -- { "pri_ldw_inc/p", SW6HWMEM(0x25,0x2), SW6, ARG_SW6HWMEM }, -- { "pri_ldw_dec/p", SW6HWMEM(0x25,0x4), SW6, ARG_SW6HWMEM }, -- { "pri_ldw_set/p", SW6HWMEM(0x25,0x6), SW6, ARG_SW6HWMEM }, -- { "pri_ldw/v", SW6HWMEM(0x25,0x8), SW6, ARG_SW6HWMEM }, -- { "pri_ldw/vpte", SW6HWMEM(0x25,0xA), SW6, ARG_SW6HWMEM }, -- { "pri_ldl/p", SW6HWMEM(0x25,0x1), SW6, ARG_SW6HWMEM }, -- { "pri_ldl_inc/p", SW6HWMEM(0x25,0x3), SW6, ARG_SW6HWMEM }, -- { "pri_ldl_dec/p", SW6HWMEM(0x25,0x5), SW6, ARG_SW6HWMEM }, -- { "pri_ldl_set/p", SW6HWMEM(0x25,0x7), SW6, ARG_SW6HWMEM }, -- { "pri_ldl/v", SW6HWMEM(0x25,0x9), SW6, ARG_SW6HWMEM }, -- { "pri_ldl/vpte", SW6HWMEM(0x25,0xB), SW6, ARG_SW6HWMEM }, -- { "fillde", MEM(0x26), SW6, ARG_PREFETCH }, -- { "flds", MEM(0x26), SW6, ARG_FMEM }, -- { "fillde_e", MEM(0x27), SW6, ARG_PREFETCH }, -- { "fldd", MEM(0x27), SW6, ARG_FMEM }, -- -- { "stb", MEM(0x28), SW6, ARG_MEM }, -- { "sth", MEM(0x29), SW6, ARG_MEM }, -- { "stw", MEM(0x2A), SW6, ARG_MEM }, -- { "stl", MEM(0x2B), SW6, ARG_MEM }, -- { "stl_u", MEM(0x2C), SW6, ARG_MEM }, -- { "pri_stw/p", SW6HWMEM(0x2D,0x0), SW6, ARG_SW6HWMEM }, -- { "pri_stw/v", SW6HWMEM(0x2D,0x8), SW6, ARG_SW6HWMEM }, -- { "pri_stl/p", SW6HWMEM(0x2D,0x1), SW6, ARG_SW6HWMEM }, -- { "pri_stl/v", SW6HWMEM(0x2D,0x9), SW6, ARG_SW6HWMEM }, -- { "fsts", MEM(0x2E), SW6, ARG_FMEM }, -- { "fstd", MEM(0x2F), SW6, ARG_FMEM }, -- { "beq", BRA(0x30), SW6, ARG_BRA }, -- { "bne", BRA(0x31), SW6, ARG_BRA }, -- { "blt", BRA(0x32), SW6, ARG_BRA }, -- { "ble", BRA(0x33), SW6, ARG_BRA }, -- { "bgt", BRA(0x34), SW6, ARG_BRA }, -- { "bge", BRA(0x35), SW6, ARG_BRA }, -- { "blbc", BRA(0x36), SW6, ARG_BRA }, -- { "blbs", BRA(0x37), SW6, ARG_BRA }, -- -- { "fbeq", BRA(0x38), SW6, ARG_FBRA }, -- { "fbne", BRA(0x39), SW6, ARG_FBRA }, -- { "fblt", BRA(0x3A), SW6, ARG_FBRA }, -- { "fble", BRA(0x3B), SW6, ARG_FBRA }, -- { "fbgt", BRA(0x3C), SW6, ARG_FBRA }, -- { "fbge", BRA(0x3D), SW6, ARG_FBRA }, -- { "ldi", MEM(0x3E), SW6, { RA, MDISP, ZB } }, -- { "ldi", MEM(0x3E), SW6, ARG_MEM }, -- { "ldih", MEM(0x3F), SW6, { RA, MDISP, ZB } }, -- { "ldih", MEM(0x3F), SW6, ARG_MEM }, -- { "unop", MEM_(0x3F) | (30 << 16), MEM_MASK, SW6 , { ZA } }, --}; -- --const unsigned sw_64_num_opcodes = sizeof(sw_64_opcodes)/sizeof(*sw_64_opcodes); diff --git a/backport-0001-CVE-2021-42574.patch b/backport-CVE-2021-42574-part1.patch similarity index 100% rename from backport-0001-CVE-2021-42574.patch rename to backport-CVE-2021-42574-part1.patch diff --git a/backport-0002-CVE-2021-42574.patch b/backport-CVE-2021-42574-part2.patch similarity index 100% rename from backport-0002-CVE-2021-42574.patch rename to backport-CVE-2021-42574-part2.patch diff --git a/backport-0003-CVE-2021-42574.patch b/backport-CVE-2021-42574-part3.patch similarity index 100% rename from backport-0003-CVE-2021-42574.patch rename to backport-CVE-2021-42574-part3.patch diff --git a/binutils.spec b/binutils.spec index 792e04b..04d5469 100644 --- a/binutils.spec +++ b/binutils.spec @@ -1,7 +1,7 @@ Summary: Binary utilities Name: binutils Version: 2.37 -Release: 33 +Release: 34 License: GPLv3+ URL: https://sourceware.org/binutils @@ -22,9 +22,9 @@ Source: https://ftp.gnu.org/gnu/binutils/binutils-%{version}.tar.xz Patch3001: backport-CVE-2019-1010204.patch Patch3002: backport-Fix-a-potential-use-of-an-uninitialised-value-in-the.patch Patch3003: backport-CVE-2021-45078.patch -Patch3004: backport-0001-CVE-2021-42574.patch -Patch3005: backport-0002-CVE-2021-42574.patch -Patch3006: backport-0003-CVE-2021-42574.patch +Patch3004: backport-CVE-2021-42574-part1.patch +Patch3005: backport-CVE-2021-42574-part2.patch +Patch3006: backport-CVE-2021-42574-part3.patch Patch3007: backport-bfd-Close-the-file-descriptor-if-there-is-no-archive.patch Patch3008: backport-binutils-AArch64-EFI.patch Patch3009: backport-PR28391-strip-objcopy-preserve-dates-.a-cannot-set-t.patch @@ -117,10 +117,10 @@ Patch5007: backport-CVE-2025-3198.patch %ifarch sw_64 # sw_64 -Patch6001: sw_64-support-not-upstream-new-files.patch -Patch6002: sw_64-support-not-upstream-modified-files.patch -Patch6003: Sw64-revert-old-support-modified.patch -Patch6004: Sw64-revert-old-support-newfile.patch +# Patch6001: Unused +# Patch6002: Unused +# Patch6003: Unused +# Patch6004: Unused Patch6005: Sw64-binutils-Add-Sw64-new-support.patch Patch6006: Sw64-Add-support-EFI.patch %endif @@ -480,6 +480,9 @@ fi %{_infodir}/bfd*info* %changelog +* Tue Aug 19 2025 eastb233 - 2.37-34 +- [NFC] format patch names + * Tue Jul 22 2025 swcompiler - 2.37-33 - Add support for Sw64 EFI (efi-*-sw_64). diff --git a/sw_64-support-not-upstream-modified-files.patch b/sw_64-support-not-upstream-modified-files.patch deleted file mode 100644 index 0cd0bf4..0000000 --- a/sw_64-support-not-upstream-modified-files.patch +++ /dev/null @@ -1,3328 +0,0 @@ -From fa35de75a81dc38986949a090f3b08dd32effba3 Mon Sep 17 00:00:00 2001 -From: yeqinglong -Date: Wed, 30 Aug 2023 15:01:58 +0800 -Subject: [PATCH] add sw_64 support not upstream modified files - ---- - Makefile.in | 1 + - Makefile.tpl | 1 + - bfd/Makefile.am | 12 ++- - bfd/Makefile.in | 16 ++- - bfd/archures.c | 12 +++ - bfd/bfd-in2.h | 109 ++++++++++++++++++++ - bfd/config.bfd | 50 +++++++++ - bfd/config.in | 2 + - bfd/configure | 24 +++++ - bfd/configure.ac | 6 ++ - bfd/configure.com | 12 ++- - bfd/ecoff.c | 9 ++ - bfd/elf-bfd.h | 3 + - bfd/elf.c | 3 + - bfd/elflink.c | 23 +++++ - bfd/libbfd-in.h | 4 + - bfd/libbfd.h | 28 +++++ - bfd/makefile.vms | 7 ++ - bfd/peicode.h | 4 + - bfd/targets.c | 17 +++ - binutils/config.in | 2 + - binutils/configure | 5 + - binutils/configure.com | 1 + - binutils/readelf.c | 103 ++++++++++++++++++ - binutils/testsuite/binutils-all/nm.exp | 10 +- - binutils/testsuite/binutils-all/objcopy.exp | 1 + - binutils/testsuite/binutils-all/objdump.exp | 2 +- - binutils/testsuite/lib/binutils-common.exp | 2 +- - config.guess | 41 ++++++++ - config.sub | 1 + - config/elf.m4 | 2 +- - config/intdiv0.m4 | 2 +- - config/picflag.m4 | 3 + - config/tcl.m4 | 6 ++ - configure | 39 ++++++- - configure.ac | 37 ++++++- - elfcpp/elfcpp.h | 2 + - gas/Makefile.am | 2 + - gas/Makefile.in | 5 + - gas/as.c | 13 ++- - gas/as.h | 6 ++ - gas/config.in | 9 ++ - gas/config/obj-ecoff.c | 10 ++ - gas/config/obj-elf.c | 6 ++ - gas/config/obj-elf.h | 5 + - gas/configure | 19 ++++ - gas/configure.tgt | 10 +- - gas/read.c | 2 +- - gas/testsuite/gas/all/gas.exp | 7 ++ - gas/testsuite/gas/all/weakref1.d | 3 +- - gas/testsuite/gas/all/weakref1g.d | 2 +- - gas/testsuite/gas/all/weakref1l.d | 2 +- - gas/testsuite/gas/all/weakref1u.d | 2 +- - gas/testsuite/gas/all/weakref1w.d | 2 +- - gas/testsuite/gas/elf/common5a.d | 2 + - gas/testsuite/gas/elf/common5b.d | 2 + - gas/testsuite/gas/elf/common5c.d | 2 + - gas/testsuite/gas/elf/common5d.d | 2 + - gas/testsuite/gas/elf/elf.exp | 14 ++- - gas/testsuite/gas/elf/ifunc-1.d | 1 + - gas/testsuite/gas/elf/symtab.d | 1 + - gas/write.c | 58 ++++++++++- - gold/Makefile.am | 4 +- - gold/Makefile.in | 5 +- - gold/configure | 14 +++ - gold/configure.ac | 1 + - gold/configure.tgt | 6 ++ - gold/reloc.h | 1 + - gold/target-reloc.h | 4 +- - include/coff/ecoff.h | 14 +++ - include/coff/pe.h | 4 + - include/elf/common.h | 5 + - include/longlong.h | 55 ++++++++++ - ld/Makefile.am | 10 ++ - ld/Makefile.in | 17 +++ - ld/config.in | 2 + - ld/configure | 7 ++ - ld/configure.tgt | 16 +++ - ld/testsuite/config/default.exp | 20 ++++ - ld/testsuite/ld-elf/binutils.exp | 1 + - ld/testsuite/ld-elf/compress1a.d | 2 +- - ld/testsuite/ld-elf/compressed1a.d | 2 +- - ld/testsuite/ld-elf/eh5.d | 2 +- - ld/testsuite/ld-elf/elf.exp | 2 +- - ld/testsuite/ld-elf/pr17550a.d | 2 +- - ld/testsuite/ld-elf/pr17550b.d | 2 +- - ld/testsuite/ld-elf/pr17550c.d | 3 + - ld/testsuite/ld-elf/pr17550d.d | 3 + - ld/testsuite/ld-elf/pr18720b.c | 2 + - ld/testsuite/ld-elf/shared.exp | 13 ++- - ld/testsuite/ld-elf/stab.d | 2 +- - ld/testsuite/ld-elfvers/vers.exp | 1 + - ld/testsuite/ld-elfvsb/elfvsb.exp | 4 + - ld/testsuite/ld-elfweak/elfweak.exp | 1 + - ld/testsuite/ld-ifunc/ifunc-26.d | 2 +- - ld/testsuite/ld-ifunc/ifunc.exp | 1 + - ld/testsuite/ld-misc/just-symbols.exp | 3 +- - ld/testsuite/ld-plugin/plugin-14.d | 1 + - ld/testsuite/ld-plugin/plugin-15.d | 1 + - ld/testsuite/ld-plugin/plugin-16.d | 1 + - ld/testsuite/ld-plugin/plugin-20.d | 1 + - ld/testsuite/ld-plugin/plugin-21.d | 1 + - ld/testsuite/ld-plugin/plugin-22.d | 1 + - ld/testsuite/ld-plugin/plugin-23.d | 1 + - ld/testsuite/ld-plugin/plugin-6.d | 1 + - ld/testsuite/ld-plugin/plugin-7.d | 1 + - ld/testsuite/ld-plugin/plugin-8.d | 1 + - ld/testsuite/ld-scripts/fill.d | 3 +- - ld/testsuite/ld-scripts/fill16.d | 3 +- - ld/testsuite/ld-scripts/pr27100.d | 2 +- - ld/testsuite/ld-shared/shared.exp | 4 + - ld/testsuite/ld-srec/srec.exp | 6 ++ - makefile.vms | 8 ++ - opcodes/Makefile.am | 2 + - opcodes/Makefile.in | 4 + - opcodes/config.in | 2 + - opcodes/configure | 7 ++ - opcodes/configure.ac | 1 + - opcodes/configure.com | 8 ++ - opcodes/disassemble.c | 10 ++ - opcodes/disassemble.h | 3 + - 121 files changed, 1041 insertions(+), 54 deletions(-) - -diff --git a/Makefile.in b/Makefile.in -index 9b3a5d75..67156011 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -619,6 +619,7 @@ all: - #### host and target specific makefile fragments come in here. - @target_makefile_frag@ - @alphaieee_frag@ -+@sw_64ieee_frag@ - @ospace_frag@ - @host_makefile_frag@ - ### -diff --git a/Makefile.tpl b/Makefile.tpl -index 84fee3dd..dda97b5d 100644 ---- a/Makefile.tpl -+++ b/Makefile.tpl -@@ -572,6 +572,7 @@ all: - #### host and target specific makefile fragments come in here. - @target_makefile_frag@ - @alphaieee_frag@ -+@sw_64ieee_frag@ - @ospace_frag@ - @host_makefile_frag@ - ### -diff --git a/bfd/Makefile.am b/bfd/Makefile.am -index 7c859428..3aec8a2b 100644 ---- a/bfd/Makefile.am -+++ b/bfd/Makefile.am -@@ -92,6 +92,7 @@ BFD64_LIBS_CFILES = archive64.c - ALL_MACHINES = \ - cpu-aarch64.lo \ - cpu-alpha.lo \ -+ cpu-sw_64.lo \ - cpu-arc.lo \ - cpu-arm.lo \ - cpu-avr.lo \ -@@ -176,6 +177,7 @@ ALL_MACHINES = \ - ALL_MACHINES_CFILES = \ - cpu-aarch64.c \ - cpu-alpha.c \ -+ cpu-sw_64.c \ - cpu-arc.c \ - cpu-arm.c \ - cpu-avr.c \ -@@ -536,6 +538,7 @@ BFD64_BACKENDS = \ - aix5ppc-core.lo \ - aout64.lo \ - coff-alpha.lo \ -+ coff-sw_64.lo \ - coff-x86_64.lo \ - coff64-rs6000.lo \ - elf32-ia64.lo \ -@@ -543,6 +546,7 @@ BFD64_BACKENDS = \ - elf32-score.lo \ - elf32-score7.lo \ - elf64-alpha.lo \ -+ elf64-sw_64.lo \ - elf64-gen.lo \ - elf64-hppa.lo \ - elf64-ia64.lo \ -@@ -574,18 +578,21 @@ BFD64_BACKENDS = \ - pei-x86_64.lo \ - pepigen.lo \ - pex64igen.lo \ -- vms-alpha.lo -+ vms-alpha.lo \ -+ vms-sw_64.lo - - BFD64_BACKENDS_CFILES = \ - aix5ppc-core.c \ - aout64.c \ - coff-alpha.c \ -+ coff-sw_64.c \ - coff-x86_64.c \ - coff64-rs6000.c \ - elf32-mips.c \ - elf32-score.c \ - elf32-score7.c \ - elf64-alpha.c \ -+ elf64-sw_64.c \ - elf64-gen.c \ - elf64-hppa.c \ - elf64-ia64-vms.c \ -@@ -612,7 +619,8 @@ BFD64_BACKENDS_CFILES = \ - pei-aarch64.c \ - pei-ia64.c \ - pei-x86_64.c \ -- vms-alpha.c -+ vms-alpha.c \ -+ vms-sw_64.c - - OPTIONAL_BACKENDS = \ - aix386-core.lo \ -diff --git a/bfd/Makefile.in b/bfd/Makefile.in -index 66fa92c1..32c1df38 100644 ---- a/bfd/Makefile.in -+++ b/bfd/Makefile.in -@@ -517,6 +517,7 @@ BFD64_LIBS_CFILES = archive64.c - ALL_MACHINES = \ - cpu-aarch64.lo \ - cpu-alpha.lo \ -+ cpu-sw_64.lo \ - cpu-arc.lo \ - cpu-arm.lo \ - cpu-avr.lo \ -@@ -601,6 +602,7 @@ ALL_MACHINES = \ - ALL_MACHINES_CFILES = \ - cpu-aarch64.c \ - cpu-alpha.c \ -+ cpu-sw_64.c \ - cpu-arc.c \ - cpu-arm.c \ - cpu-avr.c \ -@@ -963,6 +965,7 @@ BFD64_BACKENDS = \ - aix5ppc-core.lo \ - aout64.lo \ - coff-alpha.lo \ -+ coff-sw_64.lo \ - coff-x86_64.lo \ - coff64-rs6000.lo \ - elf32-ia64.lo \ -@@ -970,6 +973,7 @@ BFD64_BACKENDS = \ - elf32-score.lo \ - elf32-score7.lo \ - elf64-alpha.lo \ -+ elf64-sw_64.lo \ - elf64-gen.lo \ - elf64-hppa.lo \ - elf64-ia64.lo \ -@@ -1001,18 +1005,21 @@ BFD64_BACKENDS = \ - pei-x86_64.lo \ - pepigen.lo \ - pex64igen.lo \ -- vms-alpha.lo -+ vms-alpha.lo \ -+ vms-sw_64.lo - - BFD64_BACKENDS_CFILES = \ - aix5ppc-core.c \ - aout64.c \ - coff-alpha.c \ -+ coff-sw_64.c \ - coff-x86_64.c \ - coff64-rs6000.c \ - elf32-mips.c \ - elf32-score.c \ - elf32-score7.c \ - elf64-alpha.c \ -+ elf64-sw_64.c \ - elf64-gen.c \ - elf64-hppa.c \ - elf64-ia64-vms.c \ -@@ -1039,7 +1046,8 @@ BFD64_BACKENDS_CFILES = \ - pei-aarch64.c \ - pei-ia64.c \ - pei-x86_64.c \ -- vms-alpha.c -+ vms-alpha.c \ -+ vms-sw_64.c - - OPTIONAL_BACKENDS = \ - aix386-core.lo \ -@@ -1306,6 +1314,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-i386lynx.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cisco-core.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-alpha.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-sw_64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-bfd.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-go32.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coff-i386.Plo@am__quote@ -@@ -1326,6 +1335,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/corefile.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-aarch64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-alpha.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-sw_64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-arc.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-arm.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-avr.Plo@am__quote@ -@@ -1490,6 +1500,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-aarch64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-alpha.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-sw_64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-bpf.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-gen.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-hppa.Plo@am__quote@ -@@ -1579,6 +1590,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vaxnetbsd.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verilog.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-alpha.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-sw_64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-lib.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-misc.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wasm-module.Plo@am__quote@ -diff --git a/bfd/archures.c b/bfd/archures.c -index 390691bf..c5b07827 100644 ---- a/bfd/archures.c -+++ b/bfd/archures.c -@@ -24,6 +24,9 @@ - #include "libbfd.h" - #include "safe-ctype.h" - -+/* add sw_64 target -+ * add cpu sw6a-1621, sw6b-3231. */ -+ - /* - - SECTION -@@ -308,6 +311,11 @@ DESCRIPTION - .#define bfd_mach_alpha_ev4 0x10 - .#define bfd_mach_alpha_ev5 0x20 - .#define bfd_mach_alpha_ev6 0x30 -+.#ifdef TARGET_SW_64 -+. bfd_arch_sw_64, {* Sw_64 *} -+.#define bfd_mach_sw_64_sw6a 4 -+.#define bfd_mach_sw_64_sw6b 8 -+.#endif - . bfd_arch_arm, {* Advanced Risc Machines ARM. *} - .#define bfd_mach_arm_unknown 0 - .#define bfd_mach_arm_2 1 -@@ -610,6 +618,7 @@ DESCRIPTION - - extern const bfd_arch_info_type bfd_aarch64_arch; - extern const bfd_arch_info_type bfd_alpha_arch; -+extern const bfd_arch_info_type bfd_sw_64_arch; - extern const bfd_arch_info_type bfd_arc_arch; - extern const bfd_arch_info_type bfd_arm_arch; - extern const bfd_arch_info_type bfd_avr_arch; -@@ -699,6 +708,9 @@ static const bfd_arch_info_type * const bfd_archures_list[] = - #else - &bfd_aarch64_arch, - &bfd_alpha_arch, -+#ifdef TARGET_SW_64 -+ &bfd_sw_64_arch, -+#endif - &bfd_arc_arch, - &bfd_arm_arch, - &bfd_avr_arch, -diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h -index 5abde5fe..fc2f9b56 100644 ---- a/bfd/bfd-in2.h -+++ b/bfd/bfd-in2.h -@@ -1680,6 +1680,11 @@ enum bfd_architecture - #define bfd_mach_alpha_ev4 0x10 - #define bfd_mach_alpha_ev5 0x20 - #define bfd_mach_alpha_ev6 0x30 -+#ifdef TARGET_SW_64 -+ bfd_arch_sw_64, /* Sw_64 */ -+#define bfd_mach_sw_64_sw6a 4 -+#define bfd_mach_sw_64_sw6b 8 -+#endif - bfd_arch_arm, /* Advanced Risc Machines ARM. */ - #define bfd_mach_arm_unknown 0 - #define bfd_mach_arm_2 1 -@@ -2518,6 +2523,110 @@ between two procedure entry points is < 2^21, or else a hint. */ - BFD_RELOC_ALPHA_TPREL_LO16, - BFD_RELOC_ALPHA_TPREL16, - -+#ifdef TARGET_SW_64 -+/* Sw_64 ECOFF and ELF 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_SW_64_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_SW_64_GPDISP_LO16, -+ -+/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16 -+relocation except that there is no accompanying GPDISP_LO16 -+relocation. */ -+ BFD_RELOC_SW_64_GPDISP, -+ -+/* The Sw_64 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 ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16. -+It should refer to the symbol to be referenced, as with 16_GOTOFF, -+but it generates output not based on the position within the .got -+section, but relative to the GP value chosen for the file during the -+final link stage. -+ -+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) */ -+ BFD_RELOC_SW_64_LITERAL, -+ BFD_RELOC_SW_64_ELF_LITERAL, -+ BFD_RELOC_SW_64_ELF_LITERAL_GOT, -+ BFD_RELOC_SW_64_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_SW_64_HINT, -+ -+/* The LINKAGE relocation outputs a linkage pair in the object file, -+which is filled by the linker. */ -+ BFD_RELOC_SW_64_LINKAGE, -+ -+/* The CODEADDR relocation outputs a STO_CA in the object file, -+which is filled by the linker. */ -+ BFD_RELOC_SW_64_CODEADDR, -+ -+/* The GPREL_HI/LO relocations together form a 32-bit offset from the -+GP register. */ -+ BFD_RELOC_SW_64_GPREL_HI16, -+ BFD_RELOC_SW_64_GPREL_LO16, -+ -+/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must -+share a common GP, and the target address is adjusted for -+STO_SW_64_STD_GPLOAD. */ -+ BFD_RELOC_SW_64_BRSGP, -+ -+/* The NOP relocation outputs a NOP if the longword displacement -+between two procedure entry points is < 2^21. */ -+ BFD_RELOC_SW_64_NOP, -+ -+/* The BSR relocation outputs a BSR if the longword displacement -+between two procedure entry points is < 2^21. */ -+ BFD_RELOC_SW_64_BSR, -+ -+/* The LDA relocation outputs a LDA if the longword displacement -+between two procedure entry points is < 2^16. */ -+ BFD_RELOC_SW_64_LDA, -+ -+/* The BOH relocation outputs a BSR if the longword displacement -+between two procedure entry points is < 2^21, or else a hint. */ -+ BFD_RELOC_SW_64_BOH, -+ -+/* Sw_64 thread-local storage relocations. */ -+ BFD_RELOC_SW_64_TLSGD, -+ BFD_RELOC_SW_64_TLSLDM, -+ BFD_RELOC_SW_64_DTPMOD64, -+ BFD_RELOC_SW_64_GOTDTPREL16, -+ BFD_RELOC_SW_64_DTPREL64, -+ BFD_RELOC_SW_64_DTPREL_HI16, -+ BFD_RELOC_SW_64_DTPREL_LO16, -+ BFD_RELOC_SW_64_DTPREL16, -+ BFD_RELOC_SW_64_GOTTPREL16, -+ BFD_RELOC_SW_64_TPREL64, -+ BFD_RELOC_SW_64_TPREL_HI16, -+ BFD_RELOC_SW_64_TPREL_LO16, -+ BFD_RELOC_SW_64_TPREL16, -+ BFD_RELOC_SW_64_BR26, -+#endif -+ - /* The MIPS jump instruction. */ - BFD_RELOC_MIPS_JMP, - BFD_RELOC_MICROMIPS_JMP, -diff --git a/bfd/config.bfd b/bfd/config.bfd -index 81f4943e..9cbf7016 100644 ---- a/bfd/config.bfd -+++ b/bfd/config.bfd -@@ -165,6 +165,7 @@ targ_cpu=`echo $targ | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` - case "${targ_cpu}" in - aarch64*) targ_archs="bfd_aarch64_arch bfd_arm_arch";; - alpha*) targ_archs=bfd_alpha_arch ;; -+sw_64*) targ_archs=bfd_sw_64_arch ;; - am33_2.0*) targ_archs=bfd_mn10300_arch ;; - arc*) targ_archs=bfd_arc_arch ;; - arm*) targ_archs=bfd_arm_arch ;; -@@ -299,6 +300,55 @@ case "${targ}" in - targ_defvec=alpha_ecoff_le_vec - want64=true - ;; -+ sw_64*-*-freebsd* | sw_64*-*-kfreebsd*-gnu) -+ targ_defvec=sw_64_elf64_fbsd_vec -+ targ_selvecs="sw_64_elf64_vec sw_64_ecoff_le_vec" -+ want64=true -+ # FreeBSD <= 4.0 supports only the old nonstandard way of ABI labelling. -+ case "${targ}" in -+ sw_64*-*-freebsd3* | sw_64*-*-freebsd4 | sw_64*-*-freebsd4.0*) -+ targ_cflags=-DOLD_FREEBSD_ABI_LABEL ;; -+ esac -+ ;; -+ sw_64*-*-netbsd* | sw_64*-*-openbsd*) -+ targ_defvec=sw_64_elf64_vec -+ targ_selvecs=sw_64_ecoff_le_vec -+ want64=true -+ ;; -+ sw_64*-*-netware*) -+ targ_defvec=sw_64_ecoff_le_vec -+ targ_selvecs=sw_64_nlm32_vec -+ want64=true -+ ;; -+ sw_64*-*-linux*ecoff*) -+ targ_defvec=sw_64_ecoff_le_vec -+ targ_selvecs=sw_64_elf64_vec -+ want64=true -+ ;; -+ sw_64-*-linux-* | sw_64-*-elf*) -+ targ_defvec=sw_64_elf64_vec -+ targ_selvecs=sw_64_ecoff_le_vec -+ want64=true -+ ;; -+ sw_64sw6a-*-linux-* | sw_64sw6a-*-elf*) -+ targ_defvec=sw_64_elf64_vec -+ targ_selvecs=sw_64_ecoff_le_vec -+ want64=true -+ ;; -+ sw_64sw6b-*-linux-* | sw_64sw6b-*-elf*) -+ targ_defvec=sw_64_elf64_vec -+ targ_selvecs=sw_64_ecoff_le_vec -+ want64=true -+ ;; -+ sw_64*-*-*vms*) -+ targ_defvec=sw_64_vms_vec -+ targ_selvecs=sw_64_vms_lib_txt_vec -+ want64=true -+ ;; -+ sw_64*-*-*) -+ targ_defvec=sw_64_ecoff_le_vec -+ want64=true -+ ;; - ia64*-*-freebsd* | ia64*-*-netbsd* | ia64*-*-linux-* | ia64*-*-elf* | ia64*-*-kfreebsd*-gnu) - targ_defvec=ia64_elf64_le_vec - targ_selvecs="ia64_elf64_be_vec ia64_pei_vec" -diff --git a/bfd/config.in b/bfd/config.in -index f54a3cac..03d878d1 100644 ---- a/bfd/config.in -+++ b/bfd/config.in -@@ -341,3 +341,5 @@ - - /* Use structured /proc on Solaris. */ - #undef _STRUCTURED_PROC -+ -+#undef TARGET_SW_64 -diff --git a/bfd/configure b/bfd/configure -index fe8658e3..55e14c64 100755 ---- a/bfd/configure -+++ b/bfd/configure -@@ -11907,6 +11907,11 @@ i[34567]86-*-linux-* | x86_64-*-linux-*) - ac_default_ld_z_separate_code=1 - fi - ;; -+sw_64-*-linux-*) -+cat >>confdefs.h <<_ACEOF -+#define TARGET_SW_64 -+_ACEOF -+ ;; - esac - if test "${ac_default_ld_z_separate_code}" = unset; then - ac_default_ld_z_separate_code=0 -@@ -13287,6 +13292,12 @@ do - alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; - alpha_vms_vec) tb="$tb vms-alpha.lo vms-misc.lo vms-lib.lo"; target_size=64 ;; - alpha_vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;; -+ sw_64_ecoff_le_vec) tb="$tb coff-sw_64.lo ecoff.lo $ecoff"; target_size=64 ;; -+ sw_64_elf64_vec) tb="$tb elf64-sw_64.lo elf64.lo $elf"; target_size=64 ;; -+ sw_64_elf64_fbsd_vec) tb="$tb elf64-sw_64.lo elf64.lo $elf"; target_size=64 ;; -+ sw_64_nlm32_vec) tb="$tb nlm32-sw_64.lo nlm32.lo nlm.lo"; target_size=64 ;; -+ sw_64_vms_vec) tb="$tb vms-sw_64.lo vms-misc.lo vms-lib.lo"; target_size=64 ;; -+ sw_64_vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;; - am33_elf32_linux_vec) tb="$tb elf32-am33lin.lo elf32.lo $elf" ;; - aout0_be_vec) tb="$tb aout0.lo aout32.lo" ;; - aout64_vec) tb="$tb demo64.lo aout64.lo"; target_size=64 ;; -@@ -13701,6 +13712,19 @@ if test "${target}" = "${host}"; then - alpha*-*-*) - COREFILE=osf-core.lo - ;; -+ sw_64*-*-freebsd* | sw_64*-*-kfreebsd*-gnu | sw_64*-*-*vms*) -+ COREFILE='' -+ ;; -+ sw_64*-*-linux-*) -+ COREFILE=trad-core.lo -+ TRAD_HEADER='"hosts/sw_64linux.h"' -+ ;; -+ sw_64*-*-netbsd* | sw_64*-*-openbsd*) -+ COREFILE=netbsd-core.lo -+ ;; -+ sw_64*-*-*) -+ COREFILE=osf-core.lo -+ ;; - arm-*-freebsd* | arm-*-kfreebsd*-gnu) - COREFILE='' ;; - arm*-*-netbsd* | arm-*-openbsd*) -diff --git a/bfd/configure.ac b/bfd/configure.ac -index 577824b5..9493b900 100644 ---- a/bfd/configure.ac -+++ b/bfd/configure.ac -@@ -443,6 +443,12 @@ do - alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; - alpha_vms_vec) tb="$tb vms-alpha.lo vms-misc.lo vms-lib.lo"; target_size=64 ;; - alpha_vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;; -+ sw_64_ecoff_le_vec) tb="$tb coff-sw_64.lo ecoff.lo $ecoff"; target_size=64 ;; -+ sw_64_elf64_vec) tb="$tb elf64-sw_64.lo elf64.lo $elf"; target_size=64 ;; -+ sw_64_elf64_fbsd_vec) tb="$tb elf64-sw_64.lo elf64.lo $elf"; target_size=64 ;; -+ sw_64_nlm32_vec) tb="$tb nlm32-sw_64.lo nlm32.lo nlm.lo"; target_size=64 ;; -+ sw_64_vms_vec) tb="$tb vms-sw_64.lo vms-misc.lo vms-lib.lo"; target_size=64 ;; -+ sw_64_vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;; - am33_elf32_linux_vec) tb="$tb elf32-am33lin.lo elf32.lo $elf" ;; - aout0_be_vec) tb="$tb aout0.lo aout32.lo" ;; - aout64_vec) tb="$tb demo64.lo aout64.lo"; target_size=64 ;; -diff --git a/bfd/configure.com b/bfd/configure.com -index 0a663ca0..fa4be994 100644 ---- a/bfd/configure.com -+++ b/bfd/configure.com -@@ -26,9 +26,10 @@ $! - $ arch=F$GETSYI("ARCH_NAME") - $ arch=F$EDIT(arch,"LOWERCASE") - $if arch .eqs. "alpha" then target = "alpha" -+$if arch .eqs. "sw_64" then target = "sw_64" - $if arch .eqs. "ia64" then target = "ia64" - $! --$if (arch .eqs. "alpha") .or. (arch .eqs. "ia64") -+$if (arch .eqs. "alpha") .or. (arch .eqs. "ia64") .or. (arch .eqs. "sw_64") - $then - $! - $ write sys$output "Configuring BFD for ''target' target" -@@ -328,6 +329,15 @@ $ DEFS="""SELECT_VECS=&alpha_vms_vec"","+- - $ FILES="cpu-alpha,vms,vms-hdr,vms-gsd,vms-tir,vms-misc," - $EOD - $ endif -+$ if ARCH.eqs."sw_64" -+$ then -+$ create build.com -+$DECK -+$ DEFS="""SELECT_VECS=&sw_64_vms_vec"","+- -+ """SELECT_ARCHITECTURES=&bfd_sw_64_arch""" -+$ FILES="cpu-sw_64,vms,vms-hdr,vms-gsd,vms-tir,vms-misc," -+$EOD -+$ endif - $ if ARCH.eqs."ia64" - $ then - $ create build.com -diff --git a/bfd/ecoff.c b/bfd/ecoff.c -index 7844a50b..f13ccb74 100644 ---- a/bfd/ecoff.c -+++ b/bfd/ecoff.c -@@ -202,6 +202,12 @@ _bfd_ecoff_set_arch_mach_hook (bfd *abfd, void * filehdr) - mach = 0; - break; - -+#ifdef TARGET_SW_64 -+ case SW_64_MAGIC: -+ arch = bfd_arch_sw_64; -+ mach = 0; -+ break; -+#endif - default: - arch = bfd_arch_obscure; - mach = 0; -@@ -255,6 +261,9 @@ ecoff_get_magic (bfd *abfd) - case bfd_arch_alpha: - return ALPHA_MAGIC; - -+ case bfd_arch_sw_64: -+ return SW_64_MAGIC; -+ - default: - abort (); - return 0; -diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h -index 8f985ab8..f6499b34 100644 ---- a/bfd/elf-bfd.h -+++ b/bfd/elf-bfd.h -@@ -496,6 +496,9 @@ enum elf_target_id - { - AARCH64_ELF_DATA = 1, - ALPHA_ELF_DATA, -+#ifdef TARGET_SW_64 -+ SW_64_ELF_DATA, -+#endif - ARC_ELF_DATA, - ARM_ELF_DATA, - AVR_ELF_DATA, -diff --git a/bfd/elf.c b/bfd/elf.c -index 9c3f34c4..81a31ec0 100644 ---- a/bfd/elf.c -+++ b/bfd/elf.c -@@ -11013,6 +11013,9 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note) - - case bfd_arch_aarch64: - case bfd_arch_alpha: -+#ifdef TARGET_SW_64 -+ case bfd_arch_sw_64: -+#endif - case bfd_arch_sparc: - switch (note->type) - { -diff --git a/bfd/elflink.c b/bfd/elflink.c -index 9a052082..5589c4d9 100644 ---- a/bfd/elflink.c -+++ b/bfd/elflink.c -@@ -4106,6 +4106,16 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) - } - - ehdr = elf_elfheader (abfd); -+#ifdef TARGET_SW_64 -+ if(ehdr->e_machine != 0x9916) -+ { -+ char obj_elf_path[4096]={0}; -+ char obj_buff[4094]; -+ readlink("/proc/sel/exe",obj_elf_path,4096); -+ sprintf(obj_buff,"fail to load_symbols %s,process_name %s\n",abfd->filename,obj_elf_path); -+ //syslog(LOG_ALERT,obj_buff,strlen(obj_buff)); -+ } -+#endif - if (info->warn_alternate_em - && bed->elf_machine_code != ehdr->e_machine - && ((bed->elf_machine_alt1 != 0 -@@ -5922,6 +5932,19 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) - if (!bfd_link_add_symbols (element, info)) - goto error_return; - -+#ifdef TARGET_SW_64 -+ Elf_Internal_Ehdr *archive_ehdrp; /* Elf file header, internal form. */ -+ archive_ehdrp = elf_elfheader (element); -+ if(archive_ehdrp->e_machine != 0x9916) -+ { -+ char archive_elf_path[4096]={0}; -+ char archive_buff[4096]; -+ readlink("/proc/sel/exe",archive_elf_path,4096); -+ sprintf(archive_buff,"fail to load_symbols %s,process_name %s\n",element->filename,archive_elf_path); -+ //syslog(LOG_ALERT,archive_buff,strlen(archive_buff)); -+ } -+#endif -+ - /* 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 -diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h -index 1f7e2218..21935c2f 100644 ---- a/bfd/libbfd-in.h -+++ b/bfd/libbfd-in.h -@@ -424,8 +424,12 @@ extern bfd_cleanup _bfd_vms_lib_alpha_archive_p - (bfd *) ATTRIBUTE_HIDDEN; - extern bfd_cleanup _bfd_vms_lib_ia64_archive_p - (bfd *) ATTRIBUTE_HIDDEN; -+extern const bfd_target *_bfd_vms_lib_sw_64_archive_p -+ (bfd *) ATTRIBUTE_HIDDEN; - extern bool _bfd_vms_lib_alpha_mkarchive - (bfd *) ATTRIBUTE_HIDDEN; -+extern bfd_boolean _bfd_vms_lib_sw_64_mkarchive -+ (bfd *) ATTRIBUTE_HIDDEN; - extern bool _bfd_vms_lib_ia64_mkarchive - (bfd *) ATTRIBUTE_HIDDEN; - -diff --git a/bfd/libbfd.h b/bfd/libbfd.h -index c37ddc03..9ad9adf5 100644 ---- a/bfd/libbfd.h -+++ b/bfd/libbfd.h -@@ -1214,6 +1214,34 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", - "BFD_RELOC_ALPHA_TPREL_HI16", - "BFD_RELOC_ALPHA_TPREL_LO16", - "BFD_RELOC_ALPHA_TPREL16", -+#ifdef TARGET_SW_64 -+ "BFD_RELOC_SW_64_GPDISP_HI16", -+ "BFD_RELOC_SW_64_GPDISP_LO16", -+ "BFD_RELOC_SW_64_GPDISP", -+ "BFD_RELOC_SW_64_LITERAL", -+ "BFD_RELOC_SW_64_ELF_LITERAL", -+ "BFD_RELOC_SW_64_LITUSE", -+ "BFD_RELOC_SW_64_HINT", -+ "BFD_RELOC_SW_64_LINKAGE", -+ "BFD_RELOC_SW_64_CODEADDR", -+ "BFD_RELOC_SW_64_GPREL_HI16", -+ "BFD_RELOC_SW_64_GPREL_LO16", -+ "BFD_RELOC_SW_64_BRSGP" -+ "BFD_RELOC_SW_64_NOP", -+ "BFD_RELOC_SW_64_BSR", -+ "BFD_RELOC_SW_64_LDA", -+ "BFD_RELOC_SW_64_BOH", -+ "BFD_RELOC_SW_64_TLSGD", -+ "BFD_RELOC_SW_64_TLSLDM", -+ "BFD_RELOC_SW_64_DTPMOD64", -+ "BFD_RELOC_SW_64_GOTDTPREL16", -+ "BFD_RELOC_SW_64_DTPREL64", -+ "BFD_RELOC_SW_64_DTPREL_HI16", -+ "BFD_RELOC_SW_64_DTPREL_LO16", -+ "BFD_RELOC_SW_64_DTPREL16", -+ "BFD_RELOC_SW_64_GOTTPREL16", -+ "BFD_RELOC_SW_64_TPREL64", -+#endif - "BFD_RELOC_MIPS_JMP", - "BFD_RELOC_MICROMIPS_JMP", - "BFD_RELOC_MIPS16_JMP", -diff --git a/bfd/makefile.vms b/bfd/makefile.vms -index 4efe1581..21b9f16e 100644 ---- a/bfd/makefile.vms -+++ b/bfd/makefile.vms -@@ -36,6 +36,13 @@ OBJS:=vms-alpha.obj,vms-lib.obj,vms-misc.obj,cpu-alpha.obj - DEFS=SELECT_VECS="&alpha_vms_vec",SELECT_ARCHITECTURES="&bfd_alpha_arch" - endif - -+ifeq ($(ARCH),SW_64) -+HOSTFILE=sw_64vms.h -+OBJS:=vms-sw_64.obj,vms-lib.obj,vms-misc.obj,cpu-sw_64.obj -+DEFS=SELECT_VECS="&sw_64_vms_vec",SELECT_ARCHITECTURES="&bfd_sw_64_arch" -+endif -+ -+ - OBJS:=$(OBJS),archive.obj,archive64.obj,archures.obj,bfd.obj,bfdio.obj,\ - binary.obj,cache.obj,coffgen.obj,compress.obj,corefile.obj,dwarf2.obj,\ - elf.obj,format.obj,hash.obj,ihex.obj,init.obj,libbfd.obj,linker.obj,\ -diff --git a/bfd/peicode.h b/bfd/peicode.h -index 9374e232..4e7a7486 100644 ---- a/bfd/peicode.h -+++ b/bfd/peicode.h -@@ -1176,6 +1176,10 @@ pe_ILF_object_p (bfd * abfd) - case IMAGE_FILE_MACHINE_UNKNOWN: - case IMAGE_FILE_MACHINE_ALPHA: - case IMAGE_FILE_MACHINE_ALPHA64: -+#ifdef TARGET_SW_64 -+ case IMAGE_FILE_MACHINE_SW_64: -+ case IMAGE_FILE_MACHINE_SW_6464: -+#endif - case IMAGE_FILE_MACHINE_IA64: - break; - -diff --git a/bfd/targets.c b/bfd/targets.c -index ae6075b3..362a0dc9 100644 ---- a/bfd/targets.c -+++ b/bfd/targets.c -@@ -685,6 +685,14 @@ extern const bfd_target alpha_elf64_vec; - extern const bfd_target alpha_elf64_fbsd_vec; - extern const bfd_target alpha_vms_vec; - extern const bfd_target alpha_vms_lib_txt_vec; -+#ifdef TARGET_SW_64 -+extern const bfd_target sw_64_ecoff_le_vec; -+extern const bfd_target sw_64_elf64_vec; -+extern const bfd_target sw_64_elf64_fbsd_vec; -+extern const bfd_target sw_64_nlm32_vec; -+extern const bfd_target sw_64_vms_vec; -+extern const bfd_target sw_64_vms_lib_txt_vec; -+#endif - extern const bfd_target am33_elf32_linux_vec; - extern const bfd_target aout_vec; - extern const bfd_target arc_elf32_be_vec; -@@ -1003,6 +1011,15 @@ static const bfd_target * const _bfd_target_vector[] = - #endif - &alpha_vms_lib_txt_vec, - -+#ifdef BFD64 -+ &sw_64_ecoff_le_vec, -+ &sw_64_elf64_vec, -+ &sw_64_elf64_fbsd_vec, -+ &sw_64_nlm32_vec, -+ &sw_64_vms_vec, -+#endif -+ &sw_64_vms_lib_txt_vec, -+ - &am33_elf32_linux_vec, - - #if 0 -diff --git a/binutils/config.in b/binutils/config.in -index e6fa66fc..44c1d17a 100644 ---- a/binutils/config.in -+++ b/binutils/config.in -@@ -260,3 +260,5 @@ - - /* Define to 1 if you need to in order for `stat' and other things to work. */ - #undef _POSIX_SOURCE -+ -+#undef TARGET_SW_64 -diff --git a/binutils/configure b/binutils/configure -index 186ed103..e2f04ca1 100755 ---- a/binutils/configure -+++ b/binutils/configure -@@ -14614,6 +14614,11 @@ do - mep-*) - OBJDUMP_DEFS="-DSKIP_ZEROES=256 -DSKIP_ZEROES_AT_END=0" - ;; -+ sw_64-*-*) -+cat >>confdefs.h <<_ACEOF -+#define TARGET_SW_64 -+_ACEOF -+ ;; - esac - - # Add objdump private vectors. -diff --git a/binutils/configure.com b/binutils/configure.com -index 7b4a0b8d..85eddd39 100644 ---- a/binutils/configure.com -+++ b/binutils/configure.com -@@ -84,6 +84,7 @@ $! Add TARGET. - $! - $ if arch .eqs. "ia64" then target = "elf64-ia64-vms" - $ if arch .eqs. "alpha" then target = "vms-alpha" -+$ if arch .eqs. "sw_64" then target = "vms-sw_64" - $ if arch .eqs. "vax" then target = "vms-vax" - $! - $ open/append tfile config.h -diff --git a/binutils/readelf.c b/binutils/readelf.c -index cc9023aa..06dba4cf 100644 ---- a/binutils/readelf.c -+++ b/binutils/readelf.c -@@ -91,6 +91,9 @@ - - #include "elf/aarch64.h" - #include "elf/alpha.h" -+#ifdef TARGET_SW_64 -+#include "elf/sw_64.h" -+#endif - #include "elf/arc.h" - #include "elf/arm.h" - #include "elf/avr.h" -@@ -1021,6 +1024,9 @@ guess_is_rela (unsigned int e_machine) - case EM_AARCH64: - case EM_ADAPTEVA_EPIPHANY: - case EM_ALPHA: -+#ifdef TARGET_SW_64 -+ case EM_SW_64: -+#endif - case EM_ALTERA_NIOS2: - case EM_ARC: - case EM_ARC_COMPACT: -@@ -1617,6 +1623,12 @@ dump_relocations (Filedata * filedata, - rtype = elf_alpha_reloc_type (type); - break; - -+#ifdef TARGET_SW_64 -+ case EM_SW_64: -+ rtype = elf_sw_64_reloc_type (type); -+ break; -+#endif -+ - case EM_ARM: - rtype = elf_arm_reloc_type (type); - break; -@@ -1833,6 +1845,35 @@ dump_relocations (Filedata * filedata, - res = false; - } - } -+#ifdef TARGET_SW_64 -+ else if (filedata->file_header.e_machine == EM_SW_64 -+ && rtype != NULL -+ && streq (rtype, "R_SW_64_LITUSE") -+ ) -+ //&& is_rela) -+ { -+ switch (rels[i].r_addend) -+ { -+ case LITUSE_SW_64_ADDR: rtype = "ADDR"; break; -+ case LITUSE_SW_64_BASE: rtype = "BASE"; break; -+ case LITUSE_SW_64_BYTOFF: rtype = "BYTOFF"; break; -+ case LITUSE_SW_64_JSR: rtype = "JSR"; break; -+ case LITUSE_SW_64_TLSGD: rtype = "TLSGD"; break; -+ case LITUSE_SW_64_TLSLDM: rtype = "TLSLDM"; break; -+ case LITUSE_SW_64_JSRDIRECT: rtype = "JSRDIRECT"; break; -+ default: rtype = NULL; -+ } -+ if (rtype) -+ printf (" (%s)", rtype); -+ else -+ { -+ putchar (' '); -+ printf (_(""), -+ (unsigned long) rels[i].r_addend); -+ res = false; -+ } -+ } -+#endif - else if (symtab_index) - { - if (symtab == NULL || symtab_index >= nsyms) -@@ -2238,6 +2279,18 @@ get_alpha_dynamic_type (unsigned long type) - } - } - -+#ifdef TARGET_SW_64 -+static const char * -+get_sw_64_dynamic_type (unsigned long type) -+{ -+ switch (type) -+ { -+ case DT_SW_64_PLTRO: return "SW_64_PLTRO"; -+ default: return NULL; -+ } -+} -+#endif -+ - static const char * - get_score_dynamic_type (unsigned long type) - { -@@ -2428,6 +2481,11 @@ get_dynamic_type (Filedata * filedata, unsigned long type) - case EM_ALPHA: - result = get_alpha_dynamic_type (type); - break; -+#ifdef TARGET_SW_64 -+ case EM_SW_64: -+ result = get_sw_64_dynamic_type (type); -+ break; -+#endif - case EM_SCORE: - result = get_score_dynamic_type (type); - break; -@@ -2845,6 +2903,9 @@ get_machine_name (unsigned e_machine) - /* Large numbers... */ - case EM_MT: return "Morpho Techologies MT processor"; - case EM_ALPHA: return "Alpha"; -+#ifdef TARGET_SW_64 -+ case EM_SW_64: return "Sw_64"; -+#endif - case EM_WEBASSEMBLY: return "Web Assembly"; - case EM_DLX: return "OpenDLX"; - case EM_XSTORMY16: return "Sanyo XStormy16 CPU core"; -@@ -12355,6 +12416,21 @@ get_alpha_symbol_other (unsigned int other) - } - } - -+#ifdef TARGET_SW_64 -+static const char * -+get_sw_64_symbol_other (unsigned int other) -+{ -+ switch (other) -+ { -+ case STO_SW_64_NOPV: return "NOPV"; -+ case STO_SW_64_STD_GPLOAD: return "STD GPLOAD"; -+ default: -+ error (_("Unrecognized sw_64 specific other value: %u"), other); -+ return _(""); -+ } -+} -+#endif -+ - static const char * - get_solaris_symbol_visibility (unsigned int visibility) - { -@@ -12497,6 +12573,11 @@ get_symbol_other (Filedata * filedata, unsigned int other) - case EM_ALPHA: - result = get_alpha_symbol_other (other); - break; -+#ifdef TARGET_SW_64 -+ case EM_SW_64: -+ result = get_sw_64_symbol_other (other); -+ break; -+#endif - case EM_AARCH64: - result = get_aarch64_symbol_other (other); - break; -@@ -13790,6 +13871,10 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) - return reloc_type == 3; - case EM_ALPHA: - return reloc_type == 1; /* R_ALPHA_REFLONG. */ -+#ifdef TARGET_SW_64 -+ case EM_SW_64: -+ return reloc_type == 1; /* R_SW_64_REFLONG. */ -+#endif - case EM_ARC: - return reloc_type == 1; /* R_ARC_32. */ - case EM_ARC_COMPACT: -@@ -13987,6 +14072,10 @@ is_32bit_pcrel_reloc (Filedata * filedata, unsigned int reloc_type) - return reloc_type == 6; - case EM_ALPHA: - return reloc_type == 10; /* R_ALPHA_SREL32. */ -+#ifdef TARGET_SW_64 -+ case EM_SW_64: -+ return reloc_type == 10; /* R_SW_64_SREL32. */ -+#endif - case EM_ARC_COMPACT: - case EM_ARC_COMPACT2: - return reloc_type == 49; /* R_ARC_32_PCREL. */ -@@ -14055,6 +14144,10 @@ is_64bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) - return reloc_type == 257; /* R_AARCH64_ABS64. */ - case EM_ALPHA: - return reloc_type == 2; /* R_ALPHA_REFQUAD. */ -+#ifdef TARGET_SW_64 -+ case EM_SW_64: -+ return reloc_type == 2; /* R_SW_64_REFQUAD. */ -+#endif - case EM_IA_64: - return (reloc_type == 0x26 /* R_IA64_DIR64MSB. */ - || reloc_type == 0x27 /* R_IA64_DIR64LSB. */); -@@ -14097,6 +14190,10 @@ is_64bit_pcrel_reloc (Filedata * filedata, unsigned int reloc_type) - return reloc_type == 260; /* R_AARCH64_PREL64. */ - case EM_ALPHA: - return reloc_type == 11; /* R_ALPHA_SREL64. */ -+#ifdef TARGET_SW_64 -+ case EM_SW_64: -+ return reloc_type == 11; /* R_SW_64_SREL64. */ -+#endif - case EM_IA_64: - return (reloc_type == 0x4e /* R_IA64_PCREL64MSB. */ - || reloc_type == 0x4f /* R_IA64_PCREL64LSB. */); -@@ -14402,6 +14499,9 @@ is_none_reloc (Filedata * filedata, unsigned int reloc_type) - case EM_68K: /* R_68K_NONE. */ - case EM_ADAPTEVA_EPIPHANY: - case EM_ALPHA: /* R_ALPHA_NONE. */ -+#ifdef TARGET_SW_64 -+ case EM_SW_64: /* R_SW_64_NONE. */ -+#endif - case EM_ALTERA_NIOS2: /* R_NIOS2_NONE. */ - case EM_ARC: /* R_ARC_NONE. */ - case EM_ARC_COMPACT2: /* R_ARC_NONE. */ -@@ -20039,6 +20139,9 @@ get_netbsd_elfcore_note_type (Filedata * filedata, unsigned e_type) - - case EM_OLD_ALPHA: - case EM_ALPHA: -+#ifdef TARGET_SW_64 -+ case EM_SW_64: -+#endif - case EM_SPARC: - case EM_SPARC32PLUS: - case EM_SPARCV9: -diff --git a/binutils/testsuite/binutils-all/nm.exp b/binutils/testsuite/binutils-all/nm.exp -index 93753199..5a352dd2 100644 ---- a/binutils/testsuite/binutils-all/nm.exp -+++ b/binutils/testsuite/binutils-all/nm.exp -@@ -44,7 +44,7 @@ if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { - - # 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*" -+ setup_xfail "alpha*-*-osf*" "sw_64*-*-ecoff*" - setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" - setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" - -@@ -104,7 +104,7 @@ if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { - - # 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*" -+ setup_xfail "alpha*-*-osf*" "sw_64*-*-ecoff*" - setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" - setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" - -@@ -183,7 +183,7 @@ if {![binutils_assemble $srcdir/$subdir/$nm_1_src tmpdir/nm-1.o]} then { - - # 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*" -+ setup_xfail "alpha*-*-osf*" "sw_64*-*-ecoff*" - setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" - setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" - -@@ -263,7 +263,7 @@ if [is_elf_format] { - setup_xfail "sh*-*-*" - # The pre-compiled dwarf info in dw4.s is not compatible with the - # ALPHA, HPPA, IA64 and MIPS targets. -- setup_xfail "alpha*-*-*" "hppa*-*-*" "ia64*-*-*" "mips*-*-*" -+ setup_xfail "alpha*-*-*" "sw_64*-*-*" "hppa*-*-*" "ia64*-*-*" "mips*-*-*" - # Assembling the source file triggers an ICE in the FT32 assembler. - # FIXME: Fix the ICE... - setup_xfail "ft32-*-*" -@@ -303,7 +303,7 @@ if [is_elf_format] { - # Test nm --ifunc-chars on a indirect symbols. - - # The following targets are known to not support ifuncs. -- setup_xfail "alpha*-*-*" -+ setup_xfail "alpha*-*-*" "sw_64*-*-*" - setup_xfail "arm*-elf" "arm*-*-nto*" "arm*-*-netbsdelf*" - setup_xfail "*-*-hpux*" - setup_xfail "mips*-*-*" "tx39*-*-*" -diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp -index e1df9ff7..46bfd2a3 100644 ---- a/binutils/testsuite/binutils-all/objcopy.exp -+++ b/binutils/testsuite/binutils-all/objcopy.exp -@@ -120,6 +120,7 @@ proc objcopy_test {testname srcfile type asflags ldflags} { - - # On OSF/1, this succeeds with gas and fails with /bin/as. - setup_xfail "alpha*-*-osf*" -+ setup_xfail "sw_64*-*-osf*" - - fail "objcopy $type ($testname)" - } -diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp -index c9a7eec7..81f82721 100644 ---- a/binutils/testsuite/binutils-all/objdump.exp -+++ b/binutils/testsuite/binutils-all/objdump.exp -@@ -34,7 +34,7 @@ send_user "Version [binutil_version $OBJDUMP]" - set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"] - - set cpus_expected [list] --lappend cpus_expected aarch64 alpha am33-2 arc ARC700 ARCv2 arm cris -+lappend cpus_expected aarch64 alpha sw_64 am33-2 arc ARC700 ARCv2 arm cris - lappend cpus_expected d10v d30v fr30 fr500 fr550 h8 hppa i386 iamcu ip2022 - lappend cpus_expected m16c m32c m32r m68hc11 m68hc12 m68k MCore mep c5 h1 MicroBlaze - lappend cpus_expected mips mn10200 mn10300 ms1 msp MSP430 nds32 n1h_v3 ns32k -diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp -index 59e25df9..bd4119e1 100644 ---- a/binutils/testsuite/lib/binutils-common.exp -+++ b/binutils/testsuite/lib/binutils-common.exp -@@ -1627,7 +1627,7 @@ proc get_standard_section_names {} { - if [istarget "rx-*-elf"] { - return { "P" "D_1" "B_1" } - } -- if { [istarget "alpha*-*-*vms*"] || [is_som_format] } { -+ if { [istarget "alpha*-*-*vms*"] || [istarget "sw_64*-*-*vms*"] || [is_som_format] } { - return { {\$CODE\$} {\$DATA\$} {\$BSS\$} } - } - return -diff --git a/config.guess b/config.guess -index cc7a8107..9d4fbafa 100755 ---- a/config.guess -+++ b/config.guess -@@ -355,6 +355,36 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in - exitcode=$? - trap '' 0 - exit $exitcode ;; -+ sw_64:OSF1:*:*) -+ case $UNAME_RELEASE in -+ *4.0) -+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` -+ ;; -+ *5.*) -+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` -+ ;; -+ esac -+ # According to Compaq, /usr/sbin/psrinfo has been available on -+ # OSF/1 and Tru64 systems produced since 1995. I hope that -+ # covers most systems running today. This code pipes the CPU -+ # types through head -n 1, so we only detect the type of CPU 0. -+ SW_64_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The sw_64 \(.*\) processor.*$/\1/p' | head -n 1` -+ case "$SW_64_CPU_TYPE" in -+ "SW6A (21264)") -+ UNAME_MACHINE="sw_64sw6a" ;; -+ "SW6B (21264)") -+ UNAME_MACHINE="sw_64sw6b" ;; -+ "SW6 (21264A)") -+ UNAME_MACHINE="sw_64sw6" ;; -+ esac -+ # A Pn.n version is a patched version. -+ # A Vn.n version is a released version. -+ # A Tn.n version is a released field test version. -+ # A Xn.n version is an unreleased experimental baselevel. -+ # 1.2 uses "1.2" for uname -r. -+ OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` -+ GUESS=$UNAME_MACHINE-dec-osf$OSF_REL -+ ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; -@@ -953,6 +983,16 @@ EOF - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; -+ sw_64:Linux:*:*) -+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in -+ SW6A) UNAME_MACHINE=sw_64sw6a ;; -+ SW6B) UNAME_MACHINE=sw_64sw6b ;; -+ SW6) UNAME_MACHINE=sw_64sw6 ;; -+ esac -+ objdump --private-headers /bin/sh | grep -q ld.so.1 -+ if test "$?" = 0 ; then LIBC="gnulibc1" ; fi -+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC} -+ ;; - arc:Linux:*:* | arceb:Linux:*:* | arc64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; -@@ -1474,6 +1514,7 @@ EOF - UNAME_MACHINE=$( (uname -p) 2>/dev/null) - case "$UNAME_MACHINE" in - A*) echo alpha-dec-vms ; exit ;; -+ S*) echo sw_64-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; -diff --git a/config.sub b/config.sub -index 7384e919..f4fb2e2c 100755 ---- a/config.sub -+++ b/config.sub -@@ -1163,6 +1163,7 @@ case $cpu-$vendor in - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ - | alphapca5[67] | alpha64pca5[67] \ -+ | sw_64 | sw_64sw6a | sw_64sw6b \ - | am33_2.0 \ - | amdgcn \ - | arc | arceb | arc64 \ -diff --git a/config/elf.m4 b/config/elf.m4 -index 1772a443..537373c3 100644 ---- a/config/elf.m4 -+++ b/config/elf.m4 -@@ -17,7 +17,7 @@ target_elf=no - case $target in - *-darwin* | *-aix* | *-cygwin* | *-mingw* | *-aout* | *-*coff* | \ - *-msdosdjgpp* | *-vms* | *-wince* | *-*-pe* | \ -- alpha*-dec-osf* | *-interix* | hppa[[12]]*-*-hpux* | \ -+ alpha*-dec-osf* | sw_64*-dec-osf* | *-interix* | hppa[[12]]*-*-hpux* | \ - nvptx-*-none) - target_elf=no - ;; -diff --git a/config/intdiv0.m4 b/config/intdiv0.m4 -index 55dddcf1..8519d49e 100644 ---- a/config/intdiv0.m4 -+++ b/config/intdiv0.m4 -@@ -56,7 +56,7 @@ int main () - [ - # Guess based on the CPU. - case "$host_cpu" in -- alpha* | i[34567]86 | m68k | s390*) -+ alpha* | sw_64* | i[34567]86 | m68k | s390*) - gt_cv_int_divbyzero_sigfpe="guessing yes";; - *) - gt_cv_int_divbyzero_sigfpe="guessing no";; -diff --git a/config/picflag.m4 b/config/picflag.m4 -index 8b106f9a..1397e3a1 100644 ---- a/config/picflag.m4 -+++ b/config/picflag.m4 -@@ -20,6 +20,9 @@ case "${$2}" in - alpha*-dec-osf5*) - # PIC is the default. - ;; -+ sw_64*-dec-osf5*) -+ # PIC is the default. -+ ;; - hppa*64*-*-hpux*) - # PIC is the default for 64-bit PA HP-UX. - ;; -diff --git a/config/tcl.m4 b/config/tcl.m4 -index 4542a4b2..64319b54 100644 ---- a/config/tcl.m4 -+++ b/config/tcl.m4 -@@ -1368,6 +1368,9 @@ dnl AC_CHECK_TOOL(AR, ar) - if test "`uname -m`" = "alpha" ; then - CFLAGS="$CFLAGS -mieee" - fi -+ if test "`uname -m`" = "sw_64" ; then -+ CFLAGS="$CFLAGS -mieee" -+ fi - if test $do64bit = yes; then - AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ - hold_cflags=$CFLAGS -@@ -1418,6 +1421,9 @@ dnl AC_CHECK_TOOL(AR, ar) - if test "`uname -m`" = "alpha" ; then - CFLAGS="$CFLAGS -mieee" - fi -+ if test "`uname -m`" = "sw_64" ; then -+ CFLAGS="$CFLAGS -mieee" -+ fi - ;; - Lynx*) - SHLIB_CFLAGS="-fPIC" -diff --git a/configure b/configure -index 3dd20652..4c675f0a 100755 ---- a/configure -+++ b/configure -@@ -778,6 +778,7 @@ ac_subst_files='serialization_dependencies - host_makefile_frag - target_makefile_frag - alphaieee_frag -+sw_64ieee_frag - ospace_frag' - ac_user_opts=' - enable_option_checking -@@ -3013,7 +3014,7 @@ case "${ENABLE_GOLD}" in - *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \ - | *-*-linux* | *-*-gnu* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \ - | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* \ -- | *-*-solaris2* | *-*-nto* | *-*-nacl*) -+ | *-*-solaris2* | *-*-nto* | *-*-nacl* | sw_64-*-*-*) - case "${target}" in - *-*-linux*aout* | *-*-linux*oldld*) - ;; -@@ -3027,7 +3028,7 @@ case "${ENABLE_GOLD}" in - # Check for target supported by gold. - case "${target}" in - i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \ -- | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*) -+ | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | sw_64-*-*-*) - configdirs="$configdirs gold" - if test x${ENABLE_GOLD} = xdefault; then - default_ld=gold -@@ -3436,6 +3437,9 @@ case "${target}" in - alpha*-*-*vms*) - noconfigdirs="$noconfigdirs target-libffi" - ;; -+ sw_64*-*-*vms*) -+ noconfigdirs="$noconfigdirs target-libffi" -+ ;; - arm*-*-freebsd*) - noconfigdirs="$noconfigdirs target-libffi" - ;; -@@ -3570,6 +3574,9 @@ case "${target}" in - alpha*-dec-osf*) - noconfigdirs="$noconfigdirs target-newlib target-libgloss" - ;; -+ sw_64*-dec-osf*) -+ noconfigdirs="$noconfigdirs target-newlib target-libgloss" -+ ;; - i[3456789]86-*-linux*) - # This section makes it possible to build newlib natively on linux. - # If we are using a cross compiler then don't configure newlib. -@@ -3702,6 +3709,18 @@ case "${target}" in - # newlib is not 64 bit ready - noconfigdirs="$noconfigdirs target-newlib target-libgloss" - ;; -+ sw_64*-dec-osf*) -+ # ld works, but does not support shared libraries. -+ # gas doesn't generate exception information. -+ noconfigdirs="$noconfigdirs gas ld" -+ ;; -+ sw_64*-*-*vms*) -+ noconfigdirs="$noconfigdirs gdb target-newlib target-libgloss" -+ ;; -+ sw_64*-*-*) -+ # newlib is not 64 bit ready -+ noconfigdirs="$noconfigdirs target-newlib target-libgloss" -+ ;; - sh*-*-pe|mips*-*-pe|*arm-wince-pe) - noconfigdirs="$noconfigdirs tcl tk itcl libgui sim" - ;; -@@ -3965,6 +3984,9 @@ fi - alpha*-linux*) - host_makefile_frag="config/mh-alpha-linux" - ;; -+ sw_64*-linux*) -+ host_makefile_frag="config/mh-sw_64-linux" -+ ;; - hppa*-hp-hpux10*) - host_makefile_frag="config/mh-pa-hpux10" - ;; -@@ -6359,7 +6381,7 @@ target_elf=no - case $target in - *-darwin* | *-aix* | *-cygwin* | *-mingw* | *-aout* | *-*coff* | \ - *-msdosdjgpp* | *-vms* | *-wince* | *-*-pe* | \ -- alpha*-dec-osf* | *-interix* | hppa[12]*-*-hpux* | \ -+ alpha*-dec-osf* | sw_64*-dec-osf* | *-interix* | hppa[12]*-*-hpux* | \ - nvptx-*-none) - target_elf=no - ;; -@@ -7292,6 +7314,15 @@ case $target in - ;; - esac - -+sw_64ieee_frag=/dev/null -+case $target in -+ sw_64*-*-*) -+ # This just makes sure to use the -mieee option to build target libs. -+ # This should probably be set individually by each library. -+ sw_64ieee_frag="config/mt-sw_64ieee" -+ ;; -+esac -+ - # If --enable-target-optspace always use -Os instead of -O2 to build - # the target libraries, similarly if it is not specified, use -Os - # on selected platforms. -@@ -7996,7 +8027,7 @@ case "${target}" in - esac - - # Makefile fragments. --for frag in host_makefile_frag target_makefile_frag alphaieee_frag ospace_frag; -+for frag in host_makefile_frag target_makefile_frag alphaieee_frag sw_64ieee_frag ospace_frag; - do - eval fragval=\$$frag - if test $fragval != /dev/null; then -diff --git a/configure.ac b/configure.ac -index 48f679b8..12b4c56c 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -336,7 +336,7 @@ case "${ENABLE_GOLD}" in - *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \ - | *-*-linux* | *-*-gnu* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \ - | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* \ -- | *-*-solaris2* | *-*-nto* | *-*-nacl*) -+ | *-*-solaris2* | *-*-nto* | *-*-nacl* | sw_64-*-*-*) - case "${target}" in - *-*-linux*aout* | *-*-linux*oldld*) - ;; -@@ -350,7 +350,7 @@ case "${ENABLE_GOLD}" in - # Check for target supported by gold. - case "${target}" in - i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \ -- | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*) -+ | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | sw_64-*-*-*) - configdirs="$configdirs gold" - if test x${ENABLE_GOLD} = xdefault; then - default_ld=gold -@@ -722,6 +722,9 @@ case "${target}" in - alpha*-*-*vms*) - noconfigdirs="$noconfigdirs target-libffi" - ;; -+ sw_64*-*-*vms*) -+ noconfigdirs="$noconfigdirs target-libffi" -+ ;; - arm*-*-freebsd*) - noconfigdirs="$noconfigdirs target-libffi" - ;; -@@ -853,6 +856,9 @@ case "${target}" in - alpha*-dec-osf*) - noconfigdirs="$noconfigdirs target-newlib target-libgloss" - ;; -+ sw_64*-dec-osf*) -+ noconfigdirs="$noconfigdirs target-newlib target-libgloss" -+ ;; - i[[3456789]]86-*-linux*) - # This section makes it possible to build newlib natively on linux. - # If we are using a cross compiler then don't configure newlib. -@@ -985,6 +991,18 @@ case "${target}" in - # newlib is not 64 bit ready - noconfigdirs="$noconfigdirs target-newlib target-libgloss" - ;; -+ sw_64*-dec-osf*) -+ # ld works, but does not support shared libraries. -+ # gas doesn't generate exception information. -+ noconfigdirs="$noconfigdirs gas ld" -+ ;; -+ sw_64*-*-*vms*) -+ noconfigdirs="$noconfigdirs gdb target-newlib target-libgloss" -+ ;; -+ sw_64*-*-*) -+ # newlib is not 64 bit ready -+ noconfigdirs="$noconfigdirs target-newlib target-libgloss" -+ ;; - sh*-*-pe|mips*-*-pe|*arm-wince-pe) - noconfigdirs="$noconfigdirs tcl tk itcl libgui sim" - ;; -@@ -1229,6 +1247,9 @@ case "${host}" in - alpha*-linux*) - host_makefile_frag="config/mh-alpha-linux" - ;; -+ sw_64*-linux*) -+ host_makefile_frag="config/mh-sw_64-linux" -+ ;; - hppa*-hp-hpux10*) - host_makefile_frag="config/mh-pa-hpux10" - ;; -@@ -2608,6 +2629,15 @@ case $target in - ;; - esac - -+sw_64ieee_frag=/dev/null -+case $target in -+ sw_64*-*-*) -+ # This just makes sure to use the -mieee option to build target libs. -+ # This should probably be set individually by each library. -+ sw_64ieee_frag="config/mt-sw_64ieee" -+ ;; -+esac -+ - # If --enable-target-optspace always use -Os instead of -O2 to build - # the target libraries, similarly if it is not specified, use -Os - # on selected platforms. -@@ -3307,7 +3337,7 @@ case "${target}" in - esac - - # Makefile fragments. --for frag in host_makefile_frag target_makefile_frag alphaieee_frag ospace_frag; -+for frag in host_makefile_frag target_makefile_frag alphaieee_frag sw_64ieee_frag ospace_frag; - do - eval fragval=\$$frag - if test $fragval != /dev/null; then -@@ -3317,6 +3347,7 @@ done - AC_SUBST_FILE(host_makefile_frag) - AC_SUBST_FILE(target_makefile_frag) - AC_SUBST_FILE(alphaieee_frag) -+AC_SUBST_FILE(sw_64ieee_frag) - AC_SUBST_FILE(ospace_frag) - - # Miscellanea: directories, flags, etc. -diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h -index fdee7ce3..98ea57ce 100644 ---- a/elfcpp/elfcpp.h -+++ b/elfcpp/elfcpp.h -@@ -279,6 +279,7 @@ enum EM - EM_FRV = 0x5441, - // Infineon Technologies 16-bit microcontroller with C166-V2 core. - EM_X16X = 0x4688, -+ EM_SW_64 = 0x9916, - // Xstorym16 - EM_XSTORMY16 = 0xad45, - // Renesas M32C -@@ -792,6 +793,7 @@ enum DT - // symbol in the symbol table. - DT_SPARC_REGISTER = 0x70000001, - -+ DT_SW_64_PLTRO = 0x70000000, - // MIPS specific dynamic array tags. - // 32 bit version number for runtime linker interface. - DT_MIPS_RLD_VERSION = 0x70000001, -diff --git a/gas/Makefile.am b/gas/Makefile.am -index 3ad8422d..6d7d981b 100644 ---- a/gas/Makefile.am -+++ b/gas/Makefile.am -@@ -132,6 +132,7 @@ HFILES = \ - TARGET_CPU_CFILES = \ - config/tc-aarch64.c \ - config/tc-alpha.c \ -+ config/tc-sw_64.c \ - config/tc-arc.c \ - config/tc-arm.c \ - config/tc-avr.c \ -@@ -207,6 +208,7 @@ TARGET_CPU_CFILES = \ - TARGET_CPU_HFILES = \ - config/tc-aarch64.h \ - config/tc-alpha.h \ -+ config/tc-sw_64.h \ - config/tc-arc.h \ - config/tc-arm.h \ - config/tc-avr.h \ -diff --git a/gas/Makefile.in b/gas/Makefile.in -index 62439483..ba765d1c 100644 ---- a/gas/Makefile.in -+++ b/gas/Makefile.in -@@ -521,6 +521,7 @@ HFILES = \ - TARGET_CPU_CFILES = \ - config/tc-aarch64.c \ - config/tc-alpha.c \ -+ config/tc-sw_64.c \ - config/tc-arc.c \ - config/tc-arm.c \ - config/tc-avr.c \ -@@ -596,6 +597,7 @@ TARGET_CPU_CFILES = \ - TARGET_CPU_HFILES = \ - config/tc-aarch64.h \ - config/tc-alpha.h \ -+ config/tc-sw_64.h \ - config/tc-arc.h \ - config/tc-arm.h \ - config/tc-avr.h \ -@@ -893,6 +895,8 @@ config/tc-aarch64.$(OBJEXT): config/$(am__dirstamp) \ - config/$(DEPDIR)/$(am__dirstamp) - config/tc-alpha.$(OBJEXT): config/$(am__dirstamp) \ - config/$(DEPDIR)/$(am__dirstamp) -+config/tc-sw_64.$(OBJEXT): config/$(am__dirstamp) \ -+ config/$(DEPDIR)/$(am__dirstamp) - config/tc-arc.$(OBJEXT): config/$(am__dirstamp) \ - config/$(DEPDIR)/$(am__dirstamp) - config/tc-arm.$(OBJEXT): config/$(am__dirstamp) \ -@@ -1160,6 +1164,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/rx-parse.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-aarch64.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-alpha.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-sw_64.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-arc.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-arm.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-avr.Po@am__quote@ -diff --git a/gas/as.c b/gas/as.c -index 7de8af24..e32b4c2f 100644 ---- a/gas/as.c -+++ b/gas/as.c -@@ -232,9 +232,10 @@ print_version_id (void) - if (printed) - return; - printed = 1; -+ char *VERSION_SW="2.37-v1.0"; - - fprintf (stderr, _("GNU assembler version %s (%s) using BFD version %s\n"), -- VERSION, TARGET_ALIAS, BFD_VERSION_STRING); -+ VERSION_SW, TARGET_ALIAS, BFD_VERSION_STRING); - } - - #ifdef DEFAULT_FLAG_COMPRESS_DEBUG -@@ -503,7 +504,8 @@ parse_args (int * pargc, char *** pargv) - OPTION_WARN_FATAL, - OPTION_COMPRESS_DEBUG, - OPTION_NOCOMPRESS_DEBUG, -- OPTION_NO_PAD_SECTIONS /* = STD_BASE + 40 */ -+ OPTION_NO_PAD_SECTIONS, /* = STD_BASE + 40 */ -+ OPTION_ORG_BACKWARDS - /* When you add options here, check that they do - not collide with OPTION_MD_BASE. See as.h. */ - }; -@@ -581,6 +583,7 @@ parse_args (int * pargc, char *** pargv) - ,{"target-help", no_argument, NULL, OPTION_TARGET_HELP} - ,{"traditional-format", no_argument, NULL, OPTION_TRADITIONAL_FORMAT} - ,{"warn", no_argument, NULL, OPTION_WARN} -+ ,{"pal", no_argument, NULL, OPTION_ORG_BACKWARDS} - }; - - /* Construct the option lists from the standard list and the target -@@ -683,6 +686,12 @@ parse_args (int * pargc, char *** pargv) - flag_traditional_format = 1; - break; - -+#ifdef TARGET_SW_64 -+ case OPTION_ORG_BACKWARDS: -+ pal_org_backwrards =1; -+ break; -+#endif -+ - case OPTION_VERSION: - /* This output is intended to follow the GNU standards document. */ - printf (_("GNU assembler %s\n"), BFD_VERSION_STRING); -diff --git a/gas/as.h b/gas/as.h -index 14a768f8..98564652 100644 ---- a/gas/as.h -+++ b/gas/as.h -@@ -344,6 +344,12 @@ COMMON int linkrelax; - - COMMON int do_not_pad_sections_to_alignment; - -+#ifdef TARGET_SW_64 -+/* Support -pal for hmcode. */ -+COMMON int pal_org_backwrards; -+#endif -+ -+ - /* TRUE if we should produce a listing. */ - extern int listing; - -diff --git a/gas/config.in b/gas/config.in -index e243fd27..c68a0443 100644 ---- a/gas/config.in -+++ b/gas/config.in -@@ -325,3 +325,12 @@ - - /* Define to 1 if you need to in order for `stat' and other things to work. */ - #undef _POSIX_SOURCE -+ -+/* Default CPU for SW_64 targets. */ -+#undef SW_CPU_STRING_DEFAULT -+ -+/*Define Git verion for elf flags*/ -+#undef GIT_REVISION -+ -+#undef TARGET_SW_64 -+ -diff --git a/gas/config/obj-ecoff.c b/gas/config/obj-ecoff.c -index adc70778..e6156250 100644 ---- a/gas/config/obj-ecoff.c -+++ b/gas/config/obj-ecoff.c -@@ -128,6 +128,16 @@ ecoff_frob_file_before_fix (void) - fprmask = alpha_fprmask; - #endif - -+#ifdef TC_SW_64 -+ sw_64_frob_ecoff_data (); -+ -+ if (! bfd_ecoff_set_gp_value (stdoutput, sw_64_gp_value)) -+ as_fatal (_("Can't set GP value")); -+ -+ gprmask = sw_64_gprmask; -+ fprmask = sw_64_fprmask; -+#endif -+ - if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask)) - as_fatal (_("Can't set register masks")); - } -diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c -index e93d59cb..5e870c51 100644 ---- a/gas/config/obj-elf.c -+++ b/gas/config/obj-elf.c -@@ -40,6 +40,12 @@ - #include "elf/alpha.h" - #endif - -+#ifdef TARGET_SW_64 -+#ifdef TC_SW_64 -+#include "elf/sw_64.h" -+#endif -+#endif -+ - #ifdef TC_MIPS - #include "elf/mips.h" - #endif -diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h -index d1fd3152..f54817fc 100644 ---- a/gas/config/obj-elf.h -+++ b/gas/config/obj-elf.h -@@ -43,6 +43,11 @@ - extern int alpha_flag_mdebug; - #endif - -+#ifdef TC_SW_64 -+#define ECOFF_DEBUGGING (sw_64_flag_mdebug > 0) -+extern int sw_64_flag_mdebug; -+#endif -+ - /* For now, always set ECOFF_DEBUGGING for a MIPS target. */ - #ifdef TC_MIPS - #define ECOFF_DEBUGGING mips_flag_mdebug -diff --git a/gas/configure b/gas/configure -index 73750257..40af0cf5 100755 ---- a/gas/configure -+++ b/gas/configure -@@ -12188,6 +12188,25 @@ _ACEOF - ;; - esac - -+ case ${cpu_type} in -+ sw_64 | sw_64sw*) -+ # Set sw_cpu to the name of the default CPU. -+ sw_cpu=$with_cpu -+ cpu_types=${with_cpu:2:4} -+cat >>confdefs.h <<_ACEOF -+#define SW_CPU_STRING_DEFAULT "${with_cpu}" -+_ACEOF -+ -+# Check for git version if there was a github -+git_version=`git log -1 --format="%h"` -+git_short=${git_version:0:5}${cpu_types}"9" -+cat >> confdefs.h <<_ACEOF -+#define GIT_REVISION 0x$git_short -+#define TARGET_SW_64 -+_ACEOF -+ ;; -+ esac -+ - # Do we need the opcodes library? - case ${cpu_type} in - vax | tic30) -diff --git a/gas/configure.tgt b/gas/configure.tgt -index 6272067d..b7b67073 100644 ---- a/gas/configure.tgt -+++ b/gas/configure.tgt -@@ -49,6 +49,7 @@ case ${cpu} in - aarch64) cpu_type=aarch64 endian=little arch=aarch64;; - aarch64_be) cpu_type=aarch64 endian=big arch=aarch64;; - alpha*) cpu_type=alpha ;; -+ sw_64*) cpu_type=sw_64 ;; - am33_2.0) cpu_type=mn10300 endian=little ;; - arc*eb) cpu_type=arc endian=big ;; - arm*be|arm*b) cpu_type=arm endian=big ;; -@@ -138,6 +139,13 @@ case ${generic_target} in - alpha-*-linux-*) fmt=elf em=linux ;; - alpha-*-netbsd* | alpha-*-openbsd*) fmt=elf em=nbsd ;; - -+ sw_64-*-*vms*) fmt=evax ;; -+ sw_64-*-osf*) fmt=ecoff ;; -+ sw_64-*-linux*ecoff*) fmt=ecoff ;; -+ sw_64-*-linux-*) fmt=elf em=linux ;; -+ sw_64-*-netbsd*) fmt=elf em=nbsd ;; -+ sw_64-*-openbsd*) fmt=elf em=obsd ;; -+ - arc-*-elf*) fmt=elf ;; - arc*-*-linux*) fmt=elf bfd_gas=yes ;; - -@@ -435,7 +443,7 @@ esac - - case ${cpu_type} in - aarch64 | alpha | arm | csky | i386 | ia64 | microblaze | mips | ns32k | \ -- or1k | or1knd | pdp11 | ppc | riscv | sh | sparc | z80 | z8k) -+ or1k | or1knd | pdp11 | ppc | riscv | sh | sparc | z80 | z8k | sw_64) - bfd_gas=yes - ;; - esac -diff --git a/gas/read.c b/gas/read.c -index 584867dc..2ebb9c30 100644 ---- a/gas/read.c -+++ b/gas/read.c -@@ -2520,7 +2520,7 @@ bss_alloc (symbolS *symbolP, addressT size, unsigned int align) - subsegT current_subseg = now_subseg; - segT bss_seg = bss_section; - --#if defined (TC_MIPS) || defined (TC_ALPHA) -+#if defined (TC_MIPS) || defined (TC_ALPHA) || defined (TC_SW_64) - if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour - || OUTPUT_FLAVOR == bfd_target_elf_flavour) - { -diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp -index 389634f6..fae2a2f2 100644 ---- a/gas/testsuite/gas/all/gas.exp -+++ b/gas/testsuite/gas/all/gas.exp -@@ -57,6 +57,7 @@ if { ![istarget cris-*-*] && ![istarget crisv32-*-*] - # differences of two previously undefined symbols. Hence this test will - # not pass for these targets. - if { ![istarget alpha*-*-*vms*] -+ && ![istarget sw_64*-*-*vms*] - && ![istarget am3*-*-*] - && ![istarget avr-*-*] - && ![istarget ft32-*-*] -@@ -120,6 +121,8 @@ if { ![is_aout_format] } { - } - alpha-*-*linux*ecoff { } - alpha-*-osf* { } -+ sw_64-*-*linux*ecoff { } -+ sw_64-*-osf* { } - hppa*-*-hpux* { } - mep-*-* { } - mmix-*-* { } -@@ -139,6 +142,7 @@ if { ![is_aout_format] } { - # pdp11 gets unexpected reloc types. - switch -glob $target_triplet { - alpha*-*-* { } -+ sw_64*-*-* { } - am3*-*-* { } - cr16*-*-* { } - crx*-*-* { } -@@ -360,6 +364,8 @@ proc test_cond {} { - switch -glob $target_triplet { - alpha-*-linux*ecoff { } - alpha-*-osf* { } -+ sw_64-*-linux*ecoff { } -+ sw_64-*-osf* { } - hppa*-*-* { } - *c4x*-*-* { } - *c54x*-*-* { } -@@ -431,6 +437,7 @@ if { ![istarget "pdp11-*-*"] } { - # .set works differently on some targets. - switch -glob $target_triplet { - alpha*-*-* { } -+ sw_64*-*-* { } - mips*-*-* { } - *c54x*-*-* { } - z80-*-* { } -diff --git a/gas/testsuite/gas/all/weakref1.d b/gas/testsuite/gas/all/weakref1.d -index 4c251640..895ec2d1 100644 ---- a/gas/testsuite/gas/all/weakref1.d -+++ b/gas/testsuite/gas/all/weakref1.d -@@ -4,7 +4,8 @@ - # pdp11 lacks .long - # darwin (mach-o) reverses the order of relocs. - # the following must be present in all weakref1*.d --#notarget: alpha*-*-osf* *-*-ecoff pdp11-*-aout *-*-darwin* -+#notarget: alpha*-*-osf* sw_64*-*-osf* *-*-ecoff pdp11-*-aout *-*-darwin* -+ - #xfail: nds32*-*-* - - #... -diff --git a/gas/testsuite/gas/all/weakref1g.d b/gas/testsuite/gas/all/weakref1g.d -index eb3f31d5..013d2521 100644 ---- a/gas/testsuite/gas/all/weakref1g.d -+++ b/gas/testsuite/gas/all/weakref1g.d -@@ -4,7 +4,7 @@ - # see weakref1.d for comments on the notargets - # ecoff (OSF/alpha) lacks .weak support - # pdp11 lacks .long --#notarget: alpha*-*-osf* *-*-ecoff pdp11-*-aout -+#notarget: alpha*-*-osf* sw_64*-*-osf* *-*-ecoff pdp11-*-aout - - # the rest of this file is generated with the following script: - # # script begin -diff --git a/gas/testsuite/gas/all/weakref1l.d b/gas/testsuite/gas/all/weakref1l.d -index 3a42c00a..c573d215 100644 ---- a/gas/testsuite/gas/all/weakref1l.d -+++ b/gas/testsuite/gas/all/weakref1l.d -@@ -3,7 +3,7 @@ - #source: weakref1.s - # aix drops local symbols - # see weakref1.d for comments on the other notargets --#notarget: [is_xcoff_format] alpha*-*-osf* *-*-ecoff pdp11-*-aout -+#notarget: [is_xcoff_format] alpha*-*-osf* sw_64*-*-osf* *-*-ecoff pdp11-*-aout - - # the rest of this file is generated with the following script: - # # script begin -diff --git a/gas/testsuite/gas/all/weakref1u.d b/gas/testsuite/gas/all/weakref1u.d -index 5b8d8489..ae3c2c6e 100644 ---- a/gas/testsuite/gas/all/weakref1u.d -+++ b/gas/testsuite/gas/all/weakref1u.d -@@ -3,7 +3,7 @@ - #source: weakref1.s - # aout turns undefined into *ABS* symbols. - # see weakref1.d for comments on the other notargets --#notarget: *-*-*aout ns32k-*-* alpha*-*-osf* *-*-ecoff -+#notarget: *-*-*aout ns32k-*-* alpha*-*-osf* sw_64*-*-osf* *-*-ecoff - - # the rest of this file is generated with the following script: - # # script begin -diff --git a/gas/testsuite/gas/all/weakref1w.d b/gas/testsuite/gas/all/weakref1w.d -index 4cae455e..1333da0c 100644 ---- a/gas/testsuite/gas/all/weakref1w.d -+++ b/gas/testsuite/gas/all/weakref1w.d -@@ -2,7 +2,7 @@ - #name: weakref tests, weak undefined syms - #source: weakref1.s - # see weakref1.d for comments on the notargets --#notarget: alpha*-*-osf* *-*-ecoff pdp11-*-aout -+#notarget: alpha*-*-osf* sw_64*-*-osf* *-*-ecoff pdp11-*-aout - - # the rest of this file is generated with the following script: - # # script begin -diff --git a/gas/testsuite/gas/elf/common5a.d b/gas/testsuite/gas/elf/common5a.d -index ec136b48..d5007fe2 100644 ---- a/gas/testsuite/gas/elf/common5a.d -+++ b/gas/testsuite/gas/elf/common5a.d -@@ -3,3 +3,5 @@ - #error_output: common5a.l - #notarget: alpha-*-* - # The Alpha target uses its own .set pseudo-insn. -+#notarget: sw_64-*-* -+# The sw_64 target uses its own .set pseudo-insn. -diff --git a/gas/testsuite/gas/elf/common5b.d b/gas/testsuite/gas/elf/common5b.d -index 9369c2df..3ad43996 100644 ---- a/gas/testsuite/gas/elf/common5b.d -+++ b/gas/testsuite/gas/elf/common5b.d -@@ -3,3 +3,5 @@ - #error_output: common5b.l - #notarget: alpha-*-* - # The Alpha target uses its own .set pseudo-insn. -+#notarget: sw_64-*-* -+# The sw_64 target uses its own .set pseudo-insn. -diff --git a/gas/testsuite/gas/elf/common5c.d b/gas/testsuite/gas/elf/common5c.d -index cbb3fc68..320f9486 100644 ---- a/gas/testsuite/gas/elf/common5c.d -+++ b/gas/testsuite/gas/elf/common5c.d -@@ -3,3 +3,5 @@ - #error_output: common5a.l - #notarget: alpha-*-* - # The Alpha target uses its own .set pseudo-insn. -+#notarget: sw_64-*-* -+# The sw_64 target uses its own .set pseudo-insn. -diff --git a/gas/testsuite/gas/elf/common5d.d b/gas/testsuite/gas/elf/common5d.d -index 7b11fa24..eb7e29a5 100644 ---- a/gas/testsuite/gas/elf/common5d.d -+++ b/gas/testsuite/gas/elf/common5d.d -@@ -3,3 +3,5 @@ - #error_output: common5b.l - #notarget: alpha-*-* - # The Alpha target uses its own .set pseudo-insn. -+#notarget: sw_64-*-* -+# The sw_64 target uses its own .set pseudo-insn. -diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp -index 23804758..271e3160 100644 ---- a/gas/testsuite/gas/elf/elf.exp -+++ b/gas/testsuite/gas/elf/elf.exp -@@ -164,6 +164,7 @@ if { [is_elf_format] } then { - } - switch -glob $target_triplet { - alpha*-*-* { } -+ sw_64*-*-* { } - am3*-*-* { } - *c54x*-*-* { } - cr16*-*-* { } -@@ -216,7 +217,7 @@ if { [is_elf_format] } then { - run_elf_list_test "section5" "" "-al -Z" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\"" - } - run_dump_test "struct" -- if { ![istarget "alpha*-*-*"] } then { -+ if {! [istarget "alpha*-*-*"] && ! [istarget "sw_64*-*-*"]} then { - # The alpha port uses .set for state, e.g. nomacro. - run_dump_test "symtab" - } -@@ -242,7 +243,10 @@ if { [is_elf_format] } then { - run_elf_list_test "type-noifunc" "" "" "-s" "| grep \"1 *\\\[FONTC\\\]\"" - } - } else { -- run_dump_test ifunc-1 -+ #if {! [istarget "sw_64*-*-*"] } then { -+ # run_dump_test ifunc-1 -+ #} -+ run_dump_test ifunc-1 - run_elf_list_test "type" "" "" "-s" "| grep \"1 *\\\[FIONTCU\\\]\"" - run_elf_list_test "type-2" "" "--warn" "-s" "| grep \"0 *\\\[FIONT\\\]\"" - } -@@ -308,6 +312,9 @@ if { [is_elf_format] } then { - run_dump_test "bad-group" - run_dump_test "pr27355" - -+ #if { ![istarget "sw_64*-*-*"]} then { -+ # run_dump_test "syms" -+ #} - run_dump_test "syms" - run_dump_test "startof" - -@@ -322,6 +329,9 @@ if { [is_elf_format] } then { - run_dump_test "common3b" - run_dump_test "common4a" - run_dump_test "common4b" -+ } -+ -+ if { ![istarget "*-*-hpux*"]} then { - run_dump_test "common5a" - run_dump_test "common5b" - run_dump_test "common5c" -diff --git a/gas/testsuite/gas/elf/ifunc-1.d b/gas/testsuite/gas/elf/ifunc-1.d -index 5b2657b0..c558f2d2 100644 ---- a/gas/testsuite/gas/elf/ifunc-1.d -+++ b/gas/testsuite/gas/elf/ifunc-1.d -@@ -1,6 +1,7 @@ - #readelf: -s - #name: .set with IFUNC - #notarget: alpha* -+#notarget: sw_64* - - #... - [ ]+[0-9]+:[ ]+[0-9a-f]+[ ]+[0-9]+[ ]+IFUNC[ ]+GLOBAL[ ]+DEFAULT[ ]+[1-9] __GI_foo -diff --git a/gas/testsuite/gas/elf/symtab.d b/gas/testsuite/gas/elf/symtab.d -index 68e5e7ca..7ab6c468 100644 ---- a/gas/testsuite/gas/elf/symtab.d -+++ b/gas/testsuite/gas/elf/symtab.d -@@ -1,6 +1,7 @@ - # The Alpha has its own version of .set. - # hppa SOM does not output non-global absolute symbols. - #xfail: alpha-*-* [is_som_format] -+#xfail: sw_64-*-* [is_som_format] - #readelf: -s - #name: .set with expression - -diff --git a/gas/write.c b/gas/write.c -index 7dc78b7f..0e2624e5 100644 ---- a/gas/write.c -+++ b/gas/write.c -@@ -554,6 +554,53 @@ relax_seg (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *xxx) - info->changed = 1; - } - -+#ifdef TARGET_SW_64 -+static void -+sort_frchain (frag_list) -+fragS *frag_list; -+{ -+ fragS *fragp, *fragc, *fragi; -+ long r; -+ for (fragp = frag_list;fragp;) -+ { -+ fragc=fragp; -+ if (fragp->fr_next) -+ fragp = fragp->fr_next; -+ else -+ /* the end of the frag_list. */ -+ break; -+ r = ((long )fragp->fr_address - (long )fragc->fr_address - fragc->fr_fix) ; -+ if ( r < 0 ) -+ { -+ /*adjust the last fill frag's address ,but don't insert back,changed by WCH20080921. */ -+ if (fragp->fr_type == rs_fill && fragp->fr_next == 0) -+ { -+ fragp->fr_address=fragp->last_fr_address=fragc->fr_address+ -+ fragc->fr_fix+fragc->fr_offset; -+ continue; -+ } -+ -+ fragc->fr_next = fragp->fr_next; -+ for (fragi = frag_list; fragi != fragc; fragi=fragi->fr_next) -+ { -+ r = (fragi->fr_next->fr_address - fragp->fr_address - fragp->fr_fix) ; -+ if (r >= 0) -+ { -+ fragp->fr_next = fragi->fr_next; -+ fragi->fr_next = fragp; -+ fragp = fragc; -+ break; -+ } -+ } -+ if (fragi == fragc) -+ { -+ as_bad_where (fragp->fr_file,fragp->fr_line,"ERR,can't insert the node!\n"); -+ } -+ } -+ } -+} -+#endif -+ - static void - size_seg (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *xxx ATTRIBUTE_UNUSED) - { -@@ -566,6 +613,10 @@ size_seg (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *xxx ATTRIBUTE_UNUSED) - subseg_change (sec, 0); - - seginfo = seg_info (sec); -+#ifdef TARGET_SW_64 -+ if (pal_org_backwrards) -+ sort_frchain (seginfo->frchainP->frch_root); -+#endif - if (seginfo && seginfo->frchainP) - { - for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next) -@@ -2995,7 +3046,12 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass) - /* Growth may be negative, but variable part of frag - cannot have fewer than 0 chars. That is, we can't - .org backwards. */ -- if ((offsetT) (address + fragP->fr_fix) > target) -+ -+#ifdef TARGET_SW_64 -+ if (((offsetT) (address + fragP->fr_fix) > target) && !pal_org_backwrards) -+#else -+ if ((offsetT) (address + fragP->fr_fix) > target) -+#endif - { - growth = 0; - -diff --git a/gold/Makefile.am b/gold/Makefile.am -index 1947c18e..68dc49ce 100644 ---- a/gold/Makefile.am -+++ b/gold/Makefile.am -@@ -173,13 +173,13 @@ diststuff: $(EXTRA_DIST) - - TARGETSOURCES = \ - i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc tilegx.cc \ -- mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc -+ mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc sw_64.cc - - ALL_TARGETOBJS = \ - i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \ - arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) \ - mips.$(OBJEXT) aarch64.$(OBJEXT) aarch64-reloc-property.$(OBJEXT) \ -- s390.$(OBJEXT) -+ s390.$(OBJEXT) sw_64.$(OBJEXT) - - libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES) - libgold_a_LIBADD = $(LIBOBJS) -diff --git a/gold/Makefile.in b/gold/Makefile.in -index 9fd21214..8c2557a0 100644 ---- a/gold/Makefile.in -+++ b/gold/Makefile.in -@@ -792,13 +792,13 @@ DEFFILES = arm-reloc.def aarch64-reloc.def - EXTRA_DIST = yyscript.c yyscript.h - TARGETSOURCES = \ - i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc tilegx.cc \ -- mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc -+ mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc sw_64.cc - - ALL_TARGETOBJS = \ - i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \ - arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) \ - mips.$(OBJEXT) aarch64.$(OBJEXT) aarch64-reloc-property.$(OBJEXT) \ -- s390.$(OBJEXT) -+ s390.$(OBJEXT) sw_64.$(OBJEXT) - - libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES) - libgold_a_LIBADD = $(LIBOBJS) -@@ -1089,6 +1089,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapfile.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/merge.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mips.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sw_64.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nacl.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ -diff --git a/gold/configure b/gold/configure -index b9f062b6..340b92f4 100755 ---- a/gold/configure -+++ b/gold/configure -@@ -731,6 +731,8 @@ DEFAULT_TARGET_ARM_FALSE - DEFAULT_TARGET_ARM_TRUE - DEFAULT_TARGET_AARCH64_FALSE - DEFAULT_TARGET_AARCH64_TRUE -+DEFAULT_TARGET_SW_64_FALSE -+DEFAULT_TARGET_SW_64_TRUE - PLUGINS_FALSE - PLUGINS_TRUE - installed_linker -@@ -5318,6 +5320,14 @@ else - DEFAULT_TARGET_MIPS_FALSE= - fi - -+ if test "$targ_obj" = "sw_64"; then -+ DEFAULT_TARGET_SW_64_TRUE= -+ DEFAULT_TARGET_SW_64_FALSE='#' -+else -+ DEFAULT_TARGET_SW_64_TRUE='#' -+ DEFAULT_TARGET_SW_64_FALSE= -+fi -+ - DEFAULT_TARGET=${targ_obj} - - fi -@@ -10425,6 +10435,10 @@ if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - as_fn_error $? "conditional \"AMDEP\" was never defined. - Usually this means the macro was only invoked conditionally." "$LINENO" 5 - fi -+if test -z "${DEFAULT_TARGET_SW_64_TRUE}" && test -z "${DEFAULT_TARGET_SW_64_FALSE}"; then -+ as_fn_error $? "conditional \"DEFAULT_TARGET_SW_64\" was never defined. -+Usually this means the macro was only invoked conditionally." "$LINENO" 5 -+fi - if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. - Usually this means the macro was only invoked conditionally." "$LINENO" 5 -diff --git a/gold/configure.ac b/gold/configure.ac -index 1716a779..2f371724 100644 ---- a/gold/configure.ac -+++ b/gold/configure.ac -@@ -239,6 +239,7 @@ for targ in $target $canon_targets; do - test "$target_x86_64" = "yes" -o "$target_x32" = "yes") - AM_CONDITIONAL(DEFAULT_TARGET_TILEGX, test "$targ_obj" = "tilegx") - AM_CONDITIONAL(DEFAULT_TARGET_MIPS, test "$targ_obj" = "mips") -+ AM_CONDITIONAL(DEFAULT_TARGET_SW_64, test "$targ_obj" = "sw_64") - DEFAULT_TARGET=${targ_obj} - AC_SUBST(DEFAULT_TARGET) - fi -diff --git a/gold/configure.tgt b/gold/configure.tgt -index cac0866e..a32dd236 100644 ---- a/gold/configure.tgt -+++ b/gold/configure.tgt -@@ -181,6 +181,12 @@ s390x-*-*) - targ_big_endian=true - targ_extra_big_endian=false - ;; -+sw_64*-*-*) -+ targ_obj=sw_64 -+ targ_machine=EM_SW_64 -+ targ_size=64 -+ targ_big_endian=false -+ ;; - *) - targ_obj=UNKNOWN - ;; -diff --git a/gold/reloc.h b/gold/reloc.h -index 5f1d382a..0b7f0e5b 100644 ---- a/gold/reloc.h -+++ b/gold/reloc.h -@@ -239,6 +239,7 @@ class Relocatable_relocs - RELOC_ADJUST_FOR_SECTION_RELA, - // Like RELOC_ADJUST_FOR_SECTION_RELA but the addend should not be - // adjusted. -+ RELOC_ADJUST_FOR_SECTION_RELA_0, - RELOC_ADJUST_FOR_SECTION_0, - // Like RELOC_ADJUST_FOR_SECTION_RELA but the contents of the - // section need to be changed. The number indicates the number of -diff --git a/gold/target-reloc.h b/gold/target-reloc.h -index cd40bcc0..7f00f93d 100644 ---- a/gold/target-reloc.h -+++ b/gold/target-reloc.h -@@ -845,6 +845,7 @@ relocate_relocs( - break; - - case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA: -+ case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA_0: - case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0: - case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1: - case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2: -@@ -916,7 +917,8 @@ relocate_relocs( - - // Handle the reloc addend based on the strategy. - -- if (strategy == Relocatable_relocs::RELOC_COPY) -+ if (strategy == Relocatable_relocs::RELOC_COPY -+ || Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA_0 == strategy) - { - if (Classify_reloc::sh_type == elfcpp::SHT_RELA) - Classify_reloc::put_r_addend(&reloc_write, -diff --git a/include/coff/ecoff.h b/include/coff/ecoff.h -index 2267b779..ae54eeea 100644 ---- a/include/coff/ecoff.h -+++ b/include/coff/ecoff.h -@@ -47,6 +47,20 @@ - /* A compressed version of an ALPHA_MAGIC file created by DEC's tools. */ - #define ALPHA_MAGIC_COMPRESSED 0x188 - -+#ifdef TARGET_SW_64 -+/* Sw_64 magic numbers used in filehdr. */ -+#define SW_64_MAGIC 0x184 -+#define SW_64_MAGIC_BSD 0x187 -+/* A compressed version of an SW_64_MAGIC file created by DEC's tools. */ -+#define SW_64_MAGIC_COMPRESSED 0x189 -+#endif -+ -+/* Alpha magic numbers used in filehdr. */ -+#define SW_64_MAGIC 0x184 -+#define SW_64_MAGIC_BSD 0x187 -+/* A compressed version of an ALPHA_MAGIC file created by DEC's tools. */ -+#define SW_64_MAGIC_COMPRESSED 0x189 -+ - /* Magic numbers used in a.out header. */ - #define ECOFF_AOUT_OMAGIC 0407 /* not demand paged (ld -N). */ - #define ECOFF_AOUT_ZMAGIC 0413 /* demand load format, eg normal ld output */ -diff --git a/include/coff/pe.h b/include/coff/pe.h -index 558cf0e1..b19307a4 100644 ---- a/include/coff/pe.h -+++ b/include/coff/pe.h -@@ -134,6 +134,10 @@ - #define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 - #define IMAGE_FILE_MACHINE_ALPHA 0x0184 - #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 -+#ifdef TARGET_SW_64 -+#define IMAGE_FILE_MACHINE_SW_64 0x0184 -+#define IMAGE_FILE_MACHINE_SW_6464 0x0284 -+#endif - #define IMAGE_FILE_MACHINE_AM33 0x01d3 - #define IMAGE_FILE_MACHINE_AMD64 0x8664 - #define IMAGE_FILE_MACHINE_ARM 0x01c0 -diff --git a/include/elf/common.h b/include/elf/common.h -index 0cca2867..be66b736 100644 ---- a/include/elf/common.h -+++ b/include/elf/common.h -@@ -409,6 +409,11 @@ - /* Alpha backend magic number. Written in the absence of an ABI. */ - #define EM_ALPHA 0x9026 - -+#ifdef TARGET_SW_64 -+/* Sw_64 backend magic number. Written in the absence of an ABI. */ -+#define EM_SW_64 0x9916 -+#endif -+ - /* Cygnus M32R ELF backend. Written in the absence of an ABI. */ - #define EM_CYGNUS_M32R 0x9041 - -diff --git a/include/longlong.h b/include/longlong.h -index c3e92e54..f1997361 100644 ---- a/include/longlong.h -+++ b/include/longlong.h -@@ -191,6 +191,61 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); - #endif /* __alpha_cix__ */ - #endif /* __alpha */ - -+//__sw_64_cix__ -+#if defined (__sw_64) && W_TYPE_SIZE == 64 -+/* There is a bug in g before version 5 that -+ errors on __builtin_sw_64_umulh. */ -+#if !defined(__cplusplus) || __GNUC__ >= 5 -+#define umul_ppmm(ph, pl, m0, m1) \ -+ do { \ -+ UDItype __m0 = (m0), __m1 = (m1); \ -+ (ph) = __builtin_sw_64_umulh (__m0, __m1); \ -+ (pl) = __m0 * __m1; \ -+ } while (0) -+#define UMUL_TIME 46 -+#endif /* !c */ -+#ifndef LONGLONG_STANDALONE -+#define udiv_qrnnd(q, r, n1, n0, d) \ -+ do { UDItype __r; \ -+ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ -+ (r) = __r; \ -+ } while (0) -+extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); -+#define UDIV_TIME 220 -+#endif /* LONGLONG_STANDALONE */ -+#ifdef __sw_64_cix__ -+#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clzl (X)) -+#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctzl (X)) -+#define COUNT_LEADING_ZEROS_0 64 -+#else -+#define count_leading_zeros(COUNT,X) \ -+ do { \ -+ UDItype __xr = (X), __t, __a; \ -+ __t = __builtin_sw_64_cmpbge (0, __xr); \ -+ __a = __clz_tab[__t ^ 0xff] - 1; \ -+ __t = __builtin_sw_64_extbl (__xr, __a); \ -+ (COUNT) = 64 - (__clz_tab[__t] __a*8); \ -+ } while (0) -+#define count_trailing_zeros(COUNT,X) \ -+ do { \ -+ UDItype __xr = (X), __t, __a; \ -+ __t = __builtin_sw_64_cmpbge (0, __xr); \ -+ __t = ~__t & -~__t; \ -+ __a = ((__t & 0xCC) != 0) * 2; \ -+ __a = ((__t & 0xF0) != 0) * 4; \ -+ __a = ((__t & 0xAA) != 0); \ -+ __t = __builtin_sw_64_extbl (__xr, __a); \ -+ __a <<= 3; \ -+ __t &= -__t; \ -+ __a = ((__t & 0xCC) != 0) * 2; \ -+ __a = ((__t & 0xF0) != 0) * 4; \ -+ __a = ((__t & 0xAA) != 0); \ -+ (COUNT) = __a; \ -+ } while (0) -+#endif /* __sw_64_cix__ */ -+#endif /* __sw_64 */ -+//sw_64 -+ - #if defined (__arc__) && W_TYPE_SIZE == 32 - #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \ -diff --git a/ld/Makefile.am b/ld/Makefile.am -index d912d265..37a73df0 100644 ---- a/ld/Makefile.am -+++ b/ld/Makefile.am -@@ -159,6 +159,8 @@ ALL_EMULATION_SOURCES = \ - eaixrs6.c \ - ealpha.c \ - ealphavms.c \ -+ esw_64.c \ -+ esw_64vms.c \ - earcv2elf.c \ - earcv2elfx.c \ - earcelf.c \ -@@ -429,6 +431,9 @@ ALL_64_EMULATION_SOURCES = \ - eelf64alpha.c \ - eelf64alpha_fbsd.c \ - eelf64alpha_nbsd.c \ -+ eelf64sw_64.c \ -+ eelf64sw_64_fbsd.c \ -+ eelf64sw_64_nbsd.c \ - eelf64bmip.c \ - eelf64btsmip.c \ - eelf64btsmip_fbsd.c \ -@@ -649,6 +654,8 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixrs6.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealpha.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealphavms.Pc@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64.Pc@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64vms.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elf.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elfx.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcelf.Pc@am__quote@ -@@ -915,6 +922,9 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_fbsd.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_nbsd.Pc@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64.Pc@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_fbsd.Pc@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_nbsd.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bmip.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Pc@am__quote@ -diff --git a/ld/Makefile.in b/ld/Makefile.in -index 4e88d0ec..ad27dc3e 100644 ---- a/ld/Makefile.in -+++ b/ld/Makefile.in -@@ -648,6 +648,8 @@ ALL_EMULATION_SOURCES = \ - eaixrs6.c \ - ealpha.c \ - ealphavms.c \ -+ esw_64.c \ -+ esw_64vms.c \ - earcv2elf.c \ - earcv2elfx.c \ - earcelf.c \ -@@ -917,6 +919,9 @@ ALL_64_EMULATION_SOURCES = \ - eelf64alpha.c \ - eelf64alpha_fbsd.c \ - eelf64alpha_nbsd.c \ -+ eelf64sw_64.c \ -+ eelf64sw_64_fbsd.c \ -+ eelf64sw_64_nbsd.c \ - eelf64bmip.c \ - eelf64btsmip.c \ - eelf64btsmip_fbsd.c \ -@@ -1252,6 +1257,8 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixrs6.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealpha.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealphavms.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64vms.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcelf.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earclinux.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earclinux_nps.Po@am__quote@ -@@ -1409,6 +1416,9 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_fbsd.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_nbsd.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_fbsd.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_nbsd.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bmip.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bpf.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv.Po@am__quote@ -@@ -2306,6 +2316,8 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixrs6.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealpha.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealphavms.Pc@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64.Pc@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esw_64vms.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elf.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elfx.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcelf.Pc@am__quote@ -@@ -2572,6 +2584,11 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_fbsd.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_nbsd.Pc@am__quote@ -+#ifndef LIJM20201117 -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64.Pc@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_fbsd.Pc@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64sw_64_nbsd.Pc@am__quote@ -+#endif - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bmip.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip.Pc@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Pc@am__quote@ -diff --git a/ld/config.in b/ld/config.in -index 26d55a00..173f2348 100644 ---- a/ld/config.in -+++ b/ld/config.in -@@ -241,3 +241,5 @@ - - /* Define to 1 if you need to in order for `stat' and other things to work. */ - #undef _POSIX_SOURCE -+ -+#undef TARGET_SW_64 -diff --git a/ld/configure b/ld/configure -index e287d291..06d7ab1f 100755 ---- a/ld/configure -+++ b/ld/configure -@@ -15376,6 +15376,13 @@ else - esac - fi - -+case "${target}" in -+ sw_64-*-*) -+cat >>confdefs.h <<_ACEOF -+#define TARGET_SW_64 -+_ACEOF -+ ;; -+ esac - - case "${enable_default_hash_style}" in - sysv | both) ac_default_emit_sysv_hash=1 ;; -diff --git a/ld/configure.tgt b/ld/configure.tgt -index 8b577f21..269f7fd4 100644 ---- a/ld/configure.tgt -+++ b/ld/configure.tgt -@@ -102,6 +102,19 @@ alpha*-*-openbsd*) targ_emul=elf64alpha - alpha*-*-*vms*) targ_emul=alphavms - targ_extra_ofiles= - ;; -+sw_64*-*-linux-* | sw_64*-*-gnu*) -+ case "${targ}" in -+ sw_64sw6a*) -+ targ_emul=elf64sw_64 targ_extra_emuls=sw_64 -+ tdir_sw_64=`echo ${targ_alias} | sed -e 's/linux\(-gnu\)*/linux\1ecoff/'` ;; -+ sw_64sw6b*) -+ targ_emul=elf64sw_64 targ_extra_emuls=sw_64 -+ tdir_sw_64=`echo ${targ_alias} | sed -e 's/linux\(-gnu\)*/linux\1ecoff/'` ;; -+ *) -+ targ_emul=elf64sw_64 targ_extra_emuls=sw_64 -+ tdir_sw_64=`echo ${targ_alias} | sed -e 's/linux\(-gnu\)*/linux\1ecoff/'` ;; -+ esac -+ ;; - am33_2.0-*-linux*) targ_emul=elf32am33lin # mn10300 variant - ;; - arc*-*-elf*) targ_emul=arcelf -@@ -1085,6 +1098,9 @@ alpha*-*-*) - NATIVE_LIB_DIRS='/usr/local/lib /usr/ccs/lib /lib /usr/lib' - ;; - -+sw_64*-*-*) -+ NATIVE_LIB_DIRS='/usr/local/lib /usr/ccs/lib /lib /usr/lib' -+ ;; - esac - - case "${target}" in -diff --git a/ld/testsuite/config/default.exp b/ld/testsuite/config/default.exp -index 0795ea81..d0cce3a9 100644 ---- a/ld/testsuite/config/default.exp -+++ b/ld/testsuite/config/default.exp -@@ -434,6 +434,26 @@ if { [istarget alpha*-*-*vms*] } { - unset f src - } - -+# Provide dummy libraries that sw_64-vms-ld always loads -+if { [istarget sw_64*-*-*vms*] } { -+ set src tmpdir/empty.s -+ set f [open $src "w"] -+ close $f -+ if { [ld_assemble $as $src tmpdir/empty.o] -+ && ![ld_link $LD tmpdir/empty tmpdir/empty.o] -+ && [regsub -all {[^\n]*: cannot find -l([^\n]*)} $exec_output {tmpdir/lib\1.a } missing_libs] } { -+ regsub -all {\$} $missing_libs {\\\$} missing_libs -+ for { set i 0 } { $i < [llength $missing_libs] } { incr i } { -+ set f [lindex $missing_libs $i] -+ verbose -log "creating dummy $f" -+ ar_simple_create $ar {} $f tmpdir/empty.o -+ } -+ append LDFLAGS " -Ltmpdir" -+ unset i missing_libs -+ } -+ unset f src -+} -+ - set plug_opt "" - if { [check_compiler_available] } { - set plugin_names { -diff --git a/ld/testsuite/ld-elf/binutils.exp b/ld/testsuite/ld-elf/binutils.exp -index 426f3293..f94d79e5 100644 ---- a/ld/testsuite/ld-elf/binutils.exp -+++ b/ld/testsuite/ld-elf/binutils.exp -@@ -88,6 +88,7 @@ proc binutils_test { prog_name ld_options test {test_name ""} {readelf_options " - # These targets do not set NO_SMALL_DATA or DATA_GOT and therefore - # have `.got' in (read-write) small data rather than regular data. - set relro_got [expr !([istarget "alpha*-*-*"] \ -+ || [istarget "sw_64*-*-*"] \ - || [istarget "hppa*-*-linux-*"] \ - || [istarget "hppa*-*-netbsd*"] \ - || [istarget "hppa*-*-openbsd*"] \ -diff --git a/ld/testsuite/ld-elf/compress1a.d b/ld/testsuite/ld-elf/compress1a.d -index 0d5b68e7..f97b18b7 100644 ---- a/ld/testsuite/ld-elf/compress1a.d -+++ b/ld/testsuite/ld-elf/compress1a.d -@@ -2,7 +2,7 @@ - #as: --compress-debug-sections - #ld: -e func_cu2 - #readelf: -S --wide --#xfail: alpha-*-*ecoff -+#xfail: alpha-*-*ecoff sw_64-*-*ecoff - - #failif - #... -diff --git a/ld/testsuite/ld-elf/compressed1a.d b/ld/testsuite/ld-elf/compressed1a.d -index 3a5572ec..6780e319 100644 ---- a/ld/testsuite/ld-elf/compressed1a.d -+++ b/ld/testsuite/ld-elf/compressed1a.d -@@ -2,7 +2,7 @@ - #as: --compress-debug-sections=zlib-gabi - #ld: -e func_cu2 - #readelf: -t --#xfail: alpha-*-*ecoff -+#xfail: alpha-*-*ecoff sw_64-*-*ecoff - - #failif - #... -diff --git a/ld/testsuite/ld-elf/eh5.d b/ld/testsuite/ld-elf/eh5.d -index 4a697482..eff6e961 100644 ---- a/ld/testsuite/ld-elf/eh5.d -+++ b/ld/testsuite/ld-elf/eh5.d -@@ -4,7 +4,7 @@ - #ld: - #readelf: -wf - #target: [check_as_cfi] --#xfail: alpha-*-*ecoff hppa64-*-* tile*-*-* visium-*-* -+#xfail: alpha-*-*ecoff sw_64-*-*ecoff hppa64-*-* tile*-*-* visium-*-* - - Contents of the .eh_frame section: - -diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp -index e98bffc0..1c192537 100644 ---- a/ld/testsuite/ld-elf/elf.exp -+++ b/ld/testsuite/ld-elf/elf.exp -@@ -51,7 +51,7 @@ if [istarget "*-*-hpux*"] { - set ASFLAGS "$ASFLAGS --defsym HPUX=1" - } - --if { [istarget alpha*-*-* ] } { -++if { [istarget alpha*-*-* ] || [istarget sw_64*-*-*]} { - # The compress1 test is written expecting 32-bit addresses; force the - # executable down into the low address space to match. - # ??? How can we adjust just the one testcase? -diff --git a/ld/testsuite/ld-elf/pr17550a.d b/ld/testsuite/ld-elf/pr17550a.d -index 752c3ad6..33581821 100644 ---- a/ld/testsuite/ld-elf/pr17550a.d -+++ b/ld/testsuite/ld-elf/pr17550a.d -@@ -3,7 +3,7 @@ - #ld: -r - #readelf: -s --wide - # Disabled on alpha because alpha has a different .set directive. --#xfail: alpha-*-* -+#xfail: alpha-*-* sw_64-*-* - - #failif - #... -diff --git a/ld/testsuite/ld-elf/pr17550b.d b/ld/testsuite/ld-elf/pr17550b.d -index 09e7ddfe..bf80e9fa 100644 ---- a/ld/testsuite/ld-elf/pr17550b.d -+++ b/ld/testsuite/ld-elf/pr17550b.d -@@ -3,7 +3,7 @@ - #ld: -r - #readelf: -s --wide - # Disabled on alpha because alpha has a different .set directive. --#xfail: alpha-*-* -+#xfail: alpha-*-* sw_64-*-* - - #failif - #... -diff --git a/ld/testsuite/ld-elf/pr17550c.d b/ld/testsuite/ld-elf/pr17550c.d -index 55749fc7..97c394c1 100644 ---- a/ld/testsuite/ld-elf/pr17550c.d -+++ b/ld/testsuite/ld-elf/pr17550c.d -@@ -5,3 +5,6 @@ - #xfail: alpha-*-* [is_generic] - # Disabled on alpha because alpha has a different .set directive. - # Generic linker targets don't support comdat group sections. -+#xfail: sw_64-*-* [is_generic] -+# Disabled on sw_64 because sw_64 has a different .set directive. -+# Generic linker targets don't support comdat group sections. -diff --git a/ld/testsuite/ld-elf/pr17550d.d b/ld/testsuite/ld-elf/pr17550d.d -index 3dd108d5..f0b2ea72 100644 ---- a/ld/testsuite/ld-elf/pr17550d.d -+++ b/ld/testsuite/ld-elf/pr17550d.d -@@ -5,6 +5,9 @@ - # Disabled on alpha because alpha has a different .set directive. - # Generic linker targets don't support comdat group sections. - #xfail: alpha-*-* [is_generic] -+# Disabled on sw_64 because sw_64 has a different .set directive. -+# Generic linker targets don't support comdat group sections. -+#xfail: sw_64-*-* [is_generic] - - #... - +[0-9]+: +[0-9a-f]+ +0 +OBJECT +GLOBAL +DEFAULT +UND y -diff --git a/ld/testsuite/ld-elf/pr18720b.c b/ld/testsuite/ld-elf/pr18720b.c -index 6b3222db..826a17a1 100644 ---- a/ld/testsuite/ld-elf/pr18720b.c -+++ b/ld/testsuite/ld-elf/pr18720b.c -@@ -9,6 +9,8 @@ foo (void) - __asm__ (".symver foo,foo@FOO"); - #ifdef __alpha__ - __asm__ ("foo_alias = foo"); -+#elif __sw_64__ -+__asm__ ("foo_alias = foo"); - #else - __asm__ (".set foo_alias,foo"); - #endif -diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp -index d00358e4..f1e6e1be 100644 ---- a/ld/testsuite/ld-elf/shared.exp -+++ b/ld/testsuite/ld-elf/shared.exp -@@ -346,6 +346,7 @@ if { [check_gc_sections_available] } { - mips*-*-* { } - tic6x-*-* { } - xtensa-*-* { } -+ sw_64-*-* { } - default { - run_ld_link_tests [list \ - [list \ -@@ -464,7 +465,8 @@ run_ld_link_tests [list \ - ] - - # These targets don't copy dynamic variables into .bss. --setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*" -+# setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*" -+setup_xfail "sw_64-*-*" "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*" - # or don't have .data.rel.ro - setup_xfail "hppa*64*-*-hpux*" "tic6x-*-*" - # or complain about relocs in read-only sections -@@ -484,7 +486,8 @@ run_ld_link_tests [list \ - {pr20995c.s} {{readelf {-l --wide} pr20995-2so.r}} "pr20995-2.so"] \ - ] {![check_relro_support]} - --setup_xfail alpha-*-* xtensa-*-* -+# setup_xfail alpha-*-* xtensa-*-* -+setup_xfail sw_64-*-* alpha-*-* xtensa-*-* - run_ld_link_tests [list \ - [list \ - "pr20995-2" \ -@@ -500,7 +503,8 @@ run_ld_link_tests [list \ - # The next test checks that copy relocs are not used unnecessarily, - # but that is just an optimization so don't complain loudly. - setup_xfail *-*-* --clear_xfail alpha-*-* bfin-*-linux* csky-*-* frv-*-* hppa*-*-* i?86-*-* -+# clear_xfail alpha-*-* bfin-*-linux* csky-*-* frv-*-* hppa*-*-* i?86-*-* -+clear_xfail sw_64-*-* alpha-*-* bfin-*-linux* csky-*-* frv-*-* hppa*-*-* i?86-*-* - clear_xfail ia64-*-* microblaze-*-* powerpc*-*-* x86_64-*-* xtensa-*-* - run_ld_link_tests { - {"pr22374 function pointer initialization" -@@ -871,7 +875,8 @@ run_cc_link_tests [list \ - ] - - # pr19073.s uses .set, which has a different meaning on alpha. --if { ![istarget alpha-*-*] } { -+# if { ![istarget alpha-*-*] } { -+if { ![istarget alpha-*-*] && ![istarget sw_64-*-*] } { - append build_tests { - {"Build pr19073a.o" - "-r -nostdlib" "" -diff --git a/ld/testsuite/ld-elf/stab.d b/ld/testsuite/ld-elf/stab.d -index 27b99cb3..97d76d93 100644 ---- a/ld/testsuite/ld-elf/stab.d -+++ b/ld/testsuite/ld-elf/stab.d -@@ -2,7 +2,7 @@ - #as: -gstabs - #readelf: -S --wide - #ld: --#notarget: "ia64-*-*" "alpha*" -+#notarget: "ia64-*-*" "alpha*" "sw_64*" - - # Disabled on alpha because the entry point may be above 4GB but the stabs - # value only 32 bits. -diff --git a/ld/testsuite/ld-elfvers/vers.exp b/ld/testsuite/ld-elfvers/vers.exp -index 8a1383fe..b49b27f8 100644 ---- a/ld/testsuite/ld-elfvers/vers.exp -+++ b/ld/testsuite/ld-elfvers/vers.exp -@@ -51,6 +51,7 @@ if { ![istarget hppa*64*-*-hpux*] - && ![istarget arm*-*-linux*] - && ![istarget mips*-*-linux*] - && ![istarget alpha*-*-linux*] -+ && ![istarget sw_64*-*-linux*] - && ![istarget s390*-*-linux*] - && ![istarget sh\[34\]*-*-linux*] - && ![istarget x86_64-*-linux*] } { -diff --git a/ld/testsuite/ld-elfvsb/elfvsb.exp b/ld/testsuite/ld-elfvsb/elfvsb.exp -index ee73cfe8..5030b102 100644 ---- a/ld/testsuite/ld-elfvsb/elfvsb.exp -+++ b/ld/testsuite/ld-elfvsb/elfvsb.exp -@@ -42,6 +42,7 @@ if { ![istarget hppa*64*-*-hpux*] \ - && ![istarget powerpc*-*-linux*] \ - && ![istarget arm*-*-linux*] \ - && ![istarget alpha*-*-linux*] \ -+ && ![istarget sw_64*-*-linux*] \ - && ![istarget sparc*-*-linux*] \ - && ![istarget s390*-*-linux*] \ - && ![istarget sh\[34\]*-*-linux*] \ -@@ -267,6 +268,7 @@ proc visibility_run {visibility} { - && ![ string match $visibility "protected_undef" ] } { - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -+ setup_xfail "sw_64*-*-linux*" - } - if { ![ string match $visibility "hidden" ] - && ![ string match $visibility "hidden_undef" ] -@@ -316,6 +318,7 @@ proc visibility_run {visibility} { - && ![ string match $visibility "protected_undef" ] } { - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -+ setup_xfail "sw_64*-*-linux*" - setup_xfail "mips*-*-linux*" - } - if { [is_elf64 $tmpdir/mainnp.o] } { -@@ -372,6 +375,7 @@ proc visibility_run {visibility} { - && ![ string match $visibility "protected_undef" ] } { - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -+ setup_xfail "sw_64*-*-linux*" - } - if { ![ string match $visibility "hidden" ] - && ![ string match $visibility "hidden_undef" ] -diff --git a/ld/testsuite/ld-elfweak/elfweak.exp b/ld/testsuite/ld-elfweak/elfweak.exp -index 56949d74..bd208d46 100644 ---- a/ld/testsuite/ld-elfweak/elfweak.exp -+++ b/ld/testsuite/ld-elfweak/elfweak.exp -@@ -31,6 +31,7 @@ if { ![check_compiler_available] } { - # Square bracket expressions seem to confuse istarget. - # This is similar to the test that is used in ld-shared, BTW. - if { ![istarget alpha*-*-linux*] -+ && ![istarget sw_64*-*-linux*] - && ![istarget arm*-*-linux*] - && ![istarget hppa*64*-*-hpux*] - && ![istarget hppa*-*-linux*] -diff --git a/ld/testsuite/ld-ifunc/ifunc-26.d b/ld/testsuite/ld-ifunc/ifunc-26.d -index 05e380a8..156f85b4 100644 ---- a/ld/testsuite/ld-ifunc/ifunc-26.d -+++ b/ld/testsuite/ld-ifunc/ifunc-26.d -@@ -1,6 +1,6 @@ - #ld: -shared - #readelf: -h --#xfail: alpha-*-* -+#xfail: alpha-*-* sw_64-*-* - - ELF Header: - #... -diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp -index 45b47d7d..f66a53f4 100644 ---- a/ld/testsuite/ld-ifunc/ifunc.exp -+++ b/ld/testsuite/ld-ifunc/ifunc.exp -@@ -25,6 +25,7 @@ - - if { ![is_elf_format] || ![supports_gnu_osabi] - || [istarget alpha-*-*] -+ || [istarget sw_64*-*-*] - || [istarget arc*-*-*] - || [istarget am33*-*-*] - || [istarget bfin-*-*] -diff --git a/ld/testsuite/ld-misc/just-symbols.exp b/ld/testsuite/ld-misc/just-symbols.exp -index 51029147..1506c105 100644 ---- a/ld/testsuite/ld-misc/just-symbols.exp -+++ b/ld/testsuite/ld-misc/just-symbols.exp -@@ -26,7 +26,8 @@ - if { [istarget sh-*-pe] - || [istarget *-*-msdos] - || [istarget *c30-*-*] -- || [istarget alpha-*-vms] } { -+ || [istarget alpha-*-vms] -+ || [istarget sw_64-*-vms] } { - return - } - -diff --git a/ld/testsuite/ld-plugin/plugin-14.d b/ld/testsuite/ld-plugin/plugin-14.d -index 81365af7..6c2db663 100644 ---- a/ld/testsuite/ld-plugin/plugin-14.d -+++ b/ld/testsuite/ld-plugin/plugin-14.d -@@ -29,5 +29,6 @@ hook called: claim_file tmpdir/text.o \[@0/.* not claimed - hook called: all symbols read. - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... -diff --git a/ld/testsuite/ld-plugin/plugin-15.d b/ld/testsuite/ld-plugin/plugin-15.d -index 02c5e60b..ef13000a 100644 ---- a/ld/testsuite/ld-plugin/plugin-15.d -+++ b/ld/testsuite/ld-plugin/plugin-15.d -@@ -30,5 +30,6 @@ hook called: claim_file tmpdir/text.o \[@0/.* not claimed - hook called: all symbols read. - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... -diff --git a/ld/testsuite/ld-plugin/plugin-16.d b/ld/testsuite/ld-plugin/plugin-16.d -index 504fbdbc..5d816efb 100644 ---- a/ld/testsuite/ld-plugin/plugin-16.d -+++ b/ld/testsuite/ld-plugin/plugin-16.d -@@ -34,5 +34,6 @@ Sym: '_?func' Resolution: LDPR_PREVAILING_DEF - Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... -diff --git a/ld/testsuite/ld-plugin/plugin-20.d b/ld/testsuite/ld-plugin/plugin-20.d -index 31bc3766..3c3d53eb 100644 ---- a/ld/testsuite/ld-plugin/plugin-20.d -+++ b/ld/testsuite/ld-plugin/plugin-20.d -@@ -4,4 +4,5 @@ Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. -diff --git a/ld/testsuite/ld-plugin/plugin-21.d b/ld/testsuite/ld-plugin/plugin-21.d -index 0b85f715..cc87440a 100644 ---- a/ld/testsuite/ld-plugin/plugin-21.d -+++ b/ld/testsuite/ld-plugin/plugin-21.d -@@ -4,4 +4,5 @@ Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. -diff --git a/ld/testsuite/ld-plugin/plugin-22.d b/ld/testsuite/ld-plugin/plugin-22.d -index 1084a0b0..51a335bb 100644 ---- a/ld/testsuite/ld-plugin/plugin-22.d -+++ b/ld/testsuite/ld-plugin/plugin-22.d -@@ -4,4 +4,5 @@ Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. -diff --git a/ld/testsuite/ld-plugin/plugin-23.d b/ld/testsuite/ld-plugin/plugin-23.d -index 0b6c25c1..14bb8a60 100644 ---- a/ld/testsuite/ld-plugin/plugin-23.d -+++ b/ld/testsuite/ld-plugin/plugin-23.d -@@ -4,4 +4,5 @@ Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.* - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. -diff --git a/ld/testsuite/ld-plugin/plugin-6.d b/ld/testsuite/ld-plugin/plugin-6.d -index b1854ac0..aef588f0 100644 ---- a/ld/testsuite/ld-plugin/plugin-6.d -+++ b/ld/testsuite/ld-plugin/plugin-6.d -@@ -29,5 +29,6 @@ hook called: claim_file tmpdir/text.o \[@0/.* not claimed - hook called: all symbols read. - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... -diff --git a/ld/testsuite/ld-plugin/plugin-7.d b/ld/testsuite/ld-plugin/plugin-7.d -index c77b66fa..a2f41d19 100644 ---- a/ld/testsuite/ld-plugin/plugin-7.d -+++ b/ld/testsuite/ld-plugin/plugin-7.d -@@ -30,5 +30,6 @@ hook called: claim_file tmpdir/text.o \[@0/.* not claimed - hook called: all symbols read. - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... -diff --git a/ld/testsuite/ld-plugin/plugin-8.d b/ld/testsuite/ld-plugin/plugin-8.d -index ca24227a..e26c1050 100644 ---- a/ld/testsuite/ld-plugin/plugin-8.d -+++ b/ld/testsuite/ld-plugin/plugin-8.d -@@ -34,5 +34,6 @@ Sym: '_?func' Resolution: LDPR_PREVAILING_DEF - Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY - .*: tmpdir/main.o: in function `main': - .*main.c.*: undefined reference to `\.?func' -+.*main.c.*: undefined reference to `\.?func' - hook called: cleanup. - #... -diff --git a/ld/testsuite/ld-scripts/fill.d b/ld/testsuite/ld-scripts/fill.d -index cfe1e524..0e2ad2fe 100644 ---- a/ld/testsuite/ld-scripts/fill.d -+++ b/ld/testsuite/ld-scripts/fill.d -@@ -7,7 +7,7 @@ - #skip: ia64-*-* mips*-*-freebsd* mips*-*-gnu* mips*-*-irix* mips*-*-kfreebsd* - #skip: mips*-*-linux* mips*-*-netbsd* mips*-*-openbsd* mips*-*-sysv4* sh-*-pe - #skip: tilegx*-*-* tilepro-*-* x86_64-*-cygwin x86_64-*-mingw* x86_64-*-pe* --#xfail: alpha*-*-*ecoff sparc*-*-coff -+#xfail: alpha*-*-*ecoff sw_64*-*-*ecoff sparc*-*-coff - #xfail: tic30-*-coff tic4x-*-* tic54x-*-* z8k-*-* - # - # See also fill16.d. We use `skip' for configurations unsupported -@@ -16,6 +16,7 @@ - # configurations are listed above. - # - # alpha-linuxecoff pads out code to 16 bytes. -+# sw_64-linuxecoff pads out code to 16 bytes. - # ia64 aligns code to minimum 16 bytes. - # mips aligns to minimum 16 bytes (except for bare-metal ELF and VxWorks). - # sh-pe pads out code sections to 16 bytes -diff --git a/ld/testsuite/ld-scripts/fill16.d b/ld/testsuite/ld-scripts/fill16.d -index e5819df7..86ea9003 100644 ---- a/ld/testsuite/ld-scripts/fill16.d -+++ b/ld/testsuite/ld-scripts/fill16.d -@@ -5,7 +5,7 @@ - #objdump: -s -j .text - #notarget: [is_aout_format] - #skip: arm-*-coff i[3-7]86-*-coff [is_xcoff_format] --#xfail: alpha*-*-*ecoff sparc*-*-coff -+#xfail: alpha*-*-*ecoff sw_64*-*-*ecoff sparc*-*-coff - #xfail: tic30-*-coff tic4x-*-* tic54x-*-* z8k-*-* - #xfail: z80-*-coff - # -@@ -15,6 +15,7 @@ - # configurations are listed above. - # - # alpha-linuxecoff pads out code to 16 bytes. -+# sw_64-linuxecoff pads out code to 16 bytes. - # arm-coff always aligns code to 4 bytes. - # i386-coff always aligns code to 4 bytes. - # sh-pe pads out code sections to 16 bytes -diff --git a/ld/testsuite/ld-scripts/pr27100.d b/ld/testsuite/ld-scripts/pr27100.d -index 28b5875d..d516ca3b 100644 ---- a/ld/testsuite/ld-scripts/pr27100.d -+++ b/ld/testsuite/ld-scripts/pr27100.d -@@ -1,7 +1,7 @@ - #ld: -r -T pr27100.t - #objdump: -h - #notarget: [is_aout_format] --#xfail: alpha*-*-*vms* mmix-*-* *c54x-*-* [is_xcoff_format] -+#xfail: alpha*-*-*vms* sw_64*-*-*vms* mmix-*-* *c54x-*-* [is_xcoff_format] - - #... - .* \.data +0+60 .* -diff --git a/ld/testsuite/ld-shared/shared.exp b/ld/testsuite/ld-shared/shared.exp -index 0e45f5c0..ff1b87bb 100644 ---- a/ld/testsuite/ld-shared/shared.exp -+++ b/ld/testsuite/ld-shared/shared.exp -@@ -53,6 +53,7 @@ if { ![istarget hppa*64*-*-hpux*] \ - && ![istarget sparc*-*-linux*] \ - && ![istarget arm*-*-linux*] \ - && ![istarget alpha*-*-linux*] \ -+ && ![istarget sw_64*-*-linux*] \ - && ![istarget rs6000*-*-aix*] \ - && ![istarget powerpc*-*-aix*] \ - && ![istarget s390*-*-linux*] \ -@@ -233,6 +234,7 @@ if ![ld_compile "$CC $CFLAGS $SHCFLAG" $srcdir/$subdir/main.c $tmpdir/mainnp.o] - setup_xfail "*-*-solaris2*" - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -+ setup_xfail "sw_64*-*-linux*" - setup_xfail "powerpc64*-*-*" - if { ![istarget hppa*64*-*-linux*] } { - setup_xfail "hppa*-*-linux*" -@@ -259,6 +261,7 @@ if ![ld_compile "$CC $CFLAGS $SHCFLAG" $srcdir/$subdir/main.c $tmpdir/mainnp.o] - setup_xfail "powerpc*-*-linux*" - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -+ setup_xfail "sw_64*-*-linux*" - setup_xfail "mips*-*-linux*" - if { ![istarget hppa*64*-*-linux*] } { - setup_xfail "hppa*-*-linux*" -@@ -314,6 +317,7 @@ if ![ld_compile "$CC $CFLAGS $SHCFLAG $picflag" $srcdir/$subdir/main.c $tmpdir/m - setup_xfail "*-*-solaris2*" - setup_xfail "ia64-*-linux*" - setup_xfail "alpha*-*-linux*" -+ setup_xfail "sw_64*-*-linux*" - setup_xfail "powerpc64*-*-*" - if { ![istarget hppa*64*-*-linux*] } { - setup_xfail "hppa*-*-linux*" -diff --git a/ld/testsuite/ld-srec/srec.exp b/ld/testsuite/ld-srec/srec.exp -index c8d561b8..54953de9 100644 ---- a/ld/testsuite/ld-srec/srec.exp -+++ b/ld/testsuite/ld-srec/srec.exp -@@ -408,6 +408,9 @@ setup_xfail "v850*-*-elf" - # The S-record linker doesn't handle Alpha Elf relaxation. - setup_xfail "alpha*-*-elf*" "alpha*-*-linux-*" "alpha*-*-gnu*" - setup_xfail "alpha*-*-netbsd*" -+#setup_xfail "sw_64*-*-*" -+setup_xfail "sw_64*-*-elf*" "sw_64*-*-linux-*" "sw_64*-*-gnu*" -+setup_xfail "sw_64*-*-netbsd*" - - # The S-record linker hasn't any hope of coping with HPPA relocs. - # Or MeP complex relocs. -@@ -471,6 +474,9 @@ setup_xfail "arm*-*-*" - setup_xfail "v850*-*-elf" - setup_xfail "alpha*-*-elf*" "alpha*-*-linux-*" "alpha*-*-gnu*" - setup_xfail "alpha*-*-netbsd*" -+#setup_xfail "sw_64*-*-*" -+setup_xfail "sw_64*-*-elf*" "sw_64*-*-linux-*" "sw_64*-*-gnu*" -+setup_xfail "sw_64*-*-netbsd*" - setup_xfail "hppa*-*-*" "mep-*-*" - setup_xfail "ia64-*-*" - setup_xfail "*-*-cygwin*" "*-*-mingw*" "*-*-pe*" "*-*-winnt*" -diff --git a/makefile.vms b/makefile.vms -index a9e36340..2b921703 100644 ---- a/makefile.vms -+++ b/makefile.vms -@@ -15,6 +15,14 @@ CC = cc - GASCC = gcc - endif - -+ifeq ($(ARCH),SW_64) -+CC = gcc -+GASCC = $(CC) -+else -+CC = cc -+GASCC = gcc -+endif -+ - ifeq ($(CC),cc) - CHECK-COMPILER = check_compiler - else -diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am -index b468c0a0..53c6160c 100644 ---- a/opcodes/Makefile.am -+++ b/opcodes/Makefile.am -@@ -97,6 +97,8 @@ TARGET_LIBOPCODES_CFILES = \ - aarch64-opc-2.c \ - alpha-dis.c \ - alpha-opc.c \ -+ sw_64-dis.c \ -+ sw_64-opc.c \ - arc-dis.c \ - arc-ext.c \ - arc-opc.c \ -diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in -index 3954fdd6..ece36424 100644 ---- a/opcodes/Makefile.in -+++ b/opcodes/Makefile.in -@@ -488,6 +488,8 @@ TARGET_LIBOPCODES_CFILES = \ - aarch64-opc-2.c \ - alpha-dis.c \ - alpha-opc.c \ -+ sw_64-dis.c \ -+ sw_64-opc.c \ - arc-dis.c \ - arc-ext.c \ - arc-opc.c \ -@@ -903,6 +905,8 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aarch64-opc.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alpha-dis.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alpha-opc.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sw_64-opc.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sw_64-dis.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-dis.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-ext.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-opc.Plo@am__quote@ -diff --git a/opcodes/config.in b/opcodes/config.in -index 392cda5d..59e1358a 100644 ---- a/opcodes/config.in -+++ b/opcodes/config.in -@@ -117,3 +117,5 @@ - - /* Define to 1 if you need to in order for `stat' and other things to work. */ - #undef _POSIX_SOURCE -+ -+#undef TARGET_SW_64 -diff --git a/opcodes/configure b/opcodes/configure -index 6ca33dd5..b77fefc1 100755 ---- a/opcodes/configure -+++ b/opcodes/configure -@@ -12235,6 +12235,13 @@ if test x${all_targets} = xfalse ; then - case "$arch" in - bfd_aarch64_arch) ta="$ta aarch64-asm.lo aarch64-dis.lo aarch64-opc.lo aarch64-asm-2.lo aarch64-dis-2.lo aarch64-opc-2.lo" ;; - bfd_alpha_arch) ta="$ta alpha-dis.lo alpha-opc.lo" ;; -+# ifdef TARGET_SW_64 -+ bfd_sw_64_arch) ta="$ta sw_64-dis.lo sw_64-opc.lo" -+cat >>confdefs.h <<_ACEOF -+#define TARGET_SW_64 -+_ACEOF -+# endif -+ ;; - bfd_arc_arch) ta="$ta arc-dis.lo arc-opc.lo arc-ext.lo" ;; - bfd_arm_arch) ta="$ta arm-dis.lo" ;; - bfd_avr_arch) ta="$ta avr-dis.lo" ;; -diff --git a/opcodes/configure.ac b/opcodes/configure.ac -index e564f067..7fd0b600 100644 ---- a/opcodes/configure.ac -+++ b/opcodes/configure.ac -@@ -272,6 +272,7 @@ if test x${all_targets} = xfalse ; then - case "$arch" in - bfd_aarch64_arch) ta="$ta aarch64-asm.lo aarch64-dis.lo aarch64-opc.lo aarch64-asm-2.lo aarch64-dis-2.lo aarch64-opc-2.lo" ;; - bfd_alpha_arch) ta="$ta alpha-dis.lo alpha-opc.lo" ;; -+ bfd_sw_64_arch) ta="$ta sw_64-dis.lo sw_64-opc.lo" ;; - bfd_arc_arch) ta="$ta arc-dis.lo arc-opc.lo arc-ext.lo" ;; - bfd_arm_arch) ta="$ta arm-dis.lo" ;; - bfd_avr_arch) ta="$ta avr-dis.lo" ;; -diff --git a/opcodes/configure.com b/opcodes/configure.com -index 2e9ece71..5884c55c 100644 ---- a/opcodes/configure.com -+++ b/opcodes/configure.com -@@ -44,6 +44,14 @@ $ FILES="alpha-dis,alpha-opc" - $ DEFS="""ARCH_alpha""" - $EOD - $ endif -+$ if arch.eqs."sw_64" -+$ then -+$ create build.com -+$DECK -+$ FILES="sw_64-dis,sw_64-opc" -+$ DEFS="""ARCH_sw_64""" -+$EOD -+$ endif - $! - $ append sys$input build.com - $DECK -diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c -index 8590e945..8b416264 100644 ---- a/opcodes/disassemble.c -+++ b/opcodes/disassemble.c -@@ -26,6 +26,9 @@ - #ifdef ARCH_all - #define ARCH_aarch64 - #define ARCH_alpha -+#ifdef TARGET_SW_64 -+#define ARCH_sw_64 -+#endif - #define ARCH_arc - #define ARCH_arm - #define ARCH_avr -@@ -145,6 +148,13 @@ disassembler (enum bfd_architecture a, - disassemble = print_insn_alpha; - break; - #endif -+#ifdef TARGET_SW_64 -+#ifdef ARCH_sw_64 -+ case bfd_arch_sw_64: -+ disassemble = print_insn_sw_64; -+ break; -+#endif -+#endif - #ifdef ARCH_arc - case bfd_arch_arc: - disassemble = arc_get_disassembler (abfd); -diff --git a/opcodes/disassemble.h b/opcodes/disassemble.h -index 8ee54dc9..77028c3b 100644 ---- a/opcodes/disassemble.h -+++ b/opcodes/disassemble.h -@@ -23,6 +23,9 @@ - - extern int print_insn_aarch64 (bfd_vma, disassemble_info *); - extern int print_insn_alpha (bfd_vma, disassemble_info *); -+#ifdef TARGET_SW_64 -+extern int print_insn_sw_64 (bfd_vma, disassemble_info *); -+#endif - extern int print_insn_avr (bfd_vma, disassemble_info *); - extern int print_insn_bfin (bfd_vma, disassemble_info *); - extern int print_insn_big_arm (bfd_vma, disassemble_info *); --- -2.33.0 - diff --git a/sw_64-support-not-upstream-new-files.patch b/sw_64-support-not-upstream-new-files.patch deleted file mode 100644 index 4697d34..0000000 --- a/sw_64-support-not-upstream-new-files.patch +++ /dev/null @@ -1,31730 +0,0 @@ -From 6dcf0702d4538a08b6c4103272a14b38b4106788 Mon Sep 17 00:00:00 2001 -From: yeqinglong -Date: Wed, 30 Aug 2023 15:02:36 +0800 -Subject: [PATCH] add sw_64 support not upstream new files - ---- - bfd/coff-sw_64.c | 2470 +++++++ - bfd/cpu-sw_64.c | 59 + - bfd/elf64-sw_64.c | 5718 +++++++++++++++ - bfd/hosts/sw_64linux.h | 25 + - bfd/hosts/sw_64vms.h | 68 + - bfd/vms-sw_64.c | 10248 +++++++++++++++++++++++++++ - elfcpp/sw_64.def.h | 39 + - elfcpp/sw_64.h | 15 + - gas/config/tc-sw_64.c | 6585 +++++++++++++++++ - gas/config/tc-sw_64.h | 197 + - gas/test | 350 + - gas/testsuite/gas/elf/elf.exp.2.37 | 344 + - gas/testsuite/gas/elf/elf.exp.ok | 350 + - gold/sw_64.cc | 1787 +++++ - gprof/sw_64.c | 176 + - include/coff/sw_64.h | 386 + - include/elf/sw_64.h | 136 + - include/opcode/pe.h | 605 ++ - include/opcode/sw_64.h | 255 + - ld/emulparams/elf64sw_64.sh | 36 + - ld/emulparams/elf64sw_64_fbsd.sh | 3 + - ld/emulparams/elf64sw_64_nbsd.sh | 2 + - ld/emulparams/sw_64.sh | 3 + - ld/emulparams/sw_64vms.sh | 7 + - ld/emultempl/sw_64elf.em | 152 + - ld/scripttempl/sw_64.sc | 87 + - ld/scripttempl/sw_64vms.sc | 90 + - opcodes/sw_64-dis.c | 238 + - opcodes/sw_64-opc.c | 1055 +++ - 29 files changed, 31486 insertions(+) - create mode 100644 bfd/coff-sw_64.c - create mode 100644 bfd/cpu-sw_64.c - create mode 100644 bfd/elf64-sw_64.c - create mode 100644 bfd/hosts/sw_64linux.h - create mode 100644 bfd/hosts/sw_64vms.h - create mode 100644 bfd/vms-sw_64.c - create mode 100644 elfcpp/sw_64.def.h - create mode 100644 elfcpp/sw_64.h - create mode 100644 gas/config/tc-sw_64.c - create mode 100644 gas/config/tc-sw_64.h - create mode 100644 gas/test - create mode 100644 gas/testsuite/gas/elf/elf.exp.2.37 - create mode 100644 gas/testsuite/gas/elf/elf.exp.ok - create mode 100644 gold/sw_64.cc - create mode 100644 gprof/sw_64.c - create mode 100644 include/coff/sw_64.h - create mode 100644 include/elf/sw_64.h - create mode 100644 include/opcode/pe.h - create mode 100644 include/opcode/sw_64.h - create mode 100644 ld/emulparams/elf64sw_64.sh - create mode 100644 ld/emulparams/elf64sw_64_fbsd.sh - create mode 100644 ld/emulparams/elf64sw_64_nbsd.sh - create mode 100644 ld/emulparams/sw_64.sh - create mode 100644 ld/emulparams/sw_64vms.sh - create mode 100644 ld/emultempl/sw_64elf.em - create mode 100644 ld/scripttempl/sw_64.sc - create mode 100644 ld/scripttempl/sw_64vms.sc - create mode 100644 opcodes/sw_64-dis.c - create mode 100644 opcodes/sw_64-opc.c - -diff --git a/bfd/coff-sw_64.c b/bfd/coff-sw_64.c -new file mode 100644 -index 00000000..50a2a1a4 ---- /dev/null -+++ b/bfd/coff-sw_64.c -@@ -0,0 +1,2470 @@ -+/* BFD back-end for SW_64 Extended-Coff files. -+ Copyright (C) 1993-2021 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 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+ MA 02110-1301, USA. */ -+ -+#include "sysdep.h" -+#include "bfd.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/sw_64.h" -+#include "aout/ar.h" -+#include "libcoff.h" -+#include "libecoff.h" -+ -+/* Prototypes for static functions. */ -+ -+ -+ -+/* 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 H_GET_64 -+#define PUT_FILEHDR_SYMPTR H_PUT_64 -+#define GET_AOUTHDR_TSIZE H_GET_64 -+#define PUT_AOUTHDR_TSIZE H_PUT_64 -+#define GET_AOUTHDR_DSIZE H_GET_64 -+#define PUT_AOUTHDR_DSIZE H_PUT_64 -+#define GET_AOUTHDR_BSIZE H_GET_64 -+#define PUT_AOUTHDR_BSIZE H_PUT_64 -+#define GET_AOUTHDR_ENTRY H_GET_64 -+#define PUT_AOUTHDR_ENTRY H_PUT_64 -+#define GET_AOUTHDR_TEXT_START H_GET_64 -+#define PUT_AOUTHDR_TEXT_START H_PUT_64 -+#define GET_AOUTHDR_DATA_START H_GET_64 -+#define PUT_AOUTHDR_DATA_START H_PUT_64 -+#define GET_SCNHDR_PADDR H_GET_64 -+#define PUT_SCNHDR_PADDR H_PUT_64 -+#define GET_SCNHDR_VADDR H_GET_64 -+#define PUT_SCNHDR_VADDR H_PUT_64 -+#define GET_SCNHDR_SIZE H_GET_64 -+#define PUT_SCNHDR_SIZE H_PUT_64 -+#define GET_SCNHDR_SCNPTR H_GET_64 -+#define PUT_SCNHDR_SCNPTR H_PUT_64 -+#define GET_SCNHDR_RELPTR H_GET_64 -+#define PUT_SCNHDR_RELPTR H_PUT_64 -+#define GET_SCNHDR_LNNOPTR H_GET_64 -+#define PUT_SCNHDR_LNNOPTR H_PUT_64 -+ -+#define SW_64ECOFF -+ -+#define NO_COFF_RELOCS -+#define NO_COFF_SYMBOLS -+#define NO_COFF_LINENOS -+#define coff_swap_filehdr_in sw_64_ecoff_swap_filehdr_in -+#define coff_swap_filehdr_out sw_64_ecoff_swap_filehdr_out -+#define coff_swap_aouthdr_in sw_64_ecoff_swap_aouthdr_in -+#define coff_swap_aouthdr_out sw_64_ecoff_swap_aouthdr_out -+#define coff_swap_scnhdr_in sw_64_ecoff_swap_scnhdr_in -+#define coff_swap_scnhdr_out sw_64_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 (bfd *abfd ATTRIBUTE_UNUSED, -+ arelent *reloc ATTRIBUTE_UNUSED, -+ asymbol *sym ATTRIBUTE_UNUSED, -+ void * data ATTRIBUTE_UNUSED, -+ asection *sec ATTRIBUTE_UNUSED, -+ bfd *output_bfd ATTRIBUTE_UNUSED, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+ 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 sw_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 (SW_64_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 bfd_cleanup -+sw_64_ecoff_object_p (bfd *abfd) -+{ -+ bfd_cleanup 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 = (bfd_size_type) sec->line_filepos * 8; -+ BFD_ASSERT (size == sec->size -+ || size + 8 == sec->size); -+ if (!bfd_set_section_size (sec, size)) -+ return NULL; -+ } -+ } -+ -+ return ret; -+} -+ -+/* See whether the magic number matches. */ -+ -+static bool -+sw_64_ecoff_bad_format_hook (bfd *abfd ATTRIBUTE_UNUSED, -+ void * filehdr) -+{ -+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; -+ -+ if (! SW_64_ECOFF_BADMAG (*internal_f)) -+ return true; -+ -+ if (SW_64_ECOFF_COMPRESSEDMAG (*internal_f)) -+ _bfd_error_handler -+ (_("%pB: cannot handle compressed Alpha binaries; " -+ "use compiler flags, or objZ, to generate uncompressed binaries"), -+ abfd); -+ -+ return false; -+} -+ -+/* This is a hook called by coff_real_object_p to create any backend -+ specific information. */ -+ -+static void * -+sw_64_ecoff_mkobject_hook (bfd *abfd, void * filehdr, void * aouthdr) -+{ -+ void * 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_SW_64_OBJECT_TYPE_MASK) -+ { -+ case F_SW_64_SHARABLE: -+ abfd->flags |= DYNAMIC; -+ break; -+ case F_SW_64_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 -+sw_64_ecoff_swap_reloc_in (bfd *abfd, -+ void * ext_ptr, -+ struct internal_reloc *intern) -+{ -+ const RELOC *ext = (RELOC *) ext_ptr; -+ -+ intern->r_vaddr = H_GET_64 (abfd, ext->r_vaddr); -+ intern->r_symndx = H_GET_32 (abfd, ext->r_symndx); -+ -+ BFD_ASSERT (bfd_header_little_endian (abfd)); -+ -+ intern->r_type = ((ext->r_bits[0] & RELOC_BITS0_TYPE_LITTLE) -+ >> RELOC_BITS0_TYPE_SH_LITTLE); -+ intern->r_extern = (ext->r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0; -+ intern->r_offset = ((ext->r_bits[1] & RELOC_BITS1_OFFSET_LITTLE) -+ >> RELOC_BITS1_OFFSET_SH_LITTLE); -+ /* Ignored the reserved bits. */ -+ intern->r_size = ((ext->r_bits[3] & RELOC_BITS3_SIZE_LITTLE) -+ >> RELOC_BITS3_SIZE_SH_LITTLE); -+ -+ if (intern->r_type == SW_64_R_LITUSE -+ || intern->r_type == SW_64_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 == SW_64_R_IGNORE) -+ { -+ /* The IGNORE reloc generally follows a GPDISP reloc, and is -+ against the .lita section. The section is irrelevant. */ -+ if (! intern->r_extern && -+ intern->r_symndx == RELOC_SECTION_ABS) -+ abort (); -+ if (! intern->r_extern && intern->r_symndx == RELOC_SECTION_LITA) -+ intern->r_symndx = RELOC_SECTION_ABS; -+ } -+} -+ -+/* Swap a reloc out. */ -+ -+static void -+sw_64_ecoff_swap_reloc_out (bfd *abfd, -+ const struct internal_reloc *intern, -+ void * dst) -+{ -+ RELOC *ext = (RELOC *) dst; -+ long symndx; -+ unsigned char size; -+ -+ /* Undo the hackery done in swap_reloc_in. */ -+ if (intern->r_type == SW_64_R_LITUSE -+ || intern->r_type == SW_64_R_GPDISP) -+ { -+ symndx = intern->r_size; -+ size = 0; -+ } -+ else if (intern->r_type == SW_64_R_IGNORE -+ && ! intern->r_extern -+ && intern->r_symndx == RELOC_SECTION_ABS) -+ { -+ symndx = RELOC_SECTION_LITA; -+ size = intern->r_size; -+ } -+ else -+ { -+ symndx = intern->r_symndx; -+ size = intern->r_size; -+ } -+ -+ /* XXX FIXME: The maximum symndx value used to be 14 but this -+ fails with object files produced by DEC's C++ compiler. -+ Where does the value 14 (or 15) come from anyway ? */ -+ BFD_ASSERT (intern->r_extern -+ || (intern->r_symndx >= 0 && intern->r_symndx <= 15)); -+ -+ H_PUT_64 (abfd, intern->r_vaddr, ext->r_vaddr); -+ H_PUT_32 (abfd, symndx, ext->r_symndx); -+ -+ BFD_ASSERT (bfd_header_little_endian (abfd)); -+ -+ ext->r_bits[0] = ((intern->r_type << RELOC_BITS0_TYPE_SH_LITTLE) -+ & RELOC_BITS0_TYPE_LITTLE); -+ ext->r_bits[1] = ((intern->r_extern ? RELOC_BITS1_EXTERN_LITTLE : 0) -+ | ((intern->r_offset << RELOC_BITS1_OFFSET_SH_LITTLE) -+ & RELOC_BITS1_OFFSET_LITTLE)); -+ ext->r_bits[2] = 0; -+ ext->r_bits[3] = ((size << RELOC_BITS3_SIZE_SH_LITTLE) -+ & RELOC_BITS3_SIZE_LITTLE); -+} -+ -+/* Finish canonicalizing a reloc. Part of this is generic to all -+ ECOFF targets, and that part is in ecoff.c. The rest is done in -+ this backend routine. It must fill in the howto field. */ -+ -+static void -+sw_64_adjust_reloc_in (bfd *abfd, -+ const struct internal_reloc *intern, -+ arelent *rptr) -+{ -+ if (intern->r_type > SW_64_R_GPVALUE) -+ { -+ /* xgettext:c-format */ -+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"), -+ abfd, intern->r_type); -+ bfd_set_error (bfd_error_bad_value); -+ rptr->addend = 0; -+ rptr->howto = NULL; -+ return; -+ } -+ -+ switch (intern->r_type) -+ { -+ case SW_64_R_BRADDR: -+ case SW_64_R_SREL16: -+ case SW_64_R_SREL32: -+ case SW_64_R_SREL64: -+ /* This relocs appear to be fully resolved when they are against -+ internal symbols. Against external symbols, BRADDR at least -+ appears to be resolved against the next instruction. */ -+ if (! intern->r_extern) -+ rptr->addend = 0; -+ else -+ rptr->addend = - (intern->r_vaddr + 4); -+ break; -+ -+ case SW_64_R_GPREL32: -+ case SW_64_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 SW_64_R_LITUSE: -+ case SW_64_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 SW_64_R_OP_STORE: -+ /* The STORE reloc needs the size and offset fields. We store -+ them in the addend. */ -+ BFD_ASSERT (intern->r_offset <= 256); -+ rptr->addend = (intern->r_offset << 8) + intern->r_size; -+ break; -+ -+ case SW_64_R_OP_PUSH: -+ case SW_64_R_OP_PSUB: -+ case SW_64_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 SW_64_R_GPVALUE: -+ /* Set the addend field to the new GP value. */ -+ rptr->addend = intern->r_symndx + ecoff_data (abfd)->gp; -+ break; -+ -+ case SW_64_R_IGNORE: -+ /* If the type is SW_64_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 = &sw_64_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 -+ sw_64_adjust_reloc_in, except that there are several changes we do -+ not need to undo. */ -+ -+static void -+sw_64_adjust_reloc_out (bfd *abfd ATTRIBUTE_UNUSED, -+ const arelent *rel, -+ struct internal_reloc *intern) -+{ -+ switch (intern->r_type) -+ { -+ case SW_64_R_LITUSE: -+ case SW_64_R_GPDISP: -+ intern->r_size = rel->addend; -+ break; -+ -+ case SW_64_R_OP_STORE: -+ intern->r_size = rel->addend & 0xff; -+ intern->r_offset = (rel->addend >> 8) & 0xff; -+ break; -+ -+ case SW_64_R_OP_PUSH: -+ case SW_64_R_OP_PSUB: -+ case SW_64_R_OP_PRSHIFT: -+ intern->r_vaddr = rel->addend; -+ break; -+ -+ case SW_64_R_IGNORE: -+ intern->r_vaddr = rel->address; -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+/* The size of the stack for the relocation evaluator. */ -+#define RELOC_STACKSIZE (10) -+ -+/* Alpha ECOFF relocs have a built in expression evaluator as well as -+ other interdependencies. Rather than use a bunch of special -+ functions and global variables, we use a single routine to do all -+ the relocation for a section. I haven't yet worked out how the -+ assembler is going to handle this. */ -+ -+static bfd_byte * -+sw_64_ecoff_get_relocated_section_contents (bfd *abfd, -+ struct bfd_link_info *link_info, -+ struct bfd_link_order *link_order, -+ bfd_byte *data, -+ bool relocatable, -+ 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 = relocatable ? abfd : (bfd *) NULL; -+ bfd_vma gp; -+ bfd_size_type sz; -+ bool gp_undefined; -+ bfd_vma stack[RELOC_STACKSIZE]; -+ int tos = 0; -+ -+ if (reloc_size < 0) -+ goto error_return; -+ reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); -+ if (reloc_vector == NULL && reloc_size != 0) -+ goto error_return; -+ -+ sz = input_section->rawsize ? input_section->rawsize : input_section->size; -+ if (! bfd_get_section_contents (input_bfd, input_section, data, 0, sz)) -+ goto error_return; -+ -+ reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, -+ reloc_vector, symbols); -+ if (reloc_count < 0) -+ goto error_return; -+ if (reloc_count == 0) -+ goto successful_return; -+ -+ /* Get the GP value for the output BFD. */ -+ gp_undefined = false; -+ gp = _bfd_get_gp_value (abfd); -+ if (gp == 0) -+ { -+ if (relocatable) -+ { -+ asection *sec; -+ bfd_vma lo; -+ -+ /* Make up a value. */ -+ lo = (bfd_vma) -1; -+ for (sec = abfd->sections; sec != NULL; sec = sec->next) -+ { -+ if (sec->vma < lo -+ && (strcmp (sec->name, ".sbss") == 0 -+ || strcmp (sec->name, ".sdata") == 0 -+ || strcmp (sec->name, ".lit4") == 0 -+ || strcmp (sec->name, ".lit8") == 0 -+ || strcmp (sec->name, ".lita") == 0)) -+ lo = sec->vma; -+ } -+ gp = lo + 0x8000; -+ _bfd_set_gp_value (abfd, gp); -+ } -+ else -+ { -+ struct bfd_link_hash_entry *h; -+ -+ h = bfd_link_hash_lookup (link_info->hash, "_gp", false, false, -+ true); -+ if (h == (struct bfd_link_hash_entry *) NULL -+ || h->type != bfd_link_hash_defined) -+ gp_undefined = true; -+ else -+ { -+ gp = (h->u.def.value -+ + h->u.def.section->output_section->vma -+ + h->u.def.section->output_offset); -+ _bfd_set_gp_value (abfd, gp); -+ } -+ } -+ } -+ -+ for (; *reloc_vector != (arelent *) NULL; reloc_vector++) -+ { -+ arelent *rel; -+ bfd_reloc_status_type r; -+ char *err; -+ -+ rel = *reloc_vector; -+ r = bfd_reloc_ok; -+ switch (rel->howto->type) -+ { -+ case SW_64_R_IGNORE: -+ rel->address += input_section->output_offset; -+ break; -+ -+ case SW_64_R_REFLONG: -+ case SW_64_R_REFQUAD: -+ case SW_64_R_BRADDR: -+ case SW_64_R_HINT: -+ case SW_64_R_SREL16: -+ case SW_64_R_SREL32: -+ case SW_64_R_SREL64: -+ if (relocatable -+ && ((*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 SW_64_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 SW_64_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 SW_64_R_LITUSE: -+ /* See SW_64_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 SW_64_R_GPDISP: -+ /* This marks the ldah of an ldah/lda pair which loads the -+ gp register with the difference of the gp value and the -+ current location. The second of the pair is r_size bytes -+ ahead; it used to be marked with an SW_64_R_IGNORE reloc, -+ but that no longer happens in OSF/1 3.2. */ -+ { -+ unsigned long insn1, insn2; -+ bfd_vma addend; -+ -+ /* Get the two instructions. */ -+ insn1 = bfd_get_32 (input_bfd, data + rel->address); -+ insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend); -+ -+ BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ -+ BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ -+ -+ /* Get the existing addend. We must account for the sign -+ extension done by lda and ldah. */ -+ addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); -+ if (insn1 & 0x8000) -+ { -+ addend -= 0x80000000; -+ addend -= 0x80000000; -+ } -+ if (insn2 & 0x8000) -+ addend -= 0x10000; -+ -+ /* The existing addend includes the different between the -+ gp of the input BFD and the address in the input BFD. -+ Subtract this out. */ -+ addend -= (ecoff_data (input_bfd)->gp -+ - (input_section->vma + rel->address)); -+ -+ /* Now add in the final gp value, and subtract out the -+ final address. */ -+ addend += (gp -+ - (input_section->output_section->vma -+ + input_section->output_offset -+ + rel->address)); -+ -+ /* Change the instructions, accounting for the sign -+ extension, and write them out. */ -+ if (addend & 0x8000) -+ addend += 0x10000; -+ insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff); -+ insn2 = (insn2 & 0xffff0000) | (addend & 0xffff); -+ -+ bfd_put_32 (input_bfd, (bfd_vma) insn1, data + rel->address); -+ bfd_put_32 (input_bfd, (bfd_vma) insn2, -+ data + rel->address + rel->addend); -+ -+ rel->address += input_section->output_offset; -+ } -+ break; -+ -+ case SW_64_R_OP_PUSH: -+ /* Push a value on the reloc evaluation stack. */ -+ { -+ asymbol *symbol; -+ bfd_vma relocation; -+ -+ if (relocatable) -+ { -+ 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 SW_64_R_OP_STORE: -+ /* Store a value from the reloc stack into a bitfield. */ -+ { -+ bfd_vma val; -+ int offset, size; -+ -+ if (relocatable) -+ { -+ 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 sw_64_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 SW_64_R_OP_PSUB: -+ /* Subtract a value from the top of the stack. */ -+ { -+ asymbol *symbol; -+ bfd_vma relocation; -+ -+ if (relocatable) -+ { -+ 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 SW_64_R_OP_PRSHIFT: -+ /* Shift the value on the top of the stack. */ -+ { -+ asymbol *symbol; -+ bfd_vma relocation; -+ -+ if (relocatable) -+ { -+ 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 SW_64_R_GPVALUE: -+ /* I really don't know if this does the right thing. */ -+ gp = rel->addend; -+ gp_undefined = false; -+ break; -+ -+ default: -+ abort (); -+ } -+ -+ if (relocatable) -+ { -+ 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: -+ (*link_info->callbacks->undefined_symbol) -+ (link_info, bfd_asymbol_name (*rel->sym_ptr_ptr), -+ input_bfd, input_section, rel->address, true); -+ break; -+ case bfd_reloc_dangerous: -+ (*link_info->callbacks->reloc_dangerous) -+ (link_info, err, input_bfd, input_section, rel->address); -+ break; -+ case bfd_reloc_overflow: -+ (*link_info->callbacks->reloc_overflow) -+ (link_info, NULL, bfd_asymbol_name (*rel->sym_ptr_ptr), -+ rel->howto->name, rel->addend, input_bfd, -+ input_section, rel->address); -+ break; -+ case bfd_reloc_outofrange: -+ default: -+ abort (); -+ break; -+ } -+ } -+ } -+ -+ if (tos != 0) -+ abort (); -+ -+ successful_return: -+ free (reloc_vector); -+ return data; -+ -+ error_return: -+ free (reloc_vector); -+ return NULL; -+} -+ -+/* Get the howto structure for a generic reloc type. */ -+ -+static reloc_howto_type * -+sw_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, -+ bfd_reloc_code_real_type code) -+{ -+ int sw_64_type; -+ -+ switch (code) -+ { -+ case BFD_RELOC_32: -+ sw_64_type = SW_64_R_REFLONG; -+ break; -+ case BFD_RELOC_64: -+ case BFD_RELOC_CTOR: -+ sw_64_type = SW_64_R_REFQUAD; -+ break; -+ case BFD_RELOC_GPREL32: -+ sw_64_type = SW_64_R_GPREL32; -+ break; -+ case BFD_RELOC_SW_64_LITERAL: -+ sw_64_type = SW_64_R_LITERAL; -+ break; -+ case BFD_RELOC_SW_64_LITUSE: -+ sw_64_type = SW_64_R_LITUSE; -+ break; -+ case BFD_RELOC_SW_64_GPDISP_HI16: -+ sw_64_type = SW_64_R_GPDISP; -+ break; -+ case BFD_RELOC_SW_64_GPDISP_LO16: -+ sw_64_type = SW_64_R_IGNORE; -+ break; -+ case BFD_RELOC_23_PCREL_S2: -+ sw_64_type = SW_64_R_BRADDR; -+ break; -+ case BFD_RELOC_SW_64_HINT: -+ sw_64_type = SW_64_R_HINT; -+ break; -+ case BFD_RELOC_16_PCREL: -+ sw_64_type = SW_64_R_SREL16; -+ break; -+ case BFD_RELOC_32_PCREL: -+ sw_64_type = SW_64_R_SREL32; -+ break; -+ case BFD_RELOC_64_PCREL: -+ sw_64_type = SW_64_R_SREL64; -+ break; -+ default: -+ return (reloc_howto_type *) NULL; -+ } -+ -+ return &sw_64_howto_table[sw_64_type]; -+} -+ -+static reloc_howto_type * -+sw_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, -+ const char *r_name) -+{ -+ unsigned int i; -+ -+ for (i = 0; -+ i < sizeof (sw_64_howto_table) / sizeof (sw_64_howto_table[0]); -+ i++) -+ if (sw_64_howto_table[i].name != NULL -+ && strcasecmp (sw_64_howto_table[i].name, r_name) == 0) -+ return &sw_64_howto_table[i]; -+ -+ return NULL; -+} -+ -+/* A helper routine for sw_64_relocate_section which converts an -+ external reloc when generating relocatable output. Returns the -+ relocation amount. */ -+ -+static bfd_vma -+sw_64_convert_external_reloc (bfd *output_bfd ATTRIBUTE_UNUSED, -+ 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 (bfd_link_relocatable (info)); -+ -+ 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_section_name (hsec->output_section); -+ -+ r_symndx = (unsigned long) -1; -+ switch (name[1]) -+ { -+ case 'A': -+ if (strcmp (name, "*ABS*") == 0) -+ r_symndx = RELOC_SECTION_ABS; -+ break; -+ case 'b': -+ if (strcmp (name, ".bss") == 0) -+ r_symndx = RELOC_SECTION_BSS; -+ break; -+ case 'd': -+ if (strcmp (name, ".data") == 0) -+ r_symndx = RELOC_SECTION_DATA; -+ break; -+ case 'f': -+ if (strcmp (name, ".fini") == 0) -+ r_symndx = RELOC_SECTION_FINI; -+ break; -+ case 'i': -+ if (strcmp (name, ".init") == 0) -+ r_symndx = RELOC_SECTION_INIT; -+ break; -+ case 'l': -+ if (strcmp (name, ".lita") == 0) -+ r_symndx = RELOC_SECTION_LITA; -+ else if (strcmp (name, ".lit8") == 0) -+ r_symndx = RELOC_SECTION_LIT8; -+ else if (strcmp (name, ".lit4") == 0) -+ r_symndx = RELOC_SECTION_LIT4; -+ break; -+ case 'p': -+ if (strcmp (name, ".pdata") == 0) -+ r_symndx = RELOC_SECTION_PDATA; -+ break; -+ case 'r': -+ if (strcmp (name, ".rdata") == 0) -+ r_symndx = RELOC_SECTION_RDATA; -+ else if (strcmp (name, ".rconst") == 0) -+ r_symndx = RELOC_SECTION_RCONST; -+ break; -+ case 's': -+ if (strcmp (name, ".sdata") == 0) -+ r_symndx = RELOC_SECTION_SDATA; -+ else if (strcmp (name, ".sbss") == 0) -+ r_symndx = RELOC_SECTION_SBSS; -+ break; -+ case 't': -+ if (strcmp (name, ".text") == 0) -+ r_symndx = RELOC_SECTION_TEXT; -+ break; -+ case 'x': -+ if (strcmp (name, ".xdata") == 0) -+ r_symndx = RELOC_SECTION_XDATA; -+ break; -+ } -+ -+ if (r_symndx == (unsigned long) -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 == (unsigned long) -1) -+ { -+ /* Caller must give an error. */ -+ r_symndx = 0; -+ } -+ relocation = 0; -+ } -+ -+ /* Write out the new r_symndx value. */ -+ H_PUT_32 (input_bfd, r_symndx, 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 bool -+sw_64_relocate_section (bfd *output_bfd, -+ struct bfd_link_info *info, -+ bfd *input_bfd, -+ asection *input_section, -+ bfd_byte *contents, -+ void * external_relocs) -+{ -+ asection **symndx_to_section, *lita_sec; -+ struct ecoff_link_hash_entry **sym_hashes; -+ bfd_vma gp; -+ bool gp_undefined; -+ bfd_vma stack[RELOC_STACKSIZE]; -+ int tos = 0; -+ struct external_reloc *ext_rel; -+ struct external_reloc *ext_rel_end; -+ bfd_size_type amt; -+ -+ /* 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) -+ { -+ amt = NUM_RELOC_SECTIONS * sizeof (asection *); -+ symndx_to_section = (asection **) bfd_alloc (input_bfd, amt); -+ if (!symndx_to_section) -+ return false; -+ -+ symndx_to_section[RELOC_SECTION_NONE] = NULL; -+ symndx_to_section[RELOC_SECTION_TEXT] = -+ bfd_get_section_by_name (input_bfd, ".text"); -+ symndx_to_section[RELOC_SECTION_RDATA] = -+ bfd_get_section_by_name (input_bfd, ".rdata"); -+ symndx_to_section[RELOC_SECTION_DATA] = -+ bfd_get_section_by_name (input_bfd, ".data"); -+ symndx_to_section[RELOC_SECTION_SDATA] = -+ bfd_get_section_by_name (input_bfd, ".sdata"); -+ symndx_to_section[RELOC_SECTION_SBSS] = -+ bfd_get_section_by_name (input_bfd, ".sbss"); -+ symndx_to_section[RELOC_SECTION_BSS] = -+ bfd_get_section_by_name (input_bfd, ".bss"); -+ symndx_to_section[RELOC_SECTION_INIT] = -+ bfd_get_section_by_name (input_bfd, ".init"); -+ symndx_to_section[RELOC_SECTION_LIT8] = -+ bfd_get_section_by_name (input_bfd, ".lit8"); -+ symndx_to_section[RELOC_SECTION_LIT4] = -+ bfd_get_section_by_name (input_bfd, ".lit4"); -+ symndx_to_section[RELOC_SECTION_XDATA] = -+ bfd_get_section_by_name (input_bfd, ".xdata"); -+ symndx_to_section[RELOC_SECTION_PDATA] = -+ bfd_get_section_by_name (input_bfd, ".pdata"); -+ symndx_to_section[RELOC_SECTION_FINI] = -+ bfd_get_section_by_name (input_bfd, ".fini"); -+ symndx_to_section[RELOC_SECTION_LITA] = -+ bfd_get_section_by_name (input_bfd, ".lita"); -+ symndx_to_section[RELOC_SECTION_ABS] = bfd_abs_section_ptr; -+ symndx_to_section[RELOC_SECTION_RCONST] = -+ bfd_get_section_by_name (input_bfd, ".rconst"); -+ -+ ecoff_data (input_bfd)->symndx_to_section = symndx_to_section; -+ } -+ -+ sym_hashes = ecoff_data (input_bfd)->sym_hashes; -+ -+ /* On the Alpha, the .lita section must be addressable by the global -+ pointer. To support large programs, we need to allow multiple -+ global pointers. This works as long as each input .lita section -+ is <64KB big. This implies that when producing relocatable -+ output, the .lita section is limited to 64KB. . */ -+ -+ lita_sec = symndx_to_section[RELOC_SECTION_LITA]; -+ gp = _bfd_get_gp_value (output_bfd); -+ if (! bfd_link_relocatable (info) && lita_sec != NULL) -+ { -+ struct ecoff_section_tdata *lita_sec_data; -+ -+ /* Make sure we have a section data structure to which we can -+ hang on to the gp value we pick for the section. */ -+ lita_sec_data = ecoff_section_data (input_bfd, lita_sec); -+ if (lita_sec_data == NULL) -+ { -+ amt = sizeof (struct ecoff_section_tdata); -+ lita_sec_data = ((struct ecoff_section_tdata *) -+ bfd_zalloc (input_bfd, amt)); -+ lita_sec->used_by_bfd = lita_sec_data; -+ } -+ -+ if (lita_sec_data->gp != 0) -+ { -+ /* If we already assigned a gp to this section, we better -+ stick with that value. */ -+ gp = lita_sec_data->gp; -+ } -+ else -+ { -+ bfd_vma lita_vma; -+ bfd_size_type lita_size; -+ -+ lita_vma = lita_sec->output_offset + lita_sec->output_section->vma; -+ lita_size = lita_sec->size; -+ -+ if (gp == 0 -+ || lita_vma < gp - 0x8000 -+ || lita_vma + lita_size >= gp + 0x8000) -+ { -+ /* Either gp hasn't been set at all or the current gp -+ cannot address this .lita section. In both cases we -+ reset the gp to point into the "middle" of the -+ current input .lita section. */ -+ if (gp && !ecoff_data (output_bfd)->issued_multiple_gp_warning) -+ { -+ (*info->callbacks->warning) (info, -+ _("using multiple gp values"), -+ (char *) NULL, output_bfd, -+ (asection *) NULL, (bfd_vma) 0); -+ ecoff_data (output_bfd)->issued_multiple_gp_warning = true; -+ } -+ if (lita_vma < gp - 0x8000) -+ gp = lita_vma + lita_size - 0x8000; -+ else -+ gp = lita_vma + 0x8000; -+ -+ } -+ -+ lita_sec_data->gp = gp; -+ } -+ -+ _bfd_set_gp_value (output_bfd, gp); -+ } -+ -+ gp_undefined = (gp == 0); -+ -+ BFD_ASSERT (bfd_header_little_endian (output_bfd)); -+ BFD_ASSERT (bfd_header_little_endian (input_bfd)); -+ -+ ext_rel = (struct external_reloc *) external_relocs; -+ ext_rel_end = ext_rel + input_section->reloc_count; -+ for (; ext_rel < ext_rel_end; ext_rel++) -+ { -+ bfd_vma r_vaddr; -+ unsigned long r_symndx; -+ int r_type; -+ int r_extern; -+ int r_offset; -+ int r_size; -+ bool relocatep; -+ bool adjust_addrp; -+ bool gp_usedp; -+ bfd_vma addend; -+ -+ r_vaddr = H_GET_64 (input_bfd, ext_rel->r_vaddr); -+ r_symndx = H_GET_32 (input_bfd, 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) -+ { -+ case SW_64_R_GPRELHIGH: -+ _bfd_error_handler (_("%pB: %s unsupported"), -+ input_bfd, "SW_64_R_GPRELHIGH"); -+ bfd_set_error (bfd_error_bad_value); -+ continue; -+ -+ case SW_64_R_GPRELLOW: -+ _bfd_error_handler (_("%pB: %s unsupported"), -+ input_bfd, "SW_64_R_GPRELLOW"); -+ bfd_set_error (bfd_error_bad_value); -+ continue; -+ -+ default: -+ /* xgettext:c-format */ -+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"), -+ input_bfd, (int) r_type); -+ bfd_set_error (bfd_error_bad_value); -+ continue; -+ -+ case SW_64_R_IGNORE: -+ /* This reloc appears after a GPDISP reloc. On earlier -+ versions of OSF/1, It marked the position of the second -+ instruction to be altered by the GPDISP reloc, but it is -+ not otherwise used for anything. For some reason, the -+ address of the relocation does not appear to include the -+ section VMA, unlike the other relocation types. */ -+ if (bfd_link_relocatable (info)) -+ H_PUT_64 (input_bfd, input_section->output_offset + r_vaddr, -+ ext_rel->r_vaddr); -+ adjust_addrp = false; -+ break; -+ -+ case SW_64_R_REFLONG: -+ case SW_64_R_REFQUAD: -+ case SW_64_R_HINT: -+ relocatep = true; -+ break; -+ -+ case SW_64_R_BRADDR: -+ case SW_64_R_SREL16: -+ case SW_64_R_SREL32: -+ case SW_64_R_SREL64: -+ if (r_extern) -+ addend += - (r_vaddr + 4); -+ relocatep = true; -+ break; -+ -+ case SW_64_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 SW_64_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 SW_64_R_LITUSE: -+ /* See SW_64_R_LITERAL above for the uses of this reloc. It -+ does not cause anything to happen, itself. */ -+ break; -+ -+ case SW_64_R_GPDISP: -+ /* This marks the ldah of an ldah/lda pair which loads the -+ gp register with the difference of the gp value and the -+ current location. The second of the pair is r_symndx -+ bytes ahead. It used to be marked with an SW_64_R_IGNORE -+ reloc, but OSF/1 3.2 no longer does that. */ -+ { -+ unsigned long insn1, insn2; -+ -+ /* Get the two instructions. */ -+ insn1 = bfd_get_32 (input_bfd, -+ contents + r_vaddr - input_section->vma); -+ insn2 = bfd_get_32 (input_bfd, -+ (contents -+ + r_vaddr -+ - input_section->vma -+ + r_symndx)); -+ -+ BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ -+ BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ -+ -+ /* Get the existing addend. We must account for the sign -+ extension done by lda and ldah. */ -+ addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); -+ if (insn1 & 0x8000) -+ { -+ /* This is addend -= 0x100000000 without causing an -+ integer overflow on a 32 bit host. */ -+ addend -= 0x80000000; -+ addend -= 0x80000000; -+ } -+ if (insn2 & 0x8000) -+ addend -= 0x10000; -+ -+ /* The existing addend includes the difference between the -+ gp of the input BFD and the address in the input BFD. -+ We want to change this to the difference between the -+ final GP and the final address. */ -+ addend += (gp -+ - ecoff_data (input_bfd)->gp -+ + input_section->vma -+ - (input_section->output_section->vma -+ + input_section->output_offset)); -+ -+ /* Change the instructions, accounting for the sign -+ extension, and write them out. */ -+ if (addend & 0x8000) -+ addend += 0x10000; -+ insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff); -+ insn2 = (insn2 & 0xffff0000) | (addend & 0xffff); -+ -+ bfd_put_32 (input_bfd, (bfd_vma) insn1, -+ contents + r_vaddr - input_section->vma); -+ bfd_put_32 (input_bfd, (bfd_vma) insn2, -+ contents + r_vaddr - input_section->vma + r_symndx); -+ -+ gp_usedp = true; -+ } -+ break; -+ -+ case SW_64_R_OP_PUSH: -+ case SW_64_R_OP_PSUB: -+ case SW_64_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 (! bfd_link_relocatable (info)) -+ { -+ 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. */ -+ (*info->callbacks->undefined_symbol) -+ (info, h->root.root.string, input_bfd, -+ input_section, (bfd_vma) 0, true); -+ 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. */ -+ (*info->callbacks->unattached_reloc) -+ (info, h->root.root.string, -+ input_bfd, input_section, (bfd_vma) 0); -+ } -+ -+ addend = sw_64_convert_external_reloc (output_bfd, info, -+ input_bfd, -+ ext_rel, h); -+ } -+ } -+ -+ addend += r_vaddr; -+ -+ if (bfd_link_relocatable (info)) -+ { -+ /* Adjust r_vaddr by the addend. */ -+ H_PUT_64 (input_bfd, addend, ext_rel->r_vaddr); -+ } -+ else -+ { -+ switch (r_type) -+ { -+ case SW_64_R_OP_PUSH: -+ if (tos >= RELOC_STACKSIZE) -+ abort (); -+ stack[tos++] = addend; -+ break; -+ -+ case SW_64_R_OP_PSUB: -+ if (tos == 0) -+ abort (); -+ stack[tos - 1] -= addend; -+ break; -+ -+ case SW_64_R_OP_PRSHIFT: -+ if (tos == 0) -+ abort (); -+ stack[tos - 1] >>= addend; -+ break; -+ } -+ } -+ -+ adjust_addrp = false; -+ break; -+ -+ case SW_64_R_OP_STORE: -+ /* Store a value from the reloc stack into a bitfield. If -+ we are generating relocatable output, all we do is -+ adjust the address of the reloc. */ -+ if (! bfd_link_relocatable (info)) -+ { -+ 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 SW_64_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 = &sw_64_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 (bfd_link_relocatable (info)) -+ { -+ /* We are generating relocatable 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. */ -+ (*info->callbacks->unattached_reloc) -+ (info, h->root.root.string, input_bfd, -+ input_section, r_vaddr - input_section->vma); -+ } -+ -+ relocation = sw_64_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 -+ { -+ (*info->callbacks->undefined_symbol) -+ (info, h->root.root.string, input_bfd, input_section, -+ r_vaddr - input_section->vma, true); -+ 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 (symndx_to_section[r_symndx]); -+ (*info->callbacks->reloc_overflow) -+ (info, NULL, name, sw_64_howto_table[r_type].name, -+ (bfd_vma) 0, input_bfd, input_section, -+ r_vaddr - input_section->vma); -+ } -+ break; -+ } -+ } -+ } -+ -+ if (bfd_link_relocatable (info) && adjust_addrp) -+ { -+ /* Change the address of the relocation. */ -+ H_PUT_64 (input_bfd, -+ (input_section->output_section->vma -+ + input_section->output_offset -+ - input_section->vma -+ + r_vaddr), -+ ext_rel->r_vaddr); -+ } -+ -+ if (gp_usedp && gp_undefined) -+ { -+ (*info->callbacks->reloc_dangerous) -+ (info, _("GP relative relocation used when GP not defined"), -+ input_bfd, input_section, r_vaddr - input_section->vma); -+ /* Only give the error once per link. */ -+ gp = 4; -+ _bfd_set_gp_value (output_bfd, gp); -+ gp_undefined = false; -+ } -+ } -+ -+ if (tos != 0) -+ abort (); -+ -+ return true; -+} -+ -+/* Do final adjustments to the filehdr and the aouthdr. This routine -+ sets the dynamic bits in the file header. */ -+ -+static bool -+sw_64_adjust_headers (bfd *abfd, -+ struct internal_filehdr *fhdr, -+ struct internal_aouthdr *ahdr ATTRIBUTE_UNUSED) -+{ -+ if ((abfd->flags & (DYNAMIC | EXEC_P)) == (DYNAMIC | EXEC_P)) -+ fhdr->f_flags |= F_SW_64_CALL_SHARED; -+ else if ((abfd->flags & DYNAMIC) != 0) -+ fhdr->f_flags |= F_SW_64_SHARABLE; -+ return true; -+} -+ -+/* Archive handling. In OSF/1 (or Digital Unix) v3.2, Digital -+ introduced archive packing, in which the elements in an archive are -+ optionally compressed using a simple dictionary scheme. We know -+ how to read such archives, but we don't write them. */ -+ -+#define sw_64_ecoff_slurp_armap _bfd_ecoff_slurp_armap -+#define sw_64_ecoff_slurp_extended_name_table \ -+ _bfd_ecoff_slurp_extended_name_table -+#define sw_64_ecoff_construct_extended_name_table \ -+ _bfd_ecoff_construct_extended_name_table -+#define sw_64_ecoff_truncate_arname _bfd_ecoff_truncate_arname -+#define sw_64_ecoff_write_armap _bfd_ecoff_write_armap -+#define sw_64_ecoff_write_ar_hdr _bfd_generic_write_ar_hdr -+#define sw_64_ecoff_generic_stat_arch_elt _bfd_ecoff_generic_stat_arch_elt -+#define sw_64_ecoff_update_armap_timestamp _bfd_ecoff_update_armap_timestamp -+ -+/* A compressed file uses this instead of ARFMAG. */ -+ -+#define ARFZMAG "Z\012" -+ -+/* Read an archive header. This is like the standard routine, but it -+ also accepts ARFZMAG. */ -+ -+static void * -+sw_64_ecoff_read_ar_hdr (bfd *abfd) -+{ -+ struct areltdata *ret; -+ struct ar_hdr *h; -+ -+ ret = (struct areltdata *) _bfd_generic_read_ar_hdr_mag (abfd, ARFZMAG); -+ if (ret == NULL) -+ return NULL; -+ -+ h = (struct ar_hdr *) ret->arch_header; -+ if (strncmp (h->ar_fmag, ARFZMAG, 2) == 0) -+ { -+ bfd_byte ab[8]; -+ -+ /* This is a compressed file. We must set the size correctly. -+ The size is the eight bytes after the dummy file header. */ -+ if (bfd_seek (abfd, (file_ptr) FILHSZ, SEEK_CUR) != 0 -+ || bfd_bread (ab, (bfd_size_type) 8, abfd) != 8 -+ || bfd_seek (abfd, (file_ptr) (- (FILHSZ + 8)), SEEK_CUR) != 0) -+ { -+ free (ret); -+ return NULL; -+ } -+ -+ ret->parsed_size = H_GET_64 (abfd, ab); -+ } -+ -+ return ret; -+} -+ -+/* Get an archive element at a specified file position. This is where -+ we uncompress the archive element if necessary. */ -+ -+static bfd * -+sw_64_ecoff_get_elt_at_filepos (bfd *archive, file_ptr filepos) -+{ -+ bfd *nbfd = NULL; -+ struct areltdata *tdata; -+ struct ar_hdr *hdr; -+ bfd_byte ab[8]; -+ bfd_size_type size; -+ bfd_byte *buf, *p; -+ struct bfd_in_memory *bim; -+ ufile_ptr filesize; -+ -+ buf = NULL; -+ nbfd = _bfd_get_elt_at_filepos (archive, filepos); -+ if (nbfd == NULL) -+ goto error_return; -+ -+ if ((nbfd->flags & BFD_IN_MEMORY) != 0) -+ { -+ /* We have already expanded this BFD. */ -+ return nbfd; -+ } -+ -+ tdata = (struct areltdata *) nbfd->arelt_data; -+ hdr = (struct ar_hdr *) tdata->arch_header; -+ if (strncmp (hdr->ar_fmag, ARFZMAG, 2) != 0) -+ return nbfd; -+ -+ /* We must uncompress this element. We do this by copying it into a -+ memory buffer, and making bfd_bread and bfd_seek use that buffer. -+ This can use a lot of memory, but it's simpler than getting a -+ temporary file, making that work with the file descriptor caching -+ code, and making sure that it is deleted at all appropriate -+ times. It can be changed if it ever becomes important. */ -+ -+ /* The compressed file starts with a dummy ECOFF file header. */ -+ if (bfd_seek (nbfd, (file_ptr) FILHSZ, SEEK_SET) != 0) -+ goto error_return; -+ -+ /* The next eight bytes are the real file size. */ -+ if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8) -+ goto error_return; -+ size = H_GET_64 (nbfd, ab); -+ -+ /* The decompression algorithm will at most expand by eight times. */ -+ filesize = bfd_get_file_size (archive); -+ if (filesize != 0 && size / 8 > filesize) -+ { -+ bfd_set_error (bfd_error_malformed_archive); -+ goto error_return; -+ } -+ -+ if (size != 0) -+ { -+ bfd_size_type left; -+ bfd_byte dict[4096]; -+ unsigned int h; -+ bfd_byte b; -+ -+ buf = (bfd_byte *) bfd_malloc (size); -+ if (buf == NULL) -+ goto error_return; -+ p = buf; -+ -+ left = size; -+ -+ /* I don't know what the next eight bytes are for. */ -+ if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8) -+ goto error_return; -+ -+ /* This is the uncompression algorithm. It's a simple -+ dictionary based scheme in which each character is predicted -+ by a hash of the previous three characters. A control byte -+ indicates whether the character is predicted or whether it -+ appears in the input stream; each control byte manages the -+ next eight bytes in the output stream. */ -+ memset (dict, 0, sizeof dict); -+ h = 0; -+ while (bfd_bread (&b, (bfd_size_type) 1, nbfd) == 1) -+ { -+ unsigned int i; -+ -+ for (i = 0; i < 8; i++, b >>= 1) -+ { -+ bfd_byte n; -+ -+ if ((b & 1) == 0) -+ n = dict[h]; -+ else -+ { -+ if (bfd_bread (&n, 1, nbfd) != 1) -+ goto error_return; -+ dict[h] = n; -+ } -+ -+ *p++ = n; -+ -+ --left; -+ if (left == 0) -+ break; -+ -+ h <<= 4; -+ h ^= n; -+ h &= sizeof dict - 1; -+ } -+ -+ if (left == 0) -+ break; -+ } -+ } -+ -+ /* Now the uncompressed file contents are in buf. */ -+ bim = ((struct bfd_in_memory *) -+ bfd_malloc ((bfd_size_type) sizeof (struct bfd_in_memory))); -+ if (bim == NULL) -+ goto error_return; -+ bim->size = size; -+ bim->buffer = buf; -+ -+ nbfd->mtime_set = true; -+ nbfd->mtime = strtol (hdr->ar_date, (char **) NULL, 10); -+ -+ nbfd->flags |= BFD_IN_MEMORY; -+ nbfd->iostream = bim; -+ nbfd->iovec = &_bfd_memory_iovec; -+ nbfd->origin = 0; -+ BFD_ASSERT (! nbfd->cacheable); -+ -+ return nbfd; -+ -+ error_return: -+ free (buf); -+ if (nbfd != NULL) -+ bfd_close (nbfd); -+ return NULL; -+} -+ -+/* Open the next archived file. */ -+ -+static bfd * -+sw_64_ecoff_openr_next_archived_file (bfd *archive, bfd *last_file) -+{ -+ ufile_ptr filestart; -+ -+ if (last_file == NULL) -+ filestart = bfd_ardata (archive)->first_file_filepos; -+ else -+ { -+ struct areltdata *t; -+ struct ar_hdr *h; -+ bfd_size_type size; -+ -+ /* We can't use arelt_size here, because that uses parsed_size, -+ which is the uncompressed size. We need the compressed size. */ -+ t = (struct areltdata *) last_file->arelt_data; -+ h = (struct ar_hdr *) t->arch_header; -+ size = strtol (h->ar_size, (char **) NULL, 10); -+ -+ /* Pad to an even boundary... -+ Note that last_file->origin can be odd in the case of -+ BSD-4.4-style element with a long odd size. */ -+ filestart = last_file->proxy_origin + size; -+ filestart += filestart % 2; -+ if (filestart < last_file->proxy_origin) -+ { -+ /* Prevent looping. See PR19256. */ -+ bfd_set_error (bfd_error_malformed_archive); -+ return NULL; -+ } -+ } -+ -+ return sw_64_ecoff_get_elt_at_filepos (archive, filestart); -+} -+ -+/* Open the archive file given an index into the armap. */ -+ -+static bfd * -+sw_64_ecoff_get_elt_at_index (bfd *abfd, symindex sym_index) -+{ -+ carsym *entry; -+ -+ entry = bfd_ardata (abfd)->symdefs + sym_index; -+ return sw_64_ecoff_get_elt_at_filepos (abfd, entry->file_offset); -+} -+ -+static void -+sw_64_ecoff_swap_coff_aux_in (bfd *abfd ATTRIBUTE_UNUSED, -+ void *ext1 ATTRIBUTE_UNUSED, -+ int type ATTRIBUTE_UNUSED, -+ int in_class ATTRIBUTE_UNUSED, -+ int indx ATTRIBUTE_UNUSED, -+ int numaux ATTRIBUTE_UNUSED, -+ void *in1 ATTRIBUTE_UNUSED) -+{ -+} -+ -+static void -+sw_64_ecoff_swap_coff_sym_in (bfd *abfd ATTRIBUTE_UNUSED, -+ void *ext1 ATTRIBUTE_UNUSED, -+ void *in1 ATTRIBUTE_UNUSED) -+{ -+} -+ -+static void -+sw_64_ecoff_swap_coff_lineno_in (bfd *abfd ATTRIBUTE_UNUSED, -+ void *ext1 ATTRIBUTE_UNUSED, -+ void *in1 ATTRIBUTE_UNUSED) -+{ -+} -+ -+static unsigned int -+sw_64_ecoff_swap_coff_aux_out (bfd *abfd ATTRIBUTE_UNUSED, -+ void *inp ATTRIBUTE_UNUSED, -+ int type ATTRIBUTE_UNUSED, -+ int in_class ATTRIBUTE_UNUSED, -+ int indx ATTRIBUTE_UNUSED, -+ int numaux ATTRIBUTE_UNUSED, -+ void *extp ATTRIBUTE_UNUSED) -+{ -+ return 0; -+} -+ -+static unsigned int -+sw_64_ecoff_swap_coff_sym_out (bfd *abfd ATTRIBUTE_UNUSED, -+ void *inp ATTRIBUTE_UNUSED, -+ void *extp ATTRIBUTE_UNUSED) -+{ -+ return 0; -+} -+ -+static unsigned int -+sw_64_ecoff_swap_coff_lineno_out (bfd *abfd ATTRIBUTE_UNUSED, -+ void *inp ATTRIBUTE_UNUSED, -+ void *extp ATTRIBUTE_UNUSED) -+{ -+ return 0; -+} -+ -+static unsigned int -+sw_64_ecoff_swap_coff_reloc_out (bfd *abfd ATTRIBUTE_UNUSED, -+ void *inp ATTRIBUTE_UNUSED, -+ void *extp ATTRIBUTE_UNUSED) -+{ -+ return 0; -+} -+ -+/* This is the ECOFF backend structure. The backend field of the -+ target vector points to this. */ -+ -+static const struct ecoff_backend_data sw_64_ecoff_backend_data = -+{ -+ /* COFF backend structure. */ -+ { -+ sw_64_ecoff_swap_coff_aux_in, sw_64_ecoff_swap_coff_sym_in, -+ sw_64_ecoff_swap_coff_lineno_in, sw_64_ecoff_swap_coff_aux_out, -+ sw_64_ecoff_swap_coff_sym_out, sw_64_ecoff_swap_coff_lineno_out, -+ sw_64_ecoff_swap_coff_reloc_out, -+ sw_64_ecoff_swap_filehdr_out, sw_64_ecoff_swap_aouthdr_out, -+ sw_64_ecoff_swap_scnhdr_out, -+ FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, true, -+ ECOFF_NO_LONG_SECTION_NAMES, 4, false, 2, 32768, -+ sw_64_ecoff_swap_filehdr_in, sw_64_ecoff_swap_aouthdr_in, -+ sw_64_ecoff_swap_scnhdr_in, NULL, -+ sw_64_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, -+ sw_64_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags, -+ _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table, -+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL -+ }, -+ /* Supported architecture. */ -+ bfd_arch_sw_64, -+ /* 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. */ -+ &sw_64_howto_table[SW_64_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. */ -+ sw_64_ecoff_swap_reloc_in, -+ sw_64_ecoff_swap_reloc_out, -+ /* Backend reloc tweaking. */ -+ sw_64_adjust_reloc_in, -+ sw_64_adjust_reloc_out, -+ /* Relocate section contents while linking. */ -+ sw_64_relocate_section, -+ /* Do final adjustments to filehdr and aouthdr. */ -+ sw_64_adjust_headers, -+ /* Read an element from an archive at a given file position. */ -+ sw_64_ecoff_get_elt_at_filepos -+}; -+ -+/* Looking up a reloc type is Alpha specific. */ -+#define _bfd_ecoff_bfd_reloc_type_lookup sw_64_bfd_reloc_type_lookup -+#define _bfd_ecoff_bfd_reloc_name_lookup \ -+ sw_64_bfd_reloc_name_lookup -+ -+/* So is getting relocated section contents. */ -+#define _bfd_ecoff_bfd_get_relocated_section_contents \ -+ sw_64_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 -+ -+/* Input section flag lookup is generic. */ -+#define _bfd_ecoff_bfd_lookup_section_flags bfd_generic_lookup_section_flags -+ -+/* Relaxing sections is generic. */ -+#define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section -+#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections -+#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections -+#define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section -+#define _bfd_ecoff_bfd_group_name bfd_generic_group_name -+#define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group -+#define _bfd_ecoff_section_already_linked \ -+ _bfd_coff_section_already_linked -+#define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol -+#define _bfd_ecoff_bfd_link_hide_symbol _bfd_generic_link_hide_symbol -+#define _bfd_ecoff_bfd_define_start_stop bfd_generic_define_start_stop -+#define _bfd_ecoff_bfd_link_check_relocs _bfd_generic_link_check_relocs -+ -+/* Installing internal relocations in a section is also generic. */ -+#define _bfd_ecoff_set_reloc _bfd_generic_set_reloc -+ -+const bfd_target sw_64_ecoff_le_vec = -+{ -+ "ecoff-littlesw_64", /* name */ -+ bfd_target_ecoff_flavour, -+ BFD_ENDIAN_LITTLE, /* data byte order is little */ -+ BFD_ENDIAN_LITTLE, /* header byte order is little */ -+ -+ (HAS_RELOC | EXEC_P /* object flags */ -+ | HAS_LINENO | HAS_DEBUG -+ | HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), -+ -+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE -+ | SEC_DATA | SEC_SMALL_DATA), -+ 0, /* leading underscore */ -+ ' ', /* ar_pad_char */ -+ 15, /* ar_max_namelen */ -+ 0, /* match priority. */ -+ TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ -+ 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_check_format */ -+ _bfd_dummy_target, -+ sw_64_ecoff_object_p, -+ bfd_generic_archive_p, -+ _bfd_dummy_target -+ }, -+ { /* bfd_set_format */ -+ _bfd_bool_bfd_false_error, -+ _bfd_ecoff_mkobject, -+ _bfd_generic_mkarchive, -+ _bfd_bool_bfd_false_error -+ }, -+ { /* bfd_write_contents */ -+ _bfd_bool_bfd_false_error, -+ _bfd_ecoff_write_object_contents, -+ _bfd_write_archive_contents, -+ _bfd_bool_bfd_false_error -+ }, -+ -+ BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), -+ BFD_JUMP_TABLE_COPY (_bfd_ecoff), -+ BFD_JUMP_TABLE_CORE (_bfd_nocore), -+ BFD_JUMP_TABLE_ARCHIVE (sw_64_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), -+ -+ NULL, -+ -+ &sw_64_ecoff_backend_data -+}; -diff --git a/bfd/cpu-sw_64.c b/bfd/cpu-sw_64.c -new file mode 100644 -index 00000000..05d82e7a ---- /dev/null -+++ b/bfd/cpu-sw_64.c -@@ -0,0 +1,59 @@ -+/* BFD support for the Sw_64 architecture. -+ Copyright (C) 1992-2018 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 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+ MA 02110-1301, USA. */ -+ -+#include "sysdep.h" -+#include "bfd.h" -+#include "libbfd.h" -+ -+#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \ -+ { \ -+ BITS_WORD, /* Bits in a word. */ \ -+ BITS_ADDR, /* Bits in an address. */ \ -+ 8, /* Bits in a byte. */ \ -+ bfd_arch_sw_64, \ -+ NUMBER, \ -+ "sw_64", \ -+ PRINT, \ -+ 3, /* Section alignment power. */ \ -+ DEFAULT, \ -+ bfd_default_compatible, \ -+ bfd_default_scan, \ -+ bfd_arch_default_fill, \ -+ NEXT, \ -+ 0 /* Maximum offset of a reloc from the start of an insn. */ \ -+ } -+ -+enum -+{ -+ I_sw6a, -+ I_sw6b -+}; -+ -+#define NN(index) (&arch_info_struct[(index) + 1]) -+static const bfd_arch_info_type arch_info_struct[] = -+{ -+ N (64, 64, bfd_mach_sw_64_sw6a, "sw_64:4", false, NN(I_sw6a)), -+ N (64, 64, bfd_mach_sw_64_sw6a, "sw_64:4", false, NN(I_sw6b)), -+ /* The next element of the last one should be NULL. */ -+ N (64, 64, bfd_mach_sw_64_sw6b, "sw_64:8", false, NULL), -+}; -+ -+const bfd_arch_info_type bfd_sw_64_arch = -+ N (64, 64, 0, "sw_64", false, &arch_info_struct[0]); -diff --git a/bfd/elf64-sw_64.c b/bfd/elf64-sw_64.c -new file mode 100644 -index 00000000..2a0c8e1e ---- /dev/null -+++ b/bfd/elf64-sw_64.c -@@ -0,0 +1,5718 @@ -+/* Sw_64 specific support for 64-bit ELF -+ Copyright (C) 1996-2021 Free Software Foundation, Inc. -+ Contributed by Richard Henderson . -+ -+ This file is part of BFD, the Binary File Descriptor library. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+ MA 02110-1301, USA. */ -+ -+ -+/* We need a published ABI spec for this. Until one comes out, don't -+ assume this'll remain unchanged forever. */ -+ -+#include "sysdep.h" -+#include "bfd.h" -+#include "libbfd.h" -+#include "elf-bfd.h" -+#include "ecoff-bfd.h" -+ -+#include "elf/sw_64.h" -+ -+#define SW_64ECOFF -+ -+#define NO_COFF_RELOCS -+#define NO_COFF_SYMBOLS -+#define NO_COFF_LINENOS -+ -+/* Get the ECOFF swapping routines. Needed for the debug information. */ -+#include "coff/internal.h" -+#include "coff/sym.h" -+#include "coff/symconst.h" -+#include "coff/ecoff.h" -+#include "coff/sw_64.h" -+#include "aout/ar.h" -+#include "libcoff.h" -+#include "libecoff.h" -+#define ECOFF_64 -+#include "ecoffswap.h" -+ -+ -+/* Instruction data for plt generation and relaxation. */ -+ -+#define OP_LDI 0x3eU -+#define OP_LDIH 0x3fU -+#define OP_LDL 0x23U -+#define OP_BR 0x04U -+#define OP_BSR 0x05U -+ -+#define INSN_LDI (OP_LDI << 26) -+#define INSN_LDIH (OP_LDIH << 26) -+#define INSN_LDL (OP_LDL << 26) -+#define INSN_BR (OP_BR << 26) -+ -+#define INSN_ADDL 0x40000100 -+#define INSN_RDUNIQ 0x0000009e -+#define INSN_SUBL 0x40000120 -+#define INSN_S4SUBL 0x40000160 -+#define INSN_UNOP 0x43ff075f -+ -+#define INSN_JSR 0x04000000 -+#define INSN_JMP 0x0c000000 -+#define INSN_JSR_MASK 0xfc000000 -+#define INSN_LDL_MASK 0xfc000000 -+ -+#define INSN_A(I,A) (I | ((unsigned) A << 21)) -+#define INSN_AB(I,A,B) (INSN_A (I, A) | (B << 16)) -+#define INSN_ABC(I,A,B,C) (INSN_A (I, A) | (B << 16) | C) -+#define INSN_ABO(I,A,B,O) (INSN_A (I, A) | (B << 16) | ((O) & 0xffff)) -+#define INSN_AD(I,A,D) (INSN_A (I, A) | (((D) >> 2) & 0x1fffff)) -+ -+/* PLT/GOT Stuff */ -+ -+/* Set by ld emulation. Putting this into the link_info or hash structure -+ is simply working too hard. */ -+#ifdef USE_SECUREPLT -+bool elf64_sw_64_use_secureplt = true; -+#else -+bool elf64_sw_64_use_secureplt = false; -+#endif -+ -+#define OLD_PLT_HEADER_SIZE 32 -+#define OLD_PLT_ENTRY_SIZE 12 -+#define NEW_PLT_HEADER_SIZE 36 -+#define NEW_PLT_ENTRY_SIZE 4 -+ -+#define PLT_HEADER_SIZE \ -+ (elf64_sw_64_use_secureplt ? NEW_PLT_HEADER_SIZE : OLD_PLT_HEADER_SIZE) -+#define PLT_ENTRY_SIZE \ -+ (elf64_sw_64_use_secureplt ? NEW_PLT_ENTRY_SIZE : OLD_PLT_ENTRY_SIZE) -+ -+#define MAX_GOT_SIZE_NEW (1024*1024*2048-1) -+ -+#define MAX_GOT_SIZE (64*1024) -+ -+#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so" -+ -+ -+/* Used to implement multiple .got subsections. */ -+struct sw_64_elf_got_entry -+{ -+ struct sw_64_elf_got_entry *next; -+ -+ /* Which .got subsection? */ -+ bfd *gotobj; -+ -+ /* The addend in effect for this entry. */ -+ bfd_vma addend; -+ -+ /* The .got offset for this entry. */ -+ int got_offset; -+ -+ /* The .plt offset for this entry. */ -+ int plt_offset; -+ -+ /* How many references to this entry? */ -+ int use_count; -+ -+ /* The relocation type of this entry. */ -+ unsigned char reloc_type; -+ -+ /* How a LITERAL is used. */ -+ unsigned char flags; -+ -+ /* Have we initialized the dynamic relocation for this entry? */ -+ unsigned char reloc_done; -+ -+ /* Have we adjusted this entry for SEC_MERGE? */ -+ unsigned char reloc_xlated; -+}; -+ -+struct sw_64_elf_reloc_entry -+{ -+ struct sw_64_elf_reloc_entry *next; -+ -+ /* Which .reloc section? */ -+ asection *srel; -+ -+ /* Which section this relocation is against? */ -+ asection *sec; -+ -+ /* How many did we find? */ -+ unsigned long count; -+ -+ /* What kind of relocation? */ -+ unsigned int rtype; -+}; -+ -+struct sw_64_elf_link_hash_entry -+{ -+ struct elf_link_hash_entry root; -+ -+ /* External symbol information. */ -+ EXTR esym; -+ -+ /* Cumulative flags for all the .got entries. */ -+ int flags; -+ -+ /* Contexts in which a literal was referenced. */ -+#define SW_64_ELF_LINK_HASH_LU_ADDR 0x01 -+#define SW_64_ELF_LINK_HASH_LU_MEM 0x02 -+#define SW_64_ELF_LINK_HASH_LU_BYTE 0x04 -+#define SW_64_ELF_LINK_HASH_LU_JSR 0x08 -+#define SW_64_ELF_LINK_HASH_LU_TLSGD 0x10 -+#define SW_64_ELF_LINK_HASH_LU_TLSLDM 0x20 -+#define SW_64_ELF_LINK_HASH_LU_JSRDIRECT 0x40 -+#define SW_64_ELF_LINK_HASH_LU_PLT 0x38 -+#define SW_64_ELF_LINK_HASH_TLS_IE 0x80 -+ -+ /* Used to implement multiple .got subsections. */ -+ struct sw_64_elf_got_entry *got_entries; -+ -+ /* Used to count non-got, non-plt relocations for delayed sizing -+ of relocation sections. */ -+ struct sw_64_elf_reloc_entry *reloc_entries; -+}; -+ -+/* Sw_64 ELF linker hash table. */ -+ -+struct sw_64_elf_link_hash_table -+{ -+ struct elf_link_hash_table root; -+ -+ /* The head of a list of .got subsections linked through -+ sw_64_elf_tdata(abfd)->got_link_next. */ -+ bfd *got_list; -+ -+ /* The most recent relax pass that we've seen. The GOTs -+ should be regenerated if this doesn't match. */ -+ int relax_trip; -+}; -+ -+/* Look up an entry in a Sw_64 ELF linker hash table. */ -+ -+#define sw_64_elf_link_hash_lookup(table, string, create, copy, follow) \ -+ ((struct sw_64_elf_link_hash_entry *) \ -+ elf_link_hash_lookup (&(table)->root, (string), (create), \ -+ (copy), (follow))) -+ -+/* Traverse a Sw_64 ELF linker hash table. */ -+ -+#define sw_64_elf_link_hash_traverse(table, func, info) \ -+ (elf_link_hash_traverse \ -+ (&(table)->root, \ -+ (bool (*) (struct elf_link_hash_entry *, void *)) (func), \ -+ (info))) -+ -+/* Get the Sw_64 ELF linker hash table from a link_info structure. */ -+ -+#define sw_64_elf_hash_table(p) \ -+ ((is_elf_hash_table ((p)->hash) \ -+ && elf_hash_table_id (elf_hash_table (p)) == SW_64_ELF_DATA) \ -+ ? (struct sw_64_elf_link_hash_table *) (p)->hash : NULL) -+ -+/* Get the object's symbols as our own entry type. */ -+ -+#define sw_64_elf_sym_hashes(abfd) \ -+ ((struct sw_64_elf_link_hash_entry **)elf_sym_hashes(abfd)) -+ -+/* Should we do dynamic things to this symbol? This differs from the -+ generic version in that we never need to consider function pointer -+ equality wrt PLT entries -- we don't create a PLT entry if a symbol's -+ address is ever taken. */ -+ -+ static inline bool -+sw_64_elf_dynamic_symbol_p (struct elf_link_hash_entry *h, -+ struct bfd_link_info *info) -+{ -+ return _bfd_elf_dynamic_symbol_p (h, info, 0); -+} -+ -+/* Create an entry in a Sw_64 ELF linker hash table. */ -+ -+ static struct bfd_hash_entry * -+elf64_sw_64_link_hash_newfunc (struct bfd_hash_entry *entry, -+ struct bfd_hash_table *table, -+ const char *string) -+{ -+ struct sw_64_elf_link_hash_entry *ret = -+ (struct sw_64_elf_link_hash_entry *) entry; -+ -+ /* Allocate the structure if it has not already been allocated by a -+ subclass. */ -+ if (ret == (struct sw_64_elf_link_hash_entry *) NULL) -+ ret = ((struct sw_64_elf_link_hash_entry *) -+ bfd_hash_allocate (table, -+ sizeof (struct sw_64_elf_link_hash_entry))); -+ if (ret == (struct sw_64_elf_link_hash_entry *) NULL) -+ return (struct bfd_hash_entry *) ret; -+ -+ /* Call the allocation method of the superclass. */ -+ ret = ((struct sw_64_elf_link_hash_entry *) -+ _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, -+ table, string)); -+ if (ret != (struct sw_64_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; -+ ret->flags = 0; -+ ret->got_entries = NULL; -+ ret->reloc_entries = NULL; -+ } -+ -+ return (struct bfd_hash_entry *) ret; -+} -+ -+/* Create a Sw_64 ELF linker hash table. */ -+ -+ static struct bfd_link_hash_table * -+elf64_sw_64_bfd_link_hash_table_create (bfd *abfd) -+{ -+ struct sw_64_elf_link_hash_table *ret; -+ size_t amt = sizeof (struct sw_64_elf_link_hash_table); -+ -+ ret = (struct sw_64_elf_link_hash_table *) bfd_zmalloc (amt); -+ if (ret == (struct sw_64_elf_link_hash_table *) NULL) -+ return NULL; -+ -+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, -+ elf64_sw_64_link_hash_newfunc, -+ sizeof (struct sw_64_elf_link_hash_entry), -+ SW_64_ELF_DATA)) -+ { -+ free (ret); -+ return NULL; -+ } -+ -+ return &ret->root.root; -+} -+ -+/* Sw_64 ELF follows MIPS ELF in using a special find_nearest_line -+ routine in order to handle the ECOFF debugging information. */ -+ -+struct sw_64_elf_find_line -+{ -+ struct ecoff_debug_info d; -+ struct ecoff_find_line i; -+}; -+ -+/* We have some private fields hanging off of the elf_tdata structure. */ -+ -+struct sw_64_elf_obj_tdata -+{ -+ struct elf_obj_tdata root; -+ -+ /* For every input file, these are the got entries for that object's -+ local symbols. */ -+ struct sw_64_elf_got_entry ** local_got_entries; -+ -+ /* For every input file, this is the object that owns the got that -+ this input file uses. */ -+ bfd *gotobj; -+ -+ /* For every got, this is a linked list through the objects using this got */ -+ bfd *in_got_link_next; -+ -+ /* For every got, this is a link to the next got subsegment. */ -+ bfd *got_link_next; -+ -+ /* For every got, this is the section. */ -+ asection *got; -+ -+ /* For every got, this is it's total number of words. */ -+ int total_got_size; -+ -+ /* For every got, this is the sum of the number of words required -+ to hold all of the member object's local got. */ -+ int local_got_size; -+ -+ /* Used by elf64_sw_64_find_nearest_line entry point. */ -+ struct sw_64_elf_find_line *find_line_info; -+ -+}; -+ -+#define sw_64_elf_tdata(abfd) \ -+ ((struct sw_64_elf_obj_tdata *) (abfd)->tdata.any) -+ -+#define is_sw_64_elf(bfd) \ -+ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ -+ && elf_tdata (bfd) != NULL \ -+ && elf_object_id (bfd) == SW_64_ELF_DATA) -+ -+ static bool -+elf64_sw_64_mkobject (bfd *abfd) -+{ -+ return bfd_elf_allocate_object (abfd, sizeof (struct sw_64_elf_obj_tdata), -+ SW_64_ELF_DATA); -+} -+ -+/* Return the MACH for a sw_64 e_flags value. */ -+ unsigned long -+bfd_elf_sw_64_mach (flagword flags) -+{ -+ switch (flags) -+ { -+ case E_SW_64_MACH_SW6A: -+ return bfd_mach_sw_64_sw6a; -+ case E_SW_64_MACH_SW6B: -+ return bfd_mach_sw_64_sw6b; -+ default: -+ return 0; -+ } -+ return 0; -+} -+ -+ static bool -+elf64_sw_64_object_p (bfd *abfd) -+{ -+ /* Set the right machine number for an Sw_64 ELF file. */ -+ unsigned long mach; -+ -+ mach = bfd_elf_sw_64_mach (elf_elfheader (abfd)->e_flags); -+ return bfd_default_set_arch_mach (abfd, bfd_arch_sw_64, mach); -+} -+ -+/* A relocation function which doesn't do anything. */ -+ -+ static bfd_reloc_status_type -+elf64_sw_64_reloc_nil (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc, -+ asymbol *sym ATTRIBUTE_UNUSED, -+ void * data ATTRIBUTE_UNUSED, asection *sec, -+ bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) -+{ -+ if (output_bfd) -+ reloc->address += sec->output_offset; -+ return bfd_reloc_ok; -+} -+ -+/* A relocation function used for an unsupported reloc. */ -+ -+ static bfd_reloc_status_type -+elf64_sw_64_reloc_bad (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc, -+ asymbol *sym ATTRIBUTE_UNUSED, -+ void * data ATTRIBUTE_UNUSED, asection *sec, -+ bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) -+{ -+ if (output_bfd) -+ reloc->address += sec->output_offset; -+ return bfd_reloc_notsupported; -+} -+ -+/* Do the work of the GPDISP relocation. */ -+ -+ static bfd_reloc_status_type -+elf64_sw_64_do_reloc_gpdisp (bfd *abfd, bfd_vma gpdisp, bfd_byte *p_ldih, -+ bfd_byte *p_ldi) -+{ -+ bfd_reloc_status_type ret = bfd_reloc_ok; -+ bfd_vma addend; -+ unsigned long i_ldih, i_ldi; -+ -+ i_ldih = bfd_get_32 (abfd, p_ldih); -+ i_ldi = bfd_get_32 (abfd, p_ldi); -+ -+ /* Complain if the instructions are not correct. */ -+ if (((i_ldih >> 26) & 0x3f) != 0x3f -+ || ((i_ldi >> 26) & 0x3f) != 0x3e) -+ ret = bfd_reloc_dangerous; -+ -+ /* Extract the user-supplied offset, mirroring the sign extensions -+ that the instructions perform. */ -+ addend = ((i_ldih & 0xffff) << 16) | (i_ldi & 0xffff); -+ addend = (addend ^ 0x80008000) - 0x80008000; -+ -+ gpdisp += addend; -+ -+ if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000 -+ || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000) -+ ret = bfd_reloc_overflow; -+ -+ /* compensate for the sign extension again. */ -+ i_ldih = ((i_ldih & 0xffff0000) -+ | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff)); -+ i_ldi = (i_ldi & 0xffff0000) | (gpdisp & 0xffff); -+ -+ bfd_put_32 (abfd, (bfd_vma) i_ldih, p_ldih); -+ bfd_put_32 (abfd, (bfd_vma) i_ldi, p_ldi); -+ -+ return ret; -+} -+ -+/* The special function for the GPDISP reloc. */ -+ -+ static bfd_reloc_status_type -+elf64_sw_64_reloc_gpdisp (bfd *abfd, arelent *reloc_entry, -+ asymbol *sym ATTRIBUTE_UNUSED, void * data, -+ asection *input_section, bfd *output_bfd, -+ char **err_msg) -+{ -+ bfd_reloc_status_type ret; -+ bfd_vma gp, relocation; -+ bfd_vma high_address; -+ bfd_byte *p_ldih, *p_ldi; -+ -+ /* Don't do anything if we're not doing a final link. */ -+ if (output_bfd) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ high_address = bfd_get_section_limit (abfd, input_section); -+ if (reloc_entry->address > high_address -+ || reloc_entry->address + reloc_entry->addend > high_address) -+ return bfd_reloc_outofrange; -+ -+ /* The gp used in the portion of the output object to which this -+ input object belongs is cached on the input bfd. */ -+ gp = _bfd_get_gp_value (abfd); -+ -+ relocation = (input_section->output_section->vma -+ + input_section->output_offset -+ + reloc_entry->address); -+ -+ p_ldih = (bfd_byte *) data + reloc_entry->address; -+ p_ldi = p_ldih + reloc_entry->addend; -+ -+ ret = elf64_sw_64_do_reloc_gpdisp (abfd, gp - relocation, p_ldih, p_ldi); -+ -+ /* Complain if the instructions are not correct. */ -+ if (ret == bfd_reloc_dangerous) -+ *err_msg = _("GPDISP relocation did not find ldih and ldi instructions"); -+ -+ return ret; -+} -+ -+/* 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) -+ -+ -+#define SKIP_HOWTO(N) \ -+ HOWTO(N, 0, 0, 0, 0, 0, complain_overflow_dont, elf64_sw_64_reloc_bad, 0, 0, 0, 0, 0) -+ -+static reloc_howto_type elf64_sw_64_howto_table[] = -+{ -+ HOWTO (R_SW_64_NONE, /* type */ -+ 0, /* rightshift */ -+ 3, /* size (0 = byte, 1 = short, 2 = long) */ -+ 0, /* bitsize */ -+ true, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ elf64_sw_64_reloc_nil, /* special_function */ -+ "NONE", /* name */ -+ false, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ true), /* pcrel_offset */ -+ -+ /* A 32 bit reference to a symbol. */ -+ HOWTO (R_SW_64_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 */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "REFLONG", /* name */ -+ false, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* A 64 bit reference to a symbol. */ -+ HOWTO (R_SW_64_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 */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "REFQUAD", /* name */ -+ false, /* 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 (R_SW_64_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 */ -+ "GPREL32", /* name */ -+ false, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* Used for an instruction that refers to memory off the GP register. */ -+ HOWTO (R_SW_64_LITERAL, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "ELF_LITERAL", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* This reloc only appears immediately following an ELF_LITERAL reloc. -+ It identifies a use of the literal. 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 (R_SW_64_LITUSE, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ elf64_sw_64_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 ldih instruction -+ which loads the upper 16 bits of the gp register. The symbol -+ index of the GPDISP instruction is an offset in bytes to the ldi -+ instruction that loads the lower 16 bits. 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. -+ -+ NOTE: Unlike ECOFF, partial in-place relocation is not done. If -+ any offset is present in the instructions, it is an offset from -+ the register to the ldih instruction. This lets us avoid any -+ stupid hackery like inventing a gp value to do partial relocation -+ against. Also unlike ECOFF, we do the whole relocation off of -+ the GPDISP rather than a GPDISP_HI16/GPDISP_LO16 pair. An odd, -+ space consuming bit, that, since all the information was present -+ in the GPDISP_HI16 reloc. */ -+ HOWTO (R_SW_64_GPDISP, /* type */ -+ 16, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ elf64_sw_64_reloc_gpdisp, /* special_function */ -+ "GPDISP", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ true), /* pcrel_offset */ -+ -+ /* A 21 bit branch. */ -+ HOWTO (R_SW_64_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 */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "BRADDR", /* name */ -+ false, /* partial_inplace */ -+ 0x1fffff, /* src_mask */ -+ 0x1fffff, /* dst_mask */ -+ true), /* pcrel_offset */ -+ -+ /* A hint for a jump to a register. */ -+ HOWTO (R_SW_64_HINT, /* type */ -+ 2, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ true, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "HINT", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ true), /* pcrel_offset */ -+ -+ /* 16 bit PC relative offset. */ -+ HOWTO (R_SW_64_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 */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "SREL16", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ true), /* pcrel_offset */ -+ -+ /* 32 bit PC relative offset. */ -+ HOWTO (R_SW_64_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 */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "SREL32", /* name */ -+ false, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ true), /* pcrel_offset */ -+ -+ /* A 64 bit PC relative offset. */ -+ HOWTO (R_SW_64_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 */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "SREL64", /* name */ -+ false, /* partial_inplace */ -+ MINUS_ONE, /* src_mask */ -+ MINUS_ONE, /* dst_mask */ -+ true), /* pcrel_offset */ -+ -+ /* Skip 12 - 16; deprecated ECOFF relocs. */ -+ SKIP_HOWTO (12), -+ SKIP_HOWTO (13), -+ SKIP_HOWTO (14), -+ SKIP_HOWTO (15), -+ SKIP_HOWTO (16), -+ -+ /* The high 16 bits of the displacement from GP to the target. */ -+ HOWTO (R_SW_64_GPRELHIGH, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "GPRELHIGH", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* The low 16 bits of the displacement from GP to the target. */ -+ HOWTO (R_SW_64_GPRELLOW, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "GPRELLOW", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* A 16-bit displacement from the GP to the target. */ -+ HOWTO (R_SW_64_GPREL16, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "GPREL16", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* Skip 20 - 23; deprecated ECOFF relocs. */ -+ SKIP_HOWTO (20), -+ SKIP_HOWTO (21), -+ SKIP_HOWTO (22), -+ SKIP_HOWTO (23), -+ -+ /* Misc ELF relocations. */ -+ -+ /* A dynamic relocation to copy the target into our .dynbss section. */ -+ /* Not generated, as all Sw_64 objects use PIC, so it is not needed. It -+ is present because every other ELF has one, but should not be used -+ because .dynbss is an ugly thing. */ -+ HOWTO (R_SW_64_COPY, -+ 0, -+ 0, -+ 0, -+ false, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "COPY", -+ false, -+ 0, -+ 0, -+ true), -+ -+ /* A dynamic relocation for a .got entry. */ -+ HOWTO (R_SW_64_GLOB_DAT, -+ 0, -+ 0, -+ 0, -+ false, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "GLOB_DAT", -+ false, -+ 0, -+ 0, -+ true), -+ -+ /* A dynamic relocation for a .plt entry. */ -+ HOWTO (R_SW_64_JMP_SLOT, -+ 0, -+ 0, -+ 0, -+ false, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "JMP_SLOT", -+ false, -+ 0, -+ 0, -+ true), -+ -+ /* A dynamic relocation to add the base of the DSO to a 64-bit field. */ -+ HOWTO (R_SW_64_RELATIVE, -+ 0, -+ 0, -+ 0, -+ false, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "RELATIVE", -+ false, -+ 0, -+ 0, -+ true), -+ -+ /* A 21 bit branch that adjusts for gp loads. */ -+ HOWTO (R_SW_64_BRSGP, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 21, /* bitsize */ -+ true, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "BRSGP", /* name */ -+ false, /* partial_inplace */ -+ 0x1fffff, /* src_mask */ -+ 0x1fffff, /* dst_mask */ -+ true), /* pcrel_offset */ -+ -+ /* Creates a tls_index for the symbol in the got. */ -+ HOWTO (R_SW_64_TLSGD, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "TLSGD", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* Creates a tls_index for the (current) module in the got. */ -+ HOWTO (R_SW_64_TLSLDM, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "TLSLDM", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* A dynamic relocation for a DTP module entry. */ -+ HOWTO (R_SW_64_DTPMOD64, /* type */ -+ 0, /* rightshift */ -+ 4, /* size (0 = byte, 1 = short, 2 = long) */ -+ 64, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "DTPMOD64", /* name */ -+ false, /* partial_inplace */ -+ MINUS_ONE, /* src_mask */ -+ MINUS_ONE, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* Creates a 64-bit offset in the got for the displacement -+ from DTP to the target. */ -+ HOWTO (R_SW_64_GOTDTPREL, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "GOTDTPREL", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* A dynamic relocation for a displacement from DTP to the target. */ -+ HOWTO (R_SW_64_DTPREL64, /* type */ -+ 0, /* rightshift */ -+ 4, /* size (0 = byte, 1 = short, 2 = long) */ -+ 64, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "DTPREL64", /* name */ -+ false, /* partial_inplace */ -+ MINUS_ONE, /* src_mask */ -+ MINUS_ONE, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* The high 16 bits of the displacement from DTP to the target. */ -+ HOWTO (R_SW_64_DTPRELHI, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "DTPRELHI", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* The low 16 bits of the displacement from DTP to the target. */ -+ HOWTO (R_SW_64_DTPRELLO, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "DTPRELLO", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* A 16-bit displacement from DTP to the target. */ -+ HOWTO (R_SW_64_DTPREL16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "DTPREL16", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* Creates a 64-bit offset in the got for the displacement -+ from TP to the target. */ -+ HOWTO (R_SW_64_GOTTPREL, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "GOTTPREL", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* A dynamic relocation for a displacement from TP to the target. */ -+ HOWTO (R_SW_64_TPREL64, /* type */ -+ 0, /* rightshift */ -+ 4, /* size (0 = byte, 1 = short, 2 = long) */ -+ 64, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "TPREL64", /* name */ -+ false, /* partial_inplace */ -+ MINUS_ONE, /* src_mask */ -+ MINUS_ONE, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* The high 16 bits of the displacement from TP to the target. */ -+ HOWTO (R_SW_64_TPRELHI, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "TPRELHI", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* The low 16 bits of the displacement from TP to the target. */ -+ HOWTO (R_SW_64_TPRELLO, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "TPRELLO", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ -+ /* A 16-bit displacement from TP to the target. */ -+ HOWTO (R_SW_64_TPREL16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "TPREL16", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+ /* A 26 bit branch. */ -+ HOWTO (R_SW_64_BR26ADDR, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 26, /* bitsize */ -+ true, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "BR26ADDR", /* name */ -+ false, /* partial_inplace */ -+ 0x3ffffff, /* src_mask */ -+ 0x3ffffff, /* dst_mask */ -+ true), /* pcrel_offset */ -+ HOWTO (R_SW_64_LITERAL_GOT, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ false, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "ELF_LITERAL_GOT", /* name */ -+ false, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ false), /* pcrel_offset */ -+}; -+ -+/* A mapping from BFD reloc types to Sw_64 ELF reloc types. */ -+ -+struct elf_reloc_map -+{ -+ bfd_reloc_code_real_type bfd_reloc_val; -+ int elf_reloc_val; -+}; -+ -+static const struct elf_reloc_map elf64_sw_64_reloc_map[] = -+{ -+ {BFD_RELOC_NONE, R_SW_64_NONE}, -+ {BFD_RELOC_32, R_SW_64_REFLONG}, -+ {BFD_RELOC_64, R_SW_64_REFQUAD}, -+ {BFD_RELOC_CTOR, R_SW_64_REFQUAD}, -+ {BFD_RELOC_GPREL32, R_SW_64_GPREL32}, -+ {BFD_RELOC_SW_64_ELF_LITERAL, R_SW_64_LITERAL}, -+ {BFD_RELOC_SW_64_LITUSE, R_SW_64_LITUSE}, -+ {BFD_RELOC_SW_64_GPDISP, R_SW_64_GPDISP}, -+ {BFD_RELOC_23_PCREL_S2, R_SW_64_BRADDR}, -+ {BFD_RELOC_SW_64_HINT, R_SW_64_HINT}, -+ {BFD_RELOC_16_PCREL, R_SW_64_SREL16}, -+ {BFD_RELOC_32_PCREL, R_SW_64_SREL32}, -+ {BFD_RELOC_64_PCREL, R_SW_64_SREL64}, -+ {BFD_RELOC_SW_64_GPREL_HI16, R_SW_64_GPRELHIGH}, -+ {BFD_RELOC_SW_64_GPREL_LO16, R_SW_64_GPRELLOW}, -+ {BFD_RELOC_GPREL16, R_SW_64_GPREL16}, -+ {BFD_RELOC_SW_64_BRSGP, R_SW_64_BRSGP}, -+ {BFD_RELOC_SW_64_TLSGD, R_SW_64_TLSGD}, -+ {BFD_RELOC_SW_64_TLSLDM, R_SW_64_TLSLDM}, -+ {BFD_RELOC_SW_64_DTPMOD64, R_SW_64_DTPMOD64}, -+ {BFD_RELOC_SW_64_GOTDTPREL16, R_SW_64_GOTDTPREL}, -+ {BFD_RELOC_SW_64_DTPREL64, R_SW_64_DTPREL64}, -+ {BFD_RELOC_SW_64_DTPREL_HI16, R_SW_64_DTPRELHI}, -+ {BFD_RELOC_SW_64_DTPREL_LO16, R_SW_64_DTPRELLO}, -+ {BFD_RELOC_SW_64_DTPREL16, R_SW_64_DTPREL16}, -+ {BFD_RELOC_SW_64_GOTTPREL16, R_SW_64_GOTTPREL}, -+ {BFD_RELOC_SW_64_TPREL64, R_SW_64_TPREL64}, -+ {BFD_RELOC_SW_64_TPREL_HI16, R_SW_64_TPRELHI}, -+ {BFD_RELOC_SW_64_TPREL_LO16, R_SW_64_TPRELLO}, -+ {BFD_RELOC_SW_64_TPREL16, R_SW_64_TPREL16}, -+ {BFD_RELOC_SW_64_BR26, R_SW_64_BR26ADDR}, -+ {BFD_RELOC_SW_64_ELF_LITERAL_GOT, R_SW_64_LITERAL_GOT}, -+}; -+ -+/* Given a BFD reloc type, return a HOWTO structure. */ -+ -+ static reloc_howto_type * -+elf64_sw_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, -+ bfd_reloc_code_real_type code) -+{ -+ const struct elf_reloc_map *i, *e; -+ i = e = elf64_sw_64_reloc_map; -+ e += sizeof (elf64_sw_64_reloc_map) / sizeof (struct elf_reloc_map); -+ for (; i != e; ++i) -+ { -+ if (i->bfd_reloc_val == code) -+ return &elf64_sw_64_howto_table[i->elf_reloc_val]; -+ } -+ return 0; -+} -+ -+ static reloc_howto_type * -+elf64_sw_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, -+ const char *r_name) -+{ -+ unsigned int i; -+ -+ for (i = 0; -+ i < (sizeof (elf64_sw_64_howto_table) -+ / sizeof (elf64_sw_64_howto_table[0])); -+ i++) -+ if (elf64_sw_64_howto_table[i].name != NULL -+ && strcasecmp (elf64_sw_64_howto_table[i].name, r_name) == 0) -+ return &elf64_sw_64_howto_table[i]; -+ -+ return NULL; -+} -+ -+/* Given an Sw_64 ELF reloc type, fill in an arelent structure. */ -+ -+ static bool -+elf64_sw_64_info_to_howto (bfd *abfd, arelent *cache_ptr, -+ Elf_Internal_Rela *dst) -+{ -+ unsigned r_type = ELF64_R_TYPE(dst->r_info); -+ -+ if (r_type >= R_SW_64_max) -+ { -+ /* xgettext:c-format */ -+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"), -+ abfd, r_type); -+ bfd_set_error (bfd_error_bad_value); -+ return false; -+ } -+ cache_ptr->howto = &elf64_sw_64_howto_table[r_type]; -+ return true; -+} -+ -+/* These two relocations create a two-word entry in the got. */ -+#define sw_64_got_entry_size(r_type) \ -+ (r_type == R_SW_64_TLSGD || r_type == R_SW_64_TLSLDM ? 16 : 8) -+ -+/* This is PT_TLS segment p_vaddr. */ -+#define sw_64_get_dtprel_base(info) \ -+ (elf_hash_table (info)->tls_sec->vma) -+ -+/* Main program TLS (whose template starts at PT_TLS p_vaddr) -+ is assigned offset round(16, PT_TLS p_align). */ -+#define sw_64_get_tprel_base(info) \ -+ (elf_hash_table (info)->tls_sec->vma \ -+ - align_power ((bfd_vma) 16, \ -+ elf_hash_table (info)->tls_sec->alignment_power)) -+ -+/* Handle an Sw_64 specific section when reading an object file. This -+ is called when bfd_section_from_shdr finds a section with an unknown -+ type. */ -+ -+ static bool -+elf64_sw_64_section_from_shdr (bfd *abfd, -+ Elf_Internal_Shdr *hdr, -+ const char *name, -+ int shindex) -+{ -+ 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_SW_64_DEBUG: -+ if (strcmp (name, ".mdebug") != 0) -+ return false; -+ break; -+ default: -+ return false; -+ } -+ -+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) -+ return false; -+ newsect = hdr->bfd_section; -+ -+ if (hdr->sh_type == SHT_SW_64_DEBUG) -+ { -+ if (!bfd_set_section_flags (newsect, -+ bfd_section_flags (newsect) | SEC_DEBUGGING)) -+ return false; -+ } -+ -+ return true; -+} -+ -+/* Convert Sw_64 specific section flags to bfd internal section flags. */ -+ -+ static bool -+elf64_sw_64_section_flags (const Elf_Internal_Shdr *hdr) -+{ -+ if (hdr->sh_flags & SHF_SW_64_GPREL) -+ hdr->bfd_section->flags |= SEC_SMALL_DATA; -+ -+ return true; -+} -+ -+/* Set the correct type for an Sw_64 ELF section. We do this by the -+ section name, which is a hack, but ought to work. */ -+ -+ static bool -+elf64_sw_64_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) -+{ -+ register const char *name; -+ -+ name = bfd_section_name (sec); -+ -+ if (strcmp (name, ".mdebug") == 0) -+ { -+ hdr->sh_type = SHT_SW_64_DEBUG; -+ /* In a shared object on Irix 5.3, the .mdebug section has an -+ entsize of 0. FIXME: Does this matter? */ -+ if ((abfd->flags & DYNAMIC) != 0 ) -+ hdr->sh_entsize = 0; -+ else -+ hdr->sh_entsize = 1; -+ } -+ else if ((sec->flags & SEC_SMALL_DATA) -+ || strcmp (name, ".sdata") == 0 -+ || strcmp (name, ".sbss") == 0 -+ || strcmp (name, ".lit4") == 0 -+ || strcmp (name, ".lit8") == 0) -+ hdr->sh_flags |= SHF_SW_64_GPREL; -+ -+ return true; -+} -+ -+/* Hook called by the linker routine which adds symbols from an object -+ file. We use it to put .comm items in .sbss, and not .bss. */ -+ -+ static bool -+elf64_sw_64_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, -+ Elf_Internal_Sym *sym, -+ const char **namep ATTRIBUTE_UNUSED, -+ flagword *flagsp ATTRIBUTE_UNUSED, -+ asection **secp, bfd_vma *valp) -+{ -+ if (sym->st_shndx == SHN_COMMON -+ && !bfd_link_relocatable (info) -+ && sym->st_size <= elf_gp_size (abfd)) -+ { -+ /* Common symbols less than or equal to -G nn bytes are -+ automatically put into .sbss. */ -+ -+ asection *scomm = bfd_get_section_by_name (abfd, ".scommon"); -+ -+ if (scomm == NULL) -+ { -+ scomm = bfd_make_section_with_flags (abfd, ".scommon", -+ (SEC_ALLOC -+ | SEC_IS_COMMON -+ | SEC_SMALL_DATA -+ | SEC_LINKER_CREATED)); -+ if (scomm == NULL) -+ return false; -+ } -+ -+ *secp = scomm; -+ *valp = sym->st_size; -+ } -+ -+ return true; -+} -+ -+/* Create the .got section. */ -+ -+ static bool -+elf64_sw_64_create_got_section (bfd *abfd, -+ struct bfd_link_info *info ATTRIBUTE_UNUSED) -+{ -+ flagword flags; -+ asection *s; -+ -+ if (! is_sw_64_elf (abfd)) -+ return false; -+ -+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY -+ | SEC_LINKER_CREATED); -+ s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); -+ if (s == NULL -+ || !bfd_set_section_alignment (s, 3)) -+ return false; -+ -+ sw_64_elf_tdata (abfd)->got = s; -+ -+ /* Make sure the object's gotobj is set to itself so that we default -+ to every object with its own .got. We'll merge .gots later once -+ we've collected each object's info. */ -+ sw_64_elf_tdata (abfd)->gotobj = abfd; -+ -+ return true; -+} -+ -+/* Create all the dynamic sections. */ -+ -+ static bool -+elf64_sw_64_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) -+{ -+ asection *s; -+ flagword flags; -+ struct elf_link_hash_entry *h; -+ -+ if (! is_sw_64_elf (abfd)) -+ return false; -+ -+ /* We need to create .plt, .rela.plt, .got, and .rela.got sections. */ -+ -+ flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY -+ | SEC_LINKER_CREATED -+ | (elf64_sw_64_use_secureplt ? SEC_READONLY : 0)); -+ s = bfd_make_section_anyway_with_flags (abfd, ".plt", flags); -+ elf_hash_table (info)->splt = s; -+ if (s == NULL || ! bfd_set_section_alignment (s, 4)) -+ return false; -+ -+ /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the -+ .plt section. */ -+ h = _bfd_elf_define_linkage_sym (abfd, info, s, -+ "_PROCEDURE_LINKAGE_TABLE_"); -+ elf_hash_table (info)->hplt = h; -+ if (h == NULL) -+ return false; -+ -+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY -+ | SEC_LINKER_CREATED | SEC_READONLY); -+ s = bfd_make_section_anyway_with_flags (abfd, ".rela.plt", flags); -+ elf_hash_table (info)->srelplt = s; -+ if (s == NULL || ! bfd_set_section_alignment (s, 3)) -+ return false; -+ -+ if (elf64_sw_64_use_secureplt) -+ { -+ flags = SEC_ALLOC | SEC_LINKER_CREATED; -+ s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags); -+ elf_hash_table (info)->sgotplt = s; -+ if (s == NULL || ! bfd_set_section_alignment ( s, 3)) -+ return false; -+ } -+ -+ /* We may or may not have created a .got section for this object, but -+ we definitely havn't done the rest of the work. */ -+ -+ if (sw_64_elf_tdata(abfd)->gotobj == NULL) -+ { -+ if (!elf64_sw_64_create_got_section (abfd, info)) -+ return false; -+ } -+ -+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY -+ | SEC_LINKER_CREATED | SEC_READONLY); -+ s = bfd_make_section_anyway_with_flags (abfd, ".rela.got", flags); -+ elf_hash_table (info)->srelgot = s; -+ if (s == NULL -+ || !bfd_set_section_alignment (s, 3)) -+ return false; -+ -+ /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the -+ dynobj's .got 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 = _bfd_elf_define_linkage_sym (abfd, info, sw_64_elf_tdata(abfd)->got, -+ "_GLOBAL_OFFSET_TABLE_"); -+ elf_hash_table (info)->hgot = h; -+ if (h == NULL) -+ return false; -+ -+ return true; -+} -+ -+/* Read ECOFF debugging information from a .mdebug section into a -+ ecoff_debug_info structure. */ -+ -+ static bool -+elf64_sw_64_read_ecoff_info (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; -+ memset (debug, 0, sizeof (*debug)); -+ -+ ext_hdr = (char *) bfd_malloc (swap->external_hdr_size); -+ if (ext_hdr == NULL && swap->external_hdr_size != 0) -+ goto error_return; -+ -+ if (! bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0, -+ swap->external_hdr_size)) -+ 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. */ -+#ifdef ZZH20210707_SWGNU -+#define READ(ptr, offset, count, size, type) \ -+ do \ -+ { \ -+ size_t amt; \ -+ debug->ptr = NULL; \ -+ if (symhdr->count == 0) \ -+ break; \ -+ if (_bfd_mul_overflow (size, symhdr->count, &amt)) \ -+ { \ -+ bfd_set_error (bfd_error_file_too_big); \ -+ goto error_return; \ -+ } \ -+ if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0) \ -+ goto error_return; \ -+ debug->ptr = (type) _bfd_malloc_and_read (abfd, amt, amt); \ -+ if (debug->ptr == NULL) \ -+ goto error_return; \ -+ } while (0) -+#else -+#define READ(ptr, offset, count, size, type) \ -+ if (symhdr->count == 0) \ -+ debug->ptr = NULL; \ -+ else \ -+ { \ -+ bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ -+ debug->ptr = (type) bfd_malloc (amt); \ -+ if (debug->ptr == NULL) \ -+ goto error_return; \ -+ if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ -+ || bfd_bread (debug->ptr, amt, abfd) != amt) \ -+ goto error_return; \ -+ } -+#endif -+ -+ READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); -+ READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *); -+ READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *); -+ READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *); -+ READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *); -+ 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, void *); -+ READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *); -+ READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *); -+#undef READ -+ -+ debug->fdr = NULL; -+ -+ return true; -+ -+error_return: -+ free (ext_hdr); -+ free (debug->line); -+ free (debug->external_dnr); -+ free (debug->external_pdr); -+ free (debug->external_sym); -+ free (debug->external_opt); -+ free (debug->external_aux); -+ free (debug->ss); -+ free (debug->ssext); -+ free (debug->external_fdr); -+ free (debug->external_rfd); -+ free (debug->external_ext); -+ return false; -+} -+ -+/* Sw_64 ELF local labels start with '$'. */ -+ -+ static bool -+elf64_sw_64_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name) -+{ -+ return name[0] == '$'; -+} -+ -+ static bool -+elf64_sw_64_find_nearest_line (bfd *abfd, asymbol **symbols, -+ asection *section, bfd_vma offset, -+ const char **filename_ptr, -+ const char **functionname_ptr, -+ unsigned int *line_ptr, -+ unsigned int *discriminator_ptr) -+{ -+ asection *msec; -+ -+ if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, -+ filename_ptr, functionname_ptr, -+ line_ptr, discriminator_ptr, -+ dwarf_debug_sections, -+ &elf_tdata (abfd)->dwarf2_find_line_info) -+ == 1) -+ return true; -+ -+ msec = bfd_get_section_by_name (abfd, ".mdebug"); -+ if (msec != NULL) -+ { -+ flagword origflags; -+ struct sw_64_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, sw_64_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 = sw_64_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; -+ bfd_size_type amt = sizeof (struct sw_64_elf_find_line); -+ -+ fi = (struct sw_64_elf_find_line *) bfd_zalloc (abfd, amt); -+ if (fi == NULL) -+ { -+ msec->flags = origflags; -+ return false; -+ } -+ -+ if (!elf64_sw_64_read_ecoff_info (abfd, msec, &fi->d)) -+ { -+ msec->flags = origflags; -+ return false; -+ } -+ -+ /* Swap in the FDR information. */ -+ amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr); -+ fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt); -+ if (fi->d.fdr == NULL) -+ { -+ msec->flags = origflags; -+ return false; -+ } -+ external_fdr_size = swap->external_fdr_size; -+ fdr_ptr = fi->d.fdr; -+ fraw_src = (char *) fi->d.external_fdr; -+ fraw_end = (fraw_src -+ + fi->d.symbolic_header.ifdMax * external_fdr_size); -+ for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) -+ (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr); -+ -+ sw_64_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, symbols, section, offset, -+ filename_ptr, functionname_ptr, -+ line_ptr, discriminator_ptr); -+} -+ -+/* Structure used to pass information to sw_64_elf_output_extsym. */ -+ -+struct extsym_info -+{ -+ bfd *abfd; -+ struct bfd_link_info *info; -+ struct ecoff_debug_info *debug; -+ const struct ecoff_debug_swap *swap; -+ bool failed; -+}; -+ -+ static bool -+elf64_sw_64_output_extsym (struct sw_64_elf_link_hash_entry *h, void * data) -+{ -+ struct extsym_info *einfo = (struct extsym_info *) data; -+ bool strip; -+ asection *sec, *output_section; -+ -+ if (h->root.indx == -2) -+ strip = false; -+ else if ((h->root.def_dynamic -+ || h->root.ref_dynamic -+ || h->root.root.type == bfd_link_hash_new) -+ && !h->root.def_regular -+ && !h->root.ref_regular) -+ 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 -+ { -+ const char *name; -+ -+ sec = h->root.root.u.def.section; -+ output_section = sec->output_section; -+ -+ /* When making a shared library and symbol h is the one from -+ the another shared library, OUTPUT_SECTION may be null. */ -+ if (output_section == NULL) -+ h->esym.asym.sc = scUndefined; -+ else -+ { -+ name = bfd_section_name (output_section); -+ -+ if (strcmp (name, ".text") == 0) -+ h->esym.asym.sc = scText; -+ else if (strcmp (name, ".data") == 0) -+ h->esym.asym.sc = scData; -+ else if (strcmp (name, ".sdata") == 0) -+ h->esym.asym.sc = scSData; -+ else if (strcmp (name, ".rodata") == 0 -+ || strcmp (name, ".rdata") == 0) -+ h->esym.asym.sc = scRData; -+ else if (strcmp (name, ".bss") == 0) -+ h->esym.asym.sc = scBss; -+ else if (strcmp (name, ".sbss") == 0) -+ h->esym.asym.sc = scSBss; -+ else if (strcmp (name, ".init") == 0) -+ h->esym.asym.sc = scInit; -+ else if (strcmp (name, ".fini") == 0) -+ h->esym.asym.sc = scFini; -+ else -+ h->esym.asym.sc = scAbs; -+ } -+ } -+ -+ h->esym.asym.reserved = 0; -+ h->esym.asym.index = indexNil; -+ } -+ -+ if (h->root.root.type == bfd_link_hash_common) -+ h->esym.asym.value = h->root.root.u.c.size; -+ else if (h->root.root.type == bfd_link_hash_defined -+ || h->root.root.type == bfd_link_hash_defweak) -+ { -+ if (h->esym.asym.sc == scCommon) -+ h->esym.asym.sc = scBss; -+ else if (h->esym.asym.sc == scSCommon) -+ h->esym.asym.sc = scSBss; -+ -+ sec = h->root.root.u.def.section; -+ output_section = sec->output_section; -+ if (output_section != NULL) -+ h->esym.asym.value = (h->root.root.u.def.value -+ + sec->output_offset -+ + output_section->vma); -+ else -+ h->esym.asym.value = 0; -+ } -+ -+ 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; -+} -+ -+/* Search for and possibly create a got entry. */ -+ -+ static struct sw_64_elf_got_entry * -+get_got_entry (bfd *abfd, struct sw_64_elf_link_hash_entry *h, -+ unsigned long r_type, unsigned long r_symndx, -+ bfd_vma r_addend) -+{ -+ struct sw_64_elf_got_entry *gotent; -+ struct sw_64_elf_got_entry **slot; -+ -+ if (h) -+ slot = &h->got_entries; -+ else -+ { -+ /* This is a local .got entry -- record for merge. */ -+ -+ struct sw_64_elf_got_entry **local_got_entries; -+ -+ local_got_entries = sw_64_elf_tdata(abfd)->local_got_entries; -+ if (!local_got_entries) -+ { -+ bfd_size_type size; -+ Elf_Internal_Shdr *symtab_hdr; -+ -+ symtab_hdr = &elf_tdata(abfd)->symtab_hdr; -+ size = symtab_hdr->sh_info; -+ size *= sizeof (struct sw_64_elf_got_entry *); -+ -+ local_got_entries -+ = (struct sw_64_elf_got_entry **) bfd_zalloc (abfd, size); -+ if (!local_got_entries) -+ return NULL; -+ -+ sw_64_elf_tdata (abfd)->local_got_entries = local_got_entries; -+ } -+ -+ slot = &local_got_entries[r_symndx]; -+ } -+ -+ for (gotent = *slot; gotent ; gotent = gotent->next) -+ if (gotent->gotobj == abfd -+ && gotent->reloc_type == r_type -+ && gotent->addend == r_addend) -+ break; -+ -+ if (!gotent) -+ { -+ int entry_size; -+ size_t amt; -+ -+ amt = sizeof (struct sw_64_elf_got_entry); -+ gotent = (struct sw_64_elf_got_entry *) bfd_alloc (abfd, amt); -+ if (!gotent) -+ return NULL; -+ -+ gotent->gotobj = abfd; -+ gotent->addend = r_addend; -+ gotent->got_offset = -1; -+ gotent->plt_offset = -1; -+ gotent->use_count = 1; -+ gotent->reloc_type = r_type; -+ gotent->reloc_done = 0; -+ gotent->reloc_xlated = 0; -+ -+ gotent->next = *slot; -+ *slot = gotent; -+ -+ entry_size = sw_64_got_entry_size (r_type); -+ sw_64_elf_tdata (abfd)->total_got_size += entry_size; -+ if (!h) -+ sw_64_elf_tdata(abfd)->local_got_size += entry_size; -+ } -+ else -+ gotent->use_count += 1; -+ -+ return gotent; -+} -+ -+ static bool -+elf64_sw_64_want_plt (struct sw_64_elf_link_hash_entry *ah) -+{ -+ return ((ah->root.type == STT_FUNC -+ || ah->root.root.type == bfd_link_hash_undefweak -+ || ah->root.root.type == bfd_link_hash_undefined) -+ && (ah->flags & SW_64_ELF_LINK_HASH_LU_PLT) != 0 -+ && (ah->flags & ~SW_64_ELF_LINK_HASH_LU_PLT) == 0); -+} -+ -+/* Whether to sort relocs output by ld -r or ld --emit-relocs, by r_offset. -+ Don't do so for code sections. We want to keep ordering of LITERAL/LITUSE -+ as is. On the other hand, elf-eh-frame.c processing requires .eh_frame -+ relocs to be sorted. */ -+ -+ static bool -+elf64_sw_64_sort_relocs_p (asection *sec) -+{ -+ return (sec->flags & SEC_CODE) == 0; -+} -+ -+ -+/* Handle dynamic relocations when doing an Sw_64 ELF link. */ -+ -+ static bool -+elf64_sw_64_check_relocs (bfd *abfd, struct bfd_link_info *info, -+ asection *sec, const Elf_Internal_Rela *relocs) -+{ -+ bfd *dynobj; -+ asection *sreloc; -+ Elf_Internal_Shdr *symtab_hdr; -+ struct sw_64_elf_link_hash_entry **sym_hashes; -+ const Elf_Internal_Rela *rel, *relend; -+ -+ if (bfd_link_relocatable (info)) -+ return true; -+ -+ /* Don't do anything special with non-loaded, non-alloced sections. -+ In particular, any relocs in such sections should not affect GOT -+ and PLT reference counting (ie. we don't allow them to create GOT -+ or PLT entries), there's no possibility or desire to optimize TLS -+ relocs, and there's not much point in propagating relocs to shared -+ libs that the dynamic linker won't relocate. */ -+ if ((sec->flags & SEC_ALLOC) == 0) -+ return true; -+ -+ BFD_ASSERT (is_sw_64_elf (abfd)); -+ -+ dynobj = elf_hash_table (info)->dynobj; -+ if (dynobj == NULL) -+ elf_hash_table (info)->dynobj = dynobj = abfd; -+ -+ sreloc = NULL; -+ symtab_hdr = &elf_symtab_hdr (abfd); -+ sym_hashes = sw_64_elf_sym_hashes (abfd); -+ -+ relend = relocs + sec->reloc_count; -+ for (rel = relocs; rel < relend; ++rel) -+ { -+ enum { -+ NEED_GOT = 1, -+ NEED_GOT_ENTRY = 2, -+ NEED_DYNREL = 4 -+ }; -+ -+ unsigned long r_symndx, r_type; -+ struct sw_64_elf_link_hash_entry *h; -+ unsigned int gotent_flags; -+ bool maybe_dynamic; -+ unsigned int need; -+ bfd_vma addend; -+ -+ r_symndx = ELF64_R_SYM (rel->r_info); -+ if (r_symndx < symtab_hdr->sh_info) -+ h = NULL; -+ else -+ { -+ h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -+ -+ while (h->root.root.type == bfd_link_hash_indirect -+ || h->root.root.type == bfd_link_hash_warning) -+ h = (struct sw_64_elf_link_hash_entry *)h->root.root.u.i.link; -+ -+ /* PR15323, ref flags aren't set for references in the same -+ object. */ -+ h->root.ref_regular = 1; -+ } -+ -+ /* We can only get preliminary data on whether a symbol is -+ locally or externally defined, as not all of the input files -+ have yet been processed. Do something with what we know, as -+ this may help reduce memory usage and processing time later. */ -+ maybe_dynamic = false; -+ if (h && ((bfd_link_pic (info) -+ && (!info->symbolic -+ || info->unresolved_syms_in_shared_libs == RM_IGNORE)) -+ || !h->root.def_regular -+ || h->root.root.type == bfd_link_hash_defweak)) -+ maybe_dynamic = true; -+ -+ need = 0; -+ gotent_flags = 0; -+ r_type = ELF64_R_TYPE (rel->r_info); -+ addend = rel->r_addend; -+ -+ switch (r_type) -+ { -+ case R_SW_64_LITERAL: -+ need = NEED_GOT | NEED_GOT_ENTRY; -+ -+ /* Remember how this literal is used from its LITUSEs. -+ This will be important when it comes to decide if we can -+ create a .plt entry for a function symbol. */ -+ while (++rel < relend && ELF64_R_TYPE (rel->r_info) == R_SW_64_LITUSE) -+ if (rel->r_addend >= 1 && rel->r_addend <= 6) -+ gotent_flags |= 1 << rel->r_addend; -+ --rel; -+ -+ /* No LITUSEs -- presumably the address is used somehow. */ -+ if (gotent_flags == 0) -+ gotent_flags = SW_64_ELF_LINK_HASH_LU_ADDR; -+ break; -+ -+ case R_SW_64_GPDISP: -+ case R_SW_64_GPREL16: -+ case R_SW_64_GPREL32: -+ case R_SW_64_GPRELHIGH: -+ case R_SW_64_GPRELLOW: -+ case R_SW_64_BRSGP: -+ need = NEED_GOT; -+ break; -+ -+ case R_SW_64_REFLONG: -+ case R_SW_64_REFQUAD: -+ if (bfd_link_pic (info) || maybe_dynamic) -+ need = NEED_DYNREL; -+ break; -+ -+ case R_SW_64_TLSLDM: -+ /* The symbol for a TLSLDM reloc is ignored. Collapse the -+ reloc to the STN_UNDEF (0) symbol so that they all match. */ -+ r_symndx = STN_UNDEF; -+ h = 0; -+ maybe_dynamic = false; -+ /* FALLTHRU */ -+ -+ case R_SW_64_TLSGD: -+ case R_SW_64_GOTDTPREL: -+ need = NEED_GOT | NEED_GOT_ENTRY; -+ break; -+ -+ case R_SW_64_GOTTPREL: -+ need = NEED_GOT | NEED_GOT_ENTRY; -+ gotent_flags = SW_64_ELF_LINK_HASH_TLS_IE; -+ if (bfd_link_pic (info)) -+ info->flags |= DF_STATIC_TLS; -+ break; -+ -+ case R_SW_64_TPREL64: -+ if (bfd_link_dll (info)) -+ { -+ info->flags |= DF_STATIC_TLS; -+ need = NEED_DYNREL; -+ } -+ else if (maybe_dynamic) -+ need = NEED_DYNREL; -+ break; -+ } -+ -+ if (need & NEED_GOT) -+ { -+ if (sw_64_elf_tdata(abfd)->gotobj == NULL) -+ { -+ if (!elf64_sw_64_create_got_section (abfd, info)) -+ return false; -+ } -+ } -+ -+ if (need & NEED_GOT_ENTRY) -+ { -+ struct sw_64_elf_got_entry *gotent; -+ -+ gotent = get_got_entry (abfd, h, r_type, r_symndx, addend); -+ if (!gotent) -+ return false; -+ -+ if (gotent_flags) -+ { -+ gotent->flags |= gotent_flags; -+ if (h) -+ { -+ gotent_flags |= h->flags; -+ h->flags = gotent_flags; -+ -+ /* Make a guess as to whether a .plt entry is needed. */ -+ /* ??? It appears that we won't make it into -+ adjust_dynamic_symbol for symbols that remain -+ totally undefined. Copying this check here means -+ we can create a plt entry for them too. */ -+ h->root.needs_plt -+ = (maybe_dynamic && elf64_sw_64_want_plt (h)); -+ } -+ } -+ } -+ -+ if (need & NEED_DYNREL) -+ { -+ /* We need to create the section here now whether we eventually -+ use it or not so that it gets mapped to an output section by -+ the linker. If not used, we'll kill it in size_dynamic_sections. */ -+ if (sreloc == NULL) -+ { -+ sreloc = _bfd_elf_make_dynamic_reloc_section -+ (sec, dynobj, 3, abfd, /*rela?*/ true); -+ -+ if (sreloc == NULL) -+ return false; -+ } -+ -+ if (h) -+ { -+ /* Since we havn't seen all of the input symbols yet, we -+ don't know whether we'll actually need a dynamic relocation -+ entry for this reloc. So make a record of it. Once we -+ find out if this thing needs dynamic relocation we'll -+ expand the relocation sections by the appropriate amount. */ -+ -+ struct sw_64_elf_reloc_entry *rent; -+ -+ for (rent = h->reloc_entries; rent; rent = rent->next) -+ if (rent->rtype == r_type && rent->srel == sreloc) -+ break; -+ -+ if (!rent) -+ { -+ size_t amt = sizeof (struct sw_64_elf_reloc_entry); -+ rent = (struct sw_64_elf_reloc_entry *) bfd_alloc (abfd, amt); -+ if (!rent) -+ return false; -+ -+ rent->srel = sreloc; -+ rent->sec = sec; -+ rent->rtype = r_type; -+ rent->count = 1; -+ -+ rent->next = h->reloc_entries; -+ h->reloc_entries = rent; -+ } -+ else -+ rent->count++; -+ } -+ else if (bfd_link_pic (info)) -+ { -+ /* If this is a shared library, and the section is to be -+ loaded into memory, we need a RELATIVE reloc. */ -+ sreloc->size += sizeof (Elf64_External_Rela); -+ if (sec->flags & SEC_READONLY) -+ { -+ info->flags |= DF_TEXTREL; -+ info->callbacks->minfo -+ (_("%pB: dynamic relocation against `T' in " -+ "read-only section `%pA'\n"), -+ sec->owner, sec); -+ } -+ } -+ } -+ } -+ -+ return true; -+} -+ -+/* Return the section that should be marked against GC for a given -+ relocation. */ -+ -+ static asection * -+elf64_sw_64_gc_mark_hook (asection *sec, struct bfd_link_info *info, -+ Elf_Internal_Rela *rel, -+ struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) -+{ -+ /* These relocations don't really reference a symbol. Instead we store -+ extra data in their addend slot. Ignore the symbol. */ -+ switch (ELF64_R_TYPE (rel->r_info)) -+ { -+ case R_SW_64_LITUSE: -+ case R_SW_64_GPDISP: -+ case R_SW_64_HINT: -+ return NULL; -+ } -+ -+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); -+} -+ -+/* 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 bool -+elf64_sw_64_adjust_dynamic_symbol (struct bfd_link_info *info, -+ struct elf_link_hash_entry *h) -+{ -+ bfd *dynobj; -+ asection *s; -+ struct sw_64_elf_link_hash_entry *ah; -+ -+ dynobj = elf_hash_table(info)->dynobj; -+ ah = (struct sw_64_elf_link_hash_entry *)h; -+ -+ /* Now that we've seen all of the input symbols, finalize our decision -+ about whether this symbol should get a .plt entry. Irritatingly, it -+ is common for folk to leave undefined symbols in shared libraries, -+ and they still expect lazy binding; accept undefined symbols in lieu -+ of STT_FUNC. */ -+ if (sw_64_elf_dynamic_symbol_p (h, info) && elf64_sw_64_want_plt (ah)) -+ { -+ h->needs_plt = true; -+ -+ s = elf_hash_table(info)->splt; -+ if (!s && !elf64_sw_64_create_dynamic_sections (dynobj, info)) -+ return false; -+ -+ /* We need one plt entry per got subsection. Delay allocation of -+ the actual plt entries until size_plt_section, called from -+ size_dynamic_sections or during relaxation. */ -+ -+ return true; -+ } -+ else -+ h->needs_plt = false; -+ -+ /* 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->is_weakalias) -+ { -+ struct elf_link_hash_entry *def = weakdef (h); -+ BFD_ASSERT (def->root.type == bfd_link_hash_defined); -+ h->root.u.def.section = def->root.u.def.section; -+ h->root.u.def.value = def->root.u.def.value; -+ return true; -+ } -+ -+ /* This is a reference to a symbol defined by a dynamic object which -+ is not a function. The Sw_64, since it uses .got entries for all -+ symbols even in regular objects, does not need the hackery of a -+ .dynbss section and COPY dynamic relocations. */ -+ -+ return true; -+} -+ -+/* Record STO_SW_64_NOPV and STO_SW_64_STD_GPLOAD. */ -+ -+ static void -+elf64_sw_64_merge_symbol_attribute (struct elf_link_hash_entry *h, -+ unsigned int st_other, -+ bool definition, -+ bool dynamic) -+{ -+ if (!dynamic && definition) -+ h->other = ((h->other & ELF_ST_VISIBILITY (-1)) -+ | (st_other & ~ELF_ST_VISIBILITY (-1))); -+} -+ -+/* Symbol versioning can create new symbols, and make our old symbols -+ indirect to the new ones. Consolidate the got and reloc information -+ in these situations. */ -+ -+ static void -+elf64_sw_64_copy_indirect_symbol (struct bfd_link_info *info, -+ struct elf_link_hash_entry *dir, -+ struct elf_link_hash_entry *ind) -+{ -+ struct sw_64_elf_link_hash_entry *hi -+ = (struct sw_64_elf_link_hash_entry *) ind; -+ struct sw_64_elf_link_hash_entry *hs -+ = (struct sw_64_elf_link_hash_entry *) dir; -+ -+ /* Do the merging in the superclass. */ -+ _bfd_elf_link_hash_copy_indirect(info, dir, ind); -+ -+ /* Merge the flags. Whee. */ -+ hs->flags |= hi->flags; -+ -+ /* ??? It's unclear to me what's really supposed to happen when -+ "merging" defweak and defined symbols, given that we don't -+ actually throw away the defweak. This more-or-less copies -+ the logic related to got and plt entries in the superclass. */ -+ if (ind->root.type != bfd_link_hash_indirect) -+ return; -+ -+ /* Merge the .got entries. Cannibalize the old symbol's list in -+ doing so, since we don't need it anymore. */ -+ -+ if (hs->got_entries == NULL) -+ hs->got_entries = hi->got_entries; -+ else -+ { -+ struct sw_64_elf_got_entry *gi, *gs, *gin, *gsh; -+ -+ gsh = hs->got_entries; -+ for (gi = hi->got_entries; gi ; gi = gin) -+ { -+ gin = gi->next; -+ for (gs = gsh; gs ; gs = gs->next) -+ if (gi->gotobj == gs->gotobj -+ && gi->reloc_type == gs->reloc_type -+ && gi->addend == gs->addend) -+ { -+ gs->use_count += gi->use_count; -+ goto got_found; -+ } -+ gi->next = hs->got_entries; -+ hs->got_entries = gi; -+got_found:; -+ } -+ } -+ hi->got_entries = NULL; -+ -+ /* And similar for the reloc entries. */ -+ -+ if (hs->reloc_entries == NULL) -+ hs->reloc_entries = hi->reloc_entries; -+ else -+ { -+ struct sw_64_elf_reloc_entry *ri, *rs, *rin, *rsh; -+ -+ rsh = hs->reloc_entries; -+ for (ri = hi->reloc_entries; ri ; ri = rin) -+ { -+ rin = ri->next; -+ for (rs = rsh; rs ; rs = rs->next) -+ if (ri->rtype == rs->rtype && ri->srel == rs->srel) -+ { -+ rs->count += ri->count; -+ goto found_reloc; -+ } -+ ri->next = hs->reloc_entries; -+ hs->reloc_entries = ri; -+found_reloc:; -+ } -+ } -+ hi->reloc_entries = NULL; -+} -+ -+/* Is it possible to merge two object file's .got tables? */ -+ -+ static bool -+elf64_sw_64_can_merge_gots (bfd *a, bfd *b) -+{ -+ int total = sw_64_elf_tdata (a)->total_got_size; -+ bfd *bsub; -+ -+ /* Trivial quick fallout test. */ -+ if (total + sw_64_elf_tdata (b)->total_got_size <= MAX_GOT_SIZE) -+ return true; -+ -+ /* By their nature, local .got entries cannot be merged. */ -+ if ((total += sw_64_elf_tdata (b)->local_got_size) > MAX_GOT_SIZE) -+ return false; -+ -+ /* Failing the common trivial comparison, we must effectively -+ perform the merge. Not actually performing the merge means that -+ we don't have to store undo information in case we fail. */ -+ for (bsub = b; bsub ; bsub = sw_64_elf_tdata (bsub)->in_got_link_next) -+ { -+ struct sw_64_elf_link_hash_entry **hashes = sw_64_elf_sym_hashes (bsub); -+ Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr; -+ int i, n; -+ -+ n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; -+ for (i = 0; i < n; ++i) -+ { -+ struct sw_64_elf_got_entry *ae, *be; -+ struct sw_64_elf_link_hash_entry *h; -+ -+ h = hashes[i]; -+ while (h->root.root.type == bfd_link_hash_indirect -+ || h->root.root.type == bfd_link_hash_warning) -+ h = (struct sw_64_elf_link_hash_entry *)h->root.root.u.i.link; -+ -+ for (be = h->got_entries; be ; be = be->next) -+ { -+ if (be->use_count == 0) -+ continue; -+ if (be->gotobj != b) -+ continue; -+ -+ for (ae = h->got_entries; ae ; ae = ae->next) -+ if (ae->gotobj == a -+ && ae->reloc_type == be->reloc_type -+ && ae->addend == be->addend) -+ goto global_found; -+ -+ total += sw_64_got_entry_size (be->reloc_type); -+ if (total > MAX_GOT_SIZE) -+ return false; -+global_found:; -+ } -+ } -+ } -+ -+ return true; -+} -+ -+/* Actually merge two .got tables. */ -+ -+ static void -+elf64_sw_64_merge_gots (bfd *a, bfd *b) -+{ -+ int total = sw_64_elf_tdata (a)->total_got_size; -+ bfd *bsub; -+ -+ /* Remember local expansion. */ -+ { -+ int e = sw_64_elf_tdata (b)->local_got_size; -+ total += e; -+ sw_64_elf_tdata (a)->local_got_size += e; -+ } -+ -+ for (bsub = b; bsub ; bsub = sw_64_elf_tdata (bsub)->in_got_link_next) -+ { -+ struct sw_64_elf_got_entry **local_got_entries; -+ struct sw_64_elf_link_hash_entry **hashes; -+ Elf_Internal_Shdr *symtab_hdr; -+ int i, n; -+ -+ /* Let the local .got entries know they are part of a new subsegment. */ -+ local_got_entries = sw_64_elf_tdata (bsub)->local_got_entries; -+ if (local_got_entries) -+ { -+ n = elf_tdata (bsub)->symtab_hdr.sh_info; -+ for (i = 0; i < n; ++i) -+ { -+ struct sw_64_elf_got_entry *ent; -+ for (ent = local_got_entries[i]; ent; ent = ent->next) -+ ent->gotobj = a; -+ } -+ } -+ -+ /* Merge the global .got entries. */ -+ hashes = sw_64_elf_sym_hashes (bsub); -+ symtab_hdr = &elf_tdata (bsub)->symtab_hdr; -+ -+ n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; -+ for (i = 0; i < n; ++i) -+ { -+ struct sw_64_elf_got_entry *ae, *be, **pbe, **start; -+ struct sw_64_elf_link_hash_entry *h; -+ -+ h = hashes[i]; -+ while (h->root.root.type == bfd_link_hash_indirect -+ || h->root.root.type == bfd_link_hash_warning) -+ h = (struct sw_64_elf_link_hash_entry *)h->root.root.u.i.link; -+ -+ pbe = start = &h->got_entries; -+ while ((be = *pbe) != NULL) -+ { -+ if (be->use_count == 0) -+ { -+ *pbe = be->next; -+ memset (be, 0xa5, sizeof (*be)); -+ goto kill; -+ } -+ if (be->gotobj != b) -+ goto next; -+ -+ for (ae = *start; ae ; ae = ae->next) -+ if (ae->gotobj == a -+ && ae->reloc_type == be->reloc_type -+ && ae->addend == be->addend) -+ { -+ ae->flags |= be->flags; -+ ae->use_count += be->use_count; -+ *pbe = be->next; -+ memset (be, 0xa5, sizeof (*be)); -+ goto kill; -+ } -+ be->gotobj = a; -+ total += sw_64_got_entry_size (be->reloc_type); -+ -+next:; -+ pbe = &be->next; -+kill:; -+ } -+ } -+ -+ sw_64_elf_tdata (bsub)->gotobj = a; -+ } -+ sw_64_elf_tdata (a)->total_got_size = total; -+ -+ /* Merge the two in_got chains. */ -+ { -+ bfd *next; -+ -+ bsub = a; -+ while ((next = sw_64_elf_tdata (bsub)->in_got_link_next) != NULL) -+ bsub = next; -+ -+ sw_64_elf_tdata (bsub)->in_got_link_next = b; -+ } -+} -+ -+/* Calculate the offsets for the got entries. */ -+ -+ static bool -+elf64_sw_64_calc_got_offsets_for_symbol (struct sw_64_elf_link_hash_entry *h, -+ void * arg ATTRIBUTE_UNUSED) -+{ -+ struct sw_64_elf_got_entry *gotent; -+ -+ for (gotent = h->got_entries; gotent; gotent = gotent->next) -+ if (gotent->use_count > 0) -+ { -+ struct sw_64_elf_obj_tdata *td; -+ bfd_size_type *plge; -+ -+ td = sw_64_elf_tdata (gotent->gotobj); -+ plge = &td->got->size; -+ gotent->got_offset = *plge; -+ *plge += sw_64_got_entry_size (gotent->reloc_type); -+ } -+ -+ return true; -+} -+ -+ static void -+elf64_sw_64_calc_got_offsets (struct bfd_link_info *info) -+{ -+ bfd *i, *got_list; -+ struct sw_64_elf_link_hash_table * htab; -+ -+ htab = sw_64_elf_hash_table (info); -+ if (htab == NULL) -+ return; -+ got_list = htab->got_list; -+ -+ /* First, zero out the .got sizes, as we may be recalculating the -+ .got after optimizing it. */ -+ for (i = got_list; i ; i = sw_64_elf_tdata(i)->got_link_next) -+ sw_64_elf_tdata(i)->got->size = 0; -+ -+ /* Next, fill in the offsets for all the global entries. */ -+ sw_64_elf_link_hash_traverse (htab, -+ elf64_sw_64_calc_got_offsets_for_symbol, -+ NULL); -+ -+ /* Finally, fill in the offsets for the local entries. */ -+ for (i = got_list; i ; i = sw_64_elf_tdata(i)->got_link_next) -+ { -+ bfd_size_type got_offset = sw_64_elf_tdata(i)->got->size; -+ bfd *j; -+ -+ for (j = i; j ; j = sw_64_elf_tdata(j)->in_got_link_next) -+ { -+ struct sw_64_elf_got_entry **local_got_entries, *gotent; -+ int k, n; -+ -+ local_got_entries = sw_64_elf_tdata(j)->local_got_entries; -+ if (!local_got_entries) -+ continue; -+ -+ for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k) -+ for (gotent = local_got_entries[k]; gotent; gotent = gotent->next) -+ if (gotent->use_count > 0) -+ { -+ gotent->got_offset = got_offset; -+ got_offset += sw_64_got_entry_size (gotent->reloc_type); -+ } -+ } -+ -+ sw_64_elf_tdata(i)->got->size = got_offset; -+ } -+} -+ -+/* Constructs the gots. */ -+ -+ static bool -+elf64_sw_64_size_got_sections (struct bfd_link_info *info, -+ bool may_merge) -+{ -+ bfd *i, *got_list, *cur_got_obj = NULL; -+ struct sw_64_elf_link_hash_table * htab; -+ -+ htab = sw_64_elf_hash_table (info); -+ if (htab == NULL) -+ return false; -+ got_list = htab->got_list; -+ -+ /* On the first time through, pretend we have an existing got list -+ consisting of all of the input files. */ -+ if (got_list == NULL) -+ { -+ for (i = info->input_bfds; i ; i = i->link.next) -+ { -+ bfd *this_got; -+ -+ if (! is_sw_64_elf (i)) -+ continue; -+ -+ this_got = sw_64_elf_tdata (i)->gotobj; -+ if (this_got == NULL) -+ continue; -+ -+ /* We are assuming no merging has yet occurred. */ -+ BFD_ASSERT (this_got == i); -+ -+ if (sw_64_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE_NEW) -+ { -+ /* Yikes! A single object file has too many entries. */ -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: .got subsegment exceeds 2G (size %d)"), -+ i, sw_64_elf_tdata (this_got)->total_got_size); -+ return false; -+ } -+ -+ if (got_list == NULL) -+ got_list = this_got; -+ else -+ sw_64_elf_tdata(cur_got_obj)->got_link_next = this_got; -+ cur_got_obj = this_got; -+ } -+ -+ /* Strange degenerate case of no got references. */ -+ if (got_list == NULL) -+ return true; -+ -+ htab->got_list = got_list; -+ } -+ -+ cur_got_obj = got_list; -+ if (cur_got_obj == NULL) -+ return false; -+ -+ if (may_merge) -+ { -+ i = sw_64_elf_tdata(cur_got_obj)->got_link_next; -+ while (i != NULL) -+ { -+ if (elf64_sw_64_can_merge_gots (cur_got_obj, i)) -+ { -+ elf64_sw_64_merge_gots (cur_got_obj, i); -+ -+ sw_64_elf_tdata(i)->got->size = 0; -+ i = sw_64_elf_tdata(i)->got_link_next; -+ sw_64_elf_tdata(cur_got_obj)->got_link_next = i; -+ } -+ else -+ { -+ cur_got_obj = i; -+ i = sw_64_elf_tdata(i)->got_link_next; -+ } -+ } -+ } -+ -+ /* Once the gots have been merged, fill in the got offsets for -+ everything therein. */ -+ elf64_sw_64_calc_got_offsets (info); -+ -+ return true; -+} -+ -+ static bool -+elf64_sw_64_size_plt_section_1 (struct sw_64_elf_link_hash_entry *h, -+ void * data) -+{ -+ asection *splt = (asection *) data; -+ struct sw_64_elf_got_entry *gotent; -+ bool saw_one = false; -+ -+ /* If we didn't need an entry before, we still don't. */ -+ if (!h->root.needs_plt) -+ return true; -+ -+ /* For each LITERAL got entry still in use, allocate a plt entry. */ -+ for (gotent = h->got_entries; gotent ; gotent = gotent->next) -+ if (gotent->reloc_type == R_SW_64_LITERAL -+ && gotent->use_count > 0) -+ { -+ if (splt->size == 0) -+ splt->size = PLT_HEADER_SIZE; -+ gotent->plt_offset = splt->size; -+ splt->size += PLT_ENTRY_SIZE; -+ saw_one = true; -+ } -+ -+ /* If there weren't any, there's no longer a need for the PLT entry. */ -+ if (!saw_one) -+ h->root.needs_plt = false; -+ -+ return true; -+} -+ -+/* Called from relax_section to rebuild the PLT in light of potential changes -+ in the function's status. */ -+ -+ static void -+elf64_sw_64_size_plt_section (struct bfd_link_info *info) -+{ -+ asection *splt, *spltrel, *sgotplt; -+ unsigned long entries; -+ struct sw_64_elf_link_hash_table * htab; -+ -+ htab = sw_64_elf_hash_table (info); -+ if (htab == NULL) -+ return; -+ -+ splt = elf_hash_table(info)->splt; -+ if (splt == NULL) -+ return; -+ -+ splt->size = 0; -+ -+ sw_64_elf_link_hash_traverse (htab, -+ elf64_sw_64_size_plt_section_1, splt); -+ -+ /* Every plt entry requires a JMP_SLOT relocation. */ -+ spltrel = elf_hash_table(info)->srelplt; -+ entries = 0; -+ if (splt->size) -+ { -+ if (elf64_sw_64_use_secureplt) -+ entries = (splt->size - NEW_PLT_HEADER_SIZE) / NEW_PLT_ENTRY_SIZE; -+ else -+ entries = (splt->size - OLD_PLT_HEADER_SIZE) / OLD_PLT_ENTRY_SIZE; -+ } -+ spltrel->size = entries * sizeof (Elf64_External_Rela); -+ -+ /* When using the secureplt, we need two words somewhere in the data -+ segment for the dynamic linker to tell us where to go. This is the -+ entire contents of the .got.plt section. */ -+ if (elf64_sw_64_use_secureplt) -+ { -+ sgotplt = elf_hash_table(info)->sgotplt; -+ sgotplt->size = entries ? 16 : 0; -+ } -+} -+ -+ static bool -+elf64_sw_64_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info) -+{ -+ bfd *i; -+ struct sw_64_elf_link_hash_table * htab; -+ -+ if (bfd_link_relocatable (info)) -+ return true; -+ -+ htab = sw_64_elf_hash_table (info); -+ if (htab == NULL) -+ return false; -+ -+ if (!elf64_sw_64_size_got_sections (info, true)) -+ return false; -+ -+ /* Allocate space for all of the .got subsections. */ -+ i = htab->got_list; -+ for ( ; i ; i = sw_64_elf_tdata(i)->got_link_next) -+ { -+ asection *s = sw_64_elf_tdata(i)->got; -+ if (s->size > 0) -+ { -+ s->contents = (bfd_byte *) bfd_zalloc (i, s->size); -+ if (s->contents == NULL) -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+/* The number of dynamic relocations required by a static relocation. */ -+ -+ static int -+sw_64_dynamic_entries_for_reloc (int r_type, int dynamic, int shared, int pie) -+{ -+ switch (r_type) -+ { -+ /* May appear in GOT entries. */ -+ case R_SW_64_TLSGD: -+ return (dynamic ? 2 : shared ? 1 : 0); -+ case R_SW_64_TLSLDM: -+ return shared; -+ case R_SW_64_LITERAL: -+ return dynamic || shared; -+ case R_SW_64_GOTTPREL: -+ return dynamic || (shared && !pie); -+ case R_SW_64_GOTDTPREL: -+ return dynamic; -+ -+ /* May appear in data sections. */ -+ case R_SW_64_REFLONG: -+ case R_SW_64_REFQUAD: -+ return dynamic || shared; -+ case R_SW_64_TPREL64: -+ return dynamic || (shared && !pie); -+ -+ /* Everything else is illegal. We'll issue an error during -+ relocate_section. */ -+ default: -+ return 0; -+ } -+} -+ -+/* Work out the sizes of the dynamic relocation entries. */ -+ -+ static bool -+elf64_sw_64_calc_dynrel_sizes (struct sw_64_elf_link_hash_entry *h, -+ struct bfd_link_info *info) -+{ -+ bool dynamic; -+ struct sw_64_elf_reloc_entry *relent; -+ unsigned long entries; -+ -+ /* If the symbol was defined as a common symbol in a regular object -+ file, and there was no definition in any dynamic object, then the -+ linker will have allocated space for the symbol in a common -+ section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been -+ set. This is done for dynamic symbols in -+ elf_adjust_dynamic_symbol but this is not done for non-dynamic -+ symbols, somehow. */ -+ if (!h->root.def_regular -+ && h->root.ref_regular -+ && !h->root.def_dynamic -+ && (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)) -+ h->root.def_regular = 1; -+ -+ /* If the symbol is dynamic, we'll need all the relocations in their -+ natural form. If this is a shared object, and it has been forced -+ local, we'll need the same number of RELATIVE relocations. */ -+ dynamic = sw_64_elf_dynamic_symbol_p (&h->root, info); -+ -+ /* If the symbol is a hidden undefined weak, then we never have any -+ relocations. Avoid the loop which may want to add RELATIVE relocs -+ based on bfd_link_pic (info). */ -+ if (h->root.root.type == bfd_link_hash_undefweak && !dynamic) -+ return true; -+ -+ for (relent = h->reloc_entries; relent; relent = relent->next) -+ { -+ entries = sw_64_dynamic_entries_for_reloc (relent->rtype, dynamic, -+ bfd_link_pic (info), -+ bfd_link_pie (info)); -+ if (entries) -+ { -+ asection *sec = relent->sec; -+ relent->srel->size += -+ entries * sizeof (Elf64_External_Rela) * relent->count; -+ if ((sec->flags & SEC_READONLY) != 0) -+ { -+ info->flags |= DT_TEXTREL; -+ info->callbacks->minfo -+ (_("%pB: dynamic relocation against `T' in " -+ "read-only section `%pA'\n"), -+ sec->owner, sec); -+ } -+ } -+ } -+ -+ return true; -+} -+ -+/* Subroutine of elf64_sw_64_size_rela_got_section for doing the -+ global symbols. */ -+ -+ static bool -+elf64_sw_64_size_rela_got_1 (struct sw_64_elf_link_hash_entry *h, -+ struct bfd_link_info *info) -+{ -+ bool dynamic; -+ struct sw_64_elf_got_entry *gotent; -+ unsigned long entries; -+ -+ /* If we're using a plt for this symbol, then all of its relocations -+ for its got entries go into .rela.plt. */ -+ if (h->root.needs_plt) -+ return true; -+ -+ /* If the symbol is dynamic, we'll need all the relocations in their -+ natural form. If this is a shared object, and it has been forced -+ local, we'll need the same number of RELATIVE relocations. */ -+ dynamic = sw_64_elf_dynamic_symbol_p (&h->root, info); -+ -+ /* If the symbol is a hidden undefined weak, then we never have any -+ relocations. Avoid the loop which may want to add RELATIVE relocs -+ based on bfd_link_pic (info). */ -+ if (h->root.root.type == bfd_link_hash_undefweak && !dynamic) -+ return true; -+ -+ entries = 0; -+ for (gotent = h->got_entries; gotent ; gotent = gotent->next) -+ if (gotent->use_count > 0) -+ entries += sw_64_dynamic_entries_for_reloc (gotent->reloc_type, dynamic, -+ bfd_link_pic (info), -+ bfd_link_pie (info)); -+ -+ if (entries > 0) -+ { -+ asection *srel = elf_hash_table(info)->srelgot; -+ BFD_ASSERT (srel != NULL); -+ srel->size += sizeof (Elf64_External_Rela) * entries; -+ } -+ -+ return true; -+} -+ -+/* Set the sizes of the dynamic relocation sections. */ -+ -+ static void -+elf64_sw_64_size_rela_got_section (struct bfd_link_info *info) -+{ -+ unsigned long entries; -+ bfd *i; -+ asection *srel; -+ struct sw_64_elf_link_hash_table * htab; -+ -+ htab = sw_64_elf_hash_table (info); -+ if (htab == NULL) -+ return; -+ -+ /* Shared libraries often require RELATIVE relocs, and some relocs -+ require attention for the main application as well. */ -+ -+ entries = 0; -+ for (i = htab->got_list; -+ i ; i = sw_64_elf_tdata(i)->got_link_next) -+ { -+ bfd *j; -+ -+ for (j = i; j ; j = sw_64_elf_tdata(j)->in_got_link_next) -+ { -+ struct sw_64_elf_got_entry **local_got_entries, *gotent; -+ int k, n; -+ -+ local_got_entries = sw_64_elf_tdata(j)->local_got_entries; -+ if (!local_got_entries) -+ continue; -+ -+ for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k) -+ for (gotent = local_got_entries[k]; -+ gotent ; gotent = gotent->next) -+ if (gotent->use_count > 0) -+ entries += (sw_64_dynamic_entries_for_reloc -+ (gotent->reloc_type, 0, bfd_link_pic (info), -+ bfd_link_pie (info))); -+ } -+ } -+ -+ srel = elf_hash_table(info)->srelgot; -+ if (!srel) -+ { -+ BFD_ASSERT (entries == 0); -+ return; -+ } -+ srel->size = sizeof (Elf64_External_Rela) * entries; -+ -+ /* Now do the non-local symbols. */ -+ sw_64_elf_link_hash_traverse (htab, -+ elf64_sw_64_size_rela_got_1, info); -+} -+ -+/* Set the sizes of the dynamic sections. */ -+ -+ static bool -+elf64_sw_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info) -+{ -+ bfd *dynobj; -+ asection *s; -+ bool relplt, relocs; -+ struct sw_64_elf_link_hash_table * htab; -+ -+ htab = sw_64_elf_hash_table (info); -+ if (htab == NULL) -+ return false; -+ -+ 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 (bfd_link_executable (info) && !info->nointerp) -+ { -+ s = bfd_get_linker_section (dynobj, ".interp"); -+ BFD_ASSERT (s != NULL); -+ s->size = sizeof ELF_DYNAMIC_INTERPRETER; -+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; -+ } -+ -+ /* Now that we've seen all of the input files, we can decide which -+ symbols need dynamic relocation entries and which don't. We've -+ collected information in check_relocs that we can now apply to -+ size the dynamic relocation sections. */ -+ sw_64_elf_link_hash_traverse (htab, -+ elf64_sw_64_calc_dynrel_sizes, info); -+ -+ elf64_sw_64_size_rela_got_section (info); -+ elf64_sw_64_size_plt_section (info); -+ } -+ /* else we're not dynamic and by definition we don't need such things. */ -+ -+ /* The check_relocs and adjust_dynamic_symbol entry points have -+ determined the sizes of the various dynamic sections. Allocate -+ memory for them. */ -+ relplt = false; -+ relocs = false; -+ for (s = dynobj->sections; s != NULL; s = s->next) -+ { -+ const char *name; -+ -+ if (!(s->flags & SEC_LINKER_CREATED)) -+ 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_section_name (s); -+ -+ if (startswith (name, ".rela")) -+ { -+ if (s->size != 0) -+ { -+ if (strcmp (name, ".rela.plt") == 0) -+ relplt = true; -+ else -+ relocs = 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 (! startswith (name, ".got") -+ && strcmp (name, ".plt") != 0 -+ && strcmp (name, ".dynbss") != 0) -+ { -+ /* It's not one of our dynamic sections, so don't allocate space. */ -+ continue; -+ } -+ -+ if (s->size == 0) -+ { -+ /* If we don't need this section, strip it from the output file. -+ This is to handle .rela.bss and .rela.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. */ -+ if (!startswith (name, ".got")) -+ s->flags |= SEC_EXCLUDE; -+ } -+ else if ((s->flags & SEC_HAS_CONTENTS) != 0) -+ { -+ /* Allocate memory for the section contents. */ -+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); -+ if (s->contents == NULL) -+ return false; -+ } -+ } -+ -+ if (elf_hash_table (info)->dynamic_sections_created) -+ { -+ /* Add some entries to the .dynamic section. We fill in the -+ values later, in elf64_sw_64_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. */ -+#define add_dynamic_entry(TAG, VAL) \ -+ _bfd_elf_add_dynamic_entry (info, TAG, VAL) -+ -+#ifdef ZZH20210707_SWGNU -+ if (!_bfd_elf_add_dynamic_tags (output_bfd, info, -+ relocs || relplt)) -+ return false; -+ -+ if (relplt -+ && elf64_sw_64_use_secureplt -+ && !add_dynamic_entry (DT_SW_64_PLTRO, 1)) -+ return false; -+#else -+ if (bfd_link_executable (info)) -+ { -+ if (!add_dynamic_entry (DT_DEBUG, 0)) -+ return false; -+ } -+ -+ if (relplt) -+ { -+ if (!add_dynamic_entry (DT_PLTGOT, 0) -+ || !add_dynamic_entry (DT_PLTRELSZ, 0) -+ || !add_dynamic_entry (DT_PLTREL, DT_RELA) -+ || !add_dynamic_entry (DT_JMPREL, 0)) -+ return false; -+ -+ if (elf64_sw_64_use_secureplt -+ && !add_dynamic_entry (DT_SW_64_PLTRO, 1)) -+ return false; -+ } -+ -+ if (relocs) -+ { -+ if (!add_dynamic_entry (DT_RELA, 0) -+ || !add_dynamic_entry (DT_RELASZ, 0) -+ || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) -+ return false; -+ -+ if (info->flags & DF_TEXTREL) -+ { -+ if (!add_dynamic_entry (DT_TEXTREL, 0)) -+ return false; -+ } -+ } -+#endif -+ } -+#undef add_dynamic_entry -+ -+ return true; -+} -+ -+/* These functions do relaxation for Sw_64 ELF. -+ -+ Currently I'm only handling what I can do with existing compiler -+ and assembler support, which means no instructions are removed, -+ though some may be nopped. At this time GCC does not emit enough -+ information to do all of the relaxing that is possible. It will -+ take some not small amount of work for that to happen. -+ -+ There are a couple of interesting papers that I once read on this -+ subject, that I cannot find references to at the moment, that -+ related to Sw_64 in particular. They are by David Wall, then of -+ DEC WRL. */ -+ -+struct sw_64_relax_info -+{ -+ bfd *abfd; -+ asection *sec; -+ bfd_byte *contents; -+ Elf_Internal_Shdr *symtab_hdr; -+ Elf_Internal_Rela *relocs, *relend; -+ struct bfd_link_info *link_info; -+ bfd_vma gp; -+ bfd *gotobj; -+ asection *tsec; -+ struct sw_64_elf_link_hash_entry *h; -+ struct sw_64_elf_got_entry **first_gotent; -+ struct sw_64_elf_got_entry *gotent; -+ bool changed_contents; -+ bool changed_relocs; -+ unsigned char other; -+}; -+ -+ static Elf_Internal_Rela * -+elf64_sw_64_find_reloc_at_ofs (Elf_Internal_Rela *rel, -+ Elf_Internal_Rela *relend, -+ bfd_vma offset, int type) -+{ -+ while (rel < relend) -+ { -+ if (rel->r_offset == offset -+ && ELF64_R_TYPE (rel->r_info) == (unsigned int) type) -+ return rel; -+ ++rel; -+ } -+ return NULL; -+} -+ -+ static bool -+elf64_sw_64_relax_got_load (struct sw_64_relax_info *info, bfd_vma symval, -+ Elf_Internal_Rela *irel, unsigned long r_type) -+{ -+ unsigned int insn; -+ bfd_signed_vma disp; -+ -+ /* Get the instruction. */ -+ insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); -+ -+ if (insn >> 26 != OP_LDL) -+ { -+ reloc_howto_type *howto = elf64_sw_64_howto_table + r_type; -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: %pA+%#" PRIx64 ": warning: " -+ "%s relocation against unexpected insn"), -+ info->abfd, info->sec, (uint64_t) irel->r_offset, howto->name); -+ return true; -+ } -+ -+ /* Can't relax dynamic symbols. */ -+ if (info->h != NULL -+ && sw_64_elf_dynamic_symbol_p (&info->h->root, info->link_info)) -+ return true; -+ -+ /* Can't use local-exec relocations in shared libraries. */ -+ if (r_type == R_SW_64_GOTTPREL -+ && bfd_link_dll (info->link_info)) -+ return true; -+ -+ if (r_type == R_SW_64_LITERAL) -+ { -+ /* Look for nice constant addresses. This includes the not-uncommon -+ special case of 0 for undefweak symbols. */ -+ if ((info->h && info->h->root.root.type == bfd_link_hash_undefweak) -+ || (!bfd_link_pic (info->link_info) -+ && (symval >= (bfd_vma)-0x8000 || symval < 0x8000))) -+ { -+ disp = 0; -+ insn = (OP_LDI << 26) | (insn & (31 << 21)) | (31 << 16); -+ insn |= (symval & 0xffff); -+ r_type = R_SW_64_NONE; -+ } -+ else -+ { -+ /* We may only create GPREL relocs during the second pass. */ -+ if (info->link_info->relax_pass == 0) -+ return true; -+ -+ disp = symval - info->gp; -+ insn = (OP_LDI << 26) | (insn & 0x03ff0000); -+ r_type = R_SW_64_GPREL16; -+ } -+ } -+ else -+ { -+ bfd_vma dtp_base, tp_base; -+ -+ BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL); -+ dtp_base = sw_64_get_dtprel_base (info->link_info); -+ tp_base = sw_64_get_tprel_base (info->link_info); -+ disp = symval - (r_type == R_SW_64_GOTDTPREL ? dtp_base : tp_base); -+ -+ insn = (OP_LDI << 26) | (insn & (31 << 21)) | (31 << 16); -+ -+ switch (r_type) -+ { -+ case R_SW_64_GOTDTPREL: -+ r_type = R_SW_64_DTPREL16; -+ break; -+ case R_SW_64_GOTTPREL: -+ r_type = R_SW_64_TPREL16; -+ break; -+ default: -+ BFD_ASSERT (0); -+ return false; -+ } -+ } -+ -+ if (disp < -0x8000 || disp >= 0x8000) -+ return true; -+ -+ bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset); -+ info->changed_contents = true; -+ -+ /* Reduce the use count on this got entry by one, possibly -+ eliminating it. */ -+ if (--info->gotent->use_count == 0) -+ { -+ int sz = sw_64_got_entry_size (r_type); -+ sw_64_elf_tdata (info->gotobj)->total_got_size -= sz; -+ if (!info->h) -+ sw_64_elf_tdata (info->gotobj)->local_got_size -= sz; -+ } -+ -+ /* Smash the existing GOT relocation for its 16-bit immediate pair. */ -+ irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type); -+ info->changed_relocs = true; -+ -+ /* ??? Search forward through this basic block looking for insns -+ that use the target register. Stop after an insn modifying the -+ register is seen, or after a branch or call. -+ -+ Any such memory load insn may be substituted by a load directly -+ off the GP. This allows the memory load insn to be issued before -+ the calculated GP register would otherwise be ready. -+ -+ Any such jsr insn can be replaced by a bsr if it is in range. -+ -+ This would mean that we'd have to _add_ relocations, the pain of -+ which gives one pause. */ -+ -+ return true; -+} -+ -+ static bfd_vma -+elf64_sw_64_relax_opt_call (struct sw_64_relax_info *info, bfd_vma symval) -+{ -+ /* If the function has the same gp, and we can identify that the -+ function does not use its function pointer, we can eliminate the -+ address load. */ -+ -+ /* If the symbol is marked NOPV, we are being told the function never -+ needs its procedure value. */ -+ if ((info->other & STO_SW_64_STD_GPLOAD) == STO_SW_64_NOPV) -+ return symval; -+ -+ /* If the symbol is marked STD_GP, we are being told the function does -+ a normal ldgp in the first two words. */ -+ else if ((info->other & STO_SW_64_STD_GPLOAD) == STO_SW_64_STD_GPLOAD) -+ ; -+ -+ /* Otherwise, we may be able to identify a GP load in the first two -+ words, which we can then skip. */ -+ else -+ { -+ Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp; -+ bfd_vma ofs; -+ -+ /* Load the relocations from the section that the target symbol is in. */ -+ if (info->sec == info->tsec) -+ { -+ tsec_relocs = info->relocs; -+ tsec_relend = info->relend; -+ tsec_free = NULL; -+ } -+ else -+ { -+ tsec_relocs = (_bfd_elf_link_read_relocs -+ (info->abfd, info->tsec, NULL, -+ (Elf_Internal_Rela *) NULL, -+ info->link_info->keep_memory)); -+ if (tsec_relocs == NULL) -+ return 0; -+ tsec_relend = tsec_relocs + info->tsec->reloc_count; -+ tsec_free = (elf_section_data (info->tsec)->relocs == tsec_relocs -+ ? NULL -+ : tsec_relocs); -+ } -+ -+ /* Recover the symbol's offset within the section. */ -+ ofs = (symval - info->tsec->output_section->vma -+ - info->tsec->output_offset); -+ -+ /* Look for a GPDISP reloc. */ -+ gpdisp = (elf64_sw_64_find_reloc_at_ofs -+ (tsec_relocs, tsec_relend, ofs, R_SW_64_GPDISP)); -+ -+ if (!gpdisp || gpdisp->r_addend != 4) -+ { -+ free (tsec_free); -+ return 0; -+ } -+ free (tsec_free); -+ } -+ -+ /* We've now determined that we can skip an initial gp load. Verify -+ that the call and the target use the same gp. */ -+ if (info->link_info->output_bfd->xvec != info->tsec->owner->xvec -+ || info->gotobj != sw_64_elf_tdata (info->tsec->owner)->gotobj) -+ return 0; -+ -+ return symval + 8; -+} -+ -+ static bool -+elf64_sw_64_relax_with_lituse (struct sw_64_relax_info *info, -+ bfd_vma symval, Elf_Internal_Rela *irel) -+{ -+ Elf_Internal_Rela *urel, *erel, *irelend = info->relend; -+ int flags; -+ bfd_signed_vma disp; -+ bool fits16; -+ bool fits32; -+ bool lit_reused = false; -+ bool all_optimized = true; -+ bool changed_contents; -+ bool changed_relocs; -+ bfd_byte *contents = info->contents; -+ bfd *abfd = info->abfd; -+ bfd_vma sec_output_vma; -+ unsigned int lit_insn; -+ int relax_pass; -+ -+ lit_insn = bfd_get_32 (abfd, contents + irel->r_offset); -+ if (lit_insn >> 26 != OP_LDL) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: %pA+%#" PRIx64 ": warning: " -+ "%s relocation against unexpected insn"), -+ abfd, info->sec, (uint64_t) irel->r_offset, "LITERAL"); -+ return true; -+ } -+ -+ /* Can't relax dynamic symbols. */ -+ if (info->h != NULL && sw_64_elf_dynamic_symbol_p (&info->h->root, info->link_info)) -+ return true; -+ -+ changed_contents = info->changed_contents; -+ changed_relocs = info->changed_relocs; -+ sec_output_vma = info->sec->output_section->vma + info->sec->output_offset; -+ relax_pass = info->link_info->relax_pass; -+ -+ /* Summarize how this particular LITERAL is used. */ -+ for (erel = irel+1, flags = 0; erel < irelend; ++erel) -+ { -+ if (ELF64_R_TYPE (erel->r_info) != R_SW_64_LITUSE) -+ break; -+ if (erel->r_addend <= 6) -+ flags |= 1 << erel->r_addend; -+ } -+ -+ /* A little preparation for the loop... */ -+ disp = symval - info->gp; -+ -+ for (urel = irel+1; urel < erel; ++urel) -+ { -+ bfd_vma urel_r_offset = urel->r_offset; -+ unsigned int insn; -+ int insn_disp; -+ bfd_signed_vma xdisp; -+ Elf_Internal_Rela nrel; -+ -+ insn = bfd_get_32 (abfd, contents + urel_r_offset); -+ -+ switch (urel->r_addend) -+ { -+ case LITUSE_SW_64_ADDR: -+ default: -+ /* This type is really just a placeholder to note that all -+ uses cannot be optimized, but to still allow some. */ -+ all_optimized = false; -+ break; -+ -+ case LITUSE_SW_64_BASE: -+ /* We may only create GPREL relocs during the second pass. */ -+ if (relax_pass == 0) -+ { -+ all_optimized = false; -+ break; -+ } -+ -+ /* We can always optimize 16-bit displacements. */ -+ -+ /* Extract the displacement from the instruction, sign-extending -+ it if necessary, then test whether it is within 16 or 32 bits -+ displacement from GP. */ -+ insn_disp = ((insn & 0xffff) ^ 0x8000) - 0x8000; -+ -+ xdisp = disp + insn_disp; -+ fits16 = (xdisp >= - (bfd_signed_vma) 0x8000 && xdisp < 0x8000); -+ fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000 -+ && xdisp < 0x7fff8000); -+ -+ if (fits16) -+ { -+ /* Take the op code and dest from this insn, take the base -+ register from the literal insn. Leave the offset alone. */ -+ insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000); -+ bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); -+ changed_contents = true; -+ -+ nrel = *urel; -+ nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), -+ R_SW_64_GPREL16); -+ nrel.r_addend = irel->r_addend; -+ -+ /* As we adjust, move the reloc to the end so that we don't -+ break the LITERAL+LITUSE chain. */ -+ if (urel < --erel) -+ *urel-- = *erel; -+ *erel = nrel; -+ changed_relocs = true; -+ } -+ -+ /* If all mem+byte, we can optimize 32-bit mem displacements. */ -+ else if (fits32 && !(flags & ~6)) -+ { -+ /* FIXME: sanity check that lit insn Ra is mem insn Rb. */ -+ -+ irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), -+ R_SW_64_GPRELHIGH); -+ lit_insn = (OP_LDIH << 26) | (lit_insn & 0x03ff0000); -+ bfd_put_32 (abfd, (bfd_vma) lit_insn, contents + irel->r_offset); -+ lit_reused = true; -+ changed_contents = true; -+ -+ /* Since all relocs must be optimized, don't bother swapping -+ this relocation to the end. */ -+ urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), -+ R_SW_64_GPRELLOW); -+ urel->r_addend = irel->r_addend; -+ changed_relocs = true; -+ } -+ else -+ all_optimized = false; -+ break; -+ -+ case LITUSE_SW_64_BYTOFF: -+ /* We can always optimize byte instructions. */ -+ -+ /* FIXME: sanity check the insn for byte op. Check that the -+ literal dest reg is indeed Rb in the byte insn. */ -+ -+ insn &= ~ (unsigned) 0x001ff000; -+ insn |= ((symval & 7) << 13) | 0x1000; -+ bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); -+ changed_contents = true; -+ -+ nrel = *urel; -+ nrel.r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ nrel.r_addend = 0; -+ -+ /* As we adjust, move the reloc to the end so that we don't -+ break the LITERAL+LITUSE chain. */ -+ if (urel < --erel) -+ *urel-- = *erel; -+ *erel = nrel; -+ changed_relocs = true; -+ break; -+ -+ case LITUSE_SW_64_JSR: -+ case LITUSE_SW_64_TLSGD: -+ case LITUSE_SW_64_TLSLDM: -+ case LITUSE_SW_64_JSRDIRECT: -+ { -+ bfd_vma optdest, org; -+ bfd_signed_vma odisp; -+ -+ /* For undefined weak symbols, we're mostly interested in getting -+ rid of the got entry whenever possible, so optimize this to a -+ use of the zero register. */ -+ if (info->h && info->h->root.root.type == bfd_link_hash_undefweak) -+ { -+ insn |= 31 << 16; -+ bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); -+ -+ changed_contents = true; -+ break; -+ } -+ -+ /* If not zero, place to jump without needing pv. */ -+ optdest = elf64_sw_64_relax_opt_call (info, symval); -+ org = sec_output_vma + urel_r_offset + 4; -+ odisp = (optdest ? optdest : symval) - org; -+ -+ if (odisp >= -0x400000 && odisp < 0x400000) -+ { -+ Elf_Internal_Rela *xrel; -+ -+ /* Preserve branch prediction call stack when possible. */ -+ if ((insn & INSN_JSR_MASK) == INSN_JSR) -+ insn = (OP_BSR << 26) | (insn & 0x03e00000); -+ else -+ insn = (OP_BR << 26) | (insn & 0x03e00000); -+ bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); -+ changed_contents = true; -+ -+ nrel = *urel; -+ nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), -+ R_SW_64_BRADDR); -+ nrel.r_addend = irel->r_addend; -+ -+ if (optdest) -+ nrel.r_addend += optdest - symval; -+ else -+ all_optimized = false; -+ -+ /* Kill any HINT reloc that might exist for this insn. */ -+ xrel = (elf64_sw_64_find_reloc_at_ofs -+ (info->relocs, info->relend, urel_r_offset, -+ R_SW_64_HINT)); -+ if (xrel) -+ xrel->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ -+ /* As we adjust, move the reloc to the end so that we don't -+ break the LITERAL+LITUSE chain. */ -+ if (urel < --erel) -+ *urel-- = *erel; -+ *erel = nrel; -+ -+ info->changed_relocs = true; -+ } -+ else -+ all_optimized = false; -+ -+ /* Even if the target is not in range for a direct branch, -+ if we share a GP, we can eliminate the gp reload. */ -+ if (optdest) -+ { -+ Elf_Internal_Rela *gpdisp -+ = (elf64_sw_64_find_reloc_at_ofs -+ (info->relocs, irelend, urel_r_offset + 4, -+ R_SW_64_GPDISP)); -+ if (gpdisp) -+ { -+ bfd_byte *p_ldih = contents + gpdisp->r_offset; -+ bfd_byte *p_ldi = p_ldih + gpdisp->r_addend; -+ unsigned int ldih = bfd_get_32 (abfd, p_ldih); -+ unsigned int ldi = bfd_get_32 (abfd, p_ldi); -+ -+ /* Verify that the instruction is "ldih $29,0($26)". -+ Consider a function that ends in a noreturn call, -+ and that the next function begins with an ldgp, -+ and that by accident there is no padding between. -+ In that case the insn would use $27 as the base. */ -+ -+ if (ldih == 0xffba0000 && ldi == 0xfbba0000) -+ { -+ bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_ldih); -+ bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_ldi); -+ -+ gpdisp->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ changed_contents = true; -+ changed_relocs = true; -+ } -+ } -+ } -+ } -+ break; -+ } -+ } -+ -+ /* If we reused the literal instruction, we must have optimized all. */ -+ BFD_ASSERT(!lit_reused || all_optimized); -+ -+ /* If all cases were optimized, we can reduce the use count on this -+ got entry by one, possibly eliminating it. */ -+ if (all_optimized) -+ { -+ if (--info->gotent->use_count == 0) -+ { -+ int sz = sw_64_got_entry_size (R_SW_64_LITERAL); -+ sw_64_elf_tdata (info->gotobj)->total_got_size -= sz; -+ if (!info->h) -+ sw_64_elf_tdata (info->gotobj)->local_got_size -= sz; -+ } -+ -+ /* If the literal instruction is no longer needed (it may have been -+ reused. We can eliminate it. */ -+ /* ??? For now, I don't want to deal with compacting the section, -+ so just nop it out. */ -+ if (!lit_reused) -+ { -+ /* this will cause sw_64/brk.S err. */ -+ if (ELF64_R_TYPE ((irel-1)->r_info) == R_SW_64_LITERAL_GOT) -+ { -+ (irel-1)->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ changed_relocs = true; -+ -+ bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, contents + (irel-1)->r_offset); -+ } -+ irel->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ changed_relocs = true; -+ -+ bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, contents + irel->r_offset); -+ changed_contents = true; -+ } -+ } -+ -+ info->changed_contents = changed_contents; -+ info->changed_relocs = changed_relocs; -+ -+ if (all_optimized || relax_pass == 0) -+ return true; -+ return elf64_sw_64_relax_got_load (info, symval, irel, R_SW_64_LITERAL); -+} -+ -+ static bool -+elf64_sw_64_relax_tls_get_addr (struct sw_64_relax_info *info, bfd_vma symval, -+ Elf_Internal_Rela *irel, bool is_gd) -+{ -+ bfd_byte *pos[5]; -+ unsigned int insn, tlsgd_reg; -+ Elf_Internal_Rela *gpdisp, *hint; -+ bool dynamic, use_gottprel; -+ unsigned long new_symndx; -+ -+ dynamic = (info->h != NULL -+ && sw_64_elf_dynamic_symbol_p (&info->h->root, info->link_info)); -+ -+ /* If a TLS symbol is accessed using IE at least once, there is no point -+ to use dynamic model for it. */ -+ if (is_gd && info->h && (info->h->flags & SW_64_ELF_LINK_HASH_TLS_IE)) -+ ; -+ -+ /* If the symbol is local, and we've already committed to DF_STATIC_TLS, -+ then we might as well relax to IE. */ -+ else if (bfd_link_pic (info->link_info) && !dynamic -+ && (info->link_info->flags & DF_STATIC_TLS)) -+ ; -+ -+ /* Otherwise we must be building an executable to do anything. */ -+ else if (bfd_link_pic (info->link_info)) -+ return true; -+ -+ /* The TLSGD/TLSLDM relocation must be followed by a LITERAL and -+ the matching LITUSE_TLS relocations. */ -+ if (irel + 2 >= info->relend) -+ return true; -+ if (ELF64_R_TYPE (irel[1].r_info) != R_SW_64_LITERAL -+ || ELF64_R_TYPE (irel[2].r_info) != R_SW_64_LITUSE -+ || irel[2].r_addend != (is_gd ? LITUSE_SW_64_TLSGD : LITUSE_SW_64_TLSLDM)) -+ return true; -+ -+ /* There must be a GPDISP relocation positioned immediately after the -+ LITUSE relocation. */ -+ gpdisp = elf64_sw_64_find_reloc_at_ofs (info->relocs, info->relend, -+ irel[2].r_offset + 4, R_SW_64_GPDISP); -+ if (!gpdisp) -+ return true; -+ -+ pos[0] = info->contents + irel[0].r_offset; -+ pos[1] = info->contents + irel[1].r_offset; -+ pos[2] = info->contents + irel[2].r_offset; -+ pos[3] = info->contents + gpdisp->r_offset; -+ pos[4] = pos[3] + gpdisp->r_addend; -+ -+ /* Beware of the compiler hoisting part of the sequence out a loop -+ and adjusting the destination register for the TLSGD insn. If this -+ happens, there will be a move into $16 before the JSR insn, so only -+ transformations of the first insn pair should use this register. */ -+ tlsgd_reg = bfd_get_32 (info->abfd, pos[0]); -+ tlsgd_reg = (tlsgd_reg >> 21) & 31; -+ -+ /* Generally, the positions are not allowed to be out of order, lest the -+ modified insn sequence have different register lifetimes. We can make -+ an exception when pos 1 is adjacent to pos 0. */ -+ if (pos[1] + 4 == pos[0]) -+ { -+ bfd_byte *tmp = pos[0]; -+ pos[0] = pos[1]; -+ pos[1] = tmp; -+ } -+ if (pos[1] >= pos[2] || pos[2] >= pos[3]) -+ return true; -+ -+ /* Reduce the use count on the LITERAL relocation. Do this before we -+ smash the symndx when we adjust the relocations below. */ -+ { -+ struct sw_64_elf_got_entry *lit_gotent; -+ struct sw_64_elf_link_hash_entry *lit_h; -+ unsigned long indx; -+ -+ BFD_ASSERT (ELF64_R_SYM (irel[1].r_info) >= info->symtab_hdr->sh_info); -+ indx = ELF64_R_SYM (irel[1].r_info) - info->symtab_hdr->sh_info; -+ lit_h = sw_64_elf_sym_hashes (info->abfd)[indx]; -+ -+ while (lit_h->root.root.type == bfd_link_hash_indirect -+ || lit_h->root.root.type == bfd_link_hash_warning) -+ lit_h = (struct sw_64_elf_link_hash_entry *) lit_h->root.root.u.i.link; -+ -+ for (lit_gotent = lit_h->got_entries; lit_gotent ; -+ lit_gotent = lit_gotent->next) -+ if (lit_gotent->gotobj == info->gotobj -+ && lit_gotent->reloc_type == R_SW_64_LITERAL -+ && lit_gotent->addend == irel[1].r_addend) -+ break; -+ BFD_ASSERT (lit_gotent); -+ -+ if (--lit_gotent->use_count == 0) -+ { -+ int sz = sw_64_got_entry_size (R_SW_64_LITERAL); -+ sw_64_elf_tdata (info->gotobj)->total_got_size -= sz; -+ } -+ } -+ -+ /* Change -+ -+ ldi $16,x($gp) !tlsgd!1 -+ ldl $27,__tls_get_addr($gp) !literal!1 -+ jsr $26,($27),__tls_get_addr !lituse_tlsgd!1 -+ ldih $29,0($26) !gpdisp!2 -+ ldi $29,0($29) !gpdisp!2 -+ to -+ ldl $16,x($gp) !gottprel -+ unop -+ call_pal rduniq -+ addl $16,$0,$0 -+ unop -+ or the first pair to -+ ldi $16,x($gp) !tprel -+ unop -+ or -+ ldih $16,x($gp) !tprelhi -+ ldi $16,x($16) !tprello -+ -+ as appropriate. */ -+ -+ use_gottprel = false; -+ new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : STN_UNDEF; -+ -+ /* Some compilers warn about a Boolean-looking expression being -+ used in a switch. The explicit cast silences them. */ -+ switch ((int) (!dynamic && !bfd_link_pic (info->link_info))) -+ { -+ case 1: -+ { -+ bfd_vma tp_base; -+ bfd_signed_vma disp; -+ -+ BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL); -+ tp_base = sw_64_get_tprel_base (info->link_info); -+ disp = symval - tp_base; -+ -+ if (disp >= -0x8000 && disp < 0x8000) -+ { -+ insn = (OP_LDI << 26) | (tlsgd_reg << 21) | (31 << 16); -+ bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); -+ bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]); -+ -+ irel[0].r_offset = pos[0] - info->contents; -+ irel[0].r_info = ELF64_R_INFO (new_symndx, R_SW_64_TPREL16); -+ irel[1].r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ break; -+ } -+ else if (disp >= -(bfd_signed_vma) 0x80000000 -+ && disp < (bfd_signed_vma) 0x7fff8000 -+ && pos[0] + 4 == pos[1]) -+ { -+ insn = (OP_LDIH << 26) | (tlsgd_reg << 21) | (31 << 16); -+ bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); -+ insn = (OP_LDI << 26) | (tlsgd_reg << 21) | (tlsgd_reg << 16); -+ bfd_put_32 (info->abfd, (bfd_vma) insn, pos[1]); -+ -+ irel[0].r_offset = pos[0] - info->contents; -+ irel[0].r_info = ELF64_R_INFO (new_symndx, R_SW_64_TPRELHI); -+ irel[1].r_offset = pos[1] - info->contents; -+ irel[1].r_info = ELF64_R_INFO (new_symndx, R_SW_64_TPRELLO); -+ break; -+ } -+ } -+ /* FALLTHRU */ -+ -+ default: -+ use_gottprel = true; -+ -+ insn = (OP_LDL << 26) | (tlsgd_reg << 21) | (29 << 16); -+ bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); -+ bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]); -+ -+ irel[0].r_offset = pos[0] - info->contents; -+ irel[0].r_info = ELF64_R_INFO (new_symndx, R_SW_64_GOTTPREL); -+ irel[1].r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ break; -+ } -+ -+ bfd_put_32 (info->abfd, (bfd_vma) INSN_RDUNIQ, pos[2]); -+ -+ insn = INSN_ADDL | (16 << 21) | (0 << 16) | (0 << 0); -+ bfd_put_32 (info->abfd, (bfd_vma) insn, pos[3]); -+ -+ bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[4]); -+ -+ irel[2].r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ gpdisp->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ -+ hint = elf64_sw_64_find_reloc_at_ofs (info->relocs, info->relend, -+ irel[2].r_offset, R_SW_64_HINT); -+ if (hint) -+ hint->r_info = ELF64_R_INFO (0, R_SW_64_NONE); -+ -+ info->changed_contents = true; -+ info->changed_relocs = true; -+ -+ /* Reduce the use count on the TLSGD/TLSLDM relocation. */ -+ if (--info->gotent->use_count == 0) -+ { -+ int sz = sw_64_got_entry_size (info->gotent->reloc_type); -+ sw_64_elf_tdata (info->gotobj)->total_got_size -= sz; -+ if (!info->h) -+ sw_64_elf_tdata (info->gotobj)->local_got_size -= sz; -+ } -+ -+ /* If we've switched to a GOTTPREL relocation, increment the reference -+ count on that got entry. */ -+ if (use_gottprel) -+ { -+ struct sw_64_elf_got_entry *tprel_gotent; -+ -+ for (tprel_gotent = *info->first_gotent; tprel_gotent ; -+ tprel_gotent = tprel_gotent->next) -+ if (tprel_gotent->gotobj == info->gotobj -+ && tprel_gotent->reloc_type == R_SW_64_GOTTPREL -+ && tprel_gotent->addend == irel->r_addend) -+ break; -+ if (tprel_gotent) -+ tprel_gotent->use_count++; -+ else -+ { -+ if (info->gotent->use_count == 0) -+ tprel_gotent = info->gotent; -+ else -+ { -+ tprel_gotent = (struct sw_64_elf_got_entry *) -+ bfd_alloc (info->abfd, sizeof (struct sw_64_elf_got_entry)); -+ if (!tprel_gotent) -+ return false; -+ -+ tprel_gotent->next = *info->first_gotent; -+ *info->first_gotent = tprel_gotent; -+ -+ tprel_gotent->gotobj = info->gotobj; -+ tprel_gotent->addend = irel->r_addend; -+ tprel_gotent->got_offset = -1; -+ tprel_gotent->reloc_done = 0; -+ tprel_gotent->reloc_xlated = 0; -+ } -+ -+ tprel_gotent->use_count = 1; -+ tprel_gotent->reloc_type = R_SW_64_GOTTPREL; -+ } -+ } -+ -+ return true; -+} -+ -+ static bool -+elf64_sw_64_relax_section (bfd *abfd, asection *sec, -+ struct bfd_link_info *link_info, bool *again) -+{ -+ Elf_Internal_Shdr *symtab_hdr; -+ Elf_Internal_Rela *internal_relocs; -+ Elf_Internal_Rela *irel, *irelend; -+ Elf_Internal_Sym *isymbuf = NULL; -+ struct sw_64_elf_got_entry **local_got_entries; -+ struct sw_64_relax_info info; -+ struct sw_64_elf_link_hash_table * htab; -+ int relax_pass; -+ -+ htab = sw_64_elf_hash_table (link_info); -+ if (htab == NULL) -+ return false; -+ -+ /* There's nothing to change, yet. */ -+ *again = false; -+ -+ if (bfd_link_relocatable (link_info) -+ || ((sec->flags & (SEC_CODE | SEC_RELOC | SEC_ALLOC)) -+ != (SEC_CODE | SEC_RELOC | SEC_ALLOC)) -+ || sec->reloc_count == 0) -+ return true; -+ -+ BFD_ASSERT (is_sw_64_elf (abfd)); -+ relax_pass = link_info->relax_pass; -+ -+ /* Make sure our GOT and PLT tables are up-to-date. */ -+ if (htab->relax_trip != link_info->relax_trip) -+ { -+ htab->relax_trip = link_info->relax_trip; -+ -+ /* This should never fail after the initial round, since the only error -+ is GOT overflow, and relaxation only shrinks the table. However, we -+ may only merge got sections during the first pass. If we merge -+ sections after we've created GPREL relocs, the GP for the merged -+ section backs up which may put the relocs out of range. */ -+ if (!elf64_sw_64_size_got_sections (link_info, relax_pass == 0)) -+ abort (); -+ if (elf_hash_table (link_info)->dynamic_sections_created) -+ { -+ elf64_sw_64_size_plt_section (link_info); -+ elf64_sw_64_size_rela_got_section (link_info); -+ } -+ } -+ -+ symtab_hdr = &elf_symtab_hdr (abfd); -+ local_got_entries = sw_64_elf_tdata(abfd)->local_got_entries; -+ -+ /* Load the relocations for this section. */ -+ internal_relocs = (_bfd_elf_link_read_relocs -+ (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, -+ link_info->keep_memory)); -+ if (internal_relocs == NULL) -+ return false; -+ -+ memset(&info, 0, sizeof (info)); -+ info.abfd = abfd; -+ info.sec = sec; -+ info.link_info = link_info; -+ info.symtab_hdr = symtab_hdr; -+ info.relocs = internal_relocs; -+ info.relend = irelend = internal_relocs + sec->reloc_count; -+ -+ /* Find the GP for this object. Do not store the result back via -+ _bfd_set_gp_value, since this could change again before final. */ -+ info.gotobj = sw_64_elf_tdata (abfd)->gotobj; -+ if (info.gotobj) -+ { -+ asection *sgot = sw_64_elf_tdata (info.gotobj)->got; -+ info.gp = (sgot->output_section->vma -+ + sgot->output_offset -+ + 0x8000); -+ } -+ -+ /* Get the section contents. */ -+ if (elf_section_data (sec)->this_hdr.contents != NULL) -+ info.contents = elf_section_data (sec)->this_hdr.contents; -+ else -+ { -+ if (!bfd_malloc_and_get_section (abfd, sec, &info.contents)) -+ goto error_return; -+ } -+ -+ for (irel = internal_relocs; irel < irelend; irel++) -+ { -+ bfd_vma symval; -+ struct sw_64_elf_got_entry *gotent; -+ unsigned long r_type = ELF64_R_TYPE (irel->r_info); -+ unsigned long r_symndx = ELF64_R_SYM (irel->r_info); -+ -+ /* Early exit for unhandled or unrelaxable relocations. */ -+ if (r_type != R_SW_64_LITERAL) -+ { -+ /* We complete everything except LITERAL in the first pass. */ -+ if (relax_pass != 0) -+ continue; -+ if (r_type == R_SW_64_TLSLDM) -+ { -+ /* The symbol for a TLSLDM reloc is ignored. Collapse the -+ reloc to the STN_UNDEF (0) symbol so that they all match. */ -+ r_symndx = STN_UNDEF; -+ } -+ else if (r_type != R_SW_64_GOTDTPREL -+ && r_type != R_SW_64_GOTTPREL -+ && r_type != R_SW_64_TLSGD) -+ continue; -+ } -+ -+ /* Get the value of the symbol referred to by the reloc. */ -+ if (r_symndx < symtab_hdr->sh_info) -+ { -+ /* A local symbol. */ -+ Elf_Internal_Sym *isym; -+ -+ /* Read this BFD's local symbols. */ -+ if (isymbuf == NULL) -+ { -+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; -+ if (isymbuf == NULL) -+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, -+ symtab_hdr->sh_info, 0, -+ NULL, NULL, NULL); -+ if (isymbuf == NULL) -+ goto error_return; -+ } -+ -+ isym = isymbuf + r_symndx; -+ -+ /* Given the symbol for a TLSLDM reloc is ignored, this also -+ means forcing the symbol value to the tp base. */ -+ if (r_type == R_SW_64_TLSLDM) -+ { -+ info.tsec = bfd_abs_section_ptr; -+ symval = sw_64_get_tprel_base (info.link_info); -+ } -+ else -+ { -+ symval = isym->st_value; -+ if (isym->st_shndx == SHN_UNDEF) -+ continue; -+ else if (isym->st_shndx == SHN_ABS) -+ info.tsec = bfd_abs_section_ptr; -+ else if (isym->st_shndx == SHN_COMMON) -+ info.tsec = bfd_com_section_ptr; -+ else -+ info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); -+ } -+ -+ info.h = NULL; -+ info.other = isym->st_other; -+ if (local_got_entries) -+ info.first_gotent = &local_got_entries[r_symndx]; -+ else -+ { -+ info.first_gotent = &info.gotent; -+ info.gotent = NULL; -+ } -+ } -+ else -+ { -+ unsigned long indx; -+ struct sw_64_elf_link_hash_entry *h; -+ -+ indx = r_symndx - symtab_hdr->sh_info; -+ h = sw_64_elf_sym_hashes (abfd)[indx]; -+ BFD_ASSERT (h != NULL); -+ -+ while (h->root.root.type == bfd_link_hash_indirect -+ || h->root.root.type == bfd_link_hash_warning) -+ h = (struct sw_64_elf_link_hash_entry *)h->root.root.u.i.link; -+ -+ /* If the symbol is undefined, we can't do anything with it. */ -+ if (h->root.root.type == bfd_link_hash_undefined) -+ continue; -+ -+ /* If the symbol isn't defined in the current module, -+ again we can't do anything. */ -+ if (h->root.root.type == bfd_link_hash_undefweak) -+ { -+ info.tsec = bfd_abs_section_ptr; -+ symval = 0; -+ } -+ else if (!h->root.def_regular) -+ { -+ /* Except for TLSGD relocs, which can sometimes be -+ relaxed to GOTTPREL relocs. */ -+ if (r_type != R_SW_64_TLSGD) -+ continue; -+ info.tsec = bfd_abs_section_ptr; -+ symval = 0; -+ } -+ else -+ { -+ info.tsec = h->root.root.u.def.section; -+ symval = h->root.root.u.def.value; -+ } -+ -+ info.h = h; -+ info.other = h->root.other; -+ info.first_gotent = &h->got_entries; -+ } -+ -+ /* Search for the got entry to be used by this relocation. */ -+ for (gotent = *info.first_gotent; gotent ; gotent = gotent->next) -+ if (gotent->gotobj == info.gotobj -+ && gotent->reloc_type == r_type -+ && gotent->addend == irel->r_addend) -+ break; -+ info.gotent = gotent; -+ -+ symval += info.tsec->output_section->vma + info.tsec->output_offset; -+ symval += irel->r_addend; -+ -+ switch (r_type) -+ { -+ case R_SW_64_LITERAL: -+ BFD_ASSERT(info.gotent != NULL); -+ -+ /* If there exist LITUSE relocations immediately following, this -+ opens up all sorts of interesting optimizations, because we -+ now know every location that this address load is used. */ -+ if (irel+1 < irelend -+ && ELF64_R_TYPE (irel[1].r_info) == R_SW_64_LITUSE) -+ { -+ if (!elf64_sw_64_relax_with_lituse (&info, symval, irel)) -+ goto error_return; -+ } -+ else -+ { -+ if (!elf64_sw_64_relax_got_load (&info, symval, irel, r_type)) -+ goto error_return; -+ } -+ break; -+ -+ case R_SW_64_GOTDTPREL: -+ case R_SW_64_GOTTPREL: -+ BFD_ASSERT(info.gotent != NULL); -+ if (!elf64_sw_64_relax_got_load (&info, symval, irel, r_type)) -+ goto error_return; -+ break; -+ -+ case R_SW_64_TLSGD: -+ case R_SW_64_TLSLDM: -+ BFD_ASSERT(info.gotent != NULL); -+ if (!elf64_sw_64_relax_tls_get_addr (&info, symval, irel, -+ r_type == R_SW_64_TLSGD)) -+ goto error_return; -+ break; -+ } -+ } -+ -+ if (isymbuf != NULL -+ && symtab_hdr->contents != (unsigned char *) isymbuf) -+ { -+ if (!link_info->keep_memory) -+ free (isymbuf); -+ else -+ { -+ /* Cache the symbols for elf_link_input_bfd. */ -+ symtab_hdr->contents = (unsigned char *) isymbuf; -+ } -+ } -+ -+ if (info.contents != NULL -+ && elf_section_data (sec)->this_hdr.contents != info.contents) -+ { -+ if (!info.changed_contents && !link_info->keep_memory) -+ free (info.contents); -+ else -+ { -+ /* Cache the section contents for elf_link_input_bfd. */ -+ elf_section_data (sec)->this_hdr.contents = info.contents; -+ } -+ } -+ -+ if (elf_section_data (sec)->relocs != internal_relocs) -+ { -+ if (!info.changed_relocs) -+ free (internal_relocs); -+ else -+ elf_section_data (sec)->relocs = internal_relocs; -+ } -+ -+ *again = info.changed_contents || info.changed_relocs; -+ -+ return true; -+ -+error_return: -+ if (symtab_hdr->contents != (unsigned char *) isymbuf) -+ free (isymbuf); -+ if (elf_section_data (sec)->this_hdr.contents != info.contents) -+ free (info.contents); -+ if (elf_section_data (sec)->relocs != internal_relocs) -+ free (internal_relocs); -+ return false; -+} -+ -+/* Emit a dynamic relocation for (DYNINDX, RTYPE, ADDEND) at (SEC, OFFSET) -+ into the next available slot in SREL. */ -+ -+ static void -+elf64_sw_64_emit_dynrel (bfd *abfd, struct bfd_link_info *info, -+ asection *sec, asection *srel, bfd_vma offset, -+ long dynindx, long rtype, bfd_vma addend) -+{ -+ Elf_Internal_Rela outrel; -+ bfd_byte *loc; -+ -+ BFD_ASSERT (srel != NULL); -+ -+ outrel.r_info = ELF64_R_INFO (dynindx, rtype); -+ outrel.r_addend = addend; -+ -+ offset = _bfd_elf_section_offset (abfd, info, sec, offset); -+ if ((offset | 1) != (bfd_vma) -1) -+ outrel.r_offset = sec->output_section->vma + sec->output_offset + offset; -+ else -+ memset (&outrel, 0, sizeof (outrel)); -+ -+ loc = srel->contents; -+ loc += srel->reloc_count++ * sizeof (Elf64_External_Rela); -+ bfd_elf64_swap_reloca_out (abfd, &outrel, loc); -+ BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count <= srel->size); -+} -+ -+/* Relocate an Sw_64 ELF section for a relocatable 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. */ -+ -+ static bool -+elf64_sw_64_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info ATTRIBUTE_UNUSED, -+ bfd *input_bfd, asection *input_section, -+ bfd_byte *contents ATTRIBUTE_UNUSED, -+ Elf_Internal_Rela *relocs, -+ Elf_Internal_Sym *local_syms, -+ asection **local_sections) -+{ -+ unsigned long symtab_hdr_sh_info; -+ Elf_Internal_Rela *rel; -+ Elf_Internal_Rela *relend; -+ struct elf_link_hash_entry **sym_hashes; -+ bool ret_val = true; -+ -+ symtab_hdr_sh_info = elf_symtab_hdr (input_bfd).sh_info; -+ sym_hashes = elf_sym_hashes (input_bfd); -+ -+ relend = relocs + input_section->reloc_count; -+ for (rel = relocs; rel < relend; rel++) -+ { -+ unsigned long r_symndx; -+ Elf_Internal_Sym *sym; -+ asection *sec; -+ unsigned long r_type; -+ -+ r_type = ELF64_R_TYPE (rel->r_info); -+ if (r_type >= R_SW_64_max) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: unsupported relocation type %#x"), -+ input_bfd, (int) r_type); -+ bfd_set_error (bfd_error_bad_value); -+ ret_val = false; -+ continue; -+ } -+ -+ /* The symbol associated with GPDISP and LITUSE is -+ immaterial. Only the addend is significant. */ -+ if (r_type == R_SW_64_GPDISP || r_type == R_SW_64_LITUSE) -+ continue; -+ -+ r_symndx = ELF64_R_SYM (rel->r_info); -+ if (r_symndx < symtab_hdr_sh_info) -+ { -+ sym = local_syms + r_symndx; -+ sec = local_sections[r_symndx]; -+ } -+ else -+ { -+ struct elf_link_hash_entry *h; -+ -+ h = sym_hashes[r_symndx - symtab_hdr_sh_info]; -+ -+ while (h->root.type == bfd_link_hash_indirect -+ || h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ -+ if (h->root.type != bfd_link_hash_defined -+ && h->root.type != bfd_link_hash_defweak) -+ continue; -+ -+ sym = NULL; -+ sec = h->root.u.def.section; -+ } -+ -+ if (sec != NULL && discarded_section (sec)) -+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, -+ rel, 1, relend, -+ elf64_sw_64_howto_table + r_type, 0, -+ contents); -+ -+ if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) -+ rel->r_addend += sec->output_offset; -+ } -+ -+ return ret_val; -+} -+ -+/* Relocate an Sw_64 ELF section. */ -+ -+ static bool -+elf64_sw_64_relocate_section (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; -+ asection *sgot, *srel, *srelgot; -+ bfd *dynobj, *gotobj; -+ bfd_vma gp, tp_base, dtp_base; -+ struct sw_64_elf_got_entry **local_got_entries; -+ bool ret_val; -+ -+ BFD_ASSERT (is_sw_64_elf (input_bfd)); -+ -+ /* Handle relocatable links with a smaller loop. */ -+ if (bfd_link_relocatable (info)) -+ return elf64_sw_64_relocate_section_r (output_bfd, info, input_bfd, -+ input_section, contents, relocs, -+ local_syms, local_sections); -+ -+ /* This is a final link. */ -+ -+ ret_val = true; -+ -+ symtab_hdr = &elf_symtab_hdr (input_bfd); -+ -+ dynobj = elf_hash_table (info)->dynobj; -+ srelgot = elf_hash_table (info)->srelgot; -+ -+ if (input_section->flags & SEC_ALLOC) -+ { -+ const char *section_name; -+ section_name = (bfd_elf_string_from_elf_section -+ (input_bfd, elf_elfheader(input_bfd)->e_shstrndx, -+ _bfd_elf_single_rel_hdr (input_section)->sh_name)); -+ BFD_ASSERT(section_name != NULL); -+ srel = bfd_get_linker_section (dynobj, section_name); -+ } -+ else -+ srel = NULL; -+ -+ /* Find the gp value for this input bfd. */ -+ gotobj = sw_64_elf_tdata (input_bfd)->gotobj; -+ if (gotobj) -+ { -+ sgot = sw_64_elf_tdata (gotobj)->got; -+ gp = _bfd_get_gp_value (gotobj); -+ if (gp == 0) -+ { -+ gp = (sgot->output_section->vma -+ + sgot->output_offset -+ + 0x8000); -+ _bfd_set_gp_value (gotobj, gp); -+ } -+ } -+ else -+ { -+ sgot = NULL; -+ gp = 0; -+ } -+ -+ local_got_entries = sw_64_elf_tdata(input_bfd)->local_got_entries; -+ -+ if (elf_hash_table (info)->tls_sec != NULL) -+ { -+ dtp_base = sw_64_get_dtprel_base (info); -+ tp_base = sw_64_get_tprel_base (info); -+ } -+ else -+ dtp_base = tp_base = 0; -+ -+ relend = relocs + input_section->reloc_count; -+ for (rel = relocs; rel < relend; rel++) -+ { -+ struct sw_64_elf_link_hash_entry *h = NULL; -+ struct sw_64_elf_got_entry *gotent; -+ bfd_reloc_status_type r; -+ reloc_howto_type *howto; -+ unsigned long r_symndx; -+ Elf_Internal_Sym *sym = NULL; -+ asection *sec = NULL; -+ bfd_vma value; -+ bfd_vma addend; -+ bool dynamic_symbol_p; -+ bool unresolved_reloc = false; -+ bool undef_weak_ref = false; -+ unsigned long r_type; -+ -+ r_type = ELF64_R_TYPE(rel->r_info); -+ if (r_type >= R_SW_64_max) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: unsupported relocation type %#x"), -+ input_bfd, (int) r_type); -+ bfd_set_error (bfd_error_bad_value); -+ ret_val = false; -+ continue; -+ } -+ -+ howto = elf64_sw_64_howto_table + r_type; -+ r_symndx = ELF64_R_SYM(rel->r_info); -+ -+ /* The symbol for a TLSLDM reloc is ignored. Collapse the -+ reloc to the STN_UNDEF (0) symbol so that they all match. */ -+ if (r_type == R_SW_64_TLSLDM) -+ r_symndx = STN_UNDEF; -+ -+ if (r_symndx < symtab_hdr->sh_info) -+ { -+ asection *msec; -+ sym = local_syms + r_symndx; -+ sec = local_sections[r_symndx]; -+ msec = sec; -+ value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel); -+ -+ /* If this is a tp-relative relocation against sym STN_UNDEF (0), -+ this is hackery from relax_section. Force the value to -+ be the tls module base. */ -+ if (r_symndx == STN_UNDEF -+ && (r_type == R_SW_64_TLSLDM -+ || r_type == R_SW_64_GOTTPREL -+ || r_type == R_SW_64_TPREL64 -+ || r_type == R_SW_64_TPRELHI -+ || r_type == R_SW_64_TPRELLO -+ || r_type == R_SW_64_TPREL16)) -+ value = dtp_base; -+ -+ if (local_got_entries) -+ gotent = local_got_entries[r_symndx]; -+ else -+ gotent = NULL; -+ -+ /* Need to adjust local GOT entries' addends for SEC_MERGE -+ unless it has been done already. */ -+ if ((sec->flags & SEC_MERGE) -+ && ELF_ST_TYPE (sym->st_info) == STT_SECTION -+ && sec->sec_info_type == SEC_INFO_TYPE_MERGE -+ && gotent -+ && !gotent->reloc_xlated) -+ { -+ struct sw_64_elf_got_entry *ent; -+ -+ for (ent = gotent; ent; ent = ent->next) -+ { -+ ent->reloc_xlated = 1; -+ if (ent->use_count == 0) -+ continue; -+ msec = sec; -+ ent->addend = -+ _bfd_merged_section_offset (output_bfd, &msec, -+ elf_section_data (sec)-> -+ sec_info, -+ sym->st_value + ent->addend); -+ ent->addend -= sym->st_value; -+ ent->addend += msec->output_section->vma -+ + msec->output_offset -+ - sec->output_section->vma -+ - sec->output_offset; -+ } -+ } -+ -+ dynamic_symbol_p = false; -+ } -+ else -+ { -+ bool warned, ignored; -+ struct elf_link_hash_entry *hh; -+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd); -+ -+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, -+ r_symndx, symtab_hdr, sym_hashes, -+ hh, sec, value, -+ unresolved_reloc, warned, ignored); -+ -+ if (warned) -+ continue; -+ -+ if (value == 0 -+ && ! unresolved_reloc -+ && hh->root.type == bfd_link_hash_undefweak) -+ undef_weak_ref = true; -+ -+ h = (struct sw_64_elf_link_hash_entry *) hh; -+ dynamic_symbol_p = sw_64_elf_dynamic_symbol_p (&h->root, info); -+ gotent = h->got_entries; -+ } -+ -+ if (sec != NULL && discarded_section (sec)) -+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, -+ rel, 1, relend, howto, 0, contents); -+ -+ addend = rel->r_addend; -+ value += addend; -+ -+ /* Search for the proper got entry. */ -+ for (; gotent ; gotent = gotent->next) -+ if (gotent->gotobj == gotobj -+ && gotent->reloc_type == r_type -+ && gotent->addend == addend) -+ break; -+ -+ switch (r_type) -+ { -+ case R_SW_64_GPDISP: -+ { -+ bfd_byte *p_ldih, *p_ldi; -+ -+ BFD_ASSERT(gp != 0); -+ -+ value = (input_section->output_section->vma -+ + input_section->output_offset -+ + rel->r_offset); -+ -+ p_ldih = contents + rel->r_offset; -+ p_ldi = p_ldih + rel->r_addend; -+ -+ r = elf64_sw_64_do_reloc_gpdisp (input_bfd, gp - value, -+ p_ldih, p_ldi); -+ } -+ break; -+ -+ case R_SW_64_LITERAL: -+ BFD_ASSERT(sgot != NULL); -+ BFD_ASSERT(gp != 0); -+ BFD_ASSERT(gotent != NULL); -+ BFD_ASSERT(gotent->use_count >= 1); -+ -+ if (!gotent->reloc_done) -+ { -+ gotent->reloc_done = 1; -+ -+ bfd_put_64 (output_bfd, value, -+ sgot->contents + gotent->got_offset); -+ -+ /* If the symbol has been forced local, output a -+ RELATIVE reloc, otherwise it will be handled in -+ finish_dynamic_symbol. */ -+ if (bfd_link_pic (info) -+ && !dynamic_symbol_p -+ && !undef_weak_ref) -+ elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srelgot, -+ gotent->got_offset, 0, -+ R_SW_64_RELATIVE, value); -+ } -+ -+ value = (sgot->output_section->vma -+ + sgot->output_offset -+ + gotent->got_offset); -+ Elf_Internal_Rela *rel_got; -+ rel_got = rel-1; -+ //printf("ELF64_R_TYPE((rel_got)->r_info)=%d\n\n",ELF64_R_TYPE((rel-1)->r_info)); -+ //printf("ELF64_R_TYPE((rel)->r_info)=%d\n\n",ELF64_R_TYPE((rel)->r_info)); -+ if((ELF64_R_TYPE(rel_got->r_info) == R_SW_64_LITERAL_GOT)) -+ { -+ -+ value -= gp; -+ -+ /* ldl $27, disp($29)->ldl $27, disp($27). */ -+ unsigned int insn; -+ unsigned int operand_1; -+ unsigned long p_ldl; -+ p_ldl = contents + rel->r_offset; -+ insn = bfd_get_32 (input_bfd, p_ldl); -+ operand_1 = insn & 0x03e00000; -+ if ((insn & INSN_LDL_MASK) == INSN_LDL) -+ insn = (insn & 0xffe0ffff) | (operand_1 >> 5); -+ bfd_put_32 (input_bfd, (bfd_vma) insn, contents + rel->r_offset); -+ -+ /* emit the ldih $29, got_disp($29). */ -+ bfd_byte *p_ldih; -+ p_ldih = contents + rel_got->r_offset; -+ bfd_vma got_disp; -+ bfd_vma got_low; -+ bfd_vma got_tmp; -+ unsigned long i_ldih; -+ i_ldih = bfd_get_32 (input_bfd, p_ldih); -+ got_disp = ((i_ldih & 0xffff) << 16); -+ got_disp = (got_disp ^ 0x80008000) - 0x80008000; -+ -+ //disp = value - got_disp*65536; -+ // low = sign_extend_16 (addend); -+ // tmp = addend - low; -+ // value = sign_extend_16 (tmp >> 16); -+ if((int)value >= 0x8000 || (int)value<-0x8000) -+ { -+ // printf("hit got\n"); -+ got_low =(short)value; -+ got_tmp = value - got_low; -+ got_disp = got_disp + got_tmp; -+ //printf("int(value)=%x got_disp=%x got_low=%x got_tmp=%x\n",(int)value,got_disp,got_low,got_tmp); -+ value = (bfd_vma)got_low; -+ } -+ i_ldih = ((i_ldih & 0xffff0000) -+ | (((got_disp >> 16) + ((got_disp >> 15) & 1)) & 0xffff)); -+ bfd_put_32 (input_bfd, (bfd_vma) i_ldih, p_ldih); -+ -+ //emit ldl $27,disp($27) -+ goto default_reloc; -+ } -+ else{ -+ value -= gp; -+ goto default_reloc; -+ } -+ -+ case R_SW_64_GPREL32: -+ case R_SW_64_GPREL16: -+ case R_SW_64_GPRELLOW: -+ if (dynamic_symbol_p) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: gp-relative relocation against dynamic symbol %s"), -+ input_bfd, h->root.root.root.string); -+ ret_val = false; -+ } -+ BFD_ASSERT(gp != 0); -+ value -= gp; -+ goto default_reloc; -+ -+ case R_SW_64_GPRELHIGH: -+ if (dynamic_symbol_p) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: gp-relative relocation against dynamic symbol %s"), -+ input_bfd, h->root.root.root.string); -+ ret_val = false; -+ } -+ BFD_ASSERT(gp != 0); -+ value -= gp; -+ value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1); -+ goto default_reloc; -+ -+ case R_SW_64_HINT: -+ /* A call to a dynamic symbol is definitely out of range of -+ the 16-bit displacement. Don't bother writing anything. */ -+ if (dynamic_symbol_p) -+ { -+ r = bfd_reloc_ok; -+ break; -+ } -+ /* The regular PC-relative stuff measures from the start of -+ the instruction rather than the end. */ -+ value -= 4; -+ goto default_reloc; -+ -+ case R_SW_64_BRADDR: -+ if (dynamic_symbol_p) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: pc-relative relocation against dynamic symbol %s"), -+ input_bfd, h->root.root.root.string); -+ ret_val = false; -+ } -+ /* The regular PC-relative stuff measures from the start of -+ the instruction rather than the end. */ -+ value -= 4; -+ goto default_reloc; -+ -+ case R_SW_64_BRSGP: -+ { -+ int other; -+ const char *name; -+ -+ /* The regular PC-relative stuff measures from the start of -+ the instruction rather than the end. */ -+ value -= 4; -+ -+ /* The source and destination gp must be the same. Note that -+ the source will always have an assigned gp, since we forced -+ one in check_relocs, but that the destination may not, as -+ it might not have had any relocations at all. Also take -+ care not to crash if H is an undefined symbol. */ -+ if (h != NULL && sec != NULL -+ && sw_64_elf_tdata (sec->owner)->gotobj -+ && gotobj != sw_64_elf_tdata (sec->owner)->gotobj) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: change in gp: BRSGP %s"), -+ input_bfd, h->root.root.root.string); -+ ret_val = false; -+ } -+ -+ /* The symbol should be marked either NOPV or STD_GPLOAD. */ -+ if (h != NULL) -+ other = h->root.other; -+ else -+ other = sym->st_other; -+ switch (other & STO_SW_64_STD_GPLOAD) -+ { -+ case STO_SW_64_NOPV: -+ break; -+ case STO_SW_64_STD_GPLOAD: -+ value += 8; -+ break; -+ default: -+ if (h != NULL) -+ name = h->root.root.root.string; -+ else -+ { -+ name = (bfd_elf_string_from_elf_section -+ (input_bfd, symtab_hdr->sh_link, sym->st_name)); -+ if (name == NULL) -+ name = _(""); -+ else if (name[0] == 0) -+ name = bfd_section_name (sec); -+ } -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: !samegp reloc against symbol without .prologue: %s"), -+ input_bfd, name); -+ ret_val = false; -+ break; -+ } -+ -+ goto default_reloc; -+ } -+ -+ case R_SW_64_REFLONG: -+ case R_SW_64_REFQUAD: -+ case R_SW_64_DTPREL64: -+ case R_SW_64_TPREL64: -+ { -+ long dynindx, dyntype = r_type; -+ bfd_vma dynaddend; -+ -+ /* Careful here to remember RELATIVE relocations for global -+ variables for symbolic shared objects. */ -+ -+ if (dynamic_symbol_p) -+ { -+ BFD_ASSERT(h->root.dynindx != -1); -+ dynindx = h->root.dynindx; -+ dynaddend = addend; -+ addend = 0, value = 0; -+ } -+ else if (r_type == R_SW_64_DTPREL64) -+ { -+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -+ value -= dtp_base; -+ goto default_reloc; -+ } -+ else if (r_type == R_SW_64_TPREL64) -+ { -+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -+ if (!bfd_link_dll (info)) -+ { -+ value -= tp_base; -+ goto default_reloc; -+ } -+ dynindx = 0; -+ dynaddend = value - dtp_base; -+ } -+ else if (bfd_link_pic (info) -+ && r_symndx != STN_UNDEF -+ && (input_section->flags & SEC_ALLOC) -+ && !undef_weak_ref -+ && !(unresolved_reloc -+ && (_bfd_elf_section_offset (output_bfd, info, -+ input_section, -+ rel->r_offset) -+ == (bfd_vma) -1))) -+ { -+ if (r_type == R_SW_64_REFLONG) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: unhandled dynamic relocation against %s"), -+ input_bfd, -+ h->root.root.root.string); -+ ret_val = false; -+ } -+ dynindx = 0; -+ dyntype = R_SW_64_RELATIVE; -+ dynaddend = value; -+ } -+ else -+ goto default_reloc; -+ -+ if (input_section->flags & SEC_ALLOC) -+ elf64_sw_64_emit_dynrel (output_bfd, info, input_section, -+ srel, rel->r_offset, dynindx, -+ dyntype, dynaddend); -+ } -+ goto default_reloc; -+ -+ case R_SW_64_SREL16: -+ case R_SW_64_SREL32: -+ case R_SW_64_SREL64: -+ if (dynamic_symbol_p) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: pc-relative relocation against dynamic symbol %s"), -+ input_bfd, h->root.root.root.string); -+ ret_val = false; -+ } -+ else if (bfd_link_pic (info) -+ && undef_weak_ref) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: pc-relative relocation against undefined weak symbol %s"), -+ input_bfd, h->root.root.root.string); -+ ret_val = false; -+ } -+ -+ -+ /* ??? .eh_frame references to discarded sections will be smashed -+ to relocations against SHN_UNDEF. The .eh_frame format allows -+ NULL to be encoded as 0 in any format, so this works here. */ -+ if (r_symndx == STN_UNDEF -+ || (unresolved_reloc -+ && _bfd_elf_section_offset (output_bfd, info, -+ input_section, -+ rel->r_offset) == (bfd_vma) -1)) -+ howto = (elf64_sw_64_howto_table -+ + (r_type - R_SW_64_SREL32 + R_SW_64_REFLONG)); -+ goto default_reloc; -+ -+ case R_SW_64_TLSLDM: -+ /* Ignore the symbol for the relocation. The result is always -+ the current module. */ -+ dynamic_symbol_p = 0; -+ /* FALLTHRU */ -+ -+ case R_SW_64_TLSGD: -+ if (!gotent->reloc_done) -+ { -+ gotent->reloc_done = 1; -+ -+ /* Note that the module index for the main program is 1. */ -+ bfd_put_64 (output_bfd, -+ !bfd_link_pic (info) && !dynamic_symbol_p, -+ sgot->contents + gotent->got_offset); -+ -+ /* If the symbol has been forced local, output a -+ DTPMOD64 reloc, otherwise it will be handled in -+ finish_dynamic_symbol. */ -+ if (bfd_link_pic (info) && !dynamic_symbol_p) -+ elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srelgot, -+ gotent->got_offset, 0, -+ R_SW_64_DTPMOD64, 0); -+ -+ if (dynamic_symbol_p || r_type == R_SW_64_TLSLDM) -+ value = 0; -+ else -+ { -+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -+ value -= dtp_base; -+ } -+ bfd_put_64 (output_bfd, value, -+ sgot->contents + gotent->got_offset + 8); -+ } -+ -+ value = (sgot->output_section->vma -+ + sgot->output_offset -+ + gotent->got_offset); -+ value -= gp; -+ goto default_reloc; -+ -+ case R_SW_64_DTPRELHI: -+ case R_SW_64_DTPRELLO: -+ case R_SW_64_DTPREL16: -+ if (dynamic_symbol_p) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: dtp-relative relocation against dynamic symbol %s"), -+ input_bfd, h->root.root.root.string); -+ ret_val = false; -+ } -+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -+ value -= dtp_base; -+ if (r_type == R_SW_64_DTPRELHI) -+ value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1); -+ goto default_reloc; -+ -+ case R_SW_64_TPRELHI: -+ case R_SW_64_TPRELLO: -+ case R_SW_64_TPREL16: -+ if (bfd_link_dll (info)) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: TLS local exec code cannot be linked into shared objects"), -+ input_bfd); -+ ret_val = false; -+ } -+ else if (dynamic_symbol_p) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("%pB: tp-relative relocation against dynamic symbol %s"), -+ input_bfd, h->root.root.root.string); -+ ret_val = false; -+ } -+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -+ value -= tp_base; -+ if (r_type == R_SW_64_TPRELHI) -+ value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1); -+ goto default_reloc; -+ -+ case R_SW_64_GOTDTPREL: -+ case R_SW_64_GOTTPREL: -+ BFD_ASSERT(sgot != NULL); -+ BFD_ASSERT(gp != 0); -+ BFD_ASSERT(gotent != NULL); -+ BFD_ASSERT(gotent->use_count >= 1); -+ -+ if (!gotent->reloc_done) -+ { -+ gotent->reloc_done = 1; -+ -+ if (dynamic_symbol_p) -+ value = 0; -+ else -+ { -+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); -+ if (r_type == R_SW_64_GOTDTPREL) -+ value -= dtp_base; -+ else if (bfd_link_executable (info)) -+ value -= tp_base; -+ else -+ { -+ elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srelgot, -+ gotent->got_offset, 0, -+ R_SW_64_TPREL64, -+ value - dtp_base); -+ value = 0; -+ } -+ } -+ bfd_put_64 (output_bfd, value, -+ sgot->contents + gotent->got_offset); -+ } -+ -+ value = (sgot->output_section->vma -+ + sgot->output_offset -+ + gotent->got_offset); -+ value -= gp; -+ goto default_reloc; -+ -+ default: -+default_reloc: -+ r = _bfd_final_link_relocate (howto, input_bfd, input_section, -+ contents, rel->r_offset, value, 0); -+ break; -+ } -+ -+ switch (r) -+ { -+ case bfd_reloc_ok: -+ break; -+ -+ case bfd_reloc_overflow: -+ { -+ const char *name; -+ -+ /* Don't warn if the overflow is due to pc relative reloc -+ against discarded section. Section optimization code should -+ handle it. */ -+ -+ if (r_symndx < symtab_hdr->sh_info -+ && sec != NULL && howto->pc_relative -+ && discarded_section (sec)) -+ break; -+ -+ if (h != NULL) -+ name = NULL; -+ 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 (sec); -+ } -+ (*info->callbacks->reloc_overflow) -+ (info, (h ? &h->root.root : NULL), name, howto->name, -+ (bfd_vma) 0, input_bfd, input_section, rel->r_offset); -+ } -+ break; -+ -+ default: -+ case bfd_reloc_outofrange: -+ abort (); -+ } -+ } -+ -+ return ret_val; -+} -+ -+/* Finish up dynamic symbol handling. We set the contents of various -+ dynamic sections here. */ -+ -+ static bool -+elf64_sw_64_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, -+ struct elf_link_hash_entry *h, -+ Elf_Internal_Sym *sym) -+{ -+ struct sw_64_elf_link_hash_entry *ah = (struct sw_64_elf_link_hash_entry *)h; -+ -+ if (h->needs_plt) -+ { -+ /* Fill in the .plt entry for this symbol. */ -+ asection *splt, *sgot, *srel; -+ Elf_Internal_Rela outrel; -+ bfd_byte *loc; -+ bfd_vma got_addr, plt_addr; -+ bfd_vma plt_index; -+ struct sw_64_elf_got_entry *gotent; -+ -+ BFD_ASSERT (h->dynindx != -1); -+ -+ splt = elf_hash_table (info)->splt; -+ BFD_ASSERT (splt != NULL); -+ srel = elf_hash_table (info)->srelplt; -+ BFD_ASSERT (srel != NULL); -+ -+ for (gotent = ah->got_entries; gotent ; gotent = gotent->next) -+ if (gotent->reloc_type == R_SW_64_LITERAL -+ && gotent->use_count > 0) -+ { -+ unsigned int insn; -+ int disp; -+ -+ sgot = sw_64_elf_tdata (gotent->gotobj)->got; -+ BFD_ASSERT (sgot != NULL); -+ -+ BFD_ASSERT (gotent->got_offset != -1); -+ BFD_ASSERT (gotent->plt_offset != -1); -+ -+ got_addr = (sgot->output_section->vma -+ + sgot->output_offset -+ + gotent->got_offset); -+ plt_addr = (splt->output_section->vma -+ + splt->output_offset -+ + gotent->plt_offset); -+ -+ plt_index = (gotent->plt_offset-PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; -+ -+ /* Fill in the entry in the procedure linkage table. */ -+ if (elf64_sw_64_use_secureplt) -+ { -+ disp = (PLT_HEADER_SIZE - 4) - (gotent->plt_offset + 4); -+ insn = INSN_AD (INSN_BR, 31, disp); -+ bfd_put_32 (output_bfd, insn, -+ splt->contents + gotent->plt_offset); -+ -+ plt_index = ((gotent->plt_offset - NEW_PLT_HEADER_SIZE) -+ / NEW_PLT_ENTRY_SIZE); -+ } -+ else -+ { -+ disp = -(gotent->plt_offset + 4); -+ insn = INSN_AD (INSN_BR, 28, disp); -+ bfd_put_32 (output_bfd, insn, -+ splt->contents + gotent->plt_offset); -+ bfd_put_32 (output_bfd, INSN_UNOP, -+ splt->contents + gotent->plt_offset + 4); -+ bfd_put_32 (output_bfd, INSN_UNOP, -+ splt->contents + gotent->plt_offset + 8); -+ -+ plt_index = ((gotent->plt_offset - OLD_PLT_HEADER_SIZE) -+ / OLD_PLT_ENTRY_SIZE); -+ } -+ -+ /* Fill in the entry in the .rela.plt section. */ -+ outrel.r_offset = got_addr; -+ outrel.r_info = ELF64_R_INFO(h->dynindx, R_SW_64_JMP_SLOT); -+ outrel.r_addend = 0; -+ -+ loc = srel->contents + plt_index * sizeof (Elf64_External_Rela); -+ bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); -+ -+ /* Fill in the entry in the .got. */ -+ bfd_put_64 (output_bfd, plt_addr, -+ sgot->contents + gotent->got_offset); -+ } -+ } -+ else if (sw_64_elf_dynamic_symbol_p (h, info)) -+ { -+ /* Fill in the dynamic relocations for this symbol's .got entries. */ -+ asection *srel; -+ struct sw_64_elf_got_entry *gotent; -+ -+ srel = elf_hash_table (info)->srelgot; -+ BFD_ASSERT (srel != NULL); -+ -+ for (gotent = ((struct sw_64_elf_link_hash_entry *) h)->got_entries; -+ gotent != NULL; -+ gotent = gotent->next) -+ { -+ asection *sgot; -+ long r_type; -+ -+ if (gotent->use_count == 0) -+ continue; -+ -+ sgot = sw_64_elf_tdata (gotent->gotobj)->got; -+ -+ r_type = gotent->reloc_type; -+ switch (r_type) -+ { -+ case R_SW_64_LITERAL: -+ r_type = R_SW_64_GLOB_DAT; -+ break; -+ case R_SW_64_TLSGD: -+ r_type = R_SW_64_DTPMOD64; -+ break; -+ case R_SW_64_GOTDTPREL: -+ r_type = R_SW_64_DTPREL64; -+ break; -+ case R_SW_64_GOTTPREL: -+ r_type = R_SW_64_TPREL64; -+ break; -+ case R_SW_64_TLSLDM: -+ default: -+ abort (); -+ } -+ -+ elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srel, -+ gotent->got_offset, h->dynindx, -+ r_type, gotent->addend); -+ -+ if (gotent->reloc_type == R_SW_64_TLSGD) -+ elf64_sw_64_emit_dynrel (output_bfd, info, sgot, srel, -+ gotent->got_offset + 8, h->dynindx, -+ R_SW_64_DTPREL64, gotent->addend); -+ } -+ } -+ -+ /* Mark some specially defined symbols as absolute. */ -+ if (h == elf_hash_table (info)->hdynamic -+ || h == elf_hash_table (info)->hgot -+ || h == elf_hash_table (info)->hplt) -+ sym->st_shndx = SHN_ABS; -+ -+ return true; -+} -+ -+/* Finish up the dynamic sections. */ -+ -+ static bool -+elf64_sw_64_finish_dynamic_sections (bfd *output_bfd, -+ struct bfd_link_info *info) -+{ -+ bfd *dynobj; -+ asection *sdyn; -+ -+ dynobj = elf_hash_table (info)->dynobj; -+ sdyn = bfd_get_linker_section (dynobj, ".dynamic"); -+ -+ if (elf_hash_table (info)->dynamic_sections_created) -+ { -+ asection *splt, *sgotplt, *srelaplt; -+ Elf64_External_Dyn *dyncon, *dynconend; -+ bfd_vma plt_vma, gotplt_vma; -+ -+ splt = elf_hash_table (info)->splt; -+ srelaplt = elf_hash_table (info)->srelplt; -+ BFD_ASSERT (splt != NULL && sdyn != NULL); -+ -+ plt_vma = splt->output_section->vma + splt->output_offset; -+ -+ gotplt_vma = 0; -+ if (elf64_sw_64_use_secureplt) -+ { -+ sgotplt = elf_hash_table (info)->sgotplt; -+ BFD_ASSERT (sgotplt != NULL); -+ if (sgotplt->size > 0) -+ gotplt_vma = sgotplt->output_section->vma + sgotplt->output_offset; -+ } -+ -+ dyncon = (Elf64_External_Dyn *) sdyn->contents; -+ dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size); -+ for (; dyncon < dynconend; dyncon++) -+ { -+ Elf_Internal_Dyn dyn; -+ -+ bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); -+ -+ switch (dyn.d_tag) -+ { -+ case DT_PLTGOT: -+ dyn.d_un.d_ptr -+ = elf64_sw_64_use_secureplt ? gotplt_vma : plt_vma; -+ break; -+ case DT_PLTRELSZ: -+ dyn.d_un.d_val = srelaplt ? srelaplt->size : 0; -+ break; -+ case DT_JMPREL: -+ dyn.d_un.d_ptr = srelaplt ? (srelaplt->output_section->vma -+ + srelaplt->output_offset) : 0; -+ break; -+ } -+ -+ bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); -+ } -+ -+ /* Initialize the plt header. */ -+ if (splt->size > 0) -+ { -+ unsigned int insn; -+ int ofs; -+ -+ if (elf64_sw_64_use_secureplt) -+ { -+ ofs = gotplt_vma - (plt_vma + PLT_HEADER_SIZE); -+ -+ insn = INSN_ABC (INSN_SUBL, 27, 28, 25); -+ bfd_put_32 (output_bfd, insn, splt->contents); -+ -+ insn = INSN_ABO (INSN_LDIH, 28, 28, (ofs + 0x8000) >> 16); -+ bfd_put_32 (output_bfd, insn, splt->contents + 4); -+ -+ insn = INSN_ABC (INSN_S4SUBL, 25, 25, 25); -+ bfd_put_32 (output_bfd, insn, splt->contents + 8); -+ -+ insn = INSN_ABO (INSN_LDI, 28, 28, ofs); -+ bfd_put_32 (output_bfd, insn, splt->contents + 12); -+ -+ insn = INSN_ABO (INSN_LDL, 27, 28, 0); -+ bfd_put_32 (output_bfd, insn, splt->contents + 16); -+ -+ insn = INSN_ABC (INSN_ADDL, 25, 25, 25); -+ bfd_put_32 (output_bfd, insn, splt->contents + 20); -+ -+ insn = INSN_ABO (INSN_LDL, 28, 28, 8); -+ bfd_put_32 (output_bfd, insn, splt->contents + 24); -+ -+ insn = INSN_AB (INSN_JMP, 31, 27); -+ bfd_put_32 (output_bfd, insn, splt->contents + 28); -+ -+ insn = INSN_AD (INSN_BR, 28, -PLT_HEADER_SIZE); -+ bfd_put_32 (output_bfd, insn, splt->contents + 32); -+ } -+ else -+ { -+ insn = INSN_AD (INSN_BR, 27, 0); /* br $27, .+4 */ -+ bfd_put_32 (output_bfd, insn, splt->contents); -+ -+ insn = INSN_ABO (INSN_LDL, 27, 27, 12); -+ bfd_put_32 (output_bfd, insn, splt->contents + 4); -+ -+ insn = INSN_UNOP; -+ bfd_put_32 (output_bfd, insn, splt->contents + 8); -+ -+ insn = INSN_AB (INSN_JMP, 27, 27); -+ bfd_put_32 (output_bfd, insn, splt->contents + 12); -+ -+ /* The next two words will be filled in by ld.so. */ -+ bfd_put_64 (output_bfd, 0, splt->contents + 16); -+ bfd_put_64 (output_bfd, 0, splt->contents + 24); -+ } -+ -+ elf_section_data (splt->output_section)->this_hdr.sh_entsize = 0; -+ } -+ } -+ -+ return true; -+} -+ -+/* We need to use a special link routine to handle the .mdebug section. -+ We need to merge all instances of these sections together, not write -+ them all out sequentially. */ -+ -+ static bool -+elf64_sw_64_final_link (bfd *abfd, struct bfd_link_info *info) -+{ -+ asection *o; -+ struct bfd_link_order *p; -+ asection *mdebug_sec; -+ 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; -+ void * mdebug_handle = NULL; -+ struct sw_64_elf_link_hash_table * htab; -+ -+ htab = sw_64_elf_hash_table (info); -+ if (htab == NULL) -+ return false; -+ -+ /* Go through the sections and collect the mdebug information. */ -+ mdebug_sec = NULL; -+ for (o = abfd->sections; o != (asection *) NULL; o = o->next) -+ { -+ 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 == NULL) -+ return false; -+ -+ if (1) -+ { -+ asection *s; -+ EXTR esym; -+ bfd_vma last = 0; -+ unsigned int i; -+ static const char * const name[] = -+ { -+ ".text", ".init", ".fini", ".data", -+ ".rodata", ".sdata", ".sbss", ".bss" -+ }; -+ static const int sc[] = { scText, scInit, scFini, scData, -+ scRData, scSData, scSBss, scBss }; -+ -+ esym.jmptbl = 0; -+ esym.cobol_main = 0; -+ esym.weakext = 0; -+ esym.reserved = 0; -+ esym.ifd = ifdNil; -+ esym.asym.iss = issNil; -+ esym.asym.st = stLocal; -+ esym.asym.reserved = 0; -+ esym.asym.index = indexNil; -+ for (i = 0; i < 8; i++) -+ { -+ esym.asym.sc = sc[i]; -+ s = bfd_get_section_by_name (abfd, name[i]); -+ if (s != NULL) -+ { -+ esym.asym.value = s->vma; -+ last = s->vma + s->size; -+ } -+ else -+ esym.asym.value = last; -+ -+ if (! bfd_ecoff_debug_one_external (abfd, &debug, swap, -+ name[i], &esym)) -+ return false; -+ } -+ } -+ -+ for (p = o->map_head.link_order; -+ 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_data_link_order) -+ continue; -+ abort (); -+ } -+ -+ input_section = p->u.indirect.section; -+ input_bfd = input_section->owner; -+ -+ if (! is_sw_64_elf (input_bfd)) -+ /* I don't know what a non SW_64 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->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 (!elf64_sw_64_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 = (char *) 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 sw_64_elf_link_hash_entry *h; -+ -+ (*input_swap->swap_ext_in) (input_bfd, 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 = sw_64_elf_link_hash_lookup (htab, 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; -+ elf_link_hash_traverse (elf_hash_table (info), -+ elf64_sw_64_output_extsym, -+ &einfo); -+ if (einfo.failed) -+ return false; -+ -+ /* Set the size of the .mdebug section. */ -+ o->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->map_head.link_order = (struct bfd_link_order *) NULL; -+ -+ mdebug_sec = o; -+ } -+ } -+ -+ /* Invoke the regular ELF backend linker to do all the work. */ -+ if (! bfd_elf_final_link (abfd, info)) -+ return false; -+ -+ /* Now write out the computed sections. */ -+ -+ /* The .got subsections... */ -+ { -+ bfd *i, *dynobj = elf_hash_table(info)->dynobj; -+ for (i = htab->got_list; -+ i != NULL; -+ i = sw_64_elf_tdata(i)->got_link_next) -+ { -+ asection *sgot; -+ -+ /* elf_bfd_final_link already did everything in dynobj. */ -+ if (i == dynobj) -+ continue; -+ -+ sgot = sw_64_elf_tdata(i)->got; -+ if (! bfd_set_section_contents (abfd, sgot->output_section, -+ sgot->contents, -+ (file_ptr) sgot->output_offset, -+ sgot->size)) -+ 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); -+ } -+ -+ return true; -+} -+ -+ static enum elf_reloc_type_class -+elf64_sw_64_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, -+ const asection *rel_sec ATTRIBUTE_UNUSED, -+ const Elf_Internal_Rela *rela) -+{ -+ switch ((int) ELF64_R_TYPE (rela->r_info)) -+ { -+ case R_SW_64_RELATIVE: -+ return reloc_class_relative; -+ case R_SW_64_JMP_SLOT: -+ return reloc_class_plt; -+ case R_SW_64_COPY: -+ return reloc_class_copy; -+ default: -+ return reloc_class_normal; -+ } -+} -+ -+static const struct bfd_elf_special_section elf64_sw_64_special_sections[] = -+{ -+ { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_SW_64_GPREL }, -+ { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_SW_64_GPREL }, -+ { NULL, 0, 0, 0, 0 } -+}; -+ -+/* ECOFF swapping routines. These are used when dealing with the -+ .mdebug section, which is in the ECOFF debugging format. Copied -+ from elf32-mips.c. */ -+static const struct ecoff_debug_swap -+elf64_sw_64_ecoff_debug_swap = -+{ -+ /* 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. */ -+ elf64_sw_64_read_ecoff_info -+}; -+ -+/* Use a non-standard hash bucket size of 8. */ -+ -+static const struct elf_size_info sw_64_elf_size_info = -+{ -+ sizeof (Elf64_External_Ehdr), -+ sizeof (Elf64_External_Phdr), -+ sizeof (Elf64_External_Shdr), -+ sizeof (Elf64_External_Rel), -+ sizeof (Elf64_External_Rela), -+ sizeof (Elf64_External_Sym), -+ sizeof (Elf64_External_Dyn), -+ sizeof (Elf_External_Note), -+ 8, -+ 1, -+ 64, 3, -+ ELFCLASS64, EV_CURRENT, -+ bfd_elf64_write_out_phdrs, -+ bfd_elf64_write_shdrs_and_ehdr, -+ bfd_elf64_checksum_contents, -+ bfd_elf64_write_relocs, -+ bfd_elf64_swap_symbol_in, -+ bfd_elf64_swap_symbol_out, -+ bfd_elf64_slurp_reloc_table, -+ bfd_elf64_slurp_symbol_table, -+ bfd_elf64_swap_dyn_in, -+ bfd_elf64_swap_dyn_out, -+ bfd_elf64_swap_reloc_in, -+ bfd_elf64_swap_reloc_out, -+ bfd_elf64_swap_reloca_in, -+ bfd_elf64_swap_reloca_out -+}; -+ -+#define TARGET_LITTLE_SYM sw_64_elf64_vec -+#define TARGET_LITTLE_NAME "elf64-sw_64" -+#define ELF_ARCH bfd_arch_sw_64 -+#define ELF_TARGET_ID SW_64_ELF_DATA -+#define ELF_MACHINE_CODE EM_SW_64 -+#define ELF_MAXPAGESIZE 0x10000 -+#define ELF_COMMONPAGESIZE 0x2000 -+ -+#define bfd_elf64_bfd_link_hash_table_create \ -+ elf64_sw_64_bfd_link_hash_table_create -+ -+#define bfd_elf64_bfd_reloc_type_lookup \ -+ elf64_sw_64_bfd_reloc_type_lookup -+#define bfd_elf64_bfd_reloc_name_lookup \ -+ elf64_sw_64_bfd_reloc_name_lookup -+#define elf_info_to_howto \ -+ elf64_sw_64_info_to_howto -+ -+#define bfd_elf64_mkobject \ -+ elf64_sw_64_mkobject -+#define elf_backend_object_p \ -+ elf64_sw_64_object_p -+ -+#define elf_backend_section_from_shdr \ -+ elf64_sw_64_section_from_shdr -+#define elf_backend_section_flags \ -+ elf64_sw_64_section_flags -+#define elf_backend_fake_sections \ -+ elf64_sw_64_fake_sections -+ -+#define bfd_elf64_bfd_is_local_label_name \ -+ elf64_sw_64_is_local_label_name -+#define bfd_elf64_find_nearest_line \ -+ elf64_sw_64_find_nearest_line -+#define bfd_elf64_bfd_relax_section \ -+ elf64_sw_64_relax_section -+ -+#define elf_backend_add_symbol_hook \ -+ elf64_sw_64_add_symbol_hook -+#define elf_backend_relocs_compatible \ -+ _bfd_elf_relocs_compatible -+#define elf_backend_sort_relocs_p \ -+ elf64_sw_64_sort_relocs_p -+#define elf_backend_check_relocs \ -+ elf64_sw_64_check_relocs -+#define elf_backend_create_dynamic_sections \ -+ elf64_sw_64_create_dynamic_sections -+#define elf_backend_adjust_dynamic_symbol \ -+ elf64_sw_64_adjust_dynamic_symbol -+#define elf_backend_merge_symbol_attribute \ -+ elf64_sw_64_merge_symbol_attribute -+#define elf_backend_copy_indirect_symbol \ -+ elf64_sw_64_copy_indirect_symbol -+#define elf_backend_always_size_sections \ -+ elf64_sw_64_always_size_sections -+#define elf_backend_size_dynamic_sections \ -+ elf64_sw_64_size_dynamic_sections -+#define elf_backend_omit_section_dynsym \ -+ _bfd_elf_omit_section_dynsym_all -+#define elf_backend_relocate_section \ -+ elf64_sw_64_relocate_section -+#define elf_backend_finish_dynamic_symbol \ -+ elf64_sw_64_finish_dynamic_symbol -+#define elf_backend_finish_dynamic_sections \ -+ elf64_sw_64_finish_dynamic_sections -+#define bfd_elf64_bfd_final_link \ -+ elf64_sw_64_final_link -+#define elf_backend_reloc_type_class \ -+ elf64_sw_64_reloc_type_class -+ -+#define elf_backend_can_gc_sections 1 -+#define elf_backend_gc_mark_hook elf64_sw_64_gc_mark_hook -+ -+#define elf_backend_ecoff_debug_swap \ -+ &elf64_sw_64_ecoff_debug_swap -+ -+#define elf_backend_size_info \ -+ sw_64_elf_size_info -+ -+#define elf_backend_special_sections \ -+ elf64_sw_64_special_sections -+ -+#define elf_backend_strip_zero_sized_dynamic_sections \ -+ _bfd_elf_strip_zero_sized_dynamic_sections -+ -+/* A few constants that determine how the .plt section is set up. */ -+#define elf_backend_want_got_plt 0 -+#define elf_backend_plt_readonly 0 -+#define elf_backend_want_plt_sym 1 -+#define elf_backend_got_header_size 0 -+#define elf_backend_dtrel_excludes_plt 1 -+ -+#include "elf64-target.h" -+ -+/* FreeBSD support. */ -+ -+#undef TARGET_LITTLE_SYM -+#define TARGET_LITTLE_SYM sw_64_elf64_fbsd_vec -+#undef TARGET_LITTLE_NAME -+#define TARGET_LITTLE_NAME "elf64-sw_64-freebsd" -+#undef ELF_OSABI -+#define ELF_OSABI ELFOSABI_FREEBSD -+ -+/* The kernel recognizes executables as valid only if they carry a -+ "FreeBSD" label in the ELF header. So we put this label on all -+ executables and (for simplicity) also all other object files. */ -+ -+ static bool -+elf64_sw_64_fbsd_init_file_header (bfd *abfd, struct bfd_link_info *info) -+{ -+ Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */ -+ -+ if (!_bfd_elf_init_file_header (abfd, info)) -+ return false; -+ -+ i_ehdrp = elf_elfheader (abfd); -+ -+ /* Put an ABI label supported by FreeBSD >= 4.1. */ -+ i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi; -+#ifdef OLD_FREEBSD_ABI_LABEL -+ /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ -+ memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); -+#endif -+ return true; -+} -+#undef elf_backend_init_file_header -+#define elf_backend_init_file_header \ -+ elf64_sw_64_fbsd_init_file_header -+ -+#undef elf64_bed -+#define elf64_bed elf64_sw_64_fbsd_bed -+ -+#include "elf64-target.h" -diff --git a/bfd/hosts/sw_64linux.h b/bfd/hosts/sw_64linux.h -new file mode 100644 -index 00000000..f0f41006 ---- /dev/null -+++ b/bfd/hosts/sw_64linux.h -@@ -0,0 +1,25 @@ -+/* Copyright (C) 2007-2018 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 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+ MA 02110-1301, USA. */ -+ -+/* Linux dumps "struct task_struct" at the end of the core-file. This -+ structure is currently 1080 bytes long, but we allow up to 4096 -+ bytes to allow for some future growth. */ -+#define TRAD_CORE_EXTRA_SIZE_ALLOWED 4096 -+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(abfd) \ -+ ((abfd)->tdata.trad_core_data->u.signal) -diff --git a/bfd/hosts/sw_64vms.h b/bfd/hosts/sw_64vms.h -new file mode 100644 -index 00000000..e66bd56c ---- /dev/null -+++ b/bfd/hosts/sw_64vms.h -@@ -0,0 +1,68 @@ -+/* alphavms.h -- BFD definitions for an openVMS host -+ Copyright (C) 1996-2018 Free Software Foundation, Inc. -+ Written by Klaus Kämpf (kkaempf@progis.de) -+ of proGIS Softwareentwicklung, Aachen, Germany -+ -+ This file is part of BFD, the Binary File Descriptor library. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+ MA 02110-1301, USA. */ -+ -+#ifdef PACKAGE -+#error sysdep.h must be included in lieu of config.h -+#endif -+ -+#include "config.h" -+#include "ansidecl.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "filenames.h" -+#include "fopen-vms.h" -+ -+#define NO_FCNTL 1 -+ -+#ifndef O_ACCMODE -+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) -+#endif -+ -+extern int getpagesize (void); -+extern char *stpcpy (char *, const char *); -+ -+/* No intl. */ -+#define gettext(Msgid) (Msgid) -+#define dgettext(Domainname, Msgid) (Msgid) -+#define dcgettext(Domainname, Msgid, Category) (Msgid) -+#define ngettext(Msgid1, Msgid2, n) \ -+ (n == 1 ? Msgid1 : Msgid2) -+#define dngettext(Domainname, Msgid1, Msgid2, n) \ -+ (n == 1 ? Msgid1 : Msgid2) -+#define dcngettext(Domainname, Msgid1, Msgid2, n, Category) \ -+ (n == 1 ? Msgid1 : Msgid2) -+#define textdomain(Domainname) do {} while (0) -+#define bindtextdomain(Domainname, Dirname) do {} while (0) -+#define _(String) (String) -+#define N_(String) (String) -diff --git a/bfd/vms-sw_64.c b/bfd/vms-sw_64.c -new file mode 100644 -index 00000000..a73c8232 ---- /dev/null -+++ b/bfd/vms-sw_64.c -@@ -0,0 +1,10248 @@ -+/* vms.c -- BFD back-end for EVAX (openVMS/Sw_64) files. -+ Copyright (C) 1996-2020 Free Software Foundation, Inc. -+ -+ Initial version written by Klaus Kaempf (kkaempf@rmi.de) -+ Major rewrite by Adacore. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+ MA 02110-1301, USA. */ -+ -+/* TODO: -+ o overlayed sections -+ o PIC -+ o Generation of shared image -+ o Relocation optimizations -+ o EISD for the stack -+ o Vectors isect -+ o 64 bits sections -+ o Entry point -+ o LIB$INITIALIZE -+ o protected sections (for messages) -+ ... -+*/ -+ -+#include "sysdep.h" -+#include "bfd.h" -+#include "bfdlink.h" -+#include "libbfd.h" -+#include "bfdver.h" -+ -+#include "vms.h" -+#include "vms/eihd.h" -+#include "vms/eiha.h" -+#include "vms/eihi.h" -+#include "vms/eihs.h" -+#include "vms/eisd.h" -+#include "vms/dmt.h" -+#include "vms/dst.h" -+#include "vms/eihvn.h" -+#include "vms/eobjrec.h" -+#include "vms/egsd.h" -+#include "vms/egps.h" -+#include "vms/esgps.h" -+#include "vms/eeom.h" -+#include "vms/emh.h" -+#include "vms/eiaf.h" -+#include "vms/shl.h" -+#include "vms/eicp.h" -+#include "vms/etir.h" -+#include "vms/egsy.h" -+#include "vms/esdf.h" -+#include "vms/esdfm.h" -+#include "vms/esdfv.h" -+#include "vms/esrf.h" -+#include "vms/egst.h" -+#include "vms/eidc.h" -+#include "vms/dsc.h" -+#include "vms/prt.h" -+#include "vms/internal.h" -+ -+ -+#define MIN(a,b) ((a) < (b) ? (a) : (b)) -+ -+/* The r_type field in a reloc is one of the following values. */ -+#define SW_64_R_IGNORE 0 -+#define SW_64_R_REFQUAD 1 -+#define SW_64_R_BRADDR 2 -+#define SW_64_R_HINT 3 -+#define SW_64_R_SREL16 4 -+#define SW_64_R_SREL32 5 -+#define SW_64_R_SREL64 6 -+#define SW_64_R_OP_PUSH 7 -+#define SW_64_R_OP_STORE 8 -+#define SW_64_R_OP_PSUB 9 -+#define SW_64_R_OP_PRSHIFT 10 -+#define SW_64_R_LINKAGE 11 -+#define SW_64_R_REFLONG 12 -+#define SW_64_R_CODEADDR 13 -+#define SW_64_R_NOP 14 -+#define SW_64_R_BSR 15 -+#define SW_64_R_LDA 16 -+#define SW_64_R_BOH 17 -+ -+/* These are used with DST_S_C_LINE_NUM. */ -+#define DST_S_C_LINE_NUM_HEADER_SIZE 4 -+ -+/* These are used with DST_S_C_SOURCE */ -+ -+#define DST_S_B_PCLINE_UNSBYTE 1 -+#define DST_S_W_PCLINE_UNSWORD 1 -+#define DST_S_L_PCLINE_UNSLONG 1 -+ -+#define DST_S_B_MODBEG_NAME 14 -+#define DST_S_L_RTNBEG_ADDRESS 5 -+#define DST_S_B_RTNBEG_NAME 13 -+#define DST_S_L_RTNEND_SIZE 5 -+ -+/* These are used with DST_S_C_SOURCE. */ -+#define DST_S_C_SOURCE_HEADER_SIZE 4 -+ -+#define DST_S_B_SRC_DF_LENGTH 1 -+#define DST_S_W_SRC_DF_FILEID 3 -+#define DST_S_B_SRC_DF_FILENAME 20 -+#define DST_S_B_SRC_UNSBYTE 1 -+#define DST_S_W_SRC_UNSWORD 1 -+#define DST_S_L_SRC_UNSLONG 1 -+ -+/* Debugger symbol definitions. */ -+ -+#define DBG_S_L_DMT_MODBEG 0 -+#define DBG_S_L_DST_SIZE 4 -+#define DBG_S_W_DMT_PSECT_COUNT 8 -+#define DBG_S_C_DMT_HEADER_SIZE 12 -+ -+#define DBG_S_L_DMT_PSECT_START 0 -+#define DBG_S_L_DMT_PSECT_LENGTH 4 -+#define DBG_S_C_DMT_PSECT_SIZE 8 -+ -+/* VMS module header. */ -+ -+struct hdr_struct -+{ -+ char hdr_b_strlvl; -+ int hdr_l_arch1; -+ int hdr_l_arch2; -+ int hdr_l_recsiz; -+ char *hdr_t_name; -+ char *hdr_t_version; -+ char *hdr_t_date; -+ char *hdr_c_lnm; -+ char *hdr_c_src; -+ char *hdr_c_ttl; -+}; -+ -+#define EMH_DATE_LENGTH 17 -+ -+/* VMS End-Of-Module records (EOM/EEOM). */ -+ -+struct eom_struct -+{ -+ unsigned int eom_l_total_lps; -+ unsigned short eom_w_comcod; -+ bfd_boolean eom_has_transfer; -+ unsigned char eom_b_tfrflg; -+ unsigned int eom_l_psindx; -+ unsigned int eom_l_tfradr; -+}; -+ -+struct vms_symbol_entry -+{ -+ bfd *owner; -+ -+ /* Common fields. */ -+ unsigned char typ; -+ unsigned char data_type; -+ unsigned short flags; -+ -+ /* Section and offset/value of the symbol. */ -+ unsigned int value; -+ asection *section; -+ -+ /* Section and offset/value for the entry point (only for subprg). */ -+ asection *code_section; -+ unsigned int code_value; -+ -+ /* Symbol vector offset. */ -+ unsigned int symbol_vector; -+ -+ /* Length of the name. */ -+ unsigned char namelen; -+ -+ char name[1]; -+}; -+ -+/* Stack value for push/pop commands. */ -+ -+struct stack_struct -+{ -+ bfd_vma value; -+ unsigned int reloc; -+}; -+ -+#define STACKSIZE 128 -+ -+/* A minimal decoding of DST compilation units. We only decode -+ what's needed to get to the line number information. */ -+ -+struct fileinfo -+{ -+ char *name; -+ unsigned int srec; -+}; -+ -+struct srecinfo -+{ -+ struct srecinfo *next; -+ unsigned int line; -+ unsigned int sfile; -+ unsigned int srec; -+}; -+ -+struct lineinfo -+{ -+ struct lineinfo *next; -+ bfd_vma address; -+ unsigned int line; -+}; -+ -+struct funcinfo -+{ -+ struct funcinfo *next; -+ char *name; -+ bfd_vma low; -+ bfd_vma high; -+}; -+ -+struct module -+{ -+ /* Chain the previously read compilation unit. */ -+ struct module *next; -+ -+ /* The module name. */ -+ char *name; -+ -+ /* The start offset and size of debug info in the DST section. */ -+ unsigned int modbeg; -+ unsigned int size; -+ -+ /* The lowest and highest addresses contained in this compilation -+ unit as specified in the compilation unit header. */ -+ bfd_vma low; -+ bfd_vma high; -+ -+ /* The listing line table. */ -+ struct lineinfo *line_table; -+ -+ /* The source record table. */ -+ struct srecinfo *srec_table; -+ -+ /* A list of the functions found in this module. */ -+ struct funcinfo *func_table; -+ -+ /* Current allocation of file_table. */ -+ unsigned int file_table_count; -+ -+ /* An array of the files making up this module. */ -+ struct fileinfo *file_table; -+}; -+ -+/* BFD private data for sw_64-vms. */ -+ -+struct vms_private_data_struct -+{ -+ /* If true, relocs have been read. */ -+ bfd_boolean reloc_done; -+ -+ /* Record input buffer. */ -+ struct vms_rec_rd recrd; -+ struct vms_rec_wr recwr; -+ -+ struct hdr_struct hdr_data; /* data from HDR/EMH record */ -+ struct eom_struct eom_data; /* data from EOM/EEOM record */ -+ -+ /* Transfer addresses (entry points). */ -+ bfd_vma transfer_address[4]; -+ -+ /* Array of GSD sections to get the correspond BFD one. */ -+ unsigned int section_max; /* Size of the sections array. */ -+ unsigned int section_count; /* Number of GSD sections. */ -+ asection **sections; -+ -+ /* Array of raw symbols. */ -+ struct vms_symbol_entry **syms; -+ -+ /* Canonicalized symbols. */ -+ asymbol **csymbols; -+ -+ /* Number of symbols. */ -+ unsigned int gsd_sym_count; -+ /* Size of the syms array. */ -+ unsigned int max_sym_count; -+ /* Number of procedure symbols. */ -+ unsigned int norm_sym_count; -+ -+ /* Stack used to evaluate TIR/ETIR commands. */ -+ struct stack_struct *stack; -+ int stackptr; -+ -+ /* Content reading. */ -+ asection *image_section; /* section for image_ptr */ -+ file_ptr image_offset; /* Offset for image_ptr. */ -+ -+ struct module *modules; /* list of all compilation units */ -+ -+ /* The DST section. */ -+ asection *dst_section; -+ -+ unsigned int dst_ptr_offsets_count; /* # of offsets in following array */ -+ unsigned int *dst_ptr_offsets; /* array of saved image_ptr offsets */ -+ -+ /* Shared library support */ -+ bfd_vma symvva; /* relative virtual address of symbol vector */ -+ unsigned int ident; -+ unsigned char matchctl; -+ -+ /* Shared library index. This is used for input bfd while linking. */ -+ unsigned int shr_index; -+ -+ /* Used to place structures in the file. */ -+ file_ptr file_pos; -+ -+ /* Simply linked list of eisd. */ -+ struct vms_internal_eisd_map *eisd_head; -+ struct vms_internal_eisd_map *eisd_tail; -+ -+ /* Simply linked list of eisd for shared libraries. */ -+ struct vms_internal_eisd_map *gbl_eisd_head; -+ struct vms_internal_eisd_map *gbl_eisd_tail; -+ -+ /* linkage index counter used by conditional store commands */ -+ unsigned int vms_linkage_index; -+}; -+ -+#define PRIV2(abfd, name) \ -+ (((struct vms_private_data_struct *)(abfd)->tdata.any)->name) -+#define PRIV(name) PRIV2(abfd,name) -+ -+ -+/* Used to keep extra VMS 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 VMS relocations -+ are variable length. -+ -+ reloc_stream is the actual stream of relocation entries. */ -+ -+struct vms_section_data_struct -+{ -+ /* Maximnum number of entries in sec->relocation. */ -+ unsigned reloc_max; -+ -+ /* Corresponding eisd. Used only while generating executables. */ -+ struct vms_internal_eisd_map *eisd; -+ -+ /* PSC flags to be clear. */ -+ flagword no_flags; -+ -+ /* PSC flags to be set. */ -+ flagword flags; -+}; -+ -+#define vms_section_data(sec) \ -+ ((struct vms_section_data_struct *)sec->used_by_bfd) -+ -+/* To be called from the debugger. */ -+struct vms_private_data_struct *bfd_vms_get_data (bfd *); -+ -+static int vms_get_remaining_object_record (bfd *, unsigned int); -+static bfd_boolean _bfd_vms_slurp_object_records (bfd * abfd); -+static void sw_64_vms_add_fixup_lp (struct bfd_link_info *, bfd *, bfd *); -+static void sw_64_vms_add_fixup_ca (struct bfd_link_info *, bfd *, bfd *); -+static void sw_64_vms_add_fixup_qr (struct bfd_link_info *, bfd *, bfd *, -+ bfd_vma); -+static void sw_64_vms_add_fixup_lr (struct bfd_link_info *, unsigned int, -+ bfd_vma); -+static void sw_64_vms_add_lw_reloc (struct bfd_link_info *); -+static void sw_64_vms_add_qw_reloc (struct bfd_link_info *); -+ -+struct vector_type -+{ -+ unsigned int max_el; -+ unsigned int nbr_el; -+ void *els; -+}; -+ -+/* Number of elements in VEC. */ -+ -+#define VEC_COUNT(VEC) ((VEC).nbr_el) -+ -+/* Get the address of the Nth element. */ -+ -+#define VEC_EL(VEC, TYPE, N) (((TYPE *)((VEC).els))[N]) -+ -+#define VEC_INIT(VEC) \ -+ do { \ -+ (VEC).max_el = 0; \ -+ (VEC).nbr_el = 0; \ -+ (VEC).els = NULL; \ -+ } while (0) -+ -+/* Be sure there is room for a new element. */ -+ -+static void vector_grow1 (struct vector_type *vec, size_t elsz); -+ -+/* Allocate room for a new element and return its address. */ -+ -+#define VEC_APPEND(VEC, TYPE) \ -+ (vector_grow1 (&VEC, sizeof (TYPE)), &VEC_EL(VEC, TYPE, (VEC).nbr_el++)) -+ -+/* Append an element. */ -+ -+#define VEC_APPEND_EL(VEC, TYPE, EL) \ -+ (*(VEC_APPEND (VEC, TYPE)) = EL) -+ -+struct sw_64_vms_vma_ref -+{ -+ bfd_vma vma; /* Vma in the output. */ -+ bfd_vma ref; /* Reference in the input. */ -+}; -+ -+struct sw_64_vms_shlib_el -+{ -+ bfd *abfd; -+ bfd_boolean has_fixups; -+ -+ struct vector_type lp; /* Vector of bfd_vma. */ -+ struct vector_type ca; /* Vector of bfd_vma. */ -+ struct vector_type qr; /* Vector of struct sw_64_vms_vma_ref. */ -+}; -+ -+/* Sw_64 VMS linker hash table. */ -+ -+struct sw_64_vms_link_hash_table -+{ -+ struct bfd_link_hash_table root; -+ -+ /* Vector of shared libraries. */ -+ struct vector_type shrlibs; -+ -+ /* Fixup section. */ -+ asection *fixup; -+ -+ /* Base address. Used by fixups. */ -+ bfd_vma base_addr; -+}; -+ -+#define sw_64_vms_link_hash(INFO) \ -+ ((struct sw_64_vms_link_hash_table *)(INFO->hash)) -+ -+/* Sw_64 VMS linker hash table entry. */ -+ -+struct sw_64_vms_link_hash_entry -+{ -+ struct bfd_link_hash_entry root; -+ -+ /* Pointer to the original vms symbol. */ -+ struct vms_symbol_entry *sym; -+}; -+ -+/* Image reading. */ -+ -+/* Read & process EIHD record. -+ Return TRUE on success, FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_eihd (bfd *abfd, unsigned int *eisd_offset, -+ unsigned int *eihs_offset) -+{ -+ unsigned int imgtype, size; -+ bfd_vma symvva; -+ struct vms_eihd *eihd = (struct vms_eihd *)PRIV (recrd.rec); -+ -+ vms_debug2 ((8, "_bfd_vms_slurp_eihd\n")); -+ -+ /* PR 21813: Check for an undersized record. */ -+ if (PRIV (recrd.buf_size) < sizeof (* eihd)) -+ { -+ _bfd_error_handler (_("corrupt EIHD record - size is too small")); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ size = bfd_getl32 (eihd->size); -+ imgtype = bfd_getl32 (eihd->imgtype); -+ -+ if (imgtype == EIHD__K_EXE || imgtype == EIHD__K_LIM) -+ abfd->flags |= EXEC_P; -+ -+ symvva = bfd_getl64 (eihd->symvva); -+ if (symvva != 0) -+ { -+ PRIV (symvva) = symvva; -+ abfd->flags |= DYNAMIC; -+ } -+ -+ PRIV (ident) = bfd_getl32 (eihd->ident); -+ PRIV (matchctl) = eihd->matchctl; -+ -+ *eisd_offset = bfd_getl32 (eihd->isdoff); -+ *eihs_offset = bfd_getl32 (eihd->symdbgoff); -+ -+ vms_debug2 ((4, "EIHD size %d imgtype %d symvva 0x%lx eisd %d eihs %d\n", -+ size, imgtype, (unsigned long)symvva, -+ *eisd_offset, *eihs_offset)); -+ (void) size; -+ -+ return TRUE; -+} -+ -+/* Read & process EISD record. -+ Return TRUE on success, FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) -+{ -+ int section_count = 0; -+ -+ vms_debug2 ((8, "_bfd_vms_slurp_eisd\n")); -+ -+ while (1) -+ { -+ struct vms_eisd *eisd; -+ unsigned int rec_size; -+ unsigned int size; -+ bfd_uint64_t vaddr; -+ unsigned int flags; -+ unsigned int vbn; -+ char *name = NULL; -+ asection *section; -+ flagword bfd_flags; -+ -+ /* PR 17512: file: 3d9e9fe9. */ -+ if (offset > PRIV (recrd.rec_size) -+ || (PRIV (recrd.rec_size) - offset -+ < offsetof (struct vms_eisd, eisdsize) + 4)) -+ return FALSE; -+ eisd = (struct vms_eisd *) (PRIV (recrd.rec) + offset); -+ rec_size = bfd_getl32 (eisd->eisdsize); -+ if (rec_size == 0) -+ break; -+ -+ /* Skip to next block if pad. */ -+ if (rec_size == 0xffffffff) -+ { -+ offset = (offset + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1); -+ continue; -+ } -+ -+ /* Make sure that there is enough data present in the record. */ -+ if (rec_size < offsetof (struct vms_eisd, type) + 1) -+ return FALSE; -+ /* Make sure that the record is not too big either. */ -+ if (rec_size > PRIV (recrd.rec_size) - offset) -+ return FALSE; -+ -+ offset += rec_size; -+ -+ size = bfd_getl32 (eisd->secsize); -+ vaddr = bfd_getl64 (eisd->virt_addr); -+ flags = bfd_getl32 (eisd->flags); -+ vbn = bfd_getl32 (eisd->vbn); -+ -+ vms_debug2 ((4, "EISD at 0x%x size 0x%x addr 0x%lx flags 0x%x blk %d\n", -+ offset, size, (unsigned long)vaddr, flags, vbn)); -+ -+ /* VMS combines psects from .obj files into isects in the .exe. This -+ process doesn't preserve enough information to reliably determine -+ what's in each section without examining the data. This is -+ especially true of DWARF debug sections. */ -+ bfd_flags = SEC_ALLOC; -+ if (vbn != 0) -+ bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD; -+ -+ if (flags & EISD__M_EXE) -+ bfd_flags |= SEC_CODE; -+ -+ if (flags & EISD__M_NONSHRADR) -+ bfd_flags |= SEC_DATA; -+ -+ if (!(flags & EISD__M_WRT)) -+ bfd_flags |= SEC_READONLY; -+ -+ if (flags & EISD__M_DZRO) -+ bfd_flags |= SEC_DATA; -+ -+ if (flags & EISD__M_FIXUPVEC) -+ bfd_flags |= SEC_DATA; -+ -+ if (flags & EISD__M_CRF) -+ bfd_flags |= SEC_DATA; -+ -+ if (flags & EISD__M_GBL) -+ { -+ if (rec_size <= offsetof (struct vms_eisd, gblnam)) -+ return FALSE; -+ else if (rec_size < sizeof (struct vms_eisd)) -+ name = _bfd_vms_save_counted_string (abfd, eisd->gblnam, -+ rec_size - offsetof (struct vms_eisd, gblnam)); -+ else -+ name = _bfd_vms_save_counted_string (abfd, eisd->gblnam, -+ EISD__K_GBLNAMLEN); -+ if (name == NULL || name[0] == 0) -+ return FALSE; -+ bfd_flags |= SEC_COFF_SHARED_LIBRARY; -+ bfd_flags &= ~(SEC_ALLOC | SEC_LOAD); -+ } -+ else if (flags & EISD__M_FIXUPVEC) -+ name = "$FIXUPVEC$"; -+ else if (eisd->type == EISD__K_USRSTACK) -+ name = "$STACK$"; -+ else -+ { -+ const char *pfx; -+ -+ name = (char *) bfd_alloc (abfd, 32); -+ if (name == NULL) -+ return FALSE; -+ if (flags & EISD__M_DZRO) -+ pfx = "BSS"; -+ else if (flags & EISD__M_EXE) -+ pfx = "CODE"; -+ else if (!(flags & EISD__M_WRT)) -+ pfx = "RO"; -+ else -+ pfx = "LOCAL"; -+ BFD_ASSERT (section_count < 999); -+ sprintf (name, "$%s_%03d$", pfx, section_count++); -+ } -+ -+ section = bfd_make_section (abfd, name); -+ -+ if (!section) -+ return FALSE; -+ -+ section->filepos = vbn ? VMS_BLOCK_SIZE * (vbn - 1) : 0; -+ section->size = size; -+ section->vma = vaddr; -+ -+ if (!bfd_set_section_flags (section, bfd_flags)) -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+/* Read & process EIHS record. -+ Return TRUE on success, FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset) -+{ -+ unsigned char *p = PRIV (recrd.rec) + offset; -+ unsigned int gstvbn; -+ unsigned int gstsize ATTRIBUTE_UNUSED; -+ unsigned int dstvbn; -+ unsigned int dstsize; -+ unsigned int dmtvbn; -+ unsigned int dmtbytes; -+ asection *section; -+ -+ /* PR 21611: Check that offset is valid. */ -+ if (offset > PRIV (recrd.rec_size) - (EIHS__L_DMTBYTES + 4)) -+ { -+ _bfd_error_handler (_("unable to read EIHS record at offset %#x"), -+ offset); -+ bfd_set_error (bfd_error_file_truncated); -+ return FALSE; -+ } -+ -+ gstvbn = bfd_getl32 (p + EIHS__L_GSTVBN); -+ gstsize = bfd_getl32 (p + EIHS__L_GSTSIZE); -+ dstvbn = bfd_getl32 (p + EIHS__L_DSTVBN); -+ dstsize = bfd_getl32 (p + EIHS__L_DSTSIZE); -+ dmtvbn = bfd_getl32 (p + EIHS__L_DMTVBN); -+ dmtbytes = bfd_getl32 (p + EIHS__L_DMTBYTES); -+ -+#if VMS_DEBUG -+ vms_debug (8, "_bfd_vms_slurp_ihs\n"); -+ vms_debug (4, "EIHS record gstvbn %d gstsize %d dstvbn %d dstsize %d dmtvbn %d dmtbytes %d\n", -+ gstvbn, gstsize, dstvbn, dstsize, dmtvbn, dmtbytes); -+#endif -+ -+ if (dstvbn) -+ { -+ flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING; -+ -+ section = bfd_make_section (abfd, "$DST$"); -+ if (!section) -+ return FALSE; -+ -+ section->size = dstsize; -+ section->filepos = VMS_BLOCK_SIZE * (dstvbn - 1); -+ -+ if (!bfd_set_section_flags (section, bfd_flags)) -+ return FALSE; -+ -+ PRIV (dst_section) = section; -+ abfd->flags |= (HAS_DEBUG | HAS_LINENO); -+ } -+ -+ if (dmtvbn) -+ { -+ flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING; -+ -+ section = bfd_make_section (abfd, "$DMT$"); -+ if (!section) -+ return FALSE; -+ -+ section->size = dmtbytes; -+ section->filepos = VMS_BLOCK_SIZE * (dmtvbn - 1); -+ -+ if (!bfd_set_section_flags (section, bfd_flags)) -+ return FALSE; -+ } -+ -+ if (gstvbn) -+ { -+ if (bfd_seek (abfd, VMS_BLOCK_SIZE * (gstvbn - 1), SEEK_SET)) -+ { -+ bfd_set_error (bfd_error_file_truncated); -+ return FALSE; -+ } -+ -+ if (!_bfd_vms_slurp_object_records (abfd)) -+ return FALSE; -+ -+ abfd->flags |= HAS_SYMS; -+ } -+ -+ return TRUE; -+} -+ -+/* Object file reading. */ -+ -+/* Object file input functions. */ -+ -+/* Get next record from object file to vms_buf. -+ Set PRIV(buf_size) and return it -+ -+ This is a little tricky since it should be portable. -+ -+ The openVMS object file has 'variable length' which means that -+ read() returns data in chunks of (hopefully) correct and expected -+ size. The linker (and other tools on VMS) depend on that. Unix -+ doesn't know about 'formatted' files, so reading and writing such -+ an object file in a Unix environment is not trivial. -+ -+ With the tool 'file' (available on all VMS FTP sites), one -+ can view and change the attributes of a file. Changing from -+ 'variable length' to 'fixed length, 512 bytes' reveals the -+ record size at the first 2 bytes of every record. The same -+ may happen during the transfer of object files from VMS to Unix, -+ at least with UCX, the DEC implementation of TCP/IP. -+ -+ The VMS format repeats the size at bytes 2 & 3 of every record. -+ -+ On the first call (file_format == FF_UNKNOWN) we check if -+ the first and the third byte pair (!) of the record match. -+ If they do it's an object file in an Unix environment or with -+ wrong attributes (FF_FOREIGN), else we should be in a VMS -+ environment where read() returns the record size (FF_NATIVE). -+ -+ Reading is always done in 2 steps: -+ 1. first just the record header is read and the size extracted, -+ 2. then the read buffer is adjusted and the remaining bytes are -+ read in. -+ -+ All file I/O is done on even file positions. */ -+ -+#define VMS_OBJECT_ADJUSTMENT 2 -+ -+static void -+maybe_adjust_record_pointer_for_object (bfd *abfd) -+{ -+ /* Set the file format once for all on the first invocation. */ -+ if (PRIV (recrd.file_format) == FF_UNKNOWN) -+ { -+ if (PRIV (recrd.rec)[0] == PRIV (recrd.rec)[4] -+ && PRIV (recrd.rec)[1] == PRIV (recrd.rec)[5]) -+ PRIV (recrd.file_format) = FF_FOREIGN; -+ else -+ PRIV (recrd.file_format) = FF_NATIVE; -+ } -+ -+ /* The adjustment is needed only in an Unix environment. */ -+ if (PRIV (recrd.file_format) == FF_FOREIGN) -+ PRIV (recrd.rec) += VMS_OBJECT_ADJUSTMENT; -+} -+ -+/* Implement step #1 of the object record reading procedure. -+ Return the record type or -1 on failure. */ -+ -+static int -+_bfd_vms_get_object_record (bfd *abfd) -+{ -+ unsigned int test_len = 6; -+ int type; -+ -+ vms_debug2 ((8, "_bfd_vms_get_obj_record\n")); -+ -+ /* Skip alignment byte if the current position is odd. */ -+ if (PRIV (recrd.file_format) == FF_FOREIGN && (bfd_tell (abfd) & 1)) -+ { -+ if (bfd_bread (PRIV (recrd.buf), 1, abfd) != 1) -+ { -+ bfd_set_error (bfd_error_file_truncated); -+ return -1; -+ } -+ } -+ -+ /* Read the record header */ -+ if (bfd_bread (PRIV (recrd.buf), test_len, abfd) != test_len) -+ { -+ bfd_set_error (bfd_error_file_truncated); -+ return -1; -+ } -+ -+ /* Reset the record pointer. */ -+ PRIV (recrd.rec) = PRIV (recrd.buf); -+ maybe_adjust_record_pointer_for_object (abfd); -+ -+ if (vms_get_remaining_object_record (abfd, test_len) <= 0) -+ return -1; -+ -+ type = bfd_getl16 (PRIV (recrd.rec)); -+ -+ vms_debug2 ((8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n", -+ PRIV (recrd.rec), PRIV (recrd.rec_size), type)); -+ -+ return type; -+} -+ -+/* Implement step #2 of the object record reading procedure. -+ Return the size of the record or 0 on failure. */ -+ -+static int -+vms_get_remaining_object_record (bfd *abfd, unsigned int read_so_far) -+{ -+ unsigned int to_read; -+ -+ vms_debug2 ((8, "vms_get_remaining_obj_record\n")); -+ -+ /* Extract record size. */ -+ PRIV (recrd.rec_size) = bfd_getl16 (PRIV (recrd.rec) + 2); -+ -+ if (PRIV (recrd.rec_size) == 0) -+ { -+ bfd_set_error (bfd_error_file_truncated); -+ return 0; -+ } -+ -+ /* That's what the linker manual says. */ -+ if (PRIV (recrd.rec_size) > EOBJ__C_MAXRECSIZ) -+ { -+ bfd_set_error (bfd_error_file_truncated); -+ return 0; -+ } -+ -+ /* Take into account object adjustment. */ -+ to_read = PRIV (recrd.rec_size); -+ if (PRIV (recrd.file_format) == FF_FOREIGN) -+ to_read += VMS_OBJECT_ADJUSTMENT; -+ -+ /* Adjust the buffer. */ -+ if (to_read > PRIV (recrd.buf_size)) -+ { -+ PRIV (recrd.buf) -+ = (unsigned char *) bfd_realloc (PRIV (recrd.buf), to_read); -+ if (PRIV (recrd.buf) == NULL) -+ return 0; -+ PRIV (recrd.buf_size) = to_read; -+ } -+ /* PR 17512: file: 025-1974-0.004. */ -+ else if (to_read <= read_so_far) -+ return 0; -+ -+ /* Read the remaining record. */ -+ to_read -= read_so_far; -+ -+ vms_debug2 ((8, "vms_get_remaining_obj_record: to_read %d\n", to_read)); -+ -+ if (bfd_bread (PRIV (recrd.buf) + read_so_far, to_read, abfd) != to_read) -+ { -+ bfd_set_error (bfd_error_file_truncated); -+ return 0; -+ } -+ -+ /* Reset the record pointer. */ -+ PRIV (recrd.rec) = PRIV (recrd.buf); -+ maybe_adjust_record_pointer_for_object (abfd); -+ -+ vms_debug2 ((8, "vms_get_remaining_obj_record: size %d\n", -+ PRIV (recrd.rec_size))); -+ -+ return PRIV (recrd.rec_size); -+} -+ -+/* Read and process emh record. -+ Return TRUE on success, FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_ehdr (bfd *abfd) -+{ -+ unsigned char *ptr; -+ unsigned char *vms_rec; -+ unsigned char *end; -+ int subtype; -+ -+ vms_rec = PRIV (recrd.rec); -+ /* PR 17512: file: 62736583. */ -+ end = PRIV (recrd.buf) + PRIV (recrd.buf_size); -+ -+ vms_debug2 ((2, "HDR/EMH\n")); -+ -+ subtype = bfd_getl16 (vms_rec + 4); -+ -+ vms_debug2 ((3, "subtype %d\n", subtype)); -+ -+ switch (subtype) -+ { -+ case EMH__C_MHD: -+ /* Module header. */ -+ if (vms_rec + 21 >= end) -+ goto fail; -+ PRIV (hdr_data).hdr_b_strlvl = vms_rec[6]; -+ PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8); -+ PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12); -+ PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16); -+ if ((vms_rec + 20 + vms_rec[20] + 1) >= end) -+ goto fail; -+ PRIV (hdr_data).hdr_t_name -+ = _bfd_vms_save_counted_string (abfd, vms_rec + 20, vms_rec[20]); -+ ptr = vms_rec + 20 + vms_rec[20] + 1; -+ if ((ptr + *ptr + 1) >= end) -+ goto fail; -+ PRIV (hdr_data).hdr_t_version -+ = _bfd_vms_save_counted_string (abfd, ptr, *ptr); -+ ptr += *ptr + 1; -+ if (ptr + 17 >= end) -+ goto fail; -+ PRIV (hdr_data).hdr_t_date -+ = _bfd_vms_save_sized_string (abfd, ptr, 17); -+ break; -+ -+ case EMH__C_LNM: -+ if (vms_rec + PRIV (recrd.rec_size - 6) > end) -+ goto fail; -+ PRIV (hdr_data).hdr_c_lnm -+ = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6)); -+ break; -+ -+ case EMH__C_SRC: -+ if (vms_rec + PRIV (recrd.rec_size - 6) > end) -+ goto fail; -+ PRIV (hdr_data).hdr_c_src -+ = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6)); -+ break; -+ -+ case EMH__C_TTL: -+ if (vms_rec + PRIV (recrd.rec_size - 6) > end) -+ goto fail; -+ PRIV (hdr_data).hdr_c_ttl -+ = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6)); -+ break; -+ -+ case EMH__C_CPR: -+ case EMH__C_MTC: -+ case EMH__C_GTX: -+ break; -+ -+ default: -+ fail: -+ bfd_set_error (bfd_error_wrong_format); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+/* Typical sections for evax object files. */ -+ -+#define EVAX_ABS_NAME "$ABS$" -+#define EVAX_CODE_NAME "$CODE$" -+#define EVAX_LINK_NAME "$LINK$" -+#define EVAX_DATA_NAME "$DATA$" -+#define EVAX_BSS_NAME "$BSS$" -+#define EVAX_READONLYADDR_NAME "$READONLY_ADDR$" -+#define EVAX_READONLY_NAME "$READONLY$" -+#define EVAX_LITERAL_NAME "$LITERAL$" -+#define EVAX_LITERALS_NAME "$LITERALS" -+#define EVAX_COMMON_NAME "$COMMON$" -+#define EVAX_LOCAL_NAME "$LOCAL$" -+ -+struct sec_flags_struct -+{ -+ const char *name; /* Name of section. */ -+ int vflags_always; -+ flagword flags_always; /* Flags we set always. */ -+ int vflags_hassize; -+ flagword flags_hassize; /* Flags we set if the section has a size > 0. */ -+}; -+ -+/* These flags are deccrtl/vaxcrtl (openVMS 6.2 Sw_64) compatible. */ -+ -+static const struct sec_flags_struct evax_section_flags[] = -+ { -+ { EVAX_ABS_NAME, -+ EGPS__V_SHR, -+ 0, -+ EGPS__V_SHR, -+ 0 }, -+ { EVAX_CODE_NAME, -+ EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE, -+ SEC_CODE | SEC_READONLY, -+ EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE, -+ SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -+ { EVAX_LITERAL_NAME, -+ EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD, -+ SEC_DATA | SEC_READONLY, -+ EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD, -+ SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -+ { EVAX_LINK_NAME, -+ EGPS__V_REL | EGPS__V_RD, -+ SEC_DATA | SEC_READONLY, -+ EGPS__V_REL | EGPS__V_RD, -+ SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -+ { EVAX_DATA_NAME, -+ EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD, -+ SEC_DATA, -+ EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -+ SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -+ { EVAX_BSS_NAME, -+ EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD, -+ SEC_NO_FLAGS, -+ EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD, -+ SEC_ALLOC }, -+ { EVAX_READONLYADDR_NAME, -+ EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD, -+ SEC_DATA | SEC_READONLY, -+ EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD, -+ SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -+ { EVAX_READONLY_NAME, -+ EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD, -+ SEC_DATA | SEC_READONLY, -+ EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD, -+ SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -+ { EVAX_LOCAL_NAME, -+ EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -+ SEC_DATA, -+ EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -+ SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -+ { EVAX_LITERALS_NAME, -+ EGPS__V_PIC | EGPS__V_OVR, -+ SEC_DATA | SEC_READONLY, -+ EGPS__V_PIC | EGPS__V_OVR, -+ SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, -+ { NULL, -+ EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -+ SEC_DATA, -+ EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, -+ SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD } -+ }; -+ -+/* Retrieve BFD section flags by name and size. */ -+ -+static flagword -+vms_secflag_by_name (const struct sec_flags_struct *section_flags, -+ const char *name, -+ int hassize) -+{ -+ int i = 0; -+ -+ while (section_flags[i].name != NULL) -+ { -+ if (strcmp (name, section_flags[i].name) == 0) -+ { -+ if (hassize) -+ return section_flags[i].flags_hassize; -+ else -+ return section_flags[i].flags_always; -+ } -+ i++; -+ } -+ if (hassize) -+ return section_flags[i].flags_hassize; -+ return section_flags[i].flags_always; -+} -+ -+/* Retrieve VMS section flags by name and size. */ -+ -+static flagword -+vms_esecflag_by_name (const struct sec_flags_struct *section_flags, -+ const char *name, -+ int hassize) -+{ -+ int i = 0; -+ -+ while (section_flags[i].name != NULL) -+ { -+ if (strcmp (name, section_flags[i].name) == 0) -+ { -+ if (hassize) -+ return section_flags[i].vflags_hassize; -+ else -+ return section_flags[i].vflags_always; -+ } -+ i++; -+ } -+ if (hassize) -+ return section_flags[i].vflags_hassize; -+ return section_flags[i].vflags_always; -+} -+ -+/* Add SYM to the symbol table of ABFD. -+ Return FALSE in case of error. */ -+ -+static bfd_boolean -+add_symbol_entry (bfd *abfd, struct vms_symbol_entry *sym) -+{ -+ if (PRIV (gsd_sym_count) >= PRIV (max_sym_count)) -+ { -+ if (PRIV (max_sym_count) == 0) -+ { -+ PRIV (max_sym_count) = 128; -+ PRIV (syms) = bfd_malloc -+ (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *)); -+ } -+ else -+ { -+ PRIV (max_sym_count) *= 2; -+ PRIV (syms) = bfd_realloc -+ (PRIV (syms), -+ (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *))); -+ } -+ if (PRIV (syms) == NULL) -+ return FALSE; -+ } -+ -+ PRIV (syms)[PRIV (gsd_sym_count)++] = sym; -+ return TRUE; -+} -+ -+/* Create a symbol whose name is ASCIC and add it to ABFD. -+ Return NULL in case of error. */ -+ -+static struct vms_symbol_entry * -+add_symbol (bfd *abfd, const unsigned char *ascic, unsigned int max) -+{ -+ struct vms_symbol_entry *entry; -+ unsigned int len; -+ -+ len = *ascic++; -+ max -= 1; -+ if (len > max) -+ { -+ _bfd_error_handler (_("record is too small for symbol name length")); -+ bfd_set_error (bfd_error_bad_value); -+ return NULL; -+ } -+ -+ entry = (struct vms_symbol_entry *)bfd_zalloc (abfd, sizeof (*entry) + len); -+ if (entry == NULL) -+ return NULL; -+ entry->namelen = len; -+ memcpy (entry->name, ascic, len); -+ entry->name[len] = 0; -+ entry->owner = abfd; -+ -+ if (!add_symbol_entry (abfd, entry)) -+ return NULL; -+ return entry; -+} -+ -+/* Read and process EGSD. Return FALSE on failure. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_egsd (bfd *abfd) -+{ -+ int gsd_type; -+ unsigned int gsd_size; -+ unsigned char *vms_rec; -+ bfd_vma base_addr; -+ long psindx; -+ -+ vms_debug2 ((2, "EGSD\n")); -+ -+ if (PRIV (recrd.rec_size) < 8) -+ { -+ _bfd_error_handler (_("corrupt EGSD record: its size (%#x) is too small"), -+ PRIV (recrd.rec_size)); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ PRIV (recrd.rec) += 8; /* Skip type, size, align pad. */ -+ PRIV (recrd.rec_size) -= 8; -+ -+ /* Calculate base address for each section. */ -+ base_addr = 0; -+ -+ while (PRIV (recrd.rec_size) > 4) -+ { -+ vms_rec = PRIV (recrd.rec); -+ -+ gsd_type = bfd_getl16 (vms_rec); -+ gsd_size = bfd_getl16 (vms_rec + 2); -+ -+ vms_debug2 ((3, "egsd_type %d\n", gsd_type)); -+ -+ /* PR 21615: Check for size overflow. */ -+ if (PRIV (recrd.rec_size) < gsd_size) -+ { -+ _bfd_error_handler (_("corrupt EGSD record type %d: size (%#x) " -+ "is larger than remaining space (%#x)"), -+ gsd_type, gsd_size, PRIV (recrd.rec_size)); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ if (gsd_size < 4) -+ { -+ too_small: -+ _bfd_error_handler (_("corrupt EGSD record type %d: size (%#x) " -+ "is too small"), -+ gsd_type, gsd_size); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ switch (gsd_type) -+ { -+ case EGSD__C_PSC: -+ /* Program section definition. */ -+ { -+ struct vms_egps *egps = (struct vms_egps *) vms_rec; -+ flagword new_flags, vms_flags; -+ asection *section; -+ -+ if (offsetof (struct vms_egps, flags) + 2 > gsd_size) -+ goto too_small; -+ vms_flags = bfd_getl16 (egps->flags); -+ -+ if ((vms_flags & EGPS__V_REL) == 0) -+ { -+ /* Use the global absolute section for all -+ absolute sections. */ -+ section = bfd_abs_section_ptr; -+ } -+ else -+ { -+ char *name; -+ bfd_vma align_addr; -+ size_t left; -+ -+ if (offsetof (struct vms_egps, namlng) >= gsd_size) -+ goto too_small; -+ left = gsd_size - offsetof (struct vms_egps, namlng); -+ name = _bfd_vms_save_counted_string (abfd, &egps->namlng, left); -+ if (name == NULL || name[0] == 0) -+ return FALSE; -+ -+ section = bfd_make_section (abfd, name); -+ if (!section) -+ return FALSE; -+ -+ section->filepos = 0; -+ section->size = bfd_getl32 (egps->alloc); -+ section->alignment_power = egps->align & 31; -+ -+ vms_section_data (section)->flags = vms_flags; -+ vms_section_data (section)->no_flags = 0; -+ -+ new_flags = vms_secflag_by_name (evax_section_flags, -+ section->name, -+ section->size > 0); -+ if (section->size > 0) -+ new_flags |= SEC_LOAD; -+ if (!(vms_flags & EGPS__V_NOMOD) && section->size > 0) -+ { -+ /* Set RELOC and HAS_CONTENTS if the section is not -+ demand-zero and not empty. */ -+ new_flags |= SEC_HAS_CONTENTS; -+ if (vms_flags & EGPS__V_REL) -+ new_flags |= SEC_RELOC; -+ } -+ if (vms_flags & EGPS__V_EXE) -+ { -+ /* Set CODE if section is executable. */ -+ new_flags |= SEC_CODE; -+ new_flags &= ~SEC_DATA; -+ } -+ if (!bfd_set_section_flags (section, new_flags)) -+ return FALSE; -+ -+ /* Give a non-overlapping vma to non absolute sections. */ -+ align_addr = (bfd_vma) 1 << section->alignment_power; -+ base_addr = (base_addr + align_addr - 1) & -align_addr; -+ section->vma = base_addr; -+ base_addr += section->size; -+ } -+ -+ /* Append it to the section array. */ -+ if (PRIV (section_count) >= PRIV (section_max)) -+ { -+ if (PRIV (section_max) == 0) -+ PRIV (section_max) = 16; -+ else -+ PRIV (section_max) *= 2; -+ PRIV (sections) = bfd_realloc_or_free -+ (PRIV (sections), PRIV (section_max) * sizeof (asection *)); -+ if (PRIV (sections) == NULL) -+ return FALSE; -+ } -+ -+ PRIV (sections)[PRIV (section_count)] = section; -+ PRIV (section_count)++; -+ } -+ break; -+ -+ case EGSD__C_SYM: -+ { -+ unsigned int nameoff; -+ struct vms_symbol_entry *entry; -+ struct vms_egsy *egsy = (struct vms_egsy *) vms_rec; -+ flagword old_flags; -+ -+ if (offsetof (struct vms_egsy, flags) + 2 > gsd_size) -+ goto too_small; -+ old_flags = bfd_getl16 (egsy->flags); -+ if (old_flags & EGSY__V_DEF) -+ nameoff = ESDF__B_NAMLNG; -+ else -+ nameoff = ESRF__B_NAMLNG; -+ -+ if (nameoff >= gsd_size) -+ goto too_small; -+ entry = add_symbol (abfd, vms_rec + nameoff, gsd_size - nameoff); -+ if (entry == NULL) -+ return FALSE; -+ -+ /* Allow only duplicate reference. */ -+ if ((entry->flags & EGSY__V_DEF) && (old_flags & EGSY__V_DEF)) -+ abort (); -+ -+ if (entry->typ == 0) -+ { -+ entry->typ = gsd_type; -+ entry->data_type = egsy->datyp; -+ entry->flags = old_flags; -+ } -+ -+ if (old_flags & EGSY__V_DEF) -+ { -+ struct vms_esdf *esdf = (struct vms_esdf *) vms_rec; -+ -+ entry->value = bfd_getl64 (esdf->value); -+ if (PRIV (sections) == NULL) -+ return FALSE; -+ -+ psindx = bfd_getl32 (esdf->psindx); -+ /* PR 21813: Check for an out of range index. */ -+ if (psindx < 0 || psindx >= (int) PRIV (section_count)) -+ { -+ bad_psindx: -+ _bfd_error_handler (_("corrupt EGSD record: its psindx " -+ "field is too big (%#lx)"), -+ psindx); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ entry->section = PRIV (sections)[psindx]; -+ -+ if (old_flags & EGSY__V_NORM) -+ { -+ PRIV (norm_sym_count)++; -+ -+ entry->code_value = bfd_getl64 (esdf->code_address); -+ psindx = bfd_getl32 (esdf->ca_psindx); -+ /* PR 21813: Check for an out of range index. */ -+ if (psindx < 0 || psindx >= (int) PRIV (section_count)) -+ goto bad_psindx; -+ entry->code_section = PRIV (sections)[psindx]; -+ } -+ } -+ } -+ break; -+ -+ case EGSD__C_SYMG: -+ { -+ struct vms_symbol_entry *entry; -+ struct vms_egst *egst = (struct vms_egst *)vms_rec; -+ flagword old_flags; -+ unsigned int nameoff = offsetof (struct vms_egst, namlng); -+ -+ old_flags = bfd_getl16 (egst->header.flags); -+ -+ if (nameoff >= gsd_size) -+ goto too_small; -+ entry = add_symbol (abfd, &egst->namlng, gsd_size - nameoff); -+ if (entry == NULL) -+ return FALSE; -+ -+ entry->typ = gsd_type; -+ entry->data_type = egst->header.datyp; -+ entry->flags = old_flags; -+ -+ entry->symbol_vector = bfd_getl32 (egst->value); -+ -+ if (old_flags & EGSY__V_REL) -+ { -+ if (PRIV (sections) == NULL) -+ return FALSE; -+ psindx = bfd_getl32 (egst->psindx); -+ /* PR 21813: Check for an out of range index. */ -+ if (psindx < 0 || psindx >= (int) PRIV (section_count)) -+ goto bad_psindx; -+ entry->section = PRIV (sections)[psindx]; -+ } -+ else -+ entry->section = bfd_abs_section_ptr; -+ -+ entry->value = bfd_getl64 (egst->lp_2); -+ -+ if (old_flags & EGSY__V_NORM) -+ { -+ PRIV (norm_sym_count)++; -+ -+ entry->code_value = bfd_getl64 (egst->lp_1); -+ entry->code_section = bfd_abs_section_ptr; -+ } -+ } -+ break; -+ -+ case EGSD__C_SPSC: -+ case EGSD__C_IDC: -+ /* Currently ignored. */ -+ break; -+ case EGSD__C_SYMM: -+ case EGSD__C_SYMV: -+ default: -+ _bfd_error_handler (_("unknown EGSD subtype %d"), gsd_type); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ PRIV (recrd.rec_size) -= gsd_size; -+ PRIV (recrd.rec) += gsd_size; -+ } -+ -+ /* FIXME: Should we complain if PRIV (recrd.rec_size) is not zero ? */ -+ -+ if (PRIV (gsd_sym_count) > 0) -+ abfd->flags |= HAS_SYMS; -+ -+ return TRUE; -+} -+ -+/* Stack routines for vms ETIR commands. */ -+ -+/* Push value and section index. */ -+ -+static bfd_boolean -+_bfd_vms_push (bfd *abfd, bfd_vma val, unsigned int reloc) -+{ -+ vms_debug2 ((4, "\n", -+ (unsigned long)val, reloc, PRIV (stackptr))); -+ -+ PRIV (stack[PRIV (stackptr)]).value = val; -+ PRIV (stack[PRIV (stackptr)]).reloc = reloc; -+ PRIV (stackptr)++; -+ if (PRIV (stackptr) >= STACKSIZE) -+ { -+ bfd_set_error (bfd_error_bad_value); -+ _bfd_error_handler (_("stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr)); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+/* Pop value and section index. */ -+ -+static bfd_boolean -+_bfd_vms_pop (bfd *abfd, bfd_vma *val, unsigned int *rel) -+{ -+ if (PRIV (stackptr) == 0) -+ { -+ bfd_set_error (bfd_error_bad_value); -+ _bfd_error_handler (_("stack underflow in _bfd_vms_pop")); -+ return FALSE; -+ } -+ PRIV (stackptr)--; -+ *val = PRIV (stack[PRIV (stackptr)]).value; -+ *rel = PRIV (stack[PRIV (stackptr)]).reloc; -+ -+ vms_debug2 ((4, "\n", (unsigned long)*val, *rel)); -+ return TRUE; -+} -+ -+/* Routines to fill sections contents during tir/etir read. */ -+ -+/* Initialize image buffer pointer to be filled. */ -+ -+static void -+image_set_ptr (bfd *abfd, bfd_vma vma, int sect, struct bfd_link_info *info) -+{ -+ asection *sec; -+ -+ vms_debug2 ((4, "image_set_ptr (0x%08x, sect=%d)\n", (unsigned)vma, sect)); -+ -+ if (PRIV (sections) == NULL) -+ return; -+ if (sect < 0 || sect >= (int) PRIV (section_count)) -+ return; -+ -+ sec = PRIV (sections)[sect]; -+ -+ if (info) -+ { -+ /* Reading contents to an output bfd. */ -+ -+ if (sec->output_section == NULL) -+ { -+ /* Section discarded. */ -+ vms_debug2 ((5, " section %s discarded\n", sec->name)); -+ -+ /* This is not used. */ -+ PRIV (image_section) = NULL; -+ PRIV (image_offset) = 0; -+ return; -+ } -+ PRIV (image_offset) = sec->output_offset + vma; -+ PRIV (image_section) = sec->output_section; -+ } -+ else -+ { -+ PRIV (image_offset) = vma; -+ PRIV (image_section) = sec; -+ } -+} -+ -+/* Increment image buffer pointer by offset. */ -+ -+static void -+image_inc_ptr (bfd *abfd, bfd_vma offset) -+{ -+ vms_debug2 ((4, "image_inc_ptr (%u)\n", (unsigned)offset)); -+ -+ PRIV (image_offset) += offset; -+} -+ -+/* Save current DST location counter under specified index. */ -+ -+static void -+dst_define_location (bfd *abfd, unsigned int loc) -+{ -+ vms_debug2 ((4, "dst_define_location (%d)\n", (int)loc)); -+ -+ /* Grow the ptr offset table if necessary. */ -+ if (loc + 1 > PRIV (dst_ptr_offsets_count)) -+ { -+ PRIV (dst_ptr_offsets) = bfd_realloc (PRIV (dst_ptr_offsets), -+ (loc + 1) * sizeof (unsigned int)); -+ PRIV (dst_ptr_offsets_count) = loc + 1; -+ } -+ -+ PRIV (dst_ptr_offsets)[loc] = PRIV (image_offset); -+} -+ -+/* Restore saved DST location counter from specified index. */ -+ -+static void -+dst_restore_location (bfd *abfd, unsigned int loc) -+{ -+ vms_debug2 ((4, "dst_restore_location (%d)\n", (int)loc)); -+ -+ PRIV (image_offset) = PRIV (dst_ptr_offsets)[loc]; -+} -+ -+/* Retrieve saved DST location counter from specified index. */ -+ -+static unsigned int -+dst_retrieve_location (bfd *abfd, unsigned int loc) -+{ -+ vms_debug2 ((4, "dst_retrieve_location (%d)\n", (int)loc)); -+ -+ return PRIV (dst_ptr_offsets)[loc]; -+} -+ -+/* Write multiple bytes to section image. */ -+ -+static bfd_boolean -+image_write (bfd *abfd, unsigned char *ptr, unsigned int size) -+{ -+#if VMS_DEBUG -+ _bfd_vms_debug (8, "image_write from (%p, %d) to (%ld)\n", ptr, size, -+ (long)PRIV (image_offset)); -+#endif -+ -+ if (PRIV (image_section)->contents != NULL) -+ { -+ asection *sec = PRIV (image_section); -+ size_t off = PRIV (image_offset); -+ -+ /* Check bounds. */ -+ if (off > sec->size -+ || size > sec->size - off) -+ { -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ memcpy (sec->contents + off, ptr, size); -+ } -+#if VMS_DEBUG -+ _bfd_hexdump (9, ptr, size, 0); -+#endif -+ -+ PRIV (image_offset) += size; -+ return TRUE; -+} -+ -+/* Write byte to section image. */ -+ -+static bfd_boolean -+image_write_b (bfd * abfd, unsigned int value) -+{ -+ unsigned char data[1]; -+ -+ vms_debug2 ((6, "image_write_b (%02x)\n", (int) value)); -+ -+ *data = value; -+ -+ return image_write (abfd, data, sizeof (data)); -+} -+ -+/* Write 2-byte word to image. */ -+ -+static bfd_boolean -+image_write_w (bfd * abfd, unsigned int value) -+{ -+ unsigned char data[2]; -+ -+ vms_debug2 ((6, "image_write_w (%04x)\n", (int) value)); -+ -+ bfd_putl16 (value, data); -+ return image_write (abfd, data, sizeof (data)); -+} -+ -+/* Write 4-byte long to image. */ -+ -+static bfd_boolean -+image_write_l (bfd * abfd, unsigned long value) -+{ -+ unsigned char data[4]; -+ -+ vms_debug2 ((6, "image_write_l (%08lx)\n", value)); -+ -+ bfd_putl32 (value, data); -+ return image_write (abfd, data, sizeof (data)); -+} -+ -+/* Write 8-byte quad to image. */ -+ -+static bfd_boolean -+image_write_q (bfd * abfd, bfd_vma value) -+{ -+ unsigned char data[8]; -+ -+ vms_debug2 ((6, "image_write_q (%08lx)\n", (unsigned long)value)); -+ -+ bfd_putl64 (value, data); -+ return image_write (abfd, data, sizeof (data)); -+} -+ -+static const char * -+_bfd_vms_etir_name (int cmd) -+{ -+ switch (cmd) -+ { -+ case ETIR__C_STA_GBL: return "ETIR__C_STA_GBL"; -+ case ETIR__C_STA_LW: return "ETIR__C_STA_LW"; -+ case ETIR__C_STA_QW: return "ETIR__C_STA_QW"; -+ case ETIR__C_STA_PQ: return "ETIR__C_STA_PQ"; -+ case ETIR__C_STA_LI: return "ETIR__C_STA_LI"; -+ case ETIR__C_STA_MOD: return "ETIR__C_STA_MOD"; -+ case ETIR__C_STA_CKARG: return "ETIR__C_STA_CKARG"; -+ case ETIR__C_STO_B: return "ETIR__C_STO_B"; -+ case ETIR__C_STO_W: return "ETIR__C_STO_W"; -+ case ETIR__C_STO_GBL: return "ETIR__C_STO_GBL"; -+ case ETIR__C_STO_CA: return "ETIR__C_STO_CA"; -+ case ETIR__C_STO_RB: return "ETIR__C_STO_RB"; -+ case ETIR__C_STO_AB: return "ETIR__C_STO_AB"; -+ case ETIR__C_STO_OFF: return "ETIR__C_STO_OFF"; -+ case ETIR__C_STO_IMM: return "ETIR__C_STO_IMM"; -+ case ETIR__C_STO_IMMR: return "ETIR__C_STO_IMMR"; -+ case ETIR__C_STO_LW: return "ETIR__C_STO_LW"; -+ case ETIR__C_STO_QW: return "ETIR__C_STO_QW"; -+ case ETIR__C_STO_GBL_LW: return "ETIR__C_STO_GBL_LW"; -+ case ETIR__C_STO_LP_PSB: return "ETIR__C_STO_LP_PSB"; -+ case ETIR__C_STO_HINT_GBL: return "ETIR__C_STO_HINT_GBL"; -+ case ETIR__C_STO_HINT_PS: return "ETIR__C_STO_HINT_PS"; -+ case ETIR__C_OPR_ADD: return "ETIR__C_OPR_ADD"; -+ case ETIR__C_OPR_SUB: return "ETIR__C_OPR_SUB"; -+ case ETIR__C_OPR_INSV: return "ETIR__C_OPR_INSV"; -+ case ETIR__C_OPR_USH: return "ETIR__C_OPR_USH"; -+ case ETIR__C_OPR_ROT: return "ETIR__C_OPR_ROT"; -+ case ETIR__C_OPR_REDEF: return "ETIR__C_OPR_REDEF"; -+ case ETIR__C_OPR_DFLIT: return "ETIR__C_OPR_DFLIT"; -+ case ETIR__C_STC_LP: return "ETIR__C_STC_LP"; -+ case ETIR__C_STC_GBL: return "ETIR__C_STC_GBL"; -+ case ETIR__C_STC_GCA: return "ETIR__C_STC_GCA"; -+ case ETIR__C_STC_PS: return "ETIR__C_STC_PS"; -+ case ETIR__C_STC_NBH_PS: return "ETIR__C_STC_NBH_PS"; -+ case ETIR__C_STC_NOP_GBL: return "ETIR__C_STC_NOP_GBL"; -+ case ETIR__C_STC_NOP_PS: return "ETIR__C_STC_NOP_PS"; -+ case ETIR__C_STC_BSR_GBL: return "ETIR__C_STC_BSR_GBL"; -+ case ETIR__C_STC_BSR_PS: return "ETIR__C_STC_BSR_PS"; -+ case ETIR__C_STC_LDA_GBL: return "ETIR__C_STC_LDA_GBL"; -+ case ETIR__C_STC_LDA_PS: return "ETIR__C_STC_LDA_PS"; -+ case ETIR__C_STC_BOH_GBL: return "ETIR__C_STC_BOH_GBL"; -+ case ETIR__C_STC_BOH_PS: return "ETIR__C_STC_BOH_PS"; -+ case ETIR__C_STC_NBH_GBL: return "ETIR__C_STC_NBH_GBL"; -+ case ETIR__C_STC_LP_PSB: return "ETIR__C_STC_LP_PSB"; -+ case ETIR__C_CTL_SETRB: return "ETIR__C_CTL_SETRB"; -+ case ETIR__C_CTL_AUGRB: return "ETIR__C_CTL_AUGRB"; -+ case ETIR__C_CTL_DFLOC: return "ETIR__C_CTL_DFLOC"; -+ case ETIR__C_CTL_STLOC: return "ETIR__C_CTL_STLOC"; -+ case ETIR__C_CTL_STKDL: return "ETIR__C_CTL_STKDL"; -+ -+ default: -+ /* These names have not yet been added to this switch statement. */ -+ _bfd_error_handler (_("unknown ETIR command %d"), cmd); -+ } -+ -+ return NULL; -+} -+#define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L) -+ -+static void -+_bfd_vms_get_value (bfd *abfd, -+ const unsigned char *ascic, -+ const unsigned char *max_ascic, -+ struct bfd_link_info *info, -+ bfd_vma *vma, -+ struct sw_64_vms_link_hash_entry **hp) -+{ -+ char name[257]; -+ unsigned int len; -+ unsigned int i; -+ struct sw_64_vms_link_hash_entry *h; -+ -+ /* Not linking. Do not try to resolve the symbol. */ -+ if (info == NULL) -+ { -+ *vma = 0; -+ *hp = NULL; -+ return; -+ } -+ -+ len = *ascic; -+ if (ascic + len >= max_ascic) -+ { -+ _bfd_error_handler (_("corrupt vms value")); -+ *vma = 0; -+ *hp = NULL; -+ return; -+ } -+ -+ for (i = 0; i < len; i++) -+ name[i] = ascic[i + 1]; -+ name[i] = 0; -+ -+ h = (struct sw_64_vms_link_hash_entry *) -+ bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE); -+ -+ *hp = h; -+ -+ if (h != NULL -+ && (h->root.type == bfd_link_hash_defined -+ || h->root.type == bfd_link_hash_defweak)) -+ *vma = h->root.u.def.value -+ + h->root.u.def.section->output_offset -+ + h->root.u.def.section->output_section->vma; -+ else if (h && h->root.type == bfd_link_hash_undefweak) -+ *vma = 0; -+ else -+ { -+ (*info->callbacks->undefined_symbol) -+ (info, name, abfd, PRIV (image_section), PRIV (image_offset), TRUE); -+ *vma = 0; -+ } -+} -+ -+#define RELC_NONE 0 -+#define RELC_REL 1 -+#define RELC_SHR_BASE 0x10000 -+#define RELC_SEC_BASE 0x20000 -+#define RELC_MASK 0x0ffff -+ -+static unsigned int -+sw_64_vms_sym_to_ctxt (struct sw_64_vms_link_hash_entry *h) -+{ -+ /* Handle undefined symbols. */ -+ if (h == NULL || h->sym == NULL) -+ return RELC_NONE; -+ -+ if (h->sym->typ == EGSD__C_SYMG) -+ { -+ if (h->sym->flags & EGSY__V_REL) -+ return RELC_SHR_BASE + PRIV2 (h->sym->owner, shr_index); -+ else -+ { -+ /* Can this happen (non-relocatable symg) ? I'd like to see -+ an example. */ -+ abort (); -+ } -+ } -+ if (h->sym->typ == EGSD__C_SYM) -+ { -+ if (h->sym->flags & EGSY__V_REL) -+ return RELC_REL; -+ else -+ return RELC_NONE; -+ } -+ abort (); -+} -+ -+static bfd_vma -+sw_64_vms_get_sym_value (asection *sect, bfd_vma addr) -+{ -+ return sect->output_section->vma + sect->output_offset + addr; -+} -+ -+static bfd_vma -+sw_64_vms_fix_sec_rel (bfd *abfd, struct bfd_link_info *info, -+ unsigned int rel, bfd_vma vma) -+{ -+ asection *sec; -+ -+ if (PRIV (sections) == NULL) -+ return 0; -+ -+ sec = PRIV (sections)[rel & RELC_MASK]; -+ -+ if (info) -+ { -+ if (sec->output_section == NULL) -+ abort (); -+ return vma + sec->output_section->vma + sec->output_offset; -+ } -+ else -+ return vma + sec->vma; -+} -+ -+/* Read an ETIR record from ABFD. If INFO is not null, put the content into -+ the output section (used during linking). -+ Return FALSE in case of error. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) -+{ -+ unsigned char *ptr; -+ unsigned int length; -+ unsigned char *maxptr; -+ bfd_vma op1 = 0; -+ bfd_vma op2 = 0; -+ unsigned int rel1 = RELC_NONE; -+ unsigned int rel2 = RELC_NONE; -+ struct sw_64_vms_link_hash_entry *h; -+ -+ PRIV (recrd.rec) += ETIR__C_HEADER_SIZE; -+ PRIV (recrd.rec_size) -= ETIR__C_HEADER_SIZE; -+ -+ ptr = PRIV (recrd.rec); -+ length = PRIV (recrd.rec_size); -+ maxptr = ptr + length; -+ -+ vms_debug2 ((2, "ETIR: %d bytes\n", length)); -+ -+ while (ptr < maxptr) -+ { -+ int cmd, cmd_length; -+ -+ if (ptr + 4 > maxptr) -+ goto corrupt_etir; -+ -+ cmd = bfd_getl16 (ptr); -+ cmd_length = bfd_getl16 (ptr + 2); -+ -+ /* PR 21589 and 21579: Check for a corrupt ETIR record. */ -+ if (cmd_length < 4 || ptr + cmd_length > maxptr) -+ { -+ corrupt_etir: -+ _bfd_error_handler (_("corrupt ETIR record encountered")); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ ptr += 4; -+ -+#if VMS_DEBUG -+ _bfd_vms_debug (4, "etir: %s(%d)\n", -+ _bfd_vms_etir_name (cmd), cmd); -+ _bfd_hexdump (8, ptr, cmd_length - 4, 0); -+#endif -+ -+ switch (cmd) -+ { -+ /* Stack global -+ arg: cs symbol name -+ -+ stack 32 bit value of symbol (high bits set to 0). */ -+ case ETIR__C_STA_GBL: -+ _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); -+ if (!_bfd_vms_push (abfd, op1, sw_64_vms_sym_to_ctxt (h))) -+ return FALSE; -+ break; -+ -+ /* Stack longword -+ arg: lw value -+ -+ stack 32 bit value, sign extend to 64 bit. */ -+ case ETIR__C_STA_LW: -+ if (ptr + 4 > maxptr) -+ goto corrupt_etir; -+ if (!_bfd_vms_push (abfd, bfd_getl32 (ptr), RELC_NONE)) -+ return FALSE; -+ break; -+ -+ /* Stack quadword -+ arg: qw value -+ -+ stack 64 bit value of symbol. */ -+ case ETIR__C_STA_QW: -+ if (ptr + 8 > maxptr) -+ goto corrupt_etir; -+ if (!_bfd_vms_push (abfd, bfd_getl64 (ptr), RELC_NONE)) -+ return FALSE; -+ break; -+ -+ /* Stack psect base plus quadword offset -+ arg: lw section index -+ qw signed quadword offset (low 32 bits) -+ -+ Stack qw argument and section index -+ (see ETIR__C_STO_OFF, ETIR__C_CTL_SETRB). */ -+ case ETIR__C_STA_PQ: -+ { -+ int psect; -+ -+ if (ptr + 12 > maxptr) -+ goto corrupt_etir; -+ psect = bfd_getl32 (ptr); -+ if ((unsigned int) psect >= PRIV (section_count)) -+ { -+ _bfd_error_handler (_("bad section index in %s"), -+ _bfd_vms_etir_name (cmd)); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ op1 = bfd_getl64 (ptr + 4); -+ if (!_bfd_vms_push (abfd, op1, psect | RELC_SEC_BASE)) -+ return FALSE; -+ } -+ break; -+ -+ case ETIR__C_STA_LI: -+ case ETIR__C_STA_MOD: -+ case ETIR__C_STA_CKARG: -+ _bfd_error_handler (_("unsupported STA cmd %s"), -+ _bfd_vms_etir_name (cmd)); -+ return FALSE; -+ break; -+ -+ /* Store byte: pop stack, write byte -+ arg: -. */ -+ case ETIR__C_STO_B: -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 != RELC_NONE) -+ goto bad_context; -+ image_write_b (abfd, (unsigned int) op1 & 0xff); -+ break; -+ -+ /* Store word: pop stack, write word -+ arg: -. */ -+ case ETIR__C_STO_W: -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 != RELC_NONE) -+ goto bad_context; -+ image_write_w (abfd, (unsigned int) op1 & 0xffff); -+ break; -+ -+ /* Store longword: pop stack, write longword -+ arg: -. */ -+ case ETIR__C_STO_LW: -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 & RELC_SEC_BASE) -+ { -+ op1 = sw_64_vms_fix_sec_rel (abfd, info, rel1, op1); -+ rel1 = RELC_REL; -+ } -+ else if (rel1 & RELC_SHR_BASE) -+ { -+ sw_64_vms_add_fixup_lr (info, rel1 & RELC_MASK, op1); -+ rel1 = RELC_NONE; -+ } -+ if (rel1 != RELC_NONE) -+ { -+ if (rel1 != RELC_REL) -+ abort (); -+ sw_64_vms_add_lw_reloc (info); -+ } -+ image_write_l (abfd, op1); -+ break; -+ -+ /* Store quadword: pop stack, write quadword -+ arg: -. */ -+ case ETIR__C_STO_QW: -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 & RELC_SEC_BASE) -+ { -+ op1 = sw_64_vms_fix_sec_rel (abfd, info, rel1, op1); -+ rel1 = RELC_REL; -+ } -+ else if (rel1 & RELC_SHR_BASE) -+ abort (); -+ if (rel1 != RELC_NONE) -+ { -+ if (rel1 != RELC_REL) -+ abort (); -+ sw_64_vms_add_qw_reloc (info); -+ } -+ image_write_q (abfd, op1); -+ break; -+ -+ /* Store immediate repeated: pop stack for repeat count -+ arg: lw byte count -+ da data. */ -+ case ETIR__C_STO_IMMR: -+ { -+ int size; -+ -+ if (ptr + 4 > maxptr) -+ goto corrupt_etir; -+ size = bfd_getl32 (ptr); -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 != RELC_NONE) -+ goto bad_context; -+ while (op1-- > 0) -+ image_write (abfd, ptr + 4, size); -+ } -+ break; -+ -+ /* Store global: write symbol value -+ arg: cs global symbol name. */ -+ case ETIR__C_STO_GBL: -+ _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); -+ if (h && h->sym) -+ { -+ if (h->sym->typ == EGSD__C_SYMG) -+ { -+ sw_64_vms_add_fixup_qr -+ (info, abfd, h->sym->owner, h->sym->symbol_vector); -+ op1 = 0; -+ } -+ else -+ { -+ op1 = sw_64_vms_get_sym_value (h->sym->section, -+ h->sym->value); -+ sw_64_vms_add_qw_reloc (info); -+ } -+ } -+ image_write_q (abfd, op1); -+ break; -+ -+ /* Store code address: write address of entry point -+ arg: cs global symbol name (procedure). */ -+ case ETIR__C_STO_CA: -+ _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); -+ if (h && h->sym) -+ { -+ if (h->sym->flags & EGSY__V_NORM) -+ { -+ /* That's really a procedure. */ -+ if (h->sym->typ == EGSD__C_SYMG) -+ { -+ sw_64_vms_add_fixup_ca (info, abfd, h->sym->owner); -+ op1 = h->sym->symbol_vector; -+ } -+ else -+ { -+ op1 = sw_64_vms_get_sym_value (h->sym->code_section, -+ h->sym->code_value); -+ sw_64_vms_add_qw_reloc (info); -+ } -+ } -+ else -+ { -+ /* Symbol is not a procedure. */ -+ abort (); -+ } -+ } -+ image_write_q (abfd, op1); -+ break; -+ -+ /* Store offset to psect: pop stack, add low 32 bits to base of psect -+ arg: none. */ -+ case ETIR__C_STO_OFF: -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ -+ if (!(rel1 & RELC_SEC_BASE)) -+ abort (); -+ -+ op1 = sw_64_vms_fix_sec_rel (abfd, info, rel1, op1); -+ rel1 = RELC_REL; -+ image_write_q (abfd, op1); -+ break; -+ -+ /* Store immediate -+ arg: lw count of bytes -+ da data. */ -+ case ETIR__C_STO_IMM: -+ { -+ unsigned int size; -+ -+ if (ptr + 4 > maxptr) -+ goto corrupt_etir; -+ size = bfd_getl32 (ptr); -+ image_write (abfd, ptr + 4, size); -+ } -+ break; -+ -+ /* This code is 'reserved to digital' according to the openVMS -+ linker manual, however it is generated by the DEC C compiler -+ and defined in the include file. -+ FIXME, since the following is just a guess -+ store global longword: store 32bit value of symbol -+ arg: cs symbol name. */ -+ case ETIR__C_STO_GBL_LW: -+ _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); -+#if 0 -+ abort (); -+#endif -+ image_write_l (abfd, op1); -+ break; -+ -+ case ETIR__C_STO_RB: -+ case ETIR__C_STO_AB: -+ case ETIR__C_STO_LP_PSB: -+ _bfd_error_handler (_("%s: not supported"), -+ _bfd_vms_etir_name (cmd)); -+ return FALSE; -+ break; -+ case ETIR__C_STO_HINT_GBL: -+ case ETIR__C_STO_HINT_PS: -+ _bfd_error_handler (_("%s: not implemented"), -+ _bfd_vms_etir_name (cmd)); -+ return FALSE; -+ break; -+ -+ /* 200 Store-conditional Linkage Pair -+ arg: none. */ -+ case ETIR__C_STC_LP: -+ -+ /* 202 Store-conditional Address at global address -+ lw linkage index -+ cs global name. */ -+ -+ case ETIR__C_STC_GBL: -+ -+ /* 203 Store-conditional Code Address at global address -+ lw linkage index -+ cs procedure name. */ -+ case ETIR__C_STC_GCA: -+ -+ /* 204 Store-conditional Address at psect + offset -+ lw linkage index -+ lw psect index -+ qw offset. */ -+ case ETIR__C_STC_PS: -+ _bfd_error_handler (_("%s: not supported"), -+ _bfd_vms_etir_name (cmd)); -+ return FALSE; -+ break; -+ -+ /* 201 Store-conditional Linkage Pair with Procedure Signature -+ lw linkage index -+ cs procedure name -+ by signature length -+ da signature. */ -+ -+ case ETIR__C_STC_LP_PSB: -+ _bfd_vms_get_value (abfd, ptr + 4, maxptr, info, &op1, &h); -+ if (h && h->sym) -+ { -+ if (h->sym->typ == EGSD__C_SYMG) -+ { -+ sw_64_vms_add_fixup_lp (info, abfd, h->sym->owner); -+ op1 = h->sym->symbol_vector; -+ op2 = 0; -+ } -+ else -+ { -+ op1 = sw_64_vms_get_sym_value (h->sym->code_section, -+ h->sym->code_value); -+ op2 = sw_64_vms_get_sym_value (h->sym->section, -+ h->sym->value); -+ } -+ } -+ else -+ { -+ /* Undefined symbol. */ -+ op1 = 0; -+ op2 = 0; -+ } -+ image_write_q (abfd, op1); -+ image_write_q (abfd, op2); -+ break; -+ -+ /* 205 Store-conditional NOP at address of global -+ arg: none. */ -+ case ETIR__C_STC_NOP_GBL: -+ /* SW_64_R_NOP */ -+ -+ /* 207 Store-conditional BSR at global address -+ arg: none. */ -+ -+ case ETIR__C_STC_BSR_GBL: -+ /* SW_64_R_BSR */ -+ -+ /* 209 Store-conditional LDA at global address -+ arg: none. */ -+ -+ case ETIR__C_STC_LDA_GBL: -+ /* SW_64_R_LDA */ -+ -+ /* 211 Store-conditional BSR or Hint at global address -+ arg: none. */ -+ -+ case ETIR__C_STC_BOH_GBL: -+ /* Currentl ignored. */ -+ break; -+ -+ /* 213 Store-conditional NOP,BSR or HINT at global address -+ arg: none. */ -+ -+ case ETIR__C_STC_NBH_GBL: -+ -+ /* 206 Store-conditional NOP at pect + offset -+ arg: none. */ -+ -+ case ETIR__C_STC_NOP_PS: -+ -+ /* 208 Store-conditional BSR at pect + offset -+ arg: none. */ -+ -+ case ETIR__C_STC_BSR_PS: -+ -+ /* 210 Store-conditional LDA at psect + offset -+ arg: none. */ -+ -+ case ETIR__C_STC_LDA_PS: -+ -+ /* 212 Store-conditional BSR or Hint at pect + offset -+ arg: none. */ -+ -+ case ETIR__C_STC_BOH_PS: -+ -+ /* 214 Store-conditional NOP, BSR or HINT at psect + offset -+ arg: none. */ -+ case ETIR__C_STC_NBH_PS: -+ _bfd_error_handler (_("%s: not supported"), -+ _bfd_vms_etir_name (cmd)); -+ return FALSE; -+ break; -+ -+ /* Det relocation base: pop stack, set image location counter -+ arg: none. */ -+ case ETIR__C_CTL_SETRB: -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (!(rel1 & RELC_SEC_BASE)) -+ abort (); -+ image_set_ptr (abfd, op1, rel1 & RELC_MASK, info); -+ break; -+ -+ /* Augment relocation base: increment image location counter by offset -+ arg: lw offset value. */ -+ case ETIR__C_CTL_AUGRB: -+ if (ptr + 4 > maxptr) -+ goto corrupt_etir; -+ op1 = bfd_getl32 (ptr); -+ image_inc_ptr (abfd, op1); -+ break; -+ -+ /* Define location: pop index, save location counter under index -+ arg: none. */ -+ case ETIR__C_CTL_DFLOC: -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 != RELC_NONE) -+ goto bad_context; -+ dst_define_location (abfd, op1); -+ break; -+ -+ /* Set location: pop index, restore location counter from index -+ arg: none. */ -+ case ETIR__C_CTL_STLOC: -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 != RELC_NONE) -+ goto bad_context; -+ dst_restore_location (abfd, op1); -+ break; -+ -+ /* Stack defined location: pop index, push location counter from index -+ arg: none. */ -+ case ETIR__C_CTL_STKDL: -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 != RELC_NONE) -+ goto bad_context; -+ if (!_bfd_vms_push (abfd, dst_retrieve_location (abfd, op1), -+ RELC_NONE)) -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_NOP: /* No-op. */ -+ break; -+ -+ case ETIR__C_OPR_ADD: /* Add. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1) -+ || !_bfd_vms_pop (abfd, &op2, &rel2)) -+ return FALSE; -+ if (rel1 == RELC_NONE && rel2 != RELC_NONE) -+ rel1 = rel2; -+ else if (rel1 != RELC_NONE && rel2 != RELC_NONE) -+ goto bad_context; -+ if (!_bfd_vms_push (abfd, op1 + op2, rel1)) -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_SUB: /* Subtract. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1) -+ || !_bfd_vms_pop (abfd, &op2, &rel2)) -+ return FALSE; -+ if (rel1 == RELC_NONE && rel2 != RELC_NONE) -+ rel1 = rel2; -+ else if ((rel1 & RELC_SEC_BASE) && (rel2 & RELC_SEC_BASE)) -+ { -+ op1 = sw_64_vms_fix_sec_rel (abfd, info, rel1, op1); -+ op2 = sw_64_vms_fix_sec_rel (abfd, info, rel2, op2); -+ rel1 = RELC_NONE; -+ } -+ else if (rel1 != RELC_NONE && rel2 != RELC_NONE) -+ goto bad_context; -+ if (!_bfd_vms_push (abfd, op2 - op1, rel1)) -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_MUL: /* Multiply. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1) -+ || !_bfd_vms_pop (abfd, &op2, &rel2)) -+ return FALSE; -+ if (rel1 != RELC_NONE || rel2 != RELC_NONE) -+ goto bad_context; -+ if (!_bfd_vms_push (abfd, op1 * op2, RELC_NONE)) -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_DIV: /* Divide. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1) -+ || !_bfd_vms_pop (abfd, &op2, &rel2)) -+ return FALSE; -+ if (rel1 != RELC_NONE || rel2 != RELC_NONE) -+ goto bad_context; -+ if (op2 == 0) -+ { -+ if (!_bfd_vms_push (abfd, 0, RELC_NONE)) -+ return FALSE; -+ } -+ else -+ { -+ if (!_bfd_vms_push (abfd, op2 / op1, RELC_NONE)) -+ return FALSE; -+ } -+ break; -+ -+ case ETIR__C_OPR_AND: /* Logical AND. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1) -+ || !_bfd_vms_pop (abfd, &op2, &rel2)) -+ return FALSE; -+ if (rel1 != RELC_NONE || rel2 != RELC_NONE) -+ goto bad_context; -+ if (!_bfd_vms_push (abfd, op1 & op2, RELC_NONE)) -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_IOR: /* Logical inclusive OR. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1) -+ || !_bfd_vms_pop (abfd, &op2, &rel2)) -+ return FALSE; -+ if (rel1 != RELC_NONE || rel2 != RELC_NONE) -+ goto bad_context; -+ if (!_bfd_vms_push (abfd, op1 | op2, RELC_NONE)) -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_EOR: /* Logical exclusive OR. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1) -+ || !_bfd_vms_pop (abfd, &op2, &rel2)) -+ return FALSE; -+ if (rel1 != RELC_NONE || rel2 != RELC_NONE) -+ goto bad_context; -+ if (!_bfd_vms_push (abfd, op1 ^ op2, RELC_NONE)) -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_NEG: /* Negate. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 != RELC_NONE) -+ goto bad_context; -+ if (!_bfd_vms_push (abfd, -op1, RELC_NONE)) -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_COM: /* Complement. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (rel1 != RELC_NONE) -+ goto bad_context; -+ if (!_bfd_vms_push (abfd, ~op1, RELC_NONE)) -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_ASH: /* Arithmetic shift. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1) -+ || !_bfd_vms_pop (abfd, &op2, &rel2)) -+ return FALSE; -+ if (rel1 != RELC_NONE || rel2 != RELC_NONE) -+ { -+ bad_context: -+ _bfd_error_handler (_("invalid use of %s with contexts"), -+ _bfd_vms_etir_name (cmd)); -+ return FALSE; -+ } -+ if ((int)op2 < 0) /* Shift right. */ -+ op1 >>= -(int)op2; -+ else /* Shift left. */ -+ op1 <<= (int)op2; -+ if (!_bfd_vms_push (abfd, op1, RELC_NONE)) /* FIXME: sym. */ -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_INSV: /* Insert field. */ -+ case ETIR__C_OPR_USH: /* Unsigned shift. */ -+ case ETIR__C_OPR_ROT: /* Rotate. */ -+ case ETIR__C_OPR_REDEF: /* Redefine symbol to current location. */ -+ case ETIR__C_OPR_DFLIT: /* Define a literal. */ -+ _bfd_error_handler (_("%s: not supported"), -+ _bfd_vms_etir_name (cmd)); -+ return FALSE; -+ break; -+ -+ case ETIR__C_OPR_SEL: /* Select. */ -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ if (op1 & 0x01L) -+ { -+ if (!_bfd_vms_pop (abfd, &op1, &rel1)) -+ return FALSE; -+ } -+ else -+ { -+ if (!_bfd_vms_pop (abfd, &op1, &rel1) -+ || !_bfd_vms_pop (abfd, &op2, &rel2)) -+ return FALSE; -+ if (!_bfd_vms_push (abfd, op1, rel1)) -+ return FALSE; -+ } -+ break; -+ -+ default: -+ _bfd_error_handler (_("reserved cmd %d"), cmd); -+ return FALSE; -+ break; -+ } -+ -+ ptr += cmd_length - 4; -+ } -+ -+ return TRUE; -+} -+ -+/* Process EDBG/ETBT record. -+ Return TRUE on success, FALSE on error */ -+ -+static bfd_boolean -+vms_slurp_debug (bfd *abfd) -+{ -+ asection *section = PRIV (dst_section); -+ -+ if (section == NULL) -+ { -+ /* We have no way to find out beforehand how much debug info there -+ is in an object file, so pick an initial amount and grow it as -+ needed later. */ -+ flagword flags = SEC_HAS_CONTENTS | SEC_DEBUGGING | SEC_RELOC -+ | SEC_IN_MEMORY; -+ -+ section = bfd_make_section (abfd, "$DST$"); -+ if (!section) -+ return FALSE; -+ if (!bfd_set_section_flags (section, flags)) -+ return FALSE; -+ PRIV (dst_section) = section; -+ } -+ -+ PRIV (image_section) = section; -+ PRIV (image_offset) = section->size; -+ -+ if (!_bfd_vms_slurp_etir (abfd, NULL)) -+ return FALSE; -+ -+ section->size = PRIV (image_offset); -+ return TRUE; -+} -+ -+/* Process EDBG record. -+ Return TRUE on success, FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_edbg (bfd *abfd) -+{ -+ vms_debug2 ((2, "EDBG\n")); -+ -+ abfd->flags |= HAS_DEBUG | HAS_LINENO; -+ -+ return vms_slurp_debug (abfd); -+} -+ -+/* Process ETBT record. -+ Return TRUE on success, FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_etbt (bfd *abfd) -+{ -+ vms_debug2 ((2, "ETBT\n")); -+ -+ abfd->flags |= HAS_LINENO; -+ -+ return vms_slurp_debug (abfd); -+} -+ -+/* Process EEOM record. -+ Return TRUE on success, FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_eeom (bfd *abfd) -+{ -+ struct vms_eeom *eeom = (struct vms_eeom *) PRIV (recrd.rec); -+ -+ vms_debug2 ((2, "EEOM\n")); -+ -+ /* PR 21813: Check for an undersized record. */ -+ if (PRIV (recrd.buf_size) < sizeof (* eeom)) -+ { -+ _bfd_error_handler (_("corrupt EEOM record - size is too small")); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ PRIV (eom_data).eom_l_total_lps = bfd_getl32 (eeom->total_lps); -+ PRIV (eom_data).eom_w_comcod = bfd_getl16 (eeom->comcod); -+ if (PRIV (eom_data).eom_w_comcod > 1) -+ { -+ _bfd_error_handler (_("object module not error-free !")); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ PRIV (eom_data).eom_has_transfer = FALSE; -+ if (PRIV (recrd.rec_size) > 10) -+ { -+ PRIV (eom_data).eom_has_transfer = TRUE; -+ PRIV (eom_data).eom_b_tfrflg = eeom->tfrflg; -+ PRIV (eom_data).eom_l_psindx = bfd_getl32 (eeom->psindx); -+ PRIV (eom_data).eom_l_tfradr = bfd_getl32 (eeom->tfradr); -+ -+ abfd->start_address = PRIV (eom_data).eom_l_tfradr; -+ } -+ return TRUE; -+} -+ -+/* Slurp an ordered set of VMS object records. Return FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_slurp_object_records (bfd * abfd) -+{ -+ bfd_boolean err; -+ int type; -+ -+ do -+ { -+ vms_debug2 ((7, "reading at %08lx\n", (unsigned long)bfd_tell (abfd))); -+ -+ type = _bfd_vms_get_object_record (abfd); -+ if (type < 0) -+ { -+ vms_debug2 ((2, "next_record failed\n")); -+ return FALSE; -+ } -+ -+ switch (type) -+ { -+ case EOBJ__C_EMH: -+ err = _bfd_vms_slurp_ehdr (abfd); -+ break; -+ case EOBJ__C_EEOM: -+ err = _bfd_vms_slurp_eeom (abfd); -+ break; -+ case EOBJ__C_EGSD: -+ err = _bfd_vms_slurp_egsd (abfd); -+ break; -+ case EOBJ__C_ETIR: -+ err = TRUE; /* _bfd_vms_slurp_etir (abfd); */ -+ break; -+ case EOBJ__C_EDBG: -+ err = _bfd_vms_slurp_edbg (abfd); -+ break; -+ case EOBJ__C_ETBT: -+ err = _bfd_vms_slurp_etbt (abfd); -+ break; -+ default: -+ err = FALSE; -+ } -+ if (!err) -+ { -+ vms_debug2 ((2, "slurp type %d failed\n", type)); -+ return FALSE; -+ } -+ } -+ while (type != EOBJ__C_EEOM); -+ -+ return TRUE; -+} -+ -+/* Initialize private data */ -+static bfd_boolean -+vms_initialize (bfd * abfd) -+{ -+ bfd_size_type amt; -+ -+ amt = sizeof (struct vms_private_data_struct); -+ abfd->tdata.any = bfd_zalloc (abfd, amt); -+ if (abfd->tdata.any == NULL) -+ return FALSE; -+ -+ PRIV (recrd.file_format) = FF_UNKNOWN; -+ -+ amt = sizeof (struct stack_struct) * STACKSIZE; -+ PRIV (stack) = bfd_alloc (abfd, amt); -+ if (PRIV (stack) == NULL) -+ goto error_ret1; -+ -+ return TRUE; -+ -+ error_ret1: -+ bfd_release (abfd, abfd->tdata.any); -+ abfd->tdata.any = NULL; -+ return FALSE; -+} -+ -+/* Free malloc'd memory. */ -+ -+static void -+sw_64_vms_free_private (bfd *abfd) -+{ -+ struct module *module; -+ -+ free (PRIV (recrd.buf)); -+ free (PRIV (sections)); -+ free (PRIV (syms)); -+ free (PRIV (dst_ptr_offsets)); -+ -+ for (module = PRIV (modules); module; module = module->next) -+ free (module->file_table); -+} -+ -+/* Check the format for a file being read. -+ Return a (bfd_target *) if it's an object file or zero if not. */ -+ -+static const struct bfd_target * -+sw_64_vms_object_p (bfd *abfd) -+{ -+ void *tdata_save = abfd->tdata.any; -+ unsigned int test_len; -+ unsigned char *buf; -+ -+ vms_debug2 ((1, "vms_object_p(%p)\n", abfd)); -+ -+ /* Allocate sw_64-vms specific data. */ -+ if (!vms_initialize (abfd)) -+ { -+ abfd->tdata.any = tdata_save; -+ return NULL; -+ } -+ -+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET)) -+ goto err_wrong_format; -+ -+ /* The first challenge with VMS is to discover the kind of the file. -+ -+ Image files (executable or shared images) are stored as a raw -+ stream of bytes (like on UNIX), but there is no magic number. -+ -+ Object files are written with RMS (record management service), ie -+ each records are preceeded by its length (on a word - 2 bytes), and -+ padded for word-alignment. That would be simple but when files -+ are transfered to a UNIX filesystem (using ftp), records are lost. -+ Only the raw content of the records are transfered. Fortunately, -+ the Sw_64 Object file format also store the length of the record -+ in the records. Is that clear ? */ -+ -+ /* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id, -+ 2 bytes size repeated) and 12 bytes for images (4 bytes major id, -+ 4 bytes minor id, 4 bytes length). */ -+ test_len = 12; -+ -+ /* Size the main buffer. */ -+ buf = (unsigned char *) bfd_malloc (test_len); -+ if (buf == NULL) -+ goto error_ret; -+ PRIV (recrd.buf) = buf; -+ PRIV (recrd.buf_size) = test_len; -+ -+ /* Initialize the record pointer. */ -+ PRIV (recrd.rec) = buf; -+ -+ if (bfd_bread (buf, test_len, abfd) != test_len) -+ goto err_wrong_format; -+ -+ /* Is it an image? */ -+ if ((bfd_getl32 (buf) == EIHD__K_MAJORID) -+ && (bfd_getl32 (buf + 4) == EIHD__K_MINORID)) -+ { -+ unsigned int to_read; -+ unsigned int read_so_far; -+ unsigned int remaining; -+ unsigned int eisd_offset, eihs_offset; -+ -+ /* Extract the header size. */ -+ PRIV (recrd.rec_size) = bfd_getl32 (buf + EIHD__L_SIZE); -+ -+ /* The header size is 0 for DSF files. */ -+ if (PRIV (recrd.rec_size) == 0) -+ PRIV (recrd.rec_size) = sizeof (struct vms_eihd); -+ -+ if (PRIV (recrd.rec_size) > PRIV (recrd.buf_size)) -+ { -+ buf = bfd_realloc_or_free (buf, PRIV (recrd.rec_size)); -+ -+ if (buf == NULL) -+ { -+ PRIV (recrd.buf) = NULL; -+ goto error_ret; -+ } -+ PRIV (recrd.buf) = buf; -+ PRIV (recrd.buf_size) = PRIV (recrd.rec_size); -+ } -+ -+ /* PR 21813: Check for a truncated record. */ -+ if (PRIV (recrd.rec_size < test_len)) -+ goto error_ret; -+ /* Read the remaining record. */ -+ remaining = PRIV (recrd.rec_size) - test_len; -+ to_read = MIN (VMS_BLOCK_SIZE - test_len, remaining); -+ read_so_far = test_len; -+ -+ while (remaining > 0) -+ { -+ if (bfd_bread (buf + read_so_far, to_read, abfd) != to_read) -+ goto err_wrong_format; -+ -+ read_so_far += to_read; -+ remaining -= to_read; -+ -+ to_read = MIN (VMS_BLOCK_SIZE, remaining); -+ } -+ -+ /* Reset the record pointer. */ -+ PRIV (recrd.rec) = buf; -+ -+ /* PR 17512: file: 7d7c57c2. */ -+ if (PRIV (recrd.rec_size) < sizeof (struct vms_eihd)) -+ goto error_ret; -+ vms_debug2 ((2, "file type is image\n")); -+ -+ if (!_bfd_vms_slurp_eihd (abfd, &eisd_offset, &eihs_offset)) -+ goto err_wrong_format; -+ -+ if (!_bfd_vms_slurp_eisd (abfd, eisd_offset)) -+ goto err_wrong_format; -+ -+ /* EIHS is optional. */ -+ if (eihs_offset != 0 && !_bfd_vms_slurp_eihs (abfd, eihs_offset)) -+ goto err_wrong_format; -+ } -+ else -+ { -+ int type; -+ -+ /* Assume it's a module and adjust record pointer if necessary. */ -+ maybe_adjust_record_pointer_for_object (abfd); -+ -+ /* But is it really a module? */ -+ if (bfd_getl16 (PRIV (recrd.rec)) <= EOBJ__C_MAXRECTYP -+ && bfd_getl16 (PRIV (recrd.rec) + 2) <= EOBJ__C_MAXRECSIZ) -+ { -+ if (vms_get_remaining_object_record (abfd, test_len) <= 0) -+ goto err_wrong_format; -+ -+ vms_debug2 ((2, "file type is module\n")); -+ -+ type = bfd_getl16 (PRIV (recrd.rec)); -+ if (type != EOBJ__C_EMH || !_bfd_vms_slurp_ehdr (abfd)) -+ goto err_wrong_format; -+ -+ if (!_bfd_vms_slurp_object_records (abfd)) -+ goto err_wrong_format; -+ } -+ else -+ goto err_wrong_format; -+ } -+ -+ /* Set arch_info to sw_64. */ -+ -+ if (! bfd_default_set_arch_mach (abfd, bfd_arch_sw_64, 0)) -+ goto err_wrong_format; -+ -+ return abfd->xvec; -+ -+ err_wrong_format: -+ bfd_set_error (bfd_error_wrong_format); -+ -+ error_ret: -+ sw_64_vms_free_private (abfd); -+ if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL) -+ bfd_release (abfd, abfd->tdata.any); -+ abfd->tdata.any = tdata_save; -+ return NULL; -+} -+ -+/* Image write. */ -+ -+/* Write an EMH/MHD record. */ -+ -+static void -+_bfd_vms_write_emh (bfd *abfd) -+{ -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ -+ _bfd_vms_output_alignment (recwr, 2); -+ -+ /* EMH. */ -+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -+ _bfd_vms_output_short (recwr, EMH__C_MHD); -+ _bfd_vms_output_short (recwr, EOBJ__C_STRLVL); -+ _bfd_vms_output_long (recwr, 0); -+ _bfd_vms_output_long (recwr, 0); -+ _bfd_vms_output_long (recwr, MAX_OUTREC_SIZE); -+ -+ /* Create module name from filename. */ -+ if (bfd_get_filename (abfd) != 0) -+ { -+ char *module = vms_get_module_name (bfd_get_filename (abfd), TRUE); -+ _bfd_vms_output_counted (recwr, module); -+ free (module); -+ } -+ else -+ _bfd_vms_output_counted (recwr, "NONAME"); -+ -+ _bfd_vms_output_counted (recwr, BFD_VERSION_STRING); -+ _bfd_vms_output_dump (recwr, get_vms_time_string (), EMH_DATE_LENGTH); -+ _bfd_vms_output_fill (recwr, 0, EMH_DATE_LENGTH); -+ _bfd_vms_output_end (abfd, recwr); -+} -+ -+/* Write an EMH/LMN record. */ -+ -+static void -+_bfd_vms_write_lmn (bfd *abfd, const char *name) -+{ -+ char version [64]; -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ unsigned int ver = BFD_VERSION / 10000; -+ -+ /* LMN. */ -+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -+ _bfd_vms_output_short (recwr, EMH__C_LNM); -+ snprintf (version, sizeof (version), "%s %d.%d.%d", name, -+ ver / 10000, (ver / 100) % 100, ver % 100); -+ _bfd_vms_output_dump (recwr, (unsigned char *)version, strlen (version)); -+ _bfd_vms_output_end (abfd, recwr); -+} -+ -+ -+/* Write eom record for bfd abfd. Return FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_write_eeom (bfd *abfd) -+{ -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ -+ vms_debug2 ((2, "vms_write_eeom\n")); -+ -+ _bfd_vms_output_alignment (recwr, 2); -+ -+ _bfd_vms_output_begin (recwr, EOBJ__C_EEOM); -+ _bfd_vms_output_long (recwr, PRIV (vms_linkage_index + 1) >> 1); -+ _bfd_vms_output_byte (recwr, 0); /* Completion code. */ -+ _bfd_vms_output_byte (recwr, 0); /* Fill byte. */ -+ -+ if ((abfd->flags & EXEC_P) == 0 -+ && bfd_get_start_address (abfd) != (bfd_vma)-1) -+ { -+ asection *section; -+ -+ section = bfd_get_section_by_name (abfd, ".link"); -+ if (section == 0) -+ { -+ bfd_set_error (bfd_error_nonrepresentable_section); -+ return FALSE; -+ } -+ _bfd_vms_output_short (recwr, 0); -+ _bfd_vms_output_long (recwr, (unsigned long) section->target_index); -+ _bfd_vms_output_long (recwr, -+ (unsigned long) bfd_get_start_address (abfd)); -+ _bfd_vms_output_long (recwr, 0); -+ } -+ -+ _bfd_vms_output_end (abfd, recwr); -+ return TRUE; -+} -+ -+static void -+vector_grow1 (struct vector_type *vec, size_t elsz) -+{ -+ if (vec->nbr_el + 1 < vec->max_el) -+ return; -+ -+ if (vec->max_el == 0) -+ { -+ vec->max_el = 16; -+ vec->els = bfd_malloc2 (vec->max_el, elsz); -+ } -+ else -+ { -+ vec->max_el *= 2; -+ vec->els = bfd_realloc2 (vec->els, vec->max_el, elsz); -+ } -+} -+ -+/* Bump ABFD file position to next block. */ -+ -+static void -+sw_64_vms_file_position_block (bfd *abfd) -+{ -+ /* Next block. */ -+ PRIV (file_pos) += VMS_BLOCK_SIZE - 1; -+ PRIV (file_pos) -= (PRIV (file_pos) % VMS_BLOCK_SIZE); -+} -+ -+/* Convert from internal structure SRC to external structure DST. */ -+ -+static void -+sw_64_vms_swap_eisd_out (struct vms_internal_eisd_map *src, -+ struct vms_eisd *dst) -+{ -+ bfd_putl32 (src->u.eisd.majorid, dst->majorid); -+ bfd_putl32 (src->u.eisd.minorid, dst->minorid); -+ bfd_putl32 (src->u.eisd.eisdsize, dst->eisdsize); -+ if (src->u.eisd.eisdsize <= EISD__K_LENEND) -+ return; -+ bfd_putl32 (src->u.eisd.secsize, dst->secsize); -+ bfd_putl64 (src->u.eisd.virt_addr, dst->virt_addr); -+ bfd_putl32 (src->u.eisd.flags, dst->flags); -+ bfd_putl32 (src->u.eisd.vbn, dst->vbn); -+ dst->pfc = src->u.eisd.pfc; -+ dst->matchctl = src->u.eisd.matchctl; -+ dst->type = src->u.eisd.type; -+ dst->fill_1 = 0; -+ if (src->u.eisd.flags & EISD__M_GBL) -+ { -+ bfd_putl32 (src->u.gbl_eisd.ident, dst->ident); -+ memcpy (dst->gblnam, src->u.gbl_eisd.gblnam, -+ src->u.gbl_eisd.gblnam[0] + 1); -+ } -+} -+ -+/* Append EISD to the list of extra eisd for ABFD. */ -+ -+static void -+sw_64_vms_append_extra_eisd (bfd *abfd, struct vms_internal_eisd_map *eisd) -+{ -+ eisd->next = NULL; -+ if (PRIV (gbl_eisd_head) == NULL) -+ PRIV (gbl_eisd_head) = eisd; -+ else -+ PRIV (gbl_eisd_tail)->next = eisd; -+ PRIV (gbl_eisd_tail) = eisd; -+} -+ -+/* Create an EISD for shared image SHRIMG. -+ Return FALSE in case of error. */ -+ -+static bfd_boolean -+sw_64_vms_create_eisd_for_shared (bfd *abfd, bfd *shrimg) -+{ -+ struct vms_internal_eisd_map *eisd; -+ int namlen; -+ -+ namlen = strlen (PRIV2 (shrimg, hdr_data.hdr_t_name)); -+ if (namlen + 5 > EISD__K_GBLNAMLEN) -+ { -+ /* Won't fit. */ -+ return FALSE; -+ } -+ -+ eisd = bfd_alloc (abfd, sizeof (*eisd)); -+ if (eisd == NULL) -+ return FALSE; -+ -+ /* Fill the fields. */ -+ eisd->u.gbl_eisd.common.majorid = EISD__K_MAJORID; -+ eisd->u.gbl_eisd.common.minorid = EISD__K_MINORID; -+ eisd->u.gbl_eisd.common.eisdsize = (EISD__K_LEN + 4 + namlen + 5 + 3) & ~3; -+ eisd->u.gbl_eisd.common.secsize = VMS_BLOCK_SIZE; /* Must not be 0. */ -+ eisd->u.gbl_eisd.common.virt_addr = 0; -+ eisd->u.gbl_eisd.common.flags = EISD__M_GBL; -+ eisd->u.gbl_eisd.common.vbn = 0; -+ eisd->u.gbl_eisd.common.pfc = 0; -+ eisd->u.gbl_eisd.common.matchctl = PRIV2 (shrimg, matchctl); -+ eisd->u.gbl_eisd.common.type = EISD__K_SHRPIC; -+ -+ eisd->u.gbl_eisd.ident = PRIV2 (shrimg, ident); -+ eisd->u.gbl_eisd.gblnam[0] = namlen + 4; -+ memcpy (eisd->u.gbl_eisd.gblnam + 1, PRIV2 (shrimg, hdr_data.hdr_t_name), -+ namlen); -+ memcpy (eisd->u.gbl_eisd.gblnam + 1 + namlen, "_001", 4); -+ -+ /* Append it to the list. */ -+ sw_64_vms_append_extra_eisd (abfd, eisd); -+ -+ return TRUE; -+} -+ -+/* Create an EISD for section SEC. -+ Return FALSE in case of failure. */ -+ -+static bfd_boolean -+sw_64_vms_create_eisd_for_section (bfd *abfd, asection *sec) -+{ -+ struct vms_internal_eisd_map *eisd; -+ -+ /* Only for allocating section. */ -+ if (!(sec->flags & SEC_ALLOC)) -+ return TRUE; -+ -+ BFD_ASSERT (vms_section_data (sec)->eisd == NULL); -+ eisd = bfd_alloc (abfd, sizeof (*eisd)); -+ if (eisd == NULL) -+ return FALSE; -+ vms_section_data (sec)->eisd = eisd; -+ -+ /* Fill the fields. */ -+ eisd->u.eisd.majorid = EISD__K_MAJORID; -+ eisd->u.eisd.minorid = EISD__K_MINORID; -+ eisd->u.eisd.eisdsize = EISD__K_LEN; -+ eisd->u.eisd.secsize = -+ (sec->size + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1); -+ eisd->u.eisd.virt_addr = sec->vma; -+ eisd->u.eisd.flags = 0; -+ eisd->u.eisd.vbn = 0; /* To be later defined. */ -+ eisd->u.eisd.pfc = 0; /* Default. */ -+ eisd->u.eisd.matchctl = EISD__K_MATALL; -+ eisd->u.eisd.type = EISD__K_NORMAL; -+ -+ if (sec->flags & SEC_CODE) -+ eisd->u.eisd.flags |= EISD__M_EXE; -+ if (!(sec->flags & SEC_READONLY)) -+ eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF; -+ -+ /* If relocations or fixup will be applied, make this isect writeable. */ -+ if (sec->flags & SEC_RELOC) -+ eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF; -+ -+ if (!(sec->flags & SEC_HAS_CONTENTS)) -+ { -+ eisd->u.eisd.flags |= EISD__M_DZRO; -+ eisd->u.eisd.flags &= ~EISD__M_CRF; -+ } -+ if (sec->flags & SEC_LINKER_CREATED) -+ { -+ if (strcmp (sec->name, "$FIXUP$") == 0) -+ eisd->u.eisd.flags |= EISD__M_FIXUPVEC; -+ } -+ -+ /* Append it to the list. */ -+ eisd->next = NULL; -+ if (PRIV (eisd_head) == NULL) -+ PRIV (eisd_head) = eisd; -+ else -+ PRIV (eisd_tail)->next = eisd; -+ PRIV (eisd_tail) = eisd; -+ -+ return TRUE; -+} -+ -+/* Layout executable ABFD and write it to the disk. -+ Return FALSE in case of failure. */ -+ -+static bfd_boolean -+sw_64_vms_write_exec (bfd *abfd) -+{ -+ struct vms_eihd eihd; -+ struct vms_eiha *eiha; -+ struct vms_eihi *eihi; -+ struct vms_eihs *eihs = NULL; -+ asection *sec; -+ struct vms_internal_eisd_map *first_eisd; -+ struct vms_internal_eisd_map *eisd; -+ asection *dst; -+ asection *dmt; -+ file_ptr gst_filepos = 0; -+ unsigned int lnkflags = 0; -+ -+ /* Build the EIHD. */ -+ PRIV (file_pos) = EIHD__C_LENGTH; -+ -+ memset (&eihd, 0, sizeof (eihd)); -+ memset (eihd.fill_2, 0xff, sizeof (eihd.fill_2)); -+ -+ bfd_putl32 (EIHD__K_MAJORID, eihd.majorid); -+ bfd_putl32 (EIHD__K_MINORID, eihd.minorid); -+ -+ bfd_putl32 (sizeof (eihd), eihd.size); -+ bfd_putl32 (0, eihd.isdoff); -+ bfd_putl32 (0, eihd.activoff); -+ bfd_putl32 (0, eihd.symdbgoff); -+ bfd_putl32 (0, eihd.imgidoff); -+ bfd_putl32 (0, eihd.patchoff); -+ bfd_putl64 (0, eihd.iafva); -+ bfd_putl32 (0, eihd.version_array_off); -+ -+ bfd_putl32 (EIHD__K_EXE, eihd.imgtype); -+ bfd_putl32 (0, eihd.subtype); -+ -+ bfd_putl32 (0, eihd.imgiocnt); -+ bfd_putl32 (-1, eihd.privreqs); -+ bfd_putl32 (-1, eihd.privreqs + 4); -+ -+ bfd_putl32 ((sizeof (eihd) + VMS_BLOCK_SIZE - 1) / VMS_BLOCK_SIZE, -+ eihd.hdrblkcnt); -+ bfd_putl32 (0, eihd.ident); -+ bfd_putl32 (0, eihd.sysver); -+ -+ eihd.matchctl = 0; -+ bfd_putl32 (0, eihd.symvect_size); -+ bfd_putl32 (16, eihd.virt_mem_block_size); -+ bfd_putl32 (0, eihd.ext_fixup_off); -+ bfd_putl32 (0, eihd.noopt_psect_off); -+ bfd_putl32 (-1, eihd.alias); -+ -+ /* Alloc EIHA. */ -+ eiha = (struct vms_eiha *)((char *) &eihd + PRIV (file_pos)); -+ bfd_putl32 (PRIV (file_pos), eihd.activoff); -+ PRIV (file_pos) += sizeof (struct vms_eiha); -+ -+ bfd_putl32 (sizeof (struct vms_eiha), eiha->size); -+ bfd_putl32 (0, eiha->spare); -+ bfd_putl64 (PRIV (transfer_address[0]), eiha->tfradr1); -+ bfd_putl64 (PRIV (transfer_address[1]), eiha->tfradr2); -+ bfd_putl64 (PRIV (transfer_address[2]), eiha->tfradr3); -+ bfd_putl64 (PRIV (transfer_address[3]), eiha->tfradr4); -+ bfd_putl64 (0, eiha->inishr); -+ -+ /* Alloc EIHI. */ -+ eihi = (struct vms_eihi *)((char *) &eihd + PRIV (file_pos)); -+ bfd_putl32 (PRIV (file_pos), eihd.imgidoff); -+ PRIV (file_pos) += sizeof (struct vms_eihi); -+ -+ bfd_putl32 (EIHI__K_MAJORID, eihi->majorid); -+ bfd_putl32 (EIHI__K_MINORID, eihi->minorid); -+ { -+ char *module; -+ unsigned int len; -+ -+ /* Set module name. */ -+ module = vms_get_module_name (bfd_get_filename (abfd), TRUE); -+ len = strlen (module); -+ if (len > sizeof (eihi->imgnam) - 1) -+ len = sizeof (eihi->imgnam) - 1; -+ eihi->imgnam[0] = len; -+ memcpy (eihi->imgnam + 1, module, len); -+ free (module); -+ } -+ { -+ unsigned int lo; -+ unsigned int hi; -+ -+ /* Set time. */ -+ vms_get_time (&hi, &lo); -+ bfd_putl32 (lo, eihi->linktime + 0); -+ bfd_putl32 (hi, eihi->linktime + 4); -+ } -+ eihi->imgid[0] = 0; -+ eihi->linkid[0] = 0; -+ eihi->imgbid[0] = 0; -+ -+ /* Alloc EIHS. */ -+ dst = PRIV (dst_section); -+ dmt = bfd_get_section_by_name (abfd, "$DMT$"); -+ if (dst != NULL && dst->size != 0) -+ { -+ eihs = (struct vms_eihs *)((char *) &eihd + PRIV (file_pos)); -+ bfd_putl32 (PRIV (file_pos), eihd.symdbgoff); -+ PRIV (file_pos) += sizeof (struct vms_eihs); -+ -+ bfd_putl32 (EIHS__K_MAJORID, eihs->majorid); -+ bfd_putl32 (EIHS__K_MINORID, eihs->minorid); -+ bfd_putl32 (0, eihs->dstvbn); -+ bfd_putl32 (0, eihs->dstsize); -+ bfd_putl32 (0, eihs->gstvbn); -+ bfd_putl32 (0, eihs->gstsize); -+ bfd_putl32 (0, eihs->dmtvbn); -+ bfd_putl32 (0, eihs->dmtsize); -+ } -+ -+ /* One EISD per section. */ -+ for (sec = abfd->sections; sec; sec = sec->next) -+ { -+ if (!sw_64_vms_create_eisd_for_section (abfd, sec)) -+ return FALSE; -+ } -+ -+ /* Merge section EIDS which extra ones. */ -+ if (PRIV (eisd_tail)) -+ PRIV (eisd_tail)->next = PRIV (gbl_eisd_head); -+ else -+ PRIV (eisd_head) = PRIV (gbl_eisd_head); -+ if (PRIV (gbl_eisd_tail)) -+ PRIV (eisd_tail) = PRIV (gbl_eisd_tail); -+ -+ first_eisd = PRIV (eisd_head); -+ -+ /* Add end of eisd. */ -+ if (first_eisd) -+ { -+ eisd = bfd_zalloc (abfd, sizeof (*eisd)); -+ if (eisd == NULL) -+ return FALSE; -+ eisd->u.eisd.majorid = 0; -+ eisd->u.eisd.minorid = 0; -+ eisd->u.eisd.eisdsize = 0; -+ sw_64_vms_append_extra_eisd (abfd, eisd); -+ } -+ -+ /* Place EISD in the file. */ -+ for (eisd = first_eisd; eisd; eisd = eisd->next) -+ { -+ file_ptr room = VMS_BLOCK_SIZE - (PRIV (file_pos) % VMS_BLOCK_SIZE); -+ -+ /* First block is a little bit special: there is a word at the end. */ -+ if (PRIV (file_pos) < VMS_BLOCK_SIZE && room > 2) -+ room -= 2; -+ if (room < eisd->u.eisd.eisdsize + EISD__K_LENEND) -+ sw_64_vms_file_position_block (abfd); -+ -+ eisd->file_pos = PRIV (file_pos); -+ PRIV (file_pos) += eisd->u.eisd.eisdsize; -+ -+ if (eisd->u.eisd.flags & EISD__M_FIXUPVEC) -+ bfd_putl64 (eisd->u.eisd.virt_addr, eihd.iafva); -+ } -+ -+ if (first_eisd != NULL) -+ { -+ bfd_putl32 (first_eisd->file_pos, eihd.isdoff); -+ /* Real size of end of eisd marker. */ -+ PRIV (file_pos) += EISD__K_LENEND; -+ } -+ -+ bfd_putl32 (PRIV (file_pos), eihd.size); -+ bfd_putl32 ((PRIV (file_pos) + VMS_BLOCK_SIZE - 1) / VMS_BLOCK_SIZE, -+ eihd.hdrblkcnt); -+ -+ /* Place sections. */ -+ for (sec = abfd->sections; sec; sec = sec->next) -+ { -+ if (!(sec->flags & SEC_HAS_CONTENTS)) -+ continue; -+ -+ eisd = vms_section_data (sec)->eisd; -+ -+ /* Align on a block. */ -+ sw_64_vms_file_position_block (abfd); -+ sec->filepos = PRIV (file_pos); -+ -+ if (eisd != NULL) -+ eisd->u.eisd.vbn = (sec->filepos / VMS_BLOCK_SIZE) + 1; -+ -+ PRIV (file_pos) += sec->size; -+ } -+ -+ /* Update EIHS. */ -+ if (eihs != NULL && dst != NULL) -+ { -+ bfd_putl32 ((dst->filepos / VMS_BLOCK_SIZE) + 1, eihs->dstvbn); -+ bfd_putl32 (dst->size, eihs->dstsize); -+ -+ if (dmt != NULL) -+ { -+ lnkflags |= EIHD__M_DBGDMT; -+ bfd_putl32 ((dmt->filepos / VMS_BLOCK_SIZE) + 1, eihs->dmtvbn); -+ bfd_putl32 (dmt->size, eihs->dmtsize); -+ } -+ if (PRIV (gsd_sym_count) != 0) -+ { -+ sw_64_vms_file_position_block (abfd); -+ gst_filepos = PRIV (file_pos); -+ bfd_putl32 ((gst_filepos / VMS_BLOCK_SIZE) + 1, eihs->gstvbn); -+ bfd_putl32 ((PRIV (gsd_sym_count) + 4) / 5 + 4, eihs->gstsize); -+ } -+ } -+ -+ /* Write EISD in hdr. */ -+ for (eisd = first_eisd; eisd && eisd->file_pos < VMS_BLOCK_SIZE; -+ eisd = eisd->next) -+ sw_64_vms_swap_eisd_out -+ (eisd, (struct vms_eisd *)((char *)&eihd + eisd->file_pos)); -+ -+ /* Write first block. */ -+ bfd_putl32 (lnkflags, eihd.lnkflags); -+ if (bfd_bwrite (&eihd, sizeof (eihd), abfd) != sizeof (eihd)) -+ return FALSE; -+ -+ /* Write remaining eisd. */ -+ if (eisd != NULL) -+ { -+ unsigned char blk[VMS_BLOCK_SIZE]; -+ struct vms_internal_eisd_map *next_eisd; -+ -+ memset (blk, 0xff, sizeof (blk)); -+ while (eisd != NULL) -+ { -+ sw_64_vms_swap_eisd_out -+ (eisd, -+ (struct vms_eisd *)(blk + (eisd->file_pos % VMS_BLOCK_SIZE))); -+ -+ next_eisd = eisd->next; -+ if (next_eisd == NULL -+ || (next_eisd->file_pos / VMS_BLOCK_SIZE -+ != eisd->file_pos / VMS_BLOCK_SIZE)) -+ { -+ if (bfd_bwrite (blk, sizeof (blk), abfd) != sizeof (blk)) -+ return FALSE; -+ -+ memset (blk, 0xff, sizeof (blk)); -+ } -+ eisd = next_eisd; -+ } -+ } -+ -+ /* Write sections. */ -+ for (sec = abfd->sections; sec; sec = sec->next) -+ { -+ unsigned char blk[VMS_BLOCK_SIZE]; -+ bfd_size_type len; -+ -+ if (sec->size == 0 || !(sec->flags & SEC_HAS_CONTENTS)) -+ continue; -+ if (bfd_bwrite (sec->contents, sec->size, abfd) != sec->size) -+ return FALSE; -+ -+ /* Pad. */ -+ len = VMS_BLOCK_SIZE - sec->size % VMS_BLOCK_SIZE; -+ if (len != VMS_BLOCK_SIZE) -+ { -+ memset (blk, 0, len); -+ if (bfd_bwrite (blk, len, abfd) != len) -+ return FALSE; -+ } -+ } -+ -+ /* Write GST. */ -+ if (gst_filepos != 0) -+ { -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ unsigned int i; -+ -+ _bfd_vms_write_emh (abfd); -+ _bfd_vms_write_lmn (abfd, "GNU LD"); -+ -+ /* PSC for the absolute section. */ -+ _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -+ _bfd_vms_output_long (recwr, 0); -+ _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); -+ _bfd_vms_output_short (recwr, 0); -+ _bfd_vms_output_short (recwr, EGPS__V_PIC | EGPS__V_LIB | EGPS__V_RD); -+ _bfd_vms_output_long (recwr, 0); -+ _bfd_vms_output_counted (recwr, ".$$ABS$$."); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_end (abfd, recwr); -+ -+ for (i = 0; i < PRIV (gsd_sym_count); i++) -+ { -+ struct vms_symbol_entry *sym = PRIV (syms)[i]; -+ bfd_vma val; -+ bfd_vma ep; -+ -+ if ((i % 5) == 0) -+ { -+ _bfd_vms_output_alignment (recwr, 8); -+ _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -+ _bfd_vms_output_long (recwr, 0); -+ } -+ _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYMG); -+ _bfd_vms_output_short (recwr, 0); /* Data type, alignment. */ -+ _bfd_vms_output_short (recwr, sym->flags); -+ -+ if (sym->code_section) -+ ep = sw_64_vms_get_sym_value (sym->code_section, sym->code_value); -+ else -+ { -+ BFD_ASSERT (sym->code_value == 0); -+ ep = 0; -+ } -+ val = sw_64_vms_get_sym_value (sym->section, sym->value); -+ _bfd_vms_output_quad -+ (recwr, sym->typ == EGSD__C_SYMG ? sym->symbol_vector : val); -+ _bfd_vms_output_quad (recwr, ep); -+ _bfd_vms_output_quad (recwr, val); -+ _bfd_vms_output_long (recwr, 0); -+ _bfd_vms_output_counted (recwr, sym->name); -+ _bfd_vms_output_end_subrec (recwr); -+ if ((i % 5) == 4) -+ _bfd_vms_output_end (abfd, recwr); -+ } -+ if ((i % 5) != 0) -+ _bfd_vms_output_end (abfd, recwr); -+ -+ if (!_bfd_vms_write_eeom (abfd)) -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+/* Object write. */ -+ -+/* Write section and symbol directory of bfd abfd. Return FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_write_egsd (bfd *abfd) -+{ -+ asection *section; -+ asymbol *symbol; -+ unsigned int symnum; -+ const char *sname; -+ flagword new_flags, old_flags; -+ int abs_section_index = -1; -+ unsigned int target_index = 0; -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ -+ vms_debug2 ((2, "vms_write_egsd\n")); -+ -+ /* Egsd is quadword aligned. */ -+ _bfd_vms_output_alignment (recwr, 8); -+ -+ _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -+ _bfd_vms_output_long (recwr, 0); -+ -+ /* Number sections. */ -+ for (section = abfd->sections; section != NULL; section = section->next) -+ { -+ if (section->flags & SEC_DEBUGGING) -+ continue; -+ if (!strcmp (section->name, ".vmsdebug")) -+ { -+ section->flags |= SEC_DEBUGGING; -+ continue; -+ } -+ section->target_index = target_index++; -+ } -+ -+ for (section = abfd->sections; section != NULL; section = section->next) -+ { -+ vms_debug2 ((3, "Section #%d %s, %d bytes\n", -+ section->target_index, section->name, (int)section->size)); -+ -+ /* Don't write out the VMS debug info section since it is in the -+ ETBT and EDBG sections in etir. */ -+ if (section->flags & SEC_DEBUGGING) -+ continue; -+ -+ /* 13 bytes egsd, max 31 chars name -> should be 44 bytes. */ -+ if (_bfd_vms_output_check (recwr, 64) < 0) -+ { -+ _bfd_vms_output_end (abfd, recwr); -+ _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -+ _bfd_vms_output_long (recwr, 0); -+ } -+ -+ /* Don't know if this is necessary for the linker but for now it keeps -+ vms_slurp_gsd happy. */ -+ sname = section->name; -+ if (*sname == '.') -+ { -+ /* Remove leading dot. */ -+ sname++; -+ if ((*sname == 't') && (strcmp (sname, "text") == 0)) -+ sname = EVAX_CODE_NAME; -+ else if ((*sname == 'd') && (strcmp (sname, "data") == 0)) -+ sname = EVAX_DATA_NAME; -+ else if ((*sname == 'b') && (strcmp (sname, "bss") == 0)) -+ sname = EVAX_BSS_NAME; -+ else if ((*sname == 'l') && (strcmp (sname, "link") == 0)) -+ sname = EVAX_LINK_NAME; -+ else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0)) -+ sname = EVAX_READONLY_NAME; -+ else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) -+ sname = EVAX_LITERAL_NAME; -+ else if ((*sname == 'l') && (strcmp (sname, "literals") == 0)) -+ sname = EVAX_LITERALS_NAME; -+ else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) -+ sname = EVAX_COMMON_NAME; -+ else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) -+ sname = EVAX_LOCAL_NAME; -+ } -+ -+ if (bfd_is_com_section (section)) -+ new_flags = (EGPS__V_OVR | EGPS__V_REL | EGPS__V_GBL | EGPS__V_RD -+ | EGPS__V_WRT | EGPS__V_NOMOD | EGPS__V_COM); -+ else -+ new_flags = vms_esecflag_by_name (evax_section_flags, sname, -+ section->size > 0); -+ -+ /* Modify them as directed. */ -+ if (section->flags & SEC_READONLY) -+ new_flags &= ~EGPS__V_WRT; -+ -+ new_flags &= ~vms_section_data (section)->no_flags; -+ new_flags |= vms_section_data (section)->flags; -+ -+ vms_debug2 ((3, "sec flags %x\n", section->flags)); -+ vms_debug2 ((3, "new_flags %x, _raw_size %lu\n", -+ new_flags, (unsigned long)section->size)); -+ -+ _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); -+ _bfd_vms_output_short (recwr, section->alignment_power & 0xff); -+ _bfd_vms_output_short (recwr, new_flags); -+ _bfd_vms_output_long (recwr, (unsigned long) section->size); -+ _bfd_vms_output_counted (recwr, sname); -+ _bfd_vms_output_end_subrec (recwr); -+ -+ /* If the section is an obsolute one, remind its index as it will be -+ used later for absolute symbols. */ -+ if ((new_flags & EGPS__V_REL) == 0 && abs_section_index < 0) -+ abs_section_index = section->target_index; -+ } -+ -+ /* Output symbols. */ -+ vms_debug2 ((3, "%d symbols found\n", abfd->symcount)); -+ -+ bfd_set_start_address (abfd, (bfd_vma) -1); -+ -+ for (symnum = 0; symnum < abfd->symcount; symnum++) -+ { -+ symbol = abfd->outsymbols[symnum]; -+ old_flags = symbol->flags; -+ -+ /* Work-around a missing feature: consider __main as the main entry -+ point. */ -+ if (symbol->name[0] == '_' && strcmp (symbol->name, "__main") == 0) -+ bfd_set_start_address (abfd, (bfd_vma)symbol->value); -+ -+ /* Only put in the GSD the global and the undefined symbols. */ -+ if (old_flags & BSF_FILE) -+ continue; -+ -+ if ((old_flags & BSF_GLOBAL) == 0 && !bfd_is_und_section (symbol->section)) -+ { -+ /* If the LIB$INITIIALIZE section is present, add a reference to -+ LIB$INITIALIZE symbol. FIXME: this should be done explicitely -+ in the assembly file. */ -+ if (!((old_flags & BSF_SECTION_SYM) != 0 -+ && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0)) -+ continue; -+ } -+ -+ /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. Add 16 more -+ bytes for a possible ABS section. */ -+ if (_bfd_vms_output_check (recwr, 80 + 16) < 0) -+ { -+ _bfd_vms_output_end (abfd, recwr); -+ _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); -+ _bfd_vms_output_long (recwr, 0); -+ } -+ -+ if ((old_flags & BSF_GLOBAL) != 0 -+ && bfd_is_abs_section (symbol->section) -+ && abs_section_index <= 0) -+ { -+ /* Create an absolute section if none was defined. It is highly -+ unlikely that the name $ABS$ clashes with a user defined -+ non-absolute section name. */ -+ _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); -+ _bfd_vms_output_short (recwr, 4); -+ _bfd_vms_output_short (recwr, EGPS__V_SHR); -+ _bfd_vms_output_long (recwr, 0); -+ _bfd_vms_output_counted (recwr, "$ABS$"); -+ _bfd_vms_output_end_subrec (recwr); -+ -+ abs_section_index = target_index++; -+ } -+ -+ _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYM); -+ -+ /* Data type, alignment. */ -+ _bfd_vms_output_short (recwr, 0); -+ -+ new_flags = 0; -+ -+ if (old_flags & BSF_WEAK) -+ new_flags |= EGSY__V_WEAK; -+ if (bfd_is_com_section (symbol->section)) /* .comm */ -+ new_flags |= (EGSY__V_WEAK | EGSY__V_COMM); -+ -+ if (old_flags & BSF_FUNCTION) -+ { -+ new_flags |= EGSY__V_NORM; -+ new_flags |= EGSY__V_REL; -+ } -+ if (old_flags & BSF_GLOBAL) -+ { -+ new_flags |= EGSY__V_DEF; -+ if (!bfd_is_abs_section (symbol->section)) -+ new_flags |= EGSY__V_REL; -+ } -+ _bfd_vms_output_short (recwr, new_flags); -+ -+ if (old_flags & BSF_GLOBAL) -+ { -+ /* Symbol definition. */ -+ bfd_vma code_address = 0; -+ unsigned long ca_psindx = 0; -+ unsigned long psindx; -+ -+ if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL) -+ { -+ asymbol *sym; -+ -+ sym = -+ ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym; -+ code_address = sym->value; -+ ca_psindx = sym->section->target_index; -+ } -+ if (bfd_is_abs_section (symbol->section)) -+ psindx = abs_section_index; -+ else -+ psindx = symbol->section->target_index; -+ -+ _bfd_vms_output_quad (recwr, symbol->value); -+ _bfd_vms_output_quad (recwr, code_address); -+ _bfd_vms_output_long (recwr, ca_psindx); -+ _bfd_vms_output_long (recwr, psindx); -+ } -+ _bfd_vms_output_counted (recwr, symbol->name); -+ -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ -+ _bfd_vms_output_alignment (recwr, 8); -+ _bfd_vms_output_end (abfd, recwr); -+ -+ return TRUE; -+} -+ -+/* Write object header for bfd abfd. Return FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_write_ehdr (bfd *abfd) -+{ -+ asymbol *symbol; -+ unsigned int symnum; -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ -+ vms_debug2 ((2, "vms_write_ehdr (%p)\n", abfd)); -+ -+ _bfd_vms_output_alignment (recwr, 2); -+ -+ _bfd_vms_write_emh (abfd); -+ _bfd_vms_write_lmn (abfd, "GNU AS"); -+ -+ /* SRC. */ -+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -+ _bfd_vms_output_short (recwr, EMH__C_SRC); -+ -+ for (symnum = 0; symnum < abfd->symcount; symnum++) -+ { -+ symbol = abfd->outsymbols[symnum]; -+ -+ if (symbol->flags & BSF_FILE) -+ { -+ _bfd_vms_output_dump (recwr, (unsigned char *) symbol->name, -+ (int) strlen (symbol->name)); -+ break; -+ } -+ } -+ -+ if (symnum == abfd->symcount) -+ _bfd_vms_output_dump (recwr, (unsigned char *) STRING_COMMA_LEN ("noname")); -+ -+ _bfd_vms_output_end (abfd, recwr); -+ -+ /* TTL. */ -+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -+ _bfd_vms_output_short (recwr, EMH__C_TTL); -+ _bfd_vms_output_dump (recwr, (unsigned char *) STRING_COMMA_LEN ("TTL")); -+ _bfd_vms_output_end (abfd, recwr); -+ -+ /* CPR. */ -+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH); -+ _bfd_vms_output_short (recwr, EMH__C_CPR); -+ _bfd_vms_output_dump (recwr, -+ (unsigned char *)"GNU BFD ported by Klaus Kämpf 1994-1996", -+ 39); -+ _bfd_vms_output_end (abfd, recwr); -+ -+ return TRUE; -+} -+ -+/* Part 4.6, relocations. */ -+ -+ -+/* WRITE ETIR SECTION -+ -+ This is still under construction and therefore not documented. */ -+ -+/* Close the etir/etbt record. */ -+ -+static void -+end_etir_record (bfd * abfd) -+{ -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ -+ _bfd_vms_output_end (abfd, recwr); -+} -+ -+static void -+start_etir_or_etbt_record (bfd *abfd, asection *section, bfd_vma offset) -+{ -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ -+ if (section->flags & SEC_DEBUGGING) -+ { -+ _bfd_vms_output_begin (recwr, EOBJ__C_ETBT); -+ -+ if (offset == 0) -+ { -+ /* Push start offset. */ -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW); -+ _bfd_vms_output_long (recwr, (unsigned long) 0); -+ _bfd_vms_output_end_subrec (recwr); -+ -+ /* Set location. */ -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_CTL_DFLOC); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ } -+ else -+ { -+ _bfd_vms_output_begin (recwr, EOBJ__C_ETIR); -+ -+ if (offset == 0) -+ { -+ /* Push start offset. */ -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ); -+ _bfd_vms_output_long (recwr, (unsigned long) section->target_index); -+ _bfd_vms_output_quad (recwr, offset); -+ _bfd_vms_output_end_subrec (recwr); -+ -+ /* Start = pop (). */ -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_CTL_SETRB); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ } -+} -+ -+/* Output a STO_IMM command for SSIZE bytes of data from CPR at virtual -+ address VADDR in section specified by SEC_INDEX and NAME. */ -+ -+static void -+sto_imm (bfd *abfd, asection *section, -+ bfd_size_type ssize, unsigned char *cptr, bfd_vma vaddr) -+{ -+ bfd_size_type size; -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ -+#if VMS_DEBUG -+ _bfd_vms_debug (8, "sto_imm %d bytes\n", (int) ssize); -+ _bfd_hexdump (9, cptr, (int) ssize, (int) vaddr); -+#endif -+ -+ while (ssize > 0) -+ { -+ /* Try all the rest. */ -+ size = ssize; -+ -+ if (_bfd_vms_output_check (recwr, size) < 0) -+ { -+ /* Doesn't fit, split ! */ -+ end_etir_record (abfd); -+ -+ start_etir_or_etbt_record (abfd, section, vaddr); -+ -+ size = _bfd_vms_output_check (recwr, 0); /* get max size */ -+ if (size > ssize) /* more than what's left ? */ -+ size = ssize; -+ } -+ -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_IMM); -+ _bfd_vms_output_long (recwr, (unsigned long) (size)); -+ _bfd_vms_output_dump (recwr, cptr, size); -+ _bfd_vms_output_end_subrec (recwr); -+ -+#if VMS_DEBUG -+ _bfd_vms_debug (10, "dumped %d bytes\n", (int) size); -+ _bfd_hexdump (10, cptr, (int) size, (int) vaddr); -+#endif -+ -+ vaddr += size; -+ cptr += size; -+ ssize -= size; -+ } -+} -+ -+static void -+etir_output_check (bfd *abfd, asection *section, bfd_vma vaddr, int checklen) -+{ -+ if (_bfd_vms_output_check (&PRIV (recwr), checklen) < 0) -+ { -+ /* Not enough room in this record. Close it and open a new one. */ -+ end_etir_record (abfd); -+ start_etir_or_etbt_record (abfd, section, vaddr); -+ } -+} -+ -+/* Return whether RELOC must be deferred till the end. */ -+ -+static bfd_boolean -+defer_reloc_p (arelent *reloc) -+{ -+ switch (reloc->howto->type) -+ { -+ case SW_64_R_NOP: -+ case SW_64_R_LDA: -+ case SW_64_R_BSR: -+ case SW_64_R_BOH: -+ return TRUE; -+ -+ default: -+ return FALSE; -+ } -+} -+ -+/* Write section contents for bfd abfd. Return FALSE on error. */ -+ -+static bfd_boolean -+_bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) -+{ -+ asection *section; -+ struct vms_rec_wr *recwr = &PRIV (recwr); -+ -+ vms_debug2 ((2, "vms_write_tir (%p, %d)\n", abfd, objtype)); -+ -+ _bfd_vms_output_alignment (recwr, 4); -+ -+ PRIV (vms_linkage_index) = 0; -+ -+ for (section = abfd->sections; section; section = section->next) -+ { -+ vms_debug2 ((4, "writing %d. section '%s' (%d bytes)\n", -+ section->target_index, section->name, (int) (section->size))); -+ -+ if (!(section->flags & SEC_HAS_CONTENTS) -+ || bfd_is_com_section (section)) -+ continue; -+ -+ if (!section->contents) -+ { -+ bfd_set_error (bfd_error_no_contents); -+ return FALSE; -+ } -+ -+ start_etir_or_etbt_record (abfd, section, 0); -+ -+ if (section->flags & SEC_RELOC) -+ { -+ bfd_vma curr_addr = 0; -+ unsigned char *curr_data = section->contents; -+ bfd_size_type size; -+ int pass2_needed = 0; -+ int pass2_in_progress = 0; -+ unsigned int irel; -+ -+ if (section->reloc_count == 0) -+ _bfd_error_handler -+ (_("SEC_RELOC with no relocs in section %pA"), section); -+ -+#if VMS_DEBUG -+ else -+ { -+ int i = section->reloc_count; -+ arelent **rptr = section->orelocation; -+ _bfd_vms_debug (4, "%d relocations:\n", i); -+ while (i-- > 0) -+ { -+ _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, " -+ "addr %08lx, off %08lx, len %d: %s\n", -+ (*(*rptr)->sym_ptr_ptr)->name, -+ (*(*rptr)->sym_ptr_ptr)->section->name, -+ (long) (*(*rptr)->sym_ptr_ptr)->value, -+ (unsigned long)(*rptr)->address, -+ (unsigned long)(*rptr)->addend, -+ bfd_get_reloc_size ((*rptr)->howto), -+ ( *rptr)->howto->name); -+ rptr++; -+ } -+ } -+#endif -+ -+ new_pass: -+ for (irel = 0; irel < section->reloc_count; irel++) -+ { -+ struct evax_private_udata_struct *udata; -+ arelent *rptr = section->orelocation [irel]; -+ bfd_vma addr = rptr->address; -+ asymbol *sym = *rptr->sym_ptr_ptr; -+ asection *sec = sym->section; -+ bfd_boolean defer = defer_reloc_p (rptr); -+ unsigned int slen; -+ -+ if (pass2_in_progress) -+ { -+ /* Non-deferred relocs have already been output. */ -+ if (!defer) -+ continue; -+ } -+ else -+ { -+ /* Deferred relocs must be output at the very end. */ -+ if (defer) -+ { -+ pass2_needed = 1; -+ continue; -+ } -+ -+ /* Regular relocs are intertwined with binary data. */ -+ if (curr_addr > addr) -+ _bfd_error_handler (_("size error in section %pA"), -+ section); -+ size = addr - curr_addr; -+ sto_imm (abfd, section, size, curr_data, curr_addr); -+ curr_data += size; -+ curr_addr += size; -+ } -+ -+ size = bfd_get_reloc_size (rptr->howto); -+ -+ switch (rptr->howto->type) -+ { -+ case SW_64_R_IGNORE: -+ break; -+ -+ case SW_64_R_REFLONG: -+ if (bfd_is_und_section (sym->section)) -+ { -+ bfd_vma addend = rptr->addend; -+ slen = strlen ((char *) sym->name); -+ etir_output_check (abfd, section, curr_addr, slen); -+ if (addend) -+ { -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL); -+ _bfd_vms_output_counted (recwr, sym->name); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW); -+ _bfd_vms_output_long (recwr, (unsigned long) addend); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_OPR_ADD); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ else -+ { -+ _bfd_vms_output_begin_subrec -+ (recwr, ETIR__C_STO_GBL_LW); -+ _bfd_vms_output_counted (recwr, sym->name); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ } -+ else if (bfd_is_abs_section (sym->section)) -+ { -+ etir_output_check (abfd, section, curr_addr, 16); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW); -+ _bfd_vms_output_long (recwr, (unsigned long) sym->value); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ else -+ { -+ etir_output_check (abfd, section, curr_addr, 32); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ); -+ _bfd_vms_output_long (recwr, -+ (unsigned long) sec->target_index); -+ _bfd_vms_output_quad (recwr, rptr->addend + sym->value); -+ _bfd_vms_output_end_subrec (recwr); -+ /* ??? Table B-8 of the OpenVMS Linker Utilily Manual -+ says that we should have a ETIR__C_STO_OFF here. -+ But the relocation would not be BFD_RELOC_32 then. -+ This case is very likely unreachable. */ -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ break; -+ -+ case SW_64_R_REFQUAD: -+ if (bfd_is_und_section (sym->section)) -+ { -+ bfd_vma addend = rptr->addend; -+ slen = strlen ((char *) sym->name); -+ etir_output_check (abfd, section, curr_addr, slen); -+ if (addend) -+ { -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL); -+ _bfd_vms_output_counted (recwr, sym->name); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW); -+ _bfd_vms_output_quad (recwr, addend); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_OPR_ADD); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_QW); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ else -+ { -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_GBL); -+ _bfd_vms_output_counted (recwr, sym->name); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ } -+ else if (bfd_is_abs_section (sym->section)) -+ { -+ etir_output_check (abfd, section, curr_addr, 16); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW); -+ _bfd_vms_output_quad (recwr, sym->value); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_QW); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ else -+ { -+ etir_output_check (abfd, section, curr_addr, 32); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ); -+ _bfd_vms_output_long (recwr, -+ (unsigned long) sec->target_index); -+ _bfd_vms_output_quad (recwr, rptr->addend + sym->value); -+ _bfd_vms_output_end_subrec (recwr); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_OFF); -+ _bfd_vms_output_end_subrec (recwr); -+ } -+ break; -+ -+ case SW_64_R_HINT: -+ sto_imm (abfd, section, size, curr_data, curr_addr); -+ break; -+ -+ case SW_64_R_LINKAGE: -+ size = 16; -+ etir_output_check (abfd, section, curr_addr, 64); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_LP_PSB); -+ _bfd_vms_output_long -+ (recwr, (unsigned long) rptr->addend); -+ if (rptr->addend > PRIV (vms_linkage_index)) -+ PRIV (vms_linkage_index) = rptr->addend; -+ _bfd_vms_output_counted (recwr, sym->name); -+ _bfd_vms_output_byte (recwr, 0); -+ _bfd_vms_output_end_subrec (recwr); -+ break; -+ -+ case SW_64_R_CODEADDR: -+ slen = strlen ((char *) sym->name); -+ etir_output_check (abfd, section, curr_addr, slen); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_CA); -+ _bfd_vms_output_counted (recwr, sym->name); -+ _bfd_vms_output_end_subrec (recwr); -+ break; -+ -+ case SW_64_R_NOP: -+ udata -+ = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr; -+ etir_output_check (abfd, section, curr_addr, -+ 32 + 1 + strlen (udata->origname)); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_NOP_GBL); -+ _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex); -+ _bfd_vms_output_long -+ (recwr, (unsigned long) section->target_index); -+ _bfd_vms_output_quad (recwr, rptr->address); -+ _bfd_vms_output_long (recwr, (unsigned long) 0x47ff041f); -+ _bfd_vms_output_long -+ (recwr, (unsigned long) section->target_index); -+ _bfd_vms_output_quad (recwr, rptr->addend); -+ _bfd_vms_output_counted (recwr, udata->origname); -+ _bfd_vms_output_end_subrec (recwr); -+ break; -+ -+ case SW_64_R_BSR: -+ _bfd_error_handler (_("spurious SW_64_R_BSR reloc")); -+ break; -+ -+ case SW_64_R_LDA: -+ udata -+ = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr; -+ etir_output_check (abfd, section, curr_addr, -+ 32 + 1 + strlen (udata->origname)); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_LDA_GBL); -+ _bfd_vms_output_long -+ (recwr, (unsigned long) udata->lkindex + 1); -+ _bfd_vms_output_long -+ (recwr, (unsigned long) section->target_index); -+ _bfd_vms_output_quad (recwr, rptr->address); -+ _bfd_vms_output_long (recwr, (unsigned long) 0x237B0000); -+ _bfd_vms_output_long -+ (recwr, (unsigned long) udata->bsym->section->target_index); -+ _bfd_vms_output_quad (recwr, rptr->addend); -+ _bfd_vms_output_counted (recwr, udata->origname); -+ _bfd_vms_output_end_subrec (recwr); -+ break; -+ -+ case SW_64_R_BOH: -+ udata -+ = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr; -+ etir_output_check (abfd, section, curr_addr, -+ 32 + 1 + strlen (udata->origname)); -+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_BOH_GBL); -+ _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex); -+ _bfd_vms_output_long -+ (recwr, (unsigned long) section->target_index); -+ _bfd_vms_output_quad (recwr, rptr->address); -+ _bfd_vms_output_long (recwr, (unsigned long) 0xD3400000); -+ _bfd_vms_output_long -+ (recwr, (unsigned long) section->target_index); -+ _bfd_vms_output_quad (recwr, rptr->addend); -+ _bfd_vms_output_counted (recwr, udata->origname); -+ _bfd_vms_output_end_subrec (recwr); -+ break; -+ -+ default: -+ _bfd_error_handler (_("unhandled relocation %s"), -+ rptr->howto->name); -+ break; -+ } -+ -+ curr_data += size; -+ curr_addr += size; -+ } /* End of relocs loop. */ -+ -+ if (!pass2_in_progress) -+ { -+ /* Output rest of section. */ -+ if (curr_addr > section->size) -+ { -+ _bfd_error_handler (_("size error in section %pA"), section); -+ return FALSE; -+ } -+ size = section->size - curr_addr; -+ sto_imm (abfd, section, size, curr_data, curr_addr); -+ curr_data += size; -+ curr_addr += size; -+ -+ if (pass2_needed) -+ { -+ pass2_in_progress = 1; -+ goto new_pass; -+ } -+ } -+ } -+ -+ else /* (section->flags & SEC_RELOC) */ -+ sto_imm (abfd, section, section->size, section->contents, 0); -+ -+ end_etir_record (abfd); -+ } -+ -+ _bfd_vms_output_alignment (recwr, 2); -+ return TRUE; -+} -+ -+/* Write cached information into a file being written, at bfd_close. */ -+ -+static bfd_boolean -+sw_64_vms_write_object_contents (bfd *abfd) -+{ -+ vms_debug2 ((1, "vms_write_object_contents (%p)\n", abfd)); -+ -+ if (abfd->flags & (EXEC_P | DYNAMIC)) -+ { -+ return sw_64_vms_write_exec (abfd); -+ } -+ else -+ { -+ if (abfd->section_count > 0) /* we have sections */ -+ { -+ if (!_bfd_vms_write_ehdr (abfd)) -+ return FALSE; -+ if (!_bfd_vms_write_egsd (abfd)) -+ return FALSE; -+ if (!_bfd_vms_write_etir (abfd, EOBJ__C_ETIR)) -+ return FALSE; -+ if (!_bfd_vms_write_eeom (abfd)) -+ return FALSE; -+ } -+ } -+ return TRUE; -+} -+ -+/* Debug stuff: nearest line. */ -+ -+#define SET_MODULE_PARSED(m) \ -+ do { if ((m)->name == NULL) (m)->name = ""; } while (0) -+#define IS_MODULE_PARSED(m) ((m)->name != NULL) -+ -+/* Build a new module for the specified BFD. */ -+ -+static struct module * -+new_module (bfd *abfd) -+{ -+ struct module *module -+ = (struct module *) bfd_zalloc (abfd, sizeof (struct module)); -+ module->file_table_count = 16; /* Arbitrary. */ -+ module->file_table -+ = bfd_malloc (module->file_table_count * sizeof (struct fileinfo)); -+ return module; -+} -+ -+/* Parse debug info for a module and internalize it. */ -+ -+static void -+parse_module (bfd *abfd, struct module *module, unsigned char *ptr, -+ int length) -+{ -+ unsigned char *maxptr = ptr + length; -+ unsigned char *src_ptr, *pcl_ptr; -+ unsigned int prev_linum = 0, curr_linenum = 0; -+ bfd_vma prev_pc = 0, curr_pc = 0; -+ struct srecinfo *curr_srec, *srec; -+ struct lineinfo *curr_line, *line; -+ struct funcinfo *funcinfo; -+ -+ /* Initialize tables with zero element. */ -+ curr_srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo)); -+ module->srec_table = curr_srec; -+ -+ curr_line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo)); -+ module->line_table = curr_line; -+ -+ while (length == -1 || ptr < maxptr) -+ { -+ /* The first byte is not counted in the recorded length. */ -+ int rec_length = bfd_getl16 (ptr) + 1; -+ int rec_type = bfd_getl16 (ptr + 2); -+ -+ vms_debug2 ((2, "DST record: leng %d, type %d\n", rec_length, rec_type)); -+ -+ if (length == -1 && rec_type == DST__K_MODEND) -+ break; -+ -+ switch (rec_type) -+ { -+ case DST__K_MODBEG: -+ module->name -+ = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_MODBEG_NAME, -+ maxptr - (ptr + DST_S_B_MODBEG_NAME)); -+ -+ curr_pc = 0; -+ prev_pc = 0; -+ curr_linenum = 0; -+ prev_linum = 0; -+ -+ vms_debug2 ((3, "module: %s\n", module->name)); -+ break; -+ -+ case DST__K_MODEND: -+ break; -+ -+ case DST__K_RTNBEG: -+ funcinfo = (struct funcinfo *) -+ bfd_zalloc (abfd, sizeof (struct funcinfo)); -+ funcinfo->name -+ = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_RTNBEG_NAME, -+ maxptr - (ptr + DST_S_B_RTNBEG_NAME)); -+ funcinfo->low = bfd_getl32 (ptr + DST_S_L_RTNBEG_ADDRESS); -+ funcinfo->next = module->func_table; -+ module->func_table = funcinfo; -+ -+ vms_debug2 ((3, "routine: %s at 0x%lx\n", -+ funcinfo->name, (unsigned long) funcinfo->low)); -+ break; -+ -+ case DST__K_RTNEND: -+ module->func_table->high = module->func_table->low -+ + bfd_getl32 (ptr + DST_S_L_RTNEND_SIZE) - 1; -+ -+ if (module->func_table->high > module->high) -+ module->high = module->func_table->high; -+ -+ vms_debug2 ((3, "end routine\n")); -+ break; -+ -+ case DST__K_PROLOG: -+ vms_debug2 ((3, "prologue\n")); -+ break; -+ -+ case DST__K_EPILOG: -+ vms_debug2 ((3, "epilog\n")); -+ break; -+ -+ case DST__K_BLKBEG: -+ vms_debug2 ((3, "block\n")); -+ break; -+ -+ case DST__K_BLKEND: -+ vms_debug2 ((3, "end block\n")); -+ break; -+ -+ case DST__K_SOURCE: -+ src_ptr = ptr + DST_S_C_SOURCE_HEADER_SIZE; -+ -+ vms_debug2 ((3, "source info\n")); -+ -+ while (src_ptr < ptr + rec_length) -+ { -+ int cmd = src_ptr[0], cmd_length, data; -+ -+ switch (cmd) -+ { -+ case DST__K_SRC_DECLFILE: -+ { -+ unsigned int fileid -+ = bfd_getl16 (src_ptr + DST_S_W_SRC_DF_FILEID); -+ char *filename = _bfd_vms_save_counted_string -+ (abfd, -+ src_ptr + DST_S_B_SRC_DF_FILENAME, -+ ptr + rec_length - (src_ptr + DST_S_B_SRC_DF_FILENAME)); -+ -+ while (fileid >= module->file_table_count) -+ { -+ module->file_table_count *= 2; -+ module->file_table -+ = bfd_realloc (module->file_table, -+ module->file_table_count -+ * sizeof (struct fileinfo)); -+ } -+ -+ module->file_table [fileid].name = filename; -+ module->file_table [fileid].srec = 1; -+ cmd_length = src_ptr[DST_S_B_SRC_DF_LENGTH] + 2; -+ vms_debug2 ((4, "DST_S_C_SRC_DECLFILE: %d, %s\n", -+ fileid, module->file_table [fileid].name)); -+ } -+ break; -+ -+ case DST__K_SRC_DEFLINES_B: -+ /* Perform the association and set the next higher index -+ to the limit. */ -+ data = src_ptr[DST_S_B_SRC_UNSBYTE]; -+ srec = (struct srecinfo *) -+ bfd_zalloc (abfd, sizeof (struct srecinfo)); -+ srec->line = curr_srec->line + data; -+ srec->srec = curr_srec->srec + data; -+ srec->sfile = curr_srec->sfile; -+ curr_srec->next = srec; -+ curr_srec = srec; -+ cmd_length = 2; -+ vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_B: %d\n", data)); -+ break; -+ -+ case DST__K_SRC_DEFLINES_W: -+ /* Perform the association and set the next higher index -+ to the limit. */ -+ data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); -+ srec = (struct srecinfo *) -+ bfd_zalloc (abfd, sizeof (struct srecinfo)); -+ srec->line = curr_srec->line + data; -+ srec->srec = curr_srec->srec + data, -+ srec->sfile = curr_srec->sfile; -+ curr_srec->next = srec; -+ curr_srec = srec; -+ cmd_length = 3; -+ vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_W: %d\n", data)); -+ break; -+ -+ case DST__K_SRC_INCRLNUM_B: -+ data = src_ptr[DST_S_B_SRC_UNSBYTE]; -+ curr_srec->line += data; -+ cmd_length = 2; -+ vms_debug2 ((4, "DST_S_C_SRC_INCRLNUM_B: %d\n", data)); -+ break; -+ -+ case DST__K_SRC_SETFILE: -+ data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); -+ curr_srec->sfile = data; -+ curr_srec->srec = module->file_table[data].srec; -+ cmd_length = 3; -+ vms_debug2 ((4, "DST_S_C_SRC_SETFILE: %d\n", data)); -+ break; -+ -+ case DST__K_SRC_SETLNUM_L: -+ data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG); -+ curr_srec->line = data; -+ cmd_length = 5; -+ vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_L: %d\n", data)); -+ break; -+ -+ case DST__K_SRC_SETLNUM_W: -+ data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); -+ curr_srec->line = data; -+ cmd_length = 3; -+ vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_W: %d\n", data)); -+ break; -+ -+ case DST__K_SRC_SETREC_L: -+ data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG); -+ curr_srec->srec = data; -+ module->file_table[curr_srec->sfile].srec = data; -+ cmd_length = 5; -+ vms_debug2 ((4, "DST_S_C_SRC_SETREC_L: %d\n", data)); -+ break; -+ -+ case DST__K_SRC_SETREC_W: -+ data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); -+ curr_srec->srec = data; -+ module->file_table[curr_srec->sfile].srec = data; -+ cmd_length = 3; -+ vms_debug2 ((4, "DST_S_C_SRC_SETREC_W: %d\n", data)); -+ break; -+ -+ case DST__K_SRC_FORMFEED: -+ cmd_length = 1; -+ vms_debug2 ((4, "DST_S_C_SRC_FORMFEED\n")); -+ break; -+ -+ default: -+ _bfd_error_handler (_("unknown source command %d"), -+ cmd); -+ cmd_length = 2; -+ break; -+ } -+ -+ src_ptr += cmd_length; -+ } -+ break; -+ -+ case DST__K_LINE_NUM: -+ pcl_ptr = ptr + DST_S_C_LINE_NUM_HEADER_SIZE; -+ -+ vms_debug2 ((3, "line info\n")); -+ -+ while (pcl_ptr < ptr + rec_length) -+ { -+ /* The command byte is signed so we must sign-extend it. */ -+ int cmd = ((signed char *)pcl_ptr)[0], cmd_length, data; -+ -+ switch (cmd) -+ { -+ case DST__K_DELTA_PC_W: -+ data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); -+ curr_pc += data; -+ curr_linenum += 1; -+ cmd_length = 3; -+ vms_debug2 ((4, "DST__K_DELTA_PC_W: %d\n", data)); -+ break; -+ -+ case DST__K_DELTA_PC_L: -+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -+ curr_pc += data; -+ curr_linenum += 1; -+ cmd_length = 5; -+ vms_debug2 ((4, "DST__K_DELTA_PC_L: %d\n", data)); -+ break; -+ -+ case DST__K_INCR_LINUM: -+ data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; -+ curr_linenum += data; -+ cmd_length = 2; -+ vms_debug2 ((4, "DST__K_INCR_LINUM: %d\n", data)); -+ break; -+ -+ case DST__K_INCR_LINUM_W: -+ data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); -+ curr_linenum += data; -+ cmd_length = 3; -+ vms_debug2 ((4, "DST__K_INCR_LINUM_W: %d\n", data)); -+ break; -+ -+ case DST__K_INCR_LINUM_L: -+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -+ curr_linenum += data; -+ cmd_length = 5; -+ vms_debug2 ((4, "DST__K_INCR_LINUM_L: %d\n", data)); -+ break; -+ -+ case DST__K_SET_LINUM_INCR: -+ _bfd_error_handler -+ (_("%s not implemented"), "DST__K_SET_LINUM_INCR"); -+ cmd_length = 2; -+ break; -+ -+ case DST__K_SET_LINUM_INCR_W: -+ _bfd_error_handler -+ (_("%s not implemented"), "DST__K_SET_LINUM_INCR_W"); -+ cmd_length = 3; -+ break; -+ -+ case DST__K_RESET_LINUM_INCR: -+ _bfd_error_handler -+ (_("%s not implemented"), "DST__K_RESET_LINUM_INCR"); -+ cmd_length = 1; -+ break; -+ -+ case DST__K_BEG_STMT_MODE: -+ _bfd_error_handler -+ (_("%s not implemented"), "DST__K_BEG_STMT_MODE"); -+ cmd_length = 1; -+ break; -+ -+ case DST__K_END_STMT_MODE: -+ _bfd_error_handler -+ (_("%s not implemented"), "DST__K_END_STMT_MODE"); -+ cmd_length = 1; -+ break; -+ -+ case DST__K_SET_LINUM_B: -+ data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; -+ curr_linenum = data; -+ cmd_length = 2; -+ vms_debug2 ((4, "DST__K_SET_LINUM_B: %d\n", data)); -+ break; -+ -+ case DST__K_SET_LINUM: -+ data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); -+ curr_linenum = data; -+ cmd_length = 3; -+ vms_debug2 ((4, "DST__K_SET_LINE_NUM: %d\n", data)); -+ break; -+ -+ case DST__K_SET_LINUM_L: -+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -+ curr_linenum = data; -+ cmd_length = 5; -+ vms_debug2 ((4, "DST__K_SET_LINUM_L: %d\n", data)); -+ break; -+ -+ case DST__K_SET_PC: -+ _bfd_error_handler -+ (_("%s not implemented"), "DST__K_SET_PC"); -+ cmd_length = 2; -+ break; -+ -+ case DST__K_SET_PC_W: -+ _bfd_error_handler -+ (_("%s not implemented"), "DST__K_SET_PC_W"); -+ cmd_length = 3; -+ break; -+ -+ case DST__K_SET_PC_L: -+ _bfd_error_handler -+ (_("%s not implemented"), "DST__K_SET_PC_L"); -+ cmd_length = 5; -+ break; -+ -+ case DST__K_SET_STMTNUM: -+ _bfd_error_handler -+ (_("%s not implemented"), "DST__K_SET_STMTNUM"); -+ cmd_length = 2; -+ break; -+ -+ case DST__K_TERM: -+ data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; -+ curr_pc += data; -+ cmd_length = 2; -+ vms_debug2 ((4, "DST__K_TERM: %d\n", data)); -+ break; -+ -+ case DST__K_TERM_W: -+ data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); -+ curr_pc += data; -+ cmd_length = 3; -+ vms_debug2 ((4, "DST__K_TERM_W: %d\n", data)); -+ break; -+ -+ case DST__K_TERM_L: -+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -+ curr_pc += data; -+ cmd_length = 5; -+ vms_debug2 ((4, "DST__K_TERM_L: %d\n", data)); -+ break; -+ -+ case DST__K_SET_ABS_PC: -+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); -+ curr_pc = data; -+ cmd_length = 5; -+ vms_debug2 ((4, "DST__K_SET_ABS_PC: 0x%x\n", data)); -+ break; -+ -+ default: -+ if (cmd <= 0) -+ { -+ curr_pc -= cmd; -+ curr_linenum += 1; -+ cmd_length = 1; -+ vms_debug2 ((4, "bump pc to 0x%lx and line to %d\n", -+ (unsigned long)curr_pc, curr_linenum)); -+ } -+ else -+ { -+ _bfd_error_handler (_("unknown line command %d"), cmd); -+ cmd_length = 2; -+ } -+ break; -+ } -+ -+ if ((curr_linenum != prev_linum && curr_pc != prev_pc) -+ || cmd <= 0 -+ || cmd == DST__K_DELTA_PC_L -+ || cmd == DST__K_DELTA_PC_W) -+ { -+ line = (struct lineinfo *) -+ bfd_zalloc (abfd, sizeof (struct lineinfo)); -+ line->address = curr_pc; -+ line->line = curr_linenum; -+ -+ curr_line->next = line; -+ curr_line = line; -+ -+ prev_linum = curr_linenum; -+ prev_pc = curr_pc; -+ vms_debug2 ((4, "-> correlate pc 0x%lx with line %d\n", -+ (unsigned long)curr_pc, curr_linenum)); -+ } -+ -+ pcl_ptr += cmd_length; -+ } -+ break; -+ -+ case 0x17: /* Undocumented type used by DEC C to declare equates. */ -+ vms_debug2 ((3, "undocumented type 0x17\n")); -+ break; -+ -+ default: -+ vms_debug2 ((3, "ignoring record\n")); -+ break; -+ -+ } -+ -+ ptr += rec_length; -+ } -+ -+ /* Finalize tables with EOL marker. */ -+ srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo)); -+ srec->line = (unsigned int) -1; -+ srec->srec = (unsigned int) -1; -+ curr_srec->next = srec; -+ -+ line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo)); -+ line->line = (unsigned int) -1; -+ line->address = (bfd_vma) -1; -+ curr_line->next = line; -+ -+ /* Advertise that this module has been parsed. This is needed -+ because parsing can be either performed at module creation -+ or deferred until debug info is consumed. */ -+ SET_MODULE_PARSED (module); -+} -+ -+/* Build the list of modules for the specified BFD. */ -+ -+static struct module * -+build_module_list (bfd *abfd) -+{ -+ struct module *module, *list = NULL; -+ asection *dmt; -+ -+ if ((dmt = bfd_get_section_by_name (abfd, "$DMT$"))) -+ { -+ /* We have a DMT section so this must be an image. Parse the -+ section and build the list of modules. This is sufficient -+ since we can compute the start address and the end address -+ of every module from the section contents. */ -+ bfd_size_type size = bfd_section_size (dmt); -+ //unsigned char *ptr, *end; -+ unsigned char *buf, *ptr, *end; -+ -+ //ptr = (unsigned char *) bfd_alloc (abfd, size); -+ //if (! ptr) -+ // return NULL; -+ -+ //if (! bfd_get_section_contents (abfd, dmt, ptr, 0, size)) -+ if (! bfd_malloc_and_get_section (abfd, dmt, &buf)) -+ return NULL; -+ -+ vms_debug2 ((2, "DMT\n")); -+ -+ ptr = buf; -+ end = ptr + size; -+ -+ while (end - ptr >= DBG_S_C_DMT_HEADER_SIZE) -+ //while (ptr < end) -+ { -+ /* Each header declares a module with its start offset and size -+ of debug info in the DST section, as well as the count of -+ program sections (i.e. address spans) it contains. */ -+ unsigned int modbeg = bfd_getl32 (ptr + DBG_S_L_DMT_MODBEG); -+ unsigned int msize = bfd_getl32 (ptr + DBG_S_L_DST_SIZE); -+ //int modbeg = bfd_getl32 (ptr + DBG_S_L_DMT_MODBEG); -+ //int msize = bfd_getl32 (ptr + DBG_S_L_DST_SIZE); -+ int count = bfd_getl16 (ptr + DBG_S_W_DMT_PSECT_COUNT); -+ ptr += DBG_S_C_DMT_HEADER_SIZE; -+ -+ vms_debug2 ((3, "module: modbeg = %u, size = %u, count = %d\n", -+ modbeg, msize, count)); -+ //vms_debug2 ((3, "module: modbeg = %d, size = %d, count = %d\n", -+ // modbeg, msize, count)); -+ -+ /* We create a 'module' structure for each program section since -+ we only support contiguous addresses in a 'module' structure. -+ As a consequence, the actual debug info in the DST section is -+ shared and can be parsed multiple times; that doesn't seem to -+ cause problems in practice. */ -+ while (count-- > 0 && end - ptr >= DBG_S_C_DMT_PSECT_SIZE) -+ //while (count-- > 0) -+ { -+ unsigned int start = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_START); -+ unsigned int length = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_LENGTH); -+ //int start = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_START); -+ //int length = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_LENGTH); -+ module = new_module (abfd); -+ module->modbeg = modbeg; -+ module->size = msize; -+ module->low = start; -+ module->high = start + length; -+ module->next = list; -+ list = module; -+ ptr += DBG_S_C_DMT_PSECT_SIZE; -+ -+ vms_debug2 ((4, "section: start = 0x%x, length = %u\n", -+ start, length)); -+ //vms_debug2 ((4, "section: start = 0x%x, length = %d\n", -+ // start, length)); -+ } -+ } -+ free (buf); -+ } -+ else -+ { -+ /* We don't have a DMT section so this must be an object. Parse -+ the module right now in order to compute its start address and -+ end address. */ -+ void *dst = PRIV (dst_section)->contents; -+ -+ if (dst == NULL) -+ return NULL; -+ -+ module = new_module (abfd); -+ parse_module (abfd, module, PRIV (dst_section)->contents, -1); -+ list = module; -+ } -+ -+ return list; -+} -+ -+/* Calculate and return the name of the source file and the line nearest -+ to the wanted location in the specified module. */ -+ -+static bfd_boolean -+module_find_nearest_line (bfd *abfd, struct module *module, bfd_vma addr, -+ const char **file, const char **func, -+ unsigned int *line) -+{ -+ struct funcinfo *funcinfo; -+ struct lineinfo *lineinfo; -+ struct srecinfo *srecinfo; -+ bfd_boolean ret = FALSE; -+ -+ /* Parse this module if that was not done at module creation. */ -+ if (! IS_MODULE_PARSED (module)) -+ { -+ unsigned int size = module->size; -+ unsigned int modbeg = PRIV (dst_section)->filepos + module->modbeg; -+ unsigned char *buffer = (unsigned char *) bfd_malloc (module->size); -+ -+ if (bfd_seek (abfd, modbeg, SEEK_SET) != 0 -+ || bfd_bread (buffer, size, abfd) != size) -+ { -+ bfd_set_error (bfd_error_no_debug_section); -+ return FALSE; -+ } -+ -+ parse_module (abfd, module, buffer, size); -+ free (buffer); -+ } -+ -+ /* Find out the function (if any) that contains the address. */ -+ for (funcinfo = module->func_table; funcinfo; funcinfo = funcinfo->next) -+ if (addr >= funcinfo->low && addr <= funcinfo->high) -+ { -+ *func = funcinfo->name; -+ ret = TRUE; -+ break; -+ } -+ -+ /* Find out the source file and the line nearest to the address. */ -+ for (lineinfo = module->line_table; lineinfo; lineinfo = lineinfo->next) -+ if (lineinfo->next && addr < lineinfo->next->address) -+ { -+ for (srecinfo = module->srec_table; srecinfo; srecinfo = srecinfo->next) -+ if (srecinfo->next && lineinfo->line < srecinfo->next->line) -+ { -+ if (srecinfo->sfile > 0) -+ { -+ *file = module->file_table[srecinfo->sfile].name; -+ *line = srecinfo->srec + lineinfo->line - srecinfo->line; -+ } -+ else -+ { -+ *file = module->name; -+ *line = lineinfo->line; -+ } -+ return TRUE; -+ } -+ -+ break; -+ } -+ -+ return ret; -+} -+ -+/* 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. */ -+ -+static bfd_boolean -+_bfd_vms_find_nearest_line (bfd *abfd, -+ asymbol **symbols ATTRIBUTE_UNUSED, -+ asection *section, -+ bfd_vma offset, -+ const char **file, -+ const char **func, -+ unsigned int *line, -+ unsigned int *discriminator) -+{ -+ struct module *module; -+ -+ /* What address are we looking for? */ -+ bfd_vma addr = section->vma + offset; -+ -+ *file = NULL; -+ *func = NULL; -+ *line = 0; -+ if (discriminator) -+ *discriminator = 0; -+ -+ /* We can't do anything if there is no DST (debug symbol table). */ -+ if (PRIV (dst_section) == NULL) -+ return FALSE; -+ -+ /* Create the module list - if not already done. */ -+ if (PRIV (modules) == NULL) -+ { -+ PRIV (modules) = build_module_list (abfd); -+ if (PRIV (modules) == NULL) -+ return FALSE; -+ } -+ -+ for (module = PRIV (modules); module; module = module->next) -+ if (addr >= module->low && addr <= module->high) -+ return module_find_nearest_line (abfd, module, addr, file, func, line); -+ -+ return FALSE; -+} -+ -+/* Canonicalizations. */ -+/* Set name, value, section and flags of SYM from E. */ -+ -+static bfd_boolean -+sw_64_vms_convert_symbol (bfd *abfd, struct vms_symbol_entry *e, asymbol *sym) -+{ -+ flagword flags; -+ symvalue value; -+ asection *sec; -+ const char *name; -+ -+ name = e->name; -+ value = 0; -+ flags = BSF_NO_FLAGS; -+ sec = NULL; -+ -+ switch (e->typ) -+ { -+ case EGSD__C_SYM: -+ if (e->flags & EGSY__V_WEAK) -+ flags |= BSF_WEAK; -+ -+ if (e->flags & EGSY__V_DEF) -+ { -+ /* Symbol definition. */ -+ flags |= BSF_GLOBAL; -+ if (e->flags & EGSY__V_NORM) -+ flags |= BSF_FUNCTION; -+ value = e->value; -+ sec = e->section; -+ } -+ else -+ { -+ /* Symbol reference. */ -+ sec = bfd_und_section_ptr; -+ } -+ break; -+ -+ case EGSD__C_SYMG: -+ /* A universal symbol is by definition global... */ -+ flags |= BSF_GLOBAL; -+ -+ /* ...and dynamic in shared libraries. */ -+ if (abfd->flags & DYNAMIC) -+ flags |= BSF_DYNAMIC; -+ -+ if (e->flags & EGSY__V_WEAK) -+ flags |= BSF_WEAK; -+ -+ if (!(e->flags & EGSY__V_DEF)) -+ abort (); -+ -+ if (e->flags & EGSY__V_NORM) -+ flags |= BSF_FUNCTION; -+ -+ value = e->value; -+ /* sec = e->section; */ -+ sec = bfd_abs_section_ptr; -+ break; -+ -+ default: -+ return FALSE; -+ } -+ -+ sym->name = name; -+ sym->section = sec; -+ sym->flags = flags; -+ sym->value = value; -+ return TRUE; -+} -+ -+ -+/* Return the number of bytes required to store a vector of pointers -+ to asymbols for all the symbols in the BFD abfd, including a -+ terminal NULL pointer. If there are no symbols in the BFD, -+ then return 0. If an error occurs, return -1. */ -+ -+static long -+sw_64_vms_get_symtab_upper_bound (bfd *abfd) -+{ -+ vms_debug2 ((1, "sw_64_vms_get_symtab_upper_bound (%p), %d symbols\n", -+ abfd, PRIV (gsd_sym_count))); -+ -+ return (PRIV (gsd_sym_count) + 1) * sizeof (asymbol *); -+} -+ -+/* Read the symbols from the BFD abfd, and fills in the vector -+ location with pointers to the symbols and a trailing NULL. -+ -+ Return number of symbols read. */ -+ -+static long -+sw_64_vms_canonicalize_symtab (bfd *abfd, asymbol **symbols) -+{ -+ unsigned int i; -+ -+ vms_debug2 ((1, "sw_64_vms_canonicalize_symtab (%p, )\n", abfd)); -+ -+ if (PRIV (csymbols) == NULL) -+ { -+ PRIV (csymbols) = (asymbol **) bfd_alloc -+ (abfd, PRIV (gsd_sym_count) * sizeof (asymbol *)); -+ -+ /* Traverse table and fill symbols vector. */ -+ for (i = 0; i < PRIV (gsd_sym_count); i++) -+ { -+ struct vms_symbol_entry *e = PRIV (syms)[i]; -+ asymbol *sym; -+ -+ sym = bfd_make_empty_symbol (abfd); -+ if (sym == NULL || !sw_64_vms_convert_symbol (abfd, e, sym)) -+ { -+ bfd_release (abfd, PRIV (csymbols)); -+ PRIV (csymbols) = NULL; -+ return -1; -+ } -+ -+ PRIV (csymbols)[i] = sym; -+ } -+ } -+ -+ if (symbols != NULL) -+ { -+ for (i = 0; i < PRIV (gsd_sym_count); i++) -+ symbols[i] = PRIV (csymbols)[i]; -+ symbols[i] = NULL; -+ } -+ -+ return PRIV (gsd_sym_count); -+} -+ -+/* Read and convert relocations from ETIR. We do it once for all sections. */ -+ -+static bfd_boolean -+sw_64_vms_slurp_relocs (bfd *abfd) -+{ -+ int cur_psect = -1; -+ -+ vms_debug2 ((3, "sw_64_vms_slurp_relocs\n")); -+ -+ /* We slurp relocs only once, for all sections. */ -+ if (PRIV (reloc_done)) -+ return TRUE; -+ PRIV (reloc_done) = TRUE; -+ -+ if (sw_64_vms_canonicalize_symtab (abfd, NULL) < 0) -+ return FALSE; -+ -+ if (bfd_seek (abfd, 0, SEEK_SET) != 0) -+ return FALSE; -+ -+ while (1) -+ { -+ unsigned char *begin; -+ unsigned char *end; -+ unsigned char *ptr; -+ bfd_reloc_code_real_type reloc_code; -+ int type; -+ bfd_vma vaddr = 0; -+ -+ int length; -+ -+ bfd_vma cur_address; -+ int cur_psidx = -1; -+ unsigned char *cur_sym = NULL; -+ int prev_cmd = -1; -+ bfd_vma cur_addend = 0; -+ -+ /* Skip non-ETIR records. */ -+ type = _bfd_vms_get_object_record (abfd); -+ if (type == EOBJ__C_EEOM) -+ break; -+ if (type != EOBJ__C_ETIR) -+ continue; -+ -+ begin = PRIV (recrd.rec) + 4; -+ end = PRIV (recrd.rec) + PRIV (recrd.rec_size); -+ -+ for (ptr = begin; ptr < end; ptr += length) -+ { -+ int cmd; -+ -+ cmd = bfd_getl16 (ptr); -+ length = bfd_getl16 (ptr + 2); -+ -+ cur_address = vaddr; -+ -+ vms_debug2 ((4, "sw_64_vms_slurp_relocs: etir %s\n", -+ _bfd_vms_etir_name (cmd))); -+ -+ switch (cmd) -+ { -+ case ETIR__C_STA_GBL: /* SW_64_R_REFLONG und_section, step 1 */ -+ /* SW_64_R_REFQUAD und_section, step 1 */ -+ cur_sym = ptr + 4; -+ prev_cmd = cmd; -+ continue; -+ -+ case ETIR__C_STA_PQ: /* SW_64_R_REF{LONG|QUAD}, others part 1 */ -+ cur_psidx = bfd_getl32 (ptr + 4); -+ cur_addend = bfd_getl64 (ptr + 8); -+ prev_cmd = cmd; -+ continue; -+ -+ case ETIR__C_CTL_SETRB: -+ if (prev_cmd != ETIR__C_STA_PQ) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("unknown reloc %s + %s"), _bfd_vms_etir_name (prev_cmd), -+ _bfd_vms_etir_name (cmd)); -+ return FALSE; -+ } -+ cur_psect = cur_psidx; -+ vaddr = cur_addend; -+ cur_psidx = -1; -+ cur_addend = 0; -+ continue; -+ -+ case ETIR__C_STA_LW: /* SW_64_R_REFLONG abs_section, step 1 */ -+ /* SW_64_R_REFLONG und_section, step 2 */ -+ if (prev_cmd != -1) -+ { -+ if (prev_cmd != ETIR__C_STA_GBL) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("unknown reloc %s + %s"), _bfd_vms_etir_name (cmd), -+ _bfd_vms_etir_name (ETIR__C_STA_LW)); -+ return FALSE; -+ } -+ } -+ cur_addend = bfd_getl32 (ptr + 4); -+ prev_cmd = cmd; -+ continue; -+ -+ case ETIR__C_STA_QW: /* SW_64_R_REFQUAD abs_section, step 1 */ -+ /* SW_64_R_REFQUAD und_section, step 2 */ -+ if (prev_cmd != -1 && prev_cmd != ETIR__C_STA_GBL) -+ { -+ _bfd_error_handler -+ /* xgettext:c-format */ -+ (_("unknown reloc %s + %s"), _bfd_vms_etir_name (cmd), -+ _bfd_vms_etir_name (ETIR__C_STA_QW)); -+ return FALSE; -+ } -+ cur_addend = bfd_getl64 (ptr + 4); -+ prev_cmd = cmd; -+ continue; -+ -+ case ETIR__C_STO_LW: /* SW_64_R_REFLONG und_section, step 4 */ -+ /* SW_64_R_REFLONG abs_section, step 2 */ -+ /* SW_64_R_REFLONG others, step 2 */ -+ if (prev_cmd != ETIR__C_OPR_ADD -+ && prev_cmd != ETIR__C_STA_LW -+ && prev_cmd != ETIR__C_STA_PQ) -+ { -+ /* xgettext:c-format */ -+ _bfd_error_handler (_("unknown reloc %s + %s"), -+ _bfd_vms_etir_name (prev_cmd), -+ _bfd_vms_etir_name (ETIR__C_STO_LW)); -+ return FALSE; -+ } -+ reloc_code = BFD_RELOC_32; -+ break; -+ -+ case ETIR__C_STO_QW: /* SW_64_R_REFQUAD und_section, step 4 */ -+ /* SW_64_R_REFQUAD abs_section, step 2 */ -+ if (prev_cmd != ETIR__C_OPR_ADD && prev_cmd != ETIR__C_STA_QW) -+ { -+ /* xgettext:c-format */ -+ _bfd_error_handler (_("unknown reloc %s + %s"), -+ _bfd_vms_etir_name (prev_cmd), -+ _bfd_vms_etir_name (ETIR__C_STO_QW)); -+ return FALSE; -+ } -+ reloc_code = BFD_RELOC_64; -+ break; -+ -+ case ETIR__C_STO_OFF: /* SW_64_R_REFQUAD others, step 2 */ -+ if (prev_cmd != ETIR__C_STA_PQ) -+ { -+ /* xgettext:c-format */ -+ _bfd_error_handler (_("unknown reloc %s + %s"), -+ _bfd_vms_etir_name (prev_cmd), -+ _bfd_vms_etir_name (ETIR__C_STO_OFF)); -+ return FALSE; -+ } -+ reloc_code = BFD_RELOC_64; -+ break; -+ -+ case ETIR__C_OPR_ADD: /* SW_64_R_REFLONG und_section, step 3 */ -+ /* SW_64_R_REFQUAD und_section, step 3 */ -+ if (prev_cmd != ETIR__C_STA_LW && prev_cmd != ETIR__C_STA_QW) -+ { -+ /* xgettext:c-format */ -+ _bfd_error_handler (_("unknown reloc %s + %s"), -+ _bfd_vms_etir_name (prev_cmd), -+ _bfd_vms_etir_name (ETIR__C_OPR_ADD)); -+ return FALSE; -+ } -+ prev_cmd = ETIR__C_OPR_ADD; -+ continue; -+ -+ case ETIR__C_STO_CA: /* SW_64_R_CODEADDR */ -+ reloc_code = BFD_RELOC_SW_64_CODEADDR; -+ cur_sym = ptr + 4; -+ break; -+ -+ case ETIR__C_STO_GBL: /* SW_64_R_REFQUAD und_section */ -+ reloc_code = BFD_RELOC_64; -+ cur_sym = ptr + 4; -+ break; -+ -+ case ETIR__C_STO_GBL_LW: /* SW_64_R_REFLONG und_section */ -+ reloc_code = BFD_RELOC_32; -+ cur_sym = ptr + 4; -+ break; -+ -+ case ETIR__C_STC_LP_PSB: /* SW_64_R_LINKAGE */ -+ reloc_code = BFD_RELOC_SW_64_LINKAGE; -+ cur_sym = ptr + 8; -+ break; -+ -+ case ETIR__C_STC_NOP_GBL: /* SW_64_R_NOP */ -+ reloc_code = BFD_RELOC_SW_64_NOP; -+ goto call_reloc; -+ -+ case ETIR__C_STC_BSR_GBL: /* SW_64_R_BSR */ -+ reloc_code = BFD_RELOC_SW_64_BSR; -+ goto call_reloc; -+ -+ case ETIR__C_STC_LDA_GBL: /* SW_64_R_LDA */ -+ reloc_code = BFD_RELOC_SW_64_LDA; -+ goto call_reloc; -+ -+ case ETIR__C_STC_BOH_GBL: /* SW_64_R_BOH */ -+ reloc_code = BFD_RELOC_SW_64_BOH; -+ goto call_reloc; -+ -+ call_reloc: -+ cur_sym = ptr + 4 + 32; -+ cur_address = bfd_getl64 (ptr + 4 + 8); -+ cur_addend = bfd_getl64 (ptr + 4 + 24); -+ break; -+ -+ case ETIR__C_STO_IMM: -+ vaddr += bfd_getl32 (ptr + 4); -+ continue; -+ -+ default: -+ _bfd_error_handler (_("unknown reloc %s"), -+ _bfd_vms_etir_name (cmd)); -+ return FALSE; -+ } -+ -+ { -+ asection *sec; -+ struct vms_section_data_struct *vms_sec; -+ arelent *reloc; -+ bfd_size_type size; -+ -+ /* Get section to which the relocation applies. */ -+ if (cur_psect < 0 || cur_psect > (int)PRIV (section_count)) -+ { -+ _bfd_error_handler (_("invalid section index in ETIR")); -+ return FALSE; -+ } -+ -+ if (PRIV (sections) == NULL) -+ return FALSE; -+ sec = PRIV (sections)[cur_psect]; -+ if (sec == bfd_abs_section_ptr) -+ { -+ _bfd_error_handler (_("relocation for non-REL psect")); -+ return FALSE; -+ } -+ -+ vms_sec = vms_section_data (sec); -+ -+ /* Allocate a reloc entry. */ -+ if (sec->reloc_count >= vms_sec->reloc_max) -+ { -+ if (vms_sec->reloc_max == 0) -+ { -+ vms_sec->reloc_max = 64; -+ sec->relocation = bfd_zmalloc -+ (vms_sec->reloc_max * sizeof (arelent)); -+ } -+ else -+ { -+ vms_sec->reloc_max *= 2; -+ sec->relocation = bfd_realloc -+ (sec->relocation, vms_sec->reloc_max * sizeof (arelent)); -+ } -+ } -+ reloc = &sec->relocation[sec->reloc_count]; -+ sec->reloc_count++; -+ -+ reloc->howto = bfd_reloc_type_lookup (abfd, reloc_code); -+ -+ if (cur_sym != NULL) -+ { -+ unsigned int j; -+ unsigned int symlen = *cur_sym; -+ asymbol **sym; -+ -+ /* Linear search. */ -+ symlen = *cur_sym; -+ cur_sym++; -+ sym = NULL; -+ -+ for (j = 0; j < PRIV (gsd_sym_count); j++) -+ if (PRIV (syms)[j]->namelen == symlen -+ && memcmp (PRIV (syms)[j]->name, cur_sym, symlen) == 0) -+ { -+ sym = &PRIV (csymbols)[j]; -+ break; -+ } -+ if (sym == NULL) -+ { -+ _bfd_error_handler (_("unknown symbol in command %s"), -+ _bfd_vms_etir_name (cmd)); -+ reloc->sym_ptr_ptr = NULL; -+ } -+ else -+ reloc->sym_ptr_ptr = sym; -+ } -+ else if (cur_psidx >= 0) -+ { -+ if (PRIV (sections) == NULL || cur_psidx >= (int) PRIV (section_count)) -+ return FALSE; -+ reloc->sym_ptr_ptr = -+ PRIV (sections)[cur_psidx]->symbol_ptr_ptr; -+ } -+ else -+ reloc->sym_ptr_ptr = NULL; -+ -+ reloc->address = cur_address; -+ reloc->addend = cur_addend; -+ -+ if (reloc_code == SW_64_R_LINKAGE) -+ size = 16; -+ else -+ size = bfd_get_reloc_size (reloc->howto); -+ vaddr += size; -+ } -+ -+ cur_addend = 0; -+ prev_cmd = -1; -+ cur_sym = NULL; -+ cur_psidx = -1; -+ } -+ } -+ vms_debug2 ((3, "sw_64_vms_slurp_relocs: result = TRUE\n")); -+ -+ return TRUE; -+} -+ -+/* Return the number of bytes required to store the relocation -+ information associated with the given section. */ -+ -+static long -+sw_64_vms_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *section) -+{ -+ sw_64_vms_slurp_relocs (abfd); -+ -+ return (section->reloc_count + 1L) * sizeof (arelent *); -+ //return (section->reloc_count + 1) * sizeof (arelent *); -+} -+ -+/* Convert relocations from VMS (external) form into BFD internal -+ form. Return the number of relocations. */ -+ -+static long -+sw_64_vms_canonicalize_reloc (bfd *abfd, asection *section, arelent **relptr, -+ asymbol **symbols ATTRIBUTE_UNUSED) -+{ -+ arelent *tblptr; -+ int count; -+ -+ if (!sw_64_vms_slurp_relocs (abfd)) -+ return -1; -+ -+ count = section->reloc_count; -+ tblptr = section->relocation; -+ -+ while (count--) -+ *relptr++ = tblptr++; -+ -+ *relptr = (arelent *) NULL; -+ return section->reloc_count; -+} -+ -+/* Install a new set of internal relocs. */ -+ -+#define sw_64_vms_set_reloc _bfd_generic_set_reloc -+ -+ -+/* This is just copied from ecoff-sw_64, needs to be fixed probably. */ -+ -+/* How to process the various reloc types. */ -+ -+static bfd_reloc_status_type -+reloc_nil (bfd * abfd ATTRIBUTE_UNUSED, -+ arelent *reloc ATTRIBUTE_UNUSED, -+ asymbol *sym ATTRIBUTE_UNUSED, -+ void * data ATTRIBUTE_UNUSED, -+ asection *sec ATTRIBUTE_UNUSED, -+ bfd *output_bfd ATTRIBUTE_UNUSED, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+#if VMS_DEBUG -+ vms_debug (1, "reloc_nil (abfd %p, output_bfd %p)\n", abfd, output_bfd); -+ vms_debug (2, "In section %s, symbol %s\n", -+ sec->name, sym->name); -+ vms_debug (2, "reloc sym %s, addr %08lx, addend %08lx, reloc is a %s\n", -+ reloc->sym_ptr_ptr[0]->name, -+ (unsigned long)reloc->address, -+ (unsigned long)reloc->addend, reloc->howto->name); -+ vms_debug (2, "data at %p\n", data); -+ /* _bfd_hexdump (2, data, bfd_get_reloc_size (reloc->howto), 0); */ -+#endif -+ -+ 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 sw_64_howto_table[] = -+{ -+ HOWTO (SW_64_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, /* Source mask */ -+ 0, /* Dest mask. */ -+ TRUE), /* PC rel offset. */ -+ -+ /* A 64 bit reference to a symbol. */ -+ HOWTO (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "REFQUAD", /* Name. */ -+ TRUE, /* Partial_inplace. */ -+ MINUS_ONE, /* Source mask. */ -+ MINUS_ONE, /* Dest mask. */ -+ FALSE), /* PC rel 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 (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "BRADDR", /* Name. */ -+ TRUE, /* Partial_inplace. */ -+ 0x1fffff, /* Source mask. */ -+ 0x1fffff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* A hint for a jump to a register. */ -+ HOWTO (SW_64_R_HINT, /* Type. */ -+ 2, /* Rightshift. */ -+ 1, /* Size (0 = byte, 1 = short, 2 = long). */ -+ 14, /* Bitsize. */ -+ TRUE, /* PC relative. */ -+ 0, /* Bitpos. */ -+ complain_overflow_dont,/* Complain_on_overflow. */ -+ reloc_nil, /* Special_function. */ -+ "HINT", /* Name. */ -+ TRUE, /* Partial_inplace. */ -+ 0x3fff, /* Source mask. */ -+ 0x3fff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* 16 bit PC relative offset. */ -+ HOWTO (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "SREL16", /* Name. */ -+ TRUE, /* Partial_inplace. */ -+ 0xffff, /* Source mask. */ -+ 0xffff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* 32 bit PC relative offset. */ -+ HOWTO (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "SREL32", /* Name. */ -+ TRUE, /* Partial_inplace. */ -+ 0xffffffff, /* Source mask. */ -+ 0xffffffff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* A 64 bit PC relative offset. */ -+ HOWTO (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "SREL64", /* Name. */ -+ TRUE, /* Partial_inplace. */ -+ MINUS_ONE, /* Source mask. */ -+ MINUS_ONE, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* Push a value on the reloc evaluation stack. */ -+ HOWTO (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "OP_PUSH", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0, /* Source mask. */ -+ 0, /* Dest mask. */ -+ FALSE), /* PC rel 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 (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "OP_STORE", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0, /* Source mask. */ -+ MINUS_ONE, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* Subtract the reloc address from the value on the top of the -+ relocation stack. */ -+ HOWTO (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "OP_PSUB", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0, /* Source mask. */ -+ 0, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* Shift the value on the top of the relocation stack right by the -+ given value. */ -+ HOWTO (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "OP_PRSHIFT", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0, /* Source mask. */ -+ 0, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* Hack. Linkage is done by linker. */ -+ HOWTO (SW_64_R_LINKAGE, /* Type. */ -+ 0, /* Rightshift. */ -+ 0, /* Size (0 = byte, 1 = short, 2 = long). */ -+ 0, /* Bitsize. */ -+ FALSE, /* PC relative. */ -+ 0, /* Bitpos. */ -+ complain_overflow_dont,/* Complain_on_overflow. */ -+ reloc_nil, /* Special_function. */ -+ "LINKAGE", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0, /* Source mask. */ -+ 0, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* A 32 bit reference to a symbol. */ -+ HOWTO (SW_64_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. */ -+ reloc_nil, /* Special_function. */ -+ "REFLONG", /* Name. */ -+ TRUE, /* Partial_inplace. */ -+ 0xffffffff, /* Source mask. */ -+ 0xffffffff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ /* A 64 bit reference to a procedure, written as 32 bit value. */ -+ HOWTO (SW_64_R_CODEADDR, /* Type. */ -+ 0, /* Rightshift. */ -+ 4, /* Size (0 = byte, 1 = short, 2 = long). */ -+ 64, /* Bitsize. */ -+ FALSE, /* PC relative. */ -+ 0, /* Bitpos. */ -+ complain_overflow_signed,/* Complain_on_overflow. */ -+ reloc_nil, /* Special_function. */ -+ "CODEADDR", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0xffffffff, /* Source mask. */ -+ 0xffffffff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ HOWTO (SW_64_R_NOP, /* Type. */ -+ 0, /* Rightshift. */ -+ 3, /* Size (0 = byte, 1 = short, 2 = long). */ -+ 0, /* Bitsize. */ -+ /* The following value must match that of SW_64_R_BSR/SW_64_R_BOH -+ because the calculations for the 3 relocations are the same. -+ See B.4.5.2 of the OpenVMS Linker Utility Manual. */ -+ TRUE, /* PC relative. */ -+ 0, /* Bitpos. */ -+ complain_overflow_dont,/* Complain_on_overflow. */ -+ reloc_nil, /* Special_function. */ -+ "NOP", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0xffffffff, /* Source mask. */ -+ 0xffffffff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ HOWTO (SW_64_R_BSR, /* Type. */ -+ 0, /* Rightshift. */ -+ 3, /* Size (0 = byte, 1 = short, 2 = long). */ -+ 0, /* Bitsize. */ -+ TRUE, /* PC relative. */ -+ 0, /* Bitpos. */ -+ complain_overflow_dont,/* Complain_on_overflow. */ -+ reloc_nil, /* Special_function. */ -+ "BSR", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0xffffffff, /* Source mask. */ -+ 0xffffffff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ HOWTO (SW_64_R_LDA, /* Type. */ -+ 0, /* Rightshift. */ -+ 3, /* Size (0 = byte, 1 = short, 2 = long). */ -+ 0, /* Bitsize. */ -+ FALSE, /* PC relative. */ -+ 0, /* Bitpos. */ -+ complain_overflow_dont,/* Complain_on_overflow. */ -+ reloc_nil, /* Special_function. */ -+ "LDA", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0xffffffff, /* Source mask. */ -+ 0xffffffff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+ -+ HOWTO (SW_64_R_BOH, /* Type. */ -+ 0, /* Rightshift. */ -+ 3, /* Size (0 = byte, 1 = short, 2 = long, 3 = nil). */ -+ 0, /* Bitsize. */ -+ TRUE, /* PC relative. */ -+ 0, /* Bitpos. */ -+ complain_overflow_dont,/* Complain_on_overflow. */ -+ reloc_nil, /* Special_function. */ -+ "BOH", /* Name. */ -+ FALSE, /* Partial_inplace. */ -+ 0xffffffff, /* Source mask. */ -+ 0xffffffff, /* Dest mask. */ -+ FALSE), /* PC rel offset. */ -+}; -+ -+/* Return a pointer to a howto structure which, when invoked, will perform -+ the relocation code on data from the architecture noted. */ -+ -+static reloc_howto_type * -+sw_64_vms_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, -+ bfd_reloc_code_real_type code) -+{ -+ int sw_64_type; -+ -+ vms_debug2 ((1, "vms_bfd_reloc_type_lookup (%p, %d)\t", abfd, code)); -+ -+ switch (code) -+ { -+ case BFD_RELOC_16: sw_64_type = SW_64_R_SREL16; break; -+ case BFD_RELOC_32: sw_64_type = SW_64_R_REFLONG; break; -+ case BFD_RELOC_64: sw_64_type = SW_64_R_REFQUAD; break; -+ case BFD_RELOC_CTOR: sw_64_type = SW_64_R_REFQUAD; break; -+ case BFD_RELOC_23_PCREL_S2: sw_64_type = SW_64_R_BRADDR; break; -+ case BFD_RELOC_SW_64_HINT: sw_64_type = SW_64_R_HINT; break; -+ case BFD_RELOC_16_PCREL: sw_64_type = SW_64_R_SREL16; break; -+ case BFD_RELOC_32_PCREL: sw_64_type = SW_64_R_SREL32; break; -+ case BFD_RELOC_64_PCREL: sw_64_type = SW_64_R_SREL64; break; -+ case BFD_RELOC_SW_64_LINKAGE: sw_64_type = SW_64_R_LINKAGE; break; -+ case BFD_RELOC_SW_64_CODEADDR: sw_64_type = SW_64_R_CODEADDR; break; -+ case BFD_RELOC_SW_64_NOP: sw_64_type = SW_64_R_NOP; break; -+ case BFD_RELOC_SW_64_BSR: sw_64_type = SW_64_R_BSR; break; -+ case BFD_RELOC_SW_64_LDA: sw_64_type = SW_64_R_LDA; break; -+ case BFD_RELOC_SW_64_BOH: sw_64_type = SW_64_R_BOH; break; -+ default: -+ _bfd_error_handler (_("reloc (%d) is *UNKNOWN*"), code); -+ return NULL; -+ } -+ vms_debug2 ((2, "reloc is %s\n", sw_64_howto_table[sw_64_type].name)); -+ return & sw_64_howto_table[sw_64_type]; -+} -+ -+static reloc_howto_type * -+sw_64_vms_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, -+ const char *r_name) -+{ -+ unsigned int i; -+ -+ for (i = 0; -+ i < sizeof (sw_64_howto_table) / sizeof (sw_64_howto_table[0]); -+ i++) -+ if (sw_64_howto_table[i].name != NULL -+ && strcasecmp (sw_64_howto_table[i].name, r_name) == 0) -+ return &sw_64_howto_table[i]; -+ -+ return NULL; -+} -+ -+static long -+sw_64_vms_get_synthetic_symtab (bfd *abfd, -+ long symcount ATTRIBUTE_UNUSED, -+ asymbol **usyms ATTRIBUTE_UNUSED, -+ long dynsymcount ATTRIBUTE_UNUSED, -+ asymbol **dynsyms ATTRIBUTE_UNUSED, -+ asymbol **ret) -+{ -+ asymbol *syms; -+ unsigned int i; -+ unsigned int n = 0; -+ -+ syms = (asymbol *) bfd_malloc (PRIV (norm_sym_count) * sizeof (asymbol)); -+ *ret = syms; -+ if (syms == NULL) -+ return -1; -+ -+ for (i = 0; i < PRIV (gsd_sym_count); i++) -+ { -+ struct vms_symbol_entry *e = PRIV (syms)[i]; -+ asymbol *sym; -+ flagword flags; -+ symvalue value; -+ asection *sec; -+ const char *name; -+ char *sname; -+ int l; -+ -+ name = e->name; -+ value = 0; -+ flags = BSF_LOCAL | BSF_SYNTHETIC; -+ sec = NULL; -+ -+ switch (e->typ) -+ { -+ case EGSD__C_SYM: -+ case EGSD__C_SYMG: -+ if ((e->flags & EGSY__V_DEF) && (e->flags & EGSY__V_NORM)) -+ { -+ value = e->code_value; -+ sec = e->code_section; -+ } -+ else -+ continue; -+ break; -+ -+ default: -+ continue; -+ } -+ -+ l = strlen (name); -+ sname = bfd_alloc (abfd, l + 5); -+ if (sname == NULL) -+ return FALSE; -+ memcpy (sname, name, l); -+ memcpy (sname + l, "..en", 5); -+ -+ sym = &syms[n++]; -+ sym->name = sname; -+ sym->section = sec; -+ sym->flags = flags; -+ sym->value = value; -+ sym->udata.p = NULL; -+ } -+ -+ return n; -+} -+ -+/* Private dump. */ -+ -+static const char * -+vms_time_to_str (unsigned char *buf) -+{ -+ time_t t = vms_rawtime_to_time_t (buf); -+ char *res = ctime (&t); -+ -+ if (!res) -+ res = "*invalid time*"; -+ else -+ res[24] = 0; -+ return res; -+} -+ -+static void -+evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len) -+{ -+ struct vms_emh_common *emh = (struct vms_emh_common *)rec; -+ unsigned int subtype; -+ int extra; -+ -+ subtype = (unsigned) bfd_getl16 (emh->subtyp); -+ -+ /* xgettext:c-format */ -+ fprintf (file, _(" EMH %u (len=%u): "), subtype, rec_len); -+ -+ /* PR 21618: Check for invalid lengths. */ -+ if (rec_len < sizeof (* emh)) -+ { -+ fprintf (file, _(" Error: The length is less than the length of an EMH record\n")); -+ return; -+ } -+ extra = rec_len - sizeof (struct vms_emh_common); -+ -+ switch (subtype) -+ { -+ case EMH__C_MHD: -+ { -+ struct vms_emh_mhd *mhd = (struct vms_emh_mhd *) rec; -+ const char * name; -+ const char * nextname; -+ const char * maxname; -+ -+ /* PR 21840: Check for invalid lengths. */ -+ if (rec_len < sizeof (* mhd)) -+ { -+ fprintf (file, _(" Error: The record length is less than the size of an EMH_MHD record\n")); -+ return; -+ } -+ fprintf (file, _("Module header\n")); -+ fprintf (file, _(" structure level: %u\n"), mhd->strlvl); -+ fprintf (file, _(" max record size: %u\n"), -+ (unsigned) bfd_getl32 (mhd->recsiz)); -+ name = (char *)(mhd + 1); -+ maxname = (char *) rec + rec_len; -+ if (name > maxname - 2) -+ { -+ fprintf (file, _(" Error: The module name is missing\n")); -+ return; -+ } -+ nextname = name + name[0] + 1; -+ if (nextname >= maxname) -+ { -+ fprintf (file, _(" Error: The module name is too long\n")); -+ return; -+ } -+ fprintf (file, _(" module name : %.*s\n"), name[0], name + 1); -+ name = nextname; -+ if (name > maxname - 2) -+ { -+ fprintf (file, _(" Error: The module version is missing\n")); -+ return; -+ } -+ nextname = name + name[0] + 1; -+ if (nextname >= maxname) -+ { -+ fprintf (file, _(" Error: The module version is too long\n")); -+ return; -+ } -+ fprintf (file, _(" module version : %.*s\n"), name[0], name + 1); -+ name = nextname; -+ if ((maxname - name) < 17 && maxname[-1] != 0) -+ fprintf (file, _(" Error: The compile date is truncated\n")); -+ else -+ fprintf (file, _(" compile date : %.17s\n"), name); -+ } -+ break; -+ -+ case EMH__C_LNM: -+ fprintf (file, _("Language Processor Name\n")); -+ fprintf (file, _(" language name: %.*s\n"), extra, (char *)(emh + 1)); -+ break; -+ -+ case EMH__C_SRC: -+ fprintf (file, _("Source Files Header\n")); -+ fprintf (file, _(" file: %.*s\n"), extra, (char *)(emh + 1)); -+ break; -+ -+ case EMH__C_TTL: -+ fprintf (file, _("Title Text Header\n")); -+ fprintf (file, _(" title: %.*s\n"), extra, (char *)(emh + 1)); -+ break; -+ -+ case EMH__C_CPR: -+ fprintf (file, _("Copyright Header\n")); -+ fprintf (file, _(" copyright: %.*s\n"), extra, (char *)(emh + 1)); -+ break; -+ -+ default: -+ fprintf (file, _("unhandled emh subtype %u\n"), subtype); -+ break; -+ } -+} -+ -+static void -+evax_bfd_print_eeom (FILE *file, unsigned char *rec, unsigned int rec_len) -+{ -+ struct vms_eeom *eeom = (struct vms_eeom *)rec; -+ -+ fprintf (file, _(" EEOM (len=%u):\n"), rec_len); -+ -+ /* PR 21618: Check for invalid lengths. */ -+ if (rec_len < sizeof (* eeom)) -+ { -+ fprintf (file, _(" Error: The length is less than the length of an EEOM record\n")); -+ return; -+ } -+ -+ fprintf (file, _(" number of cond linkage pairs: %u\n"), -+ (unsigned)bfd_getl32 (eeom->total_lps)); -+ fprintf (file, _(" completion code: %u\n"), -+ (unsigned)bfd_getl16 (eeom->comcod)); -+ if (rec_len > 10) -+ { -+ fprintf (file, _(" transfer addr flags: 0x%02x\n"), eeom->tfrflg); -+ fprintf (file, _(" transfer addr psect: %u\n"), -+ (unsigned)bfd_getl32 (eeom->psindx)); -+ fprintf (file, _(" transfer address : 0x%08x\n"), -+ (unsigned)bfd_getl32 (eeom->tfradr)); -+ } -+} -+ -+static void -+exav_bfd_print_egsy_flags (unsigned int flags, FILE *file) -+{ -+ if (flags & EGSY__V_WEAK) -+ fputs (_(" WEAK"), file); -+ if (flags & EGSY__V_DEF) -+ fputs (_(" DEF"), file); -+ if (flags & EGSY__V_UNI) -+ fputs (_(" UNI"), file); -+ if (flags & EGSY__V_REL) -+ fputs (_(" REL"), file); -+ if (flags & EGSY__V_COMM) -+ fputs (_(" COMM"), file); -+ if (flags & EGSY__V_VECEP) -+ fputs (_(" VECEP"), file); -+ if (flags & EGSY__V_NORM) -+ fputs (_(" NORM"), file); -+ if (flags & EGSY__V_QUAD_VAL) -+ fputs (_(" QVAL"), file); -+} -+ -+static void -+evax_bfd_print_egsd_flags (FILE *file, unsigned int flags) -+{ -+ if (flags & EGPS__V_PIC) -+ fputs (_(" PIC"), file); -+ if (flags & EGPS__V_LIB) -+ fputs (_(" LIB"), file); -+ if (flags & EGPS__V_OVR) -+ fputs (_(" OVR"), file); -+ if (flags & EGPS__V_REL) -+ fputs (_(" REL"), file); -+ if (flags & EGPS__V_GBL) -+ fputs (_(" GBL"), file); -+ if (flags & EGPS__V_SHR) -+ fputs (_(" SHR"), file); -+ if (flags & EGPS__V_EXE) -+ fputs (_(" EXE"), file); -+ if (flags & EGPS__V_RD) -+ fputs (_(" RD"), file); -+ if (flags & EGPS__V_WRT) -+ fputs (_(" WRT"), file); -+ if (flags & EGPS__V_VEC) -+ fputs (_(" VEC"), file); -+ if (flags & EGPS__V_NOMOD) -+ fputs (_(" NOMOD"), file); -+ if (flags & EGPS__V_COM) -+ fputs (_(" COM"), file); -+ if (flags & EGPS__V_ALLOC_64BIT) -+ fputs (_(" 64B"), file); -+} -+ -+static void -+evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len) -+{ -+ unsigned int off = sizeof (struct vms_egsd); -+ unsigned int n = 0; -+ //unsigned int n; -+ -+ fprintf (file, _(" EGSD (len=%u):\n"), rec_len); -+ if (rec_len < sizeof (struct vms_egsd) + sizeof (struct vms_egsd_entry)) -+ return; -+ -+ while (off <= rec_len - sizeof (struct vms_egsd_entry)) -+ //n = 0; -+ //for (off = sizeof (struct vms_egsd); off < rec_len; ) -+ { -+ struct vms_egsd_entry *e = (struct vms_egsd_entry *)(rec + off); -+ unsigned int type; -+ unsigned int len; -+ unsigned int rest; -+ -+ type = (unsigned)bfd_getl16 (e->gsdtyp); -+ len = (unsigned)bfd_getl16 (e->gsdsiz); -+ -+ /* xgettext:c-format */ -+ fprintf (file, _(" EGSD entry %2u (type: %u, len: %u): "), -+ n, type, len); -+ n++; -+ -+ if (len < sizeof (struct vms_egsd_entry) || len > rec_len - off) -+ //if (off + len > rec_len || off + len < off) -+ { -+ fprintf (file, _(" Erroneous length\n")); -+ //fprintf (file, _(" Error: length larger than remaining space in record\n")); -+ return; -+ } -+ -+ switch (type) -+ { -+ case EGSD__C_PSC: -+ /* -+ { -+ struct vms_egps *egps = (struct vms_egps *)e; -+ unsigned int flags = bfd_getl16 (egps->flags); -+ unsigned int l; -+ -+ fprintf (file, _("PSC - Program section definition\n")); -+ fprintf (file, _(" alignment : 2**%u\n"), egps->align); -+ fprintf (file, _(" flags : 0x%04x"), flags); -+ evax_bfd_print_egsd_flags (file, flags); -+ fputc ('\n', file); -+ l = bfd_getl32 (egps->alloc); -+ fprintf (file, _(" alloc (len): %u (0x%08x)\n"), l, l); -+ fprintf (file, _(" name : %.*s\n"), -+ egps->namlng, egps->name); -+ }*/ -+ if (len >= offsetof (struct vms_egps, name)) -+ { -+ struct vms_egps *egps = (struct vms_egps *) e; -+ unsigned int flags = bfd_getl16 (egps->flags); -+ unsigned int l; -+ -+ fprintf (file, _("PSC - Program section definition\n")); -+ fprintf (file, _(" alignment : 2**%u\n"), egps->align); -+ fprintf (file, _(" flags : 0x%04x"), flags); -+ evax_bfd_print_egsd_flags (file, flags); -+ fputc ('\n', file); -+ l = bfd_getl32 (egps->alloc); -+ fprintf (file, _(" alloc (len): %u (0x%08x)\n"), l, l); -+ rest = len - offsetof (struct vms_egps, name); -+ fprintf (file, _(" name : %.*s\n"), -+ egps->namlng > rest ? rest : egps->namlng, -+ egps->name); -+ } -+ break; -+ case EGSD__C_SPSC: -+ /*{ -+ struct vms_esgps *esgps = (struct vms_esgps *)e; -+ unsigned int flags = bfd_getl16 (esgps->flags); -+ unsigned int l; -+ -+ fprintf (file, _("SPSC - Shared Image Program section def\n")); -+ fprintf (file, _(" alignment : 2**%u\n"), esgps->align); -+ fprintf (file, _(" flags : 0x%04x"), flags); -+ evax_bfd_print_egsd_flags (file, flags); -+ fputc ('\n', file); -+ l = bfd_getl32 (esgps->alloc); -+ fprintf (file, _(" alloc (len) : %u (0x%08x)\n"), l, l); -+ fprintf (file, _(" image offset : 0x%08x\n"), -+ (unsigned int)bfd_getl32 (esgps->base)); -+ fprintf (file, _(" symvec offset : 0x%08x\n"), -+ (unsigned int)bfd_getl32 (esgps->value)); -+ fprintf (file, _(" name : %.*s\n"), -+ esgps->namlng, esgps->name); -+ }*/ -+ if (len >= offsetof (struct vms_esgps, name)) -+ { -+ struct vms_esgps *esgps = (struct vms_esgps *) e; -+ unsigned int flags = bfd_getl16 (esgps->flags); -+ unsigned int l; -+ -+ fprintf (file, _("SPSC - Shared Image Program section def\n")); -+ fprintf (file, _(" alignment : 2**%u\n"), esgps->align); -+ fprintf (file, _(" flags : 0x%04x"), flags); -+ evax_bfd_print_egsd_flags (file, flags); -+ fputc ('\n', file); -+ l = bfd_getl32 (esgps->alloc); -+ fprintf (file, _(" alloc (len) : %u (0x%08x)\n"), l, l); -+ fprintf (file, _(" image offset : 0x%08x\n"), -+ (unsigned int) bfd_getl32 (esgps->base)); -+ fprintf (file, _(" symvec offset : 0x%08x\n"), -+ (unsigned int) bfd_getl32 (esgps->value)); -+ rest = len - offsetof (struct vms_esgps, name); -+ fprintf (file, _(" name : %.*s\n"), -+ esgps->namlng > rest ? rest : esgps->namlng, -+ esgps->name); -+ } -+ break; -+ case EGSD__C_SYM: -+ if (len >= sizeof (struct vms_egsy)) -+ { -+ struct vms_egsy *egsy = (struct vms_egsy *) e; -+ unsigned int flags = bfd_getl16 (egsy->flags); -+ //{ -+ //struct vms_egsy *egsy = (struct vms_egsy *)e; -+ //unsigned int flags = bfd_getl16 (egsy->flags); -+ -+ if ((flags & EGSY__V_DEF) != 0 -+ && len >= offsetof (struct vms_esdf, name)) -+ { -+ struct vms_esdf *esdf = (struct vms_esdf *) e; -+ //if (flags & EGSY__V_DEF) -+ //{ -+ //struct vms_esdf *esdf = (struct vms_esdf *)e; -+ /* -+ fprintf (file, _("SYM - Global symbol definition\n")); -+ fprintf (file, _(" flags: 0x%04x"), flags); -+ exav_bfd_print_egsy_flags (flags, file); -+ fputc ('\n', file); -+ fprintf (file, _(" psect offset: 0x%08x\n"), -+ (unsigned)bfd_getl32 (esdf->value)); -+ if (flags & EGSY__V_NORM) -+ { -+ fprintf (file, _(" code address: 0x%08x\n"), -+ (unsigned)bfd_getl32 (esdf->code_address)); -+ fprintf (file, _(" psect index for entry point : %u\n"), -+ (unsigned)bfd_getl32 (esdf->ca_psindx)); -+ } -+ fprintf (file, _(" psect index : %u\n"), -+ (unsigned)bfd_getl32 (esdf->psindx)); -+ fprintf (file, _(" name : %.*s\n"), -+ esdf->namlng, esdf->name); -+ } -+ else -+ { -+ struct vms_esrf *esrf = (struct vms_esrf *)e;*/ -+ -+ fprintf (file, _("SYM - Global symbol definition\n")); -+ fprintf (file, _(" flags: 0x%04x"), flags); -+ exav_bfd_print_egsy_flags (flags, file); -+ fputc ('\n', file); -+ fprintf (file, _(" psect offset: 0x%08x\n"), -+ (unsigned) bfd_getl32 (esdf->value)); -+ if (flags & EGSY__V_NORM) -+ { -+ fprintf (file, _(" code address: 0x%08x\n"), -+ (unsigned) bfd_getl32 (esdf->code_address)); -+ fprintf (file, _(" psect index for entry point : %u\n"), -+ (unsigned) bfd_getl32 (esdf->ca_psindx)); -+ } -+ fprintf (file, _(" psect index : %u\n"), -+ (unsigned) bfd_getl32 (esdf->psindx)); -+ rest = len - offsetof (struct vms_esdf, name); -+ fprintf (file, _(" name : %.*s\n"), -+ esdf->namlng > rest ? rest : esdf->namlng, -+ esdf->name); -+ } -+ else if (len >= offsetof (struct vms_esrf, name)) -+ { -+ struct vms_esrf *esrf = (struct vms_esrf *)e; -+ -+ /*fprintf (file, _("SYM - Global symbol reference\n")); -+ fprintf (file, _(" name : %.*s\n"), -+ esrf->namlng, esrf->name); -+ } -+ }*/ -+ fprintf (file, _("SYM - Global symbol reference\n")); -+ rest = len - offsetof (struct vms_esrf, name); -+ fprintf (file, _(" name : %.*s\n"), -+ esrf->namlng > rest ? rest : esrf->namlng, -+ esrf->name); -+ } -+ } -+ break; -+ case EGSD__C_IDC: -+ /*{ -+ struct vms_eidc *eidc = (struct vms_eidc *)e; -+ unsigned int flags = bfd_getl32 (eidc->flags); -+ unsigned char *p; -+ -+ fprintf (file, _("IDC - Ident Consistency check\n")); -+ fprintf (file, _(" flags : 0x%08x"), flags); -+ if (flags & EIDC__V_BINIDENT) -+ fputs (" BINDENT", file); -+ fputc ('\n', file); -+ fprintf (file, _(" id match : %x\n"), -+ (flags >> EIDC__V_IDMATCH_SH) & EIDC__V_IDMATCH_MASK); -+ fprintf (file, _(" error severity: %x\n"), -+ (flags >> EIDC__V_ERRSEV_SH) & EIDC__V_ERRSEV_MASK); -+ p = eidc->name; -+ fprintf (file, _(" entity name : %.*s\n"), p[0], p + 1); -+ p += 1 + p[0]; -+ fprintf (file, _(" object name : %.*s\n"), p[0], p + 1); -+ p += 1 + p[0]; -+ if (flags & EIDC__V_BINIDENT) -+ fprintf (file, _(" binary ident : 0x%08x\n"), -+ (unsigned)bfd_getl32 (p + 1)); -+ else -+ fprintf (file, _(" ascii ident : %.*s\n"), p[0], p + 1); -+ }*/ -+ if (len >= sizeof (struct vms_eidc)) -+ { -+ struct vms_eidc *eidc = (struct vms_eidc *) e; -+ unsigned int flags = bfd_getl32 (eidc->flags); -+ unsigned char *p; -+ -+ fprintf (file, _("IDC - Ident Consistency check\n")); -+ fprintf (file, _(" flags : 0x%08x"), flags); -+ if (flags & EIDC__V_BINIDENT) -+ fputs (" BINDENT", file); -+ fputc ('\n', file); -+ fprintf (file, _(" id match : %x\n"), -+ (flags >> EIDC__V_IDMATCH_SH) & EIDC__V_IDMATCH_MASK); -+ fprintf (file, _(" error severity: %x\n"), -+ (flags >> EIDC__V_ERRSEV_SH) & EIDC__V_ERRSEV_MASK); -+ p = eidc->name; -+ rest = len - (p - (unsigned char *) e); -+ fprintf (file, _(" entity name : %.*s\n"), -+ p[0] > rest - 1 ? rest - 1 : p[0], p + 1); -+ if (rest > 1u + p[0]) -+ { -+ rest -= 1 + p[0]; -+ p += 1 + p[0]; -+ fprintf (file, _(" object name : %.*s\n"), -+ p[0] > rest - 1 ? rest - 1 : p[0], p + 1); -+ if (rest > 1u + p[0]) -+ { -+ rest -= 1 + p[0]; -+ p += 1 + p[0]; -+ if (flags & EIDC__V_BINIDENT) -+ { -+ if (rest >= 4) -+ fprintf (file, _(" binary ident : 0x%08x\n"), -+ (unsigned) bfd_getl32 (p)); -+ } -+ else -+ fprintf (file, _(" ascii ident : %.*s\n"), -+ p[0] > rest - 1 ? rest - 1 : p[0], p + 1); -+ } -+ } -+ } -+ break; -+ case EGSD__C_SYMG: -+ /*{ -+ struct vms_egst *egst = (struct vms_egst *)e; -+ unsigned int flags = bfd_getl16 (egst->header.flags);*/ -+ if (len >= offsetof (struct vms_egst, name)) -+ { -+ struct vms_egst *egst = (struct vms_egst *) e; -+ unsigned int flags = bfd_getl16 (egst->header.flags); -+ -+ /*fprintf (file, _("SYMG - Universal symbol definition\n")); -+ fprintf (file, _(" flags: 0x%04x"), flags); -+ exav_bfd_print_egsy_flags (flags, file); -+ fputc ('\n', file); -+ fprintf (file, _(" symbol vector offset: 0x%08x\n"), -+ (unsigned)bfd_getl32 (egst->value)); -+ fprintf (file, _(" entry point: 0x%08x\n"), -+ (unsigned)bfd_getl32 (egst->lp_1)); -+ fprintf (file, _(" proc descr : 0x%08x\n"), -+ (unsigned)bfd_getl32 (egst->lp_2)); -+ fprintf (file, _(" psect index: %u\n"), -+ (unsigned)bfd_getl32 (egst->psindx)); -+ fprintf (file, _(" name : %.*s\n"), -+ egst->namlng, egst->name); -+ }*/ -+ fprintf (file, _("SYMG - Universal symbol definition\n")); -+ fprintf (file, _(" flags: 0x%04x"), flags); -+ exav_bfd_print_egsy_flags (flags, file); -+ fputc ('\n', file); -+ fprintf (file, _(" symbol vector offset: 0x%08x\n"), -+ (unsigned) bfd_getl32 (egst->value)); -+ fprintf (file, _(" entry point: 0x%08x\n"), -+ (unsigned) bfd_getl32 (egst->lp_1)); -+ fprintf (file, _(" proc descr : 0x%08x\n"), -+ (unsigned) bfd_getl32 (egst->lp_2)); -+ fprintf (file, _(" psect index: %u\n"), -+ (unsigned) bfd_getl32 (egst->psindx)); -+ rest = len - offsetof (struct vms_egst, name); -+ fprintf (file, _(" name : %.*s\n"), -+ egst->namlng > rest ? rest : egst->namlng, -+ egst->name); -+ } -+ break; -+ case EGSD__C_SYMV: -+ /*{ -+ struct vms_esdfv *esdfv = (struct vms_esdfv *)e; -+ unsigned int flags = bfd_getl16 (esdfv->flags);*/ -+ if (len >= offsetof (struct vms_esdfv, name)) -+ { -+ struct vms_esdfv *esdfv = (struct vms_esdfv *) e; -+ unsigned int flags = bfd_getl16 (esdfv->flags); -+ -+ /*fprintf (file, _("SYMV - Vectored symbol definition\n")); -+ fprintf (file, _(" flags: 0x%04x"), flags); -+ exav_bfd_print_egsy_flags (flags, file); -+ fputc ('\n', file); -+ fprintf (file, _(" vector : 0x%08x\n"), -+ (unsigned)bfd_getl32 (esdfv->vector)); -+ fprintf (file, _(" psect offset: %u\n"), -+ (unsigned)bfd_getl32 (esdfv->value)); -+ fprintf (file, _(" psect index : %u\n"), -+ (unsigned)bfd_getl32 (esdfv->psindx)); -+ fprintf (file, _(" name : %.*s\n"), -+ esdfv->namlng, esdfv->name); -+ }*/ -+ fprintf (file, _("SYMV - Vectored symbol definition\n")); -+ fprintf (file, _(" flags: 0x%04x"), flags); -+ exav_bfd_print_egsy_flags (flags, file); -+ fputc ('\n', file); -+ fprintf (file, _(" vector : 0x%08x\n"), -+ (unsigned) bfd_getl32 (esdfv->vector)); -+ fprintf (file, _(" psect offset: %u\n"), -+ (unsigned) bfd_getl32 (esdfv->value)); -+ fprintf (file, _(" psect index : %u\n"), -+ (unsigned) bfd_getl32 (esdfv->psindx)); -+ rest = len - offsetof (struct vms_esdfv, name); -+ fprintf (file, _(" name : %.*s\n"), -+ esdfv->namlng > rest ? rest : esdfv->namlng, -+ esdfv->name); -+ } -+ break; -+ case EGSD__C_SYMM: -+ /*{ -+ struct vms_esdfm *esdfm = (struct vms_esdfm *)e; -+ unsigned int flags = bfd_getl16 (esdfm->flags);*/ -+ if (len >= offsetof (struct vms_esdfm, name)) -+ { -+ struct vms_esdfm *esdfm = (struct vms_esdfm *) e; -+ unsigned int flags = bfd_getl16 (esdfm->flags); -+ -+ /*fprintf (file, _("SYMM - Global symbol definition with version\n")); -+ fprintf (file, _(" flags: 0x%04x"), flags); -+ exav_bfd_print_egsy_flags (flags, file); -+ fputc ('\n', file); -+ fprintf (file, _(" version mask: 0x%08x\n"), -+ (unsigned)bfd_getl32 (esdfm->version_mask)); -+ fprintf (file, _(" psect offset: %u\n"), -+ (unsigned)bfd_getl32 (esdfm->value)); -+ fprintf (file, _(" psect index : %u\n"), -+ (unsigned)bfd_getl32 (esdfm->psindx)); -+ fprintf (file, _(" name : %.*s\n"), -+ esdfm->namlng, esdfm->name); -+ }*/ -+ fprintf (file, -+ _("SYMM - Global symbol definition with version\n")); -+ fprintf (file, _(" flags: 0x%04x"), flags); -+ exav_bfd_print_egsy_flags (flags, file); -+ fputc ('\n', file); -+ fprintf (file, _(" version mask: 0x%08x\n"), -+ (unsigned)bfd_getl32 (esdfm->version_mask)); -+ fprintf (file, _(" psect offset: %u\n"), -+ (unsigned)bfd_getl32 (esdfm->value)); -+ fprintf (file, _(" psect index : %u\n"), -+ (unsigned)bfd_getl32 (esdfm->psindx)); -+ rest = len - offsetof (struct vms_esdfm, name); -+ fprintf (file, _(" name : %.*s\n"), -+ esdfm->namlng > rest ? rest : esdfm->namlng, -+ esdfm->name); -+ } -+ break; -+ default: -+ fprintf (file, _("unhandled egsd entry type %u\n"), type); -+ break; -+ } -+ off += len; -+ } -+} -+ -+static void -+evax_bfd_print_hex (FILE *file, const char *pfx, -+ const unsigned char *buf, unsigned int len) -+{ -+ unsigned int i; -+ unsigned int n; -+ -+ n = 0; -+ for (i = 0; i < len; i++) -+ { -+ if (n == 0) -+ fputs (pfx, file); -+ fprintf (file, " %02x", buf[i]); -+ n++; -+ if (n == 16) -+ { -+ n = 0; -+ fputc ('\n', file); -+ } -+ } -+ if (n != 0) -+ fputc ('\n', file); -+} -+ -+static void -+evax_bfd_print_etir_stc_ir (FILE *file, const unsigned char *buf, -+ unsigned int len, int is_ps) -+//evax_bfd_print_etir_stc_ir (FILE *file, const unsigned char *buf, int is_ps) -+{ -+ if (is_ps ? len < 44 : len < 33) -+ return; -+ -+ /* xgettext:c-format */ -+ fprintf (file, _(" linkage index: %u, replacement insn: 0x%08x\n"), -+ (unsigned)bfd_getl32 (buf), -+ (unsigned)bfd_getl32 (buf + 16)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" psect idx 1: %u, offset 1: 0x%08x %08x\n"), -+ (unsigned)bfd_getl32 (buf + 4), -+ (unsigned)bfd_getl32 (buf + 12), -+ (unsigned)bfd_getl32 (buf + 8)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" psect idx 2: %u, offset 2: 0x%08x %08x\n"), -+ (unsigned)bfd_getl32 (buf + 20), -+ (unsigned)bfd_getl32 (buf + 28), -+ (unsigned)bfd_getl32 (buf + 24)); -+ if (is_ps) -+ /* xgettext:c-format */ -+ fprintf (file, _(" psect idx 3: %u, offset 3: 0x%08x %08x\n"), -+ (unsigned)bfd_getl32 (buf + 32), -+ (unsigned)bfd_getl32 (buf + 40), -+ (unsigned)bfd_getl32 (buf + 36)); -+ else -+ //fprintf (file, _(" global name: %.*s\n"), buf[32], buf + 33); -+ fprintf (file, _(" global name: %.*s\n"), -+ buf[32] > len - 33 ? len - 33 : buf[32], -+ buf + 33); -+} -+ -+static void -+evax_bfd_print_etir (FILE *file, const char *name, -+ unsigned char *rec, unsigned int rec_len) -+{ -+ unsigned int off = sizeof (struct vms_eobjrec); -+ //unsigned int off = sizeof (struct vms_egsd); -+ //unsigned int sec_len = 0; -+ -+ /* xgettext:c-format */ -+ fprintf (file, _(" %s (len=%u):\n"), name, (unsigned) rec_len); -+ if (rec_len < sizeof (struct vms_eobjrec) + sizeof (struct vms_etir)) -+ return; -+ //fprintf (file, _(" %s (len=%u+%u):\n"), name, -+// (unsigned)(rec_len - sizeof (struct vms_eobjrec)), -+// (unsigned)sizeof (struct vms_eobjrec)); -+ -+ while (off <= rec_len - sizeof (struct vms_etir)) -+ //for (off = sizeof (struct vms_eobjrec); off < rec_len; ) -+ { -+ struct vms_etir *etir = (struct vms_etir *)(rec + off); -+ unsigned char *buf; -+ unsigned int type; -+ unsigned int size; -+ unsigned int rest; -+ -+ type = bfd_getl16 (etir->rectyp); -+ size = bfd_getl16 (etir->size); -+ buf = rec + off + sizeof (struct vms_etir); -+ -+ if (size < sizeof (struct vms_etir) || size > rec_len - off) -+ //if (off + size > rec_len || off + size < off) -+ { -+ fprintf (file, _(" Erroneous length\n")); -+ //fprintf (file, _(" Error: length larger than remaining space in record\n")); -+ return; -+ } -+ -+ /* xgettext:c-format */ -+ fprintf (file, _(" (type: %3u, size: %3u): "), type, size); -+ rest = size - sizeof (struct vms_etir); -+ //fprintf (file, _(" (type: %3u, size: 4+%3u): "), type, size - 4); -+ switch (type) -+ { -+ case ETIR__C_STA_GBL: -+ if (rest >= 1) -+ fprintf (file, _("STA_GBL (stack global) %.*s\n"), -+ buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1); -+ //fprintf (file, _("STA_GBL (stack global) %.*s\n"), -+ // buf[0], buf + 1); -+ break; -+ case ETIR__C_STA_LW: -+ fprintf (file, _("STA_LW (stack longword)")); -+ if (rest >= 4) -+ fprintf (file, " 0x%08x\n", -+ (unsigned) bfd_getl32 (buf)); -+ //fprintf (file, _("STA_LW (stack longword) 0x%08x\n"), -+ // (unsigned)bfd_getl32 (buf)); -+ break; -+ case ETIR__C_STA_QW: -+ fprintf (file, _("STA_QW (stack quadword)")); -+ if (rest >= 8) -+ fprintf (file, " 0x%08x %08x\n", -+ (unsigned) bfd_getl32 (buf + 4), -+ (unsigned) bfd_getl32 (buf + 0)); -+ //fprintf (file, _("STA_QW (stack quadword) 0x%08x %08x\n"), -+ // (unsigned)bfd_getl32 (buf + 4), -+ // (unsigned)bfd_getl32 (buf + 0)); -+ break; -+ case ETIR__C_STA_PQ: -+ fprintf (file, _("STA_PQ (stack psect base + offset)\n")); -+ if (rest >= 12) -+ /* xgettext:c-format */ -+ fprintf (file, _(" psect: %u, offset: 0x%08x %08x\n"), -+ (unsigned) bfd_getl32 (buf + 0), -+ (unsigned) bfd_getl32 (buf + 8), -+ (unsigned) bfd_getl32 (buf + 4)); -+ /*fprintf (file, _(" psect: %u, offset: 0x%08x %08x\n"), -+ (unsigned)bfd_getl32 (buf + 0), -+ (unsigned)bfd_getl32 (buf + 8), -+ (unsigned)bfd_getl32 (buf + 4));*/ -+ break; -+ case ETIR__C_STA_LI: -+ fprintf (file, _("STA_LI (stack literal)\n")); -+ break; -+ case ETIR__C_STA_MOD: -+ fprintf (file, _("STA_MOD (stack module)\n")); -+ break; -+ case ETIR__C_STA_CKARG: -+ fprintf (file, _("STA_CKARG (compare procedure argument)\n")); -+ break; -+ -+ case ETIR__C_STO_B: -+ fprintf (file, _("STO_B (store byte)\n")); -+ break; -+ case ETIR__C_STO_W: -+ fprintf (file, _("STO_W (store word)\n")); -+ break; -+ case ETIR__C_STO_LW: -+ fprintf (file, _("STO_LW (store longword)\n")); -+ break; -+ case ETIR__C_STO_QW: -+ fprintf (file, _("STO_QW (store quadword)\n")); -+ break; -+ case ETIR__C_STO_IMMR: -+ /*{ -+ unsigned int len = bfd_getl32 (buf); -+ fprintf (file, -+ _("STO_IMMR (store immediate repeat) %u bytes\n"), -+ len); -+ evax_bfd_print_hex (file, " ", buf + 4, len); -+ sec_len += len; -+ }*/ -+ if (rest >= 4) -+ { -+ unsigned int rpt = bfd_getl32 (buf); -+ fprintf (file, -+ _("STO_IMMR (store immediate repeat) %u bytes\n"), -+ rpt); -+ if (rpt > rest - 4) -+ rpt = rest - 4; -+ evax_bfd_print_hex (file, " ", buf + 4, rpt); -+ } -+ break; -+ case ETIR__C_STO_GBL: -+ /*fprintf (file, _("STO_GBL (store global) %.*s\n"), -+ buf[0], buf + 1);*/ -+ if (rest >= 1) -+ fprintf (file, _("STO_GBL (store global) %.*s\n"), -+ buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1); -+ break; -+ case ETIR__C_STO_CA: -+ /*fprintf (file, _("STO_CA (store code address) %.*s\n"), -+ buf[0], buf + 1);*/ -+ if (rest >= 1) -+ fprintf (file, _("STO_CA (store code address) %.*s\n"), -+ buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1); -+ break; -+ case ETIR__C_STO_RB: -+ fprintf (file, _("STO_RB (store relative branch)\n")); -+ break; -+ case ETIR__C_STO_AB: -+ fprintf (file, _("STO_AB (store absolute branch)\n")); -+ break; -+ case ETIR__C_STO_OFF: -+ fprintf (file, _("STO_OFF (store offset to psect)\n")); -+ break; -+ case ETIR__C_STO_IMM: -+ /*{ -+ unsigned int len = bfd_getl32 (buf); -+ fprintf (file, -+ _("STO_IMM (store immediate) %u bytes\n"), -+ len); -+ evax_bfd_print_hex (file, " ", buf + 4, len); -+ sec_len += len; -+ }*/ -+ if (rest >= 4) -+ { -+ unsigned int rpt = bfd_getl32 (buf); -+ fprintf (file, -+ _("STO_IMM (store immediate) %u bytes\n"), -+ rpt); -+ if (rpt > rest - 4) -+ rpt = rest - 4; -+ evax_bfd_print_hex (file, " ", buf + 4, rpt); -+ } -+ break; -+ case ETIR__C_STO_GBL_LW: -+ /*fprintf (file, _("STO_GBL_LW (store global longword) %.*s\n"), -+ buf[0], buf + 1);*/ -+ if (rest >= 1) -+ fprintf (file, _("STO_GBL_LW (store global longword) %.*s\n"), -+ buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1); -+ break; -+ case ETIR__C_STO_LP_PSB: -+ fprintf (file, _("STO_OFF (store LP with procedure signature)\n")); -+ break; -+ case ETIR__C_STO_HINT_GBL: -+ fprintf (file, _("STO_BR_GBL (store branch global) *todo*\n")); -+ break; -+ case ETIR__C_STO_HINT_PS: -+ fprintf (file, _("STO_BR_PS (store branch psect + offset) *todo*\n")); -+ break; -+ -+ case ETIR__C_OPR_NOP: -+ fprintf (file, _("OPR_NOP (no-operation)\n")); -+ break; -+ case ETIR__C_OPR_ADD: -+ fprintf (file, _("OPR_ADD (add)\n")); -+ break; -+ case ETIR__C_OPR_SUB: -+ fprintf (file, _("OPR_SUB (subtract)\n")); -+ break; -+ case ETIR__C_OPR_MUL: -+ fprintf (file, _("OPR_MUL (multiply)\n")); -+ break; -+ case ETIR__C_OPR_DIV: -+ fprintf (file, _("OPR_DIV (divide)\n")); -+ break; -+ case ETIR__C_OPR_AND: -+ fprintf (file, _("OPR_AND (logical and)\n")); -+ break; -+ case ETIR__C_OPR_IOR: -+ fprintf (file, _("OPR_IOR (logical inclusive or)\n")); -+ break; -+ case ETIR__C_OPR_EOR: -+ fprintf (file, _("OPR_EOR (logical exclusive or)\n")); -+ break; -+ case ETIR__C_OPR_NEG: -+ fprintf (file, _("OPR_NEG (negate)\n")); -+ break; -+ case ETIR__C_OPR_COM: -+ fprintf (file, _("OPR_COM (complement)\n")); -+ break; -+ case ETIR__C_OPR_INSV: -+ fprintf (file, _("OPR_INSV (insert field)\n")); -+ break; -+ case ETIR__C_OPR_ASH: -+ fprintf (file, _("OPR_ASH (arithmetic shift)\n")); -+ break; -+ case ETIR__C_OPR_USH: -+ fprintf (file, _("OPR_USH (unsigned shift)\n")); -+ break; -+ case ETIR__C_OPR_ROT: -+ fprintf (file, _("OPR_ROT (rotate)\n")); -+ break; -+ case ETIR__C_OPR_SEL: -+ fprintf (file, _("OPR_SEL (select)\n")); -+ break; -+ case ETIR__C_OPR_REDEF: -+ fprintf (file, _("OPR_REDEF (redefine symbol to curr location)\n")); -+ break; -+ case ETIR__C_OPR_DFLIT: -+ fprintf (file, _("OPR_REDEF (define a literal)\n")); -+ break; -+ -+ case ETIR__C_STC_LP: -+ fprintf (file, _("STC_LP (store cond linkage pair)\n")); -+ break; -+ case ETIR__C_STC_LP_PSB: -+ fprintf (file, -+ _("STC_LP_PSB (store cond linkage pair + signature)\n")); -+ /* xgettext:c-format */ -+ /*fprintf (file, _(" linkage index: %u, procedure: %.*s\n"), -+ (unsigned)bfd_getl32 (buf), buf[4], buf + 5); -+ buf += 4 + 1 + buf[4]; -+ fprintf (file, _(" signature: %.*s\n"), buf[0], buf + 1);*/ -+ if (rest >= 5) -+ { -+ /* xgettext:c-format */ -+ fprintf (file, _(" linkage index: %u, procedure: %.*s\n"), -+ (unsigned) bfd_getl32 (buf), -+ buf[4] > rest - 5 ? rest - 5 : buf[4], buf + 5); -+ if (rest > 4 + 1u + buf[4]) -+ { -+ rest -= 4 + 1 + buf[4]; -+ buf += 4 + 1 + buf[4]; -+ fprintf (file, _(" signature: %.*s\n"), -+ buf[0] > rest - 1 ? rest - 1: buf[0], buf + 1); -+ } -+ } -+ break; -+ case ETIR__C_STC_GBL: -+ fprintf (file, _("STC_GBL (store cond global)\n")); -+ /* xgettext:c-format */ -+ /*fprintf (file, _(" linkage index: %u, global: %.*s\n"), -+ (unsigned)bfd_getl32 (buf), buf[4], buf + 5);*/ -+ if (rest >= 5) -+ /* xgettext:c-format */ -+ fprintf (file, _(" linkage index: %u, global: %.*s\n"), -+ (unsigned) bfd_getl32 (buf), -+ buf[4] > rest - 5 ? rest - 5 : buf[4], buf + 5); -+ break; -+ case ETIR__C_STC_GCA: -+ fprintf (file, _("STC_GCA (store cond code address)\n")); -+ /* xgettext:c-format */ -+ /*fprintf (file, _(" linkage index: %u, procedure name: %.*s\n"), -+ (unsigned)bfd_getl32 (buf), buf[4], buf + 5);*/ -+ if (rest >= 5) -+ /* xgettext:c-format */ -+ fprintf (file, _(" linkage index: %u, procedure name: %.*s\n"), -+ (unsigned) bfd_getl32 (buf), -+ buf[4] > rest - 5 ? rest - 5 : buf[4], buf + 5); -+ break; -+ case ETIR__C_STC_PS: -+ fprintf (file, _("STC_PS (store cond psect + offset)\n")); -+ /*fprintf (file, -+ _(" linkage index: %u, psect: %u, offset: 0x%08x %08x\n"), -+ (unsigned)bfd_getl32 (buf), -+ (unsigned)bfd_getl32 (buf + 4), -+ (unsigned)bfd_getl32 (buf + 12), -+ (unsigned)bfd_getl32 (buf + 8));*/ -+ if (rest >= 16) -+ fprintf (file, -+ /* xgettext:c-format */ -+ _(" linkage index: %u, psect: %u, offset: 0x%08x %08x\n"), -+ (unsigned)bfd_getl32 (buf), -+ (unsigned)bfd_getl32 (buf + 4), -+ (unsigned)bfd_getl32 (buf + 12), -+ (unsigned)bfd_getl32 (buf + 8)); -+ break; -+ case ETIR__C_STC_NOP_GBL: -+ fprintf (file, _("STC_NOP_GBL (store cond NOP at global addr)\n")); -+ //evax_bfd_print_etir_stc_ir (file, buf, 0); -+ evax_bfd_print_etir_stc_ir (file, buf, rest, 0); -+ break; -+ case ETIR__C_STC_NOP_PS: -+ fprintf (file, _("STC_NOP_PS (store cond NOP at psect + offset)\n")); -+ //evax_bfd_print_etir_stc_ir (file, buf, 1); -+ evax_bfd_print_etir_stc_ir (file, buf, rest, 1); -+ break; -+ case ETIR__C_STC_BSR_GBL: -+ fprintf (file, _("STC_BSR_GBL (store cond BSR at global addr)\n")); -+ //evax_bfd_print_etir_stc_ir (file, buf, 0); -+ evax_bfd_print_etir_stc_ir (file, buf, rest, 0); -+ break; -+ case ETIR__C_STC_BSR_PS: -+ fprintf (file, _("STC_BSR_PS (store cond BSR at psect + offset)\n")); -+ //evax_bfd_print_etir_stc_ir (file, buf, 1); -+ evax_bfd_print_etir_stc_ir (file, buf, rest, 1); -+ break; -+ case ETIR__C_STC_LDA_GBL: -+ fprintf (file, _("STC_LDA_GBL (store cond LDA at global addr)\n")); -+ //evax_bfd_print_etir_stc_ir (file, buf, 0); -+ evax_bfd_print_etir_stc_ir (file, buf, rest, 0); -+ break; -+ case ETIR__C_STC_LDA_PS: -+ fprintf (file, _("STC_LDA_PS (store cond LDA at psect + offset)\n")); -+ //evax_bfd_print_etir_stc_ir (file, buf, 1); -+ evax_bfd_print_etir_stc_ir (file, buf, rest, 1); -+ break; -+ case ETIR__C_STC_BOH_GBL: -+ fprintf (file, _("STC_BOH_GBL (store cond BOH at global addr)\n")); -+ //evax_bfd_print_etir_stc_ir (file, buf, 0); -+ evax_bfd_print_etir_stc_ir (file, buf, rest, 0); -+ break; -+ case ETIR__C_STC_BOH_PS: -+ fprintf (file, _("STC_BOH_PS (store cond BOH at psect + offset)\n")); -+ //evax_bfd_print_etir_stc_ir (file, buf, 1); -+ evax_bfd_print_etir_stc_ir (file, buf, rest, 1); -+ break; -+ case ETIR__C_STC_NBH_GBL: -+ fprintf (file, -+ _("STC_NBH_GBL (store cond or hint at global addr)\n")); -+ break; -+ case ETIR__C_STC_NBH_PS: -+ fprintf (file, -+ _("STC_NBH_PS (store cond or hint at psect + offset)\n")); -+ break; -+ -+ case ETIR__C_CTL_SETRB: -+ fprintf (file, _("CTL_SETRB (set relocation base)\n")); -+ //sec_len += 4; -+ break; -+ case ETIR__C_CTL_AUGRB: -+ /*{ -+ unsigned int val = bfd_getl32 (buf); -+ fprintf (file, _("CTL_AUGRB (augment relocation base) %u\n"), val); -+ }*/ -+ if (rest >= 4) -+ { -+ unsigned int val = bfd_getl32 (buf); -+ fprintf (file, _("CTL_AUGRB (augment relocation base) %u\n"), -+ val); -+ } -+ break; -+ case ETIR__C_CTL_DFLOC: -+ fprintf (file, _("CTL_DFLOC (define location)\n")); -+ break; -+ case ETIR__C_CTL_STLOC: -+ fprintf (file, _("CTL_STLOC (set location)\n")); -+ break; -+ case ETIR__C_CTL_STKDL: -+ fprintf (file, _("CTL_STKDL (stack defined location)\n")); -+ break; -+ default: -+ fprintf (file, _("*unhandled*\n")); -+ break; -+ } -+ off += size; -+ } -+} -+ -+static void -+evax_bfd_print_eobj (struct bfd *abfd, FILE *file) -+{ -+ bfd_boolean is_first = TRUE; -+ bfd_boolean has_records = FALSE; -+ -+ while (1) -+ { -+ unsigned int rec_len; -+ unsigned int pad_len; -+ unsigned char *rec; -+ unsigned int hdr_size; -+ unsigned int type; -+ -+ if (is_first) -+ { -+ unsigned char buf[6]; -+ -+ is_first = FALSE; -+ -+ /* Read 6 bytes. */ -+ if (bfd_bread (buf, sizeof (buf), abfd) != sizeof (buf)) -+ { -+ fprintf (file, _("cannot read GST record length\n")); -+ return; -+ } -+ rec_len = bfd_getl16 (buf + 0); -+ if (rec_len == bfd_getl16 (buf + 4) -+ && bfd_getl16 (buf + 2) == EOBJ__C_EMH) -+ { -+ /* The format is raw: record-size, type, record-size. */ -+ has_records = TRUE; -+ pad_len = (rec_len + 1) & ~1U; -+ hdr_size = 4; -+ } -+ else if (rec_len == EOBJ__C_EMH) -+ { -+ has_records = FALSE; -+ pad_len = bfd_getl16 (buf + 2); -+ hdr_size = 6; -+ } -+ else -+ { -+ /* Ill-formed. */ -+ fprintf (file, _("cannot find EMH in first GST record\n")); -+ return; -+ } -+ rec = bfd_malloc (pad_len); -+ memcpy (rec, buf + sizeof (buf) - hdr_size, hdr_size); -+ } -+ else -+ { -+ unsigned int rec_len2 = 0; -+ unsigned char hdr[4]; -+ -+ if (has_records) -+ { -+ unsigned char buf_len[2]; -+ -+ if (bfd_bread (buf_len, sizeof (buf_len), abfd) -+ != sizeof (buf_len)) -+ { -+ fprintf (file, _("cannot read GST record length\n")); -+ return; -+ } -+ rec_len2 = (unsigned)bfd_getl16 (buf_len); -+ } -+ -+ if (bfd_bread (hdr, sizeof (hdr), abfd) != sizeof (hdr)) -+ { -+ fprintf (file, _("cannot read GST record header\n")); -+ return; -+ } -+ rec_len = (unsigned)bfd_getl16 (hdr + 2); -+ if (has_records) -+ pad_len = (rec_len + 1) & ~1U; -+ else -+ pad_len = rec_len; -+ rec = bfd_malloc (pad_len); -+ memcpy (rec, hdr, sizeof (hdr)); -+ hdr_size = sizeof (hdr); -+ if (has_records && rec_len2 != rec_len) -+ { -+ fprintf (file, _(" corrupted GST\n")); -+ break; -+ } -+ } -+ -+ if (bfd_bread (rec + hdr_size, pad_len - hdr_size, abfd) -+ != pad_len - hdr_size) -+ { -+ fprintf (file, _("cannot read GST record\n")); -+ return; -+ } -+ -+ type = (unsigned)bfd_getl16 (rec); -+ -+ switch (type) -+ { -+ case EOBJ__C_EMH: -+ evax_bfd_print_emh (file, rec, rec_len); -+ break; -+ case EOBJ__C_EGSD: -+ evax_bfd_print_egsd (file, rec, rec_len); -+ break; -+ case EOBJ__C_EEOM: -+ evax_bfd_print_eeom (file, rec, rec_len); -+ free (rec); -+ return; -+ break; -+ case EOBJ__C_ETIR: -+ evax_bfd_print_etir (file, "ETIR", rec, rec_len); -+ break; -+ case EOBJ__C_EDBG: -+ evax_bfd_print_etir (file, "EDBG", rec, rec_len); -+ break; -+ case EOBJ__C_ETBT: -+ evax_bfd_print_etir (file, "ETBT", rec, rec_len); -+ break; -+ default: -+ fprintf (file, _(" unhandled EOBJ record type %u\n"), type); -+ break; -+ } -+ free (rec); -+ } -+} -+ -+static void -+evax_bfd_print_relocation_records (FILE *file, const unsigned char *buf, -+ size_t buf_size, size_t off, -+//evax_bfd_print_relocation_records (FILE *file, const unsigned char *rel, -+ unsigned int stride) -+{ -+ //while (1) -+ while (off <= buf_size - 8) -+ { -+ unsigned int base; -+ unsigned int count; -+ unsigned int j; -+ -+ //count = bfd_getl32 (rel + 0); -+ count = bfd_getl32 (buf + off + 0); -+ -+ if (count == 0) -+ break; -+ //base = bfd_getl32 (rel + 4); -+ base = bfd_getl32 (buf + off + 4); -+ -+ /* xgettext:c-format */ -+ fprintf (file, _(" bitcount: %u, base addr: 0x%08x\n"), -+ count, base); -+ -+ //rel += 8; -+ //for (j = 0; count > 0; j += 4, count -= 32) -+ off += 8; -+ for (j = 0; count > 0 && off <= buf_size - 4; j += 4, count -= 32) -+ { -+ unsigned int k; -+ unsigned int n = 0; -+ unsigned int val; -+ -+ //val = bfd_getl32 (rel); -+ //rel += 4; -+ val = bfd_getl32 (buf + off); -+ off += 4; -+ -+ /* xgettext:c-format */ -+ fprintf (file, _(" bitmap: 0x%08x (count: %u):\n"), val, count); -+ -+ for (k = 0; k < 32; k++) -+ if (val & (1u << k)) -+ { -+ if (n == 0) -+ fputs (" ", file); -+ fprintf (file, _(" %08x"), base + (j * 8 + k) * stride); -+ n++; -+ if (n == 8) -+ { -+ fputs ("\n", file); -+ n = 0; -+ } -+ } -+ if (n) -+ fputs ("\n", file); -+ } -+ } -+} -+ -+static void -+//evax_bfd_print_address_fixups (FILE *file, const unsigned char *rel) -+evax_bfd_print_address_fixups (FILE *file, const unsigned char *buf, -+ size_t buf_size, size_t off) -+{ -+ //while (1) -+ while (off <= buf_size - 8) -+ { -+ unsigned int j; -+ unsigned int count; -+ -+ //count = bfd_getl32 (rel + 0); -+ count = bfd_getl32 (buf + off + 0); -+ if (count == 0) -+ return; -+ /* xgettext:c-format */ -+ fprintf (file, _(" image %u (%u entries)\n"), -+ //(unsigned)bfd_getl32 (rel + 4), count); -+ //rel += 8; -+ //for (j = 0; j < count; j++) -+ (unsigned) bfd_getl32 (buf + off + 4), count); -+ off += 8; -+ for (j = 0; j < count && off <= buf_size - 8; j++) -+ { -+ /* xgettext:c-format */ -+ fprintf (file, _(" offset: 0x%08x, val: 0x%08x\n"), -+ //(unsigned)bfd_getl32 (rel + 0), -+ //(unsigned)bfd_getl32 (rel + 4)); -+ //rel += 8; -+ (unsigned) bfd_getl32 (buf + off + 0), -+ (unsigned) bfd_getl32 (buf + off + 4)); -+ off += 8; -+ } -+ } -+} -+ -+static void -+//evax_bfd_print_reference_fixups (FILE *file, const unsigned char *rel) -+evax_bfd_print_reference_fixups (FILE *file, const unsigned char *buf, -+ size_t buf_size, size_t off) -+{ -+ unsigned int count; -+ -+ //while (1) -+ while (off <= buf_size - 8) -+ { -+ unsigned int j; -+ unsigned int n = 0; -+ -+ //count = bfd_getl32 (rel + 0); -+ count = bfd_getl32 (buf + off + 0); -+ if (count == 0) -+ break; -+ /* xgettext:c-format */ -+ fprintf (file, _(" image %u (%u entries), offsets:\n"), -+ //(unsigned)bfd_getl32 (rel + 4), count); -+ //rel += 8; -+ //for (j = 0; j < count; j++) -+ (unsigned) bfd_getl32 (buf + off + 4), count); -+ off += 8; -+ for (j = 0; j < count && off <= buf_size - 4; j++) -+ { -+ if (n == 0) -+ fputs (" ", file); -+ //fprintf (file, _(" 0x%08x"), (unsigned)bfd_getl32 (rel)); -+ fprintf (file, _(" 0x%08x"), (unsigned) bfd_getl32 (buf + off)); -+ n++; -+ if (n == 7) -+ { -+ fputs ("\n", file); -+ n = 0; -+ } -+ //rel += 4; -+ off += 4; -+ } -+ if (n) -+ fputs ("\n", file); -+ } -+} -+ -+static void -+evax_bfd_print_indent (int indent, FILE *file) -+{ -+ for (; indent; indent--) -+ fputc (' ', file); -+} -+ -+static const char * -+evax_bfd_get_dsc_name (unsigned int v) -+{ -+ switch (v) -+ { -+ case DSC__K_DTYPE_Z: -+ return "Z (Unspecified)"; -+ case DSC__K_DTYPE_V: -+ return "V (Bit)"; -+ case DSC__K_DTYPE_BU: -+ return "BU (Byte logical)"; -+ case DSC__K_DTYPE_WU: -+ return "WU (Word logical)"; -+ case DSC__K_DTYPE_LU: -+ return "LU (Longword logical)"; -+ case DSC__K_DTYPE_QU: -+ return "QU (Quadword logical)"; -+ case DSC__K_DTYPE_B: -+ return "B (Byte integer)"; -+ case DSC__K_DTYPE_W: -+ return "W (Word integer)"; -+ case DSC__K_DTYPE_L: -+ return "L (Longword integer)"; -+ case DSC__K_DTYPE_Q: -+ return "Q (Quadword integer)"; -+ case DSC__K_DTYPE_F: -+ return "F (Single-precision floating)"; -+ case DSC__K_DTYPE_D: -+ return "D (Double-precision floating)"; -+ case DSC__K_DTYPE_FC: -+ return "FC (Complex)"; -+ case DSC__K_DTYPE_DC: -+ return "DC (Double-precision Complex)"; -+ case DSC__K_DTYPE_T: -+ return "T (ASCII text string)"; -+ case DSC__K_DTYPE_NU: -+ return "NU (Numeric string, unsigned)"; -+ case DSC__K_DTYPE_NL: -+ return "NL (Numeric string, left separate sign)"; -+ case DSC__K_DTYPE_NLO: -+ return "NLO (Numeric string, left overpunched sign)"; -+ case DSC__K_DTYPE_NR: -+ return "NR (Numeric string, right separate sign)"; -+ case DSC__K_DTYPE_NRO: -+ return "NRO (Numeric string, right overpunched sig)"; -+ case DSC__K_DTYPE_NZ: -+ return "NZ (Numeric string, zoned sign)"; -+ case DSC__K_DTYPE_P: -+ return "P (Packed decimal string)"; -+ case DSC__K_DTYPE_ZI: -+ return "ZI (Sequence of instructions)"; -+ case DSC__K_DTYPE_ZEM: -+ return "ZEM (Procedure entry mask)"; -+ case DSC__K_DTYPE_DSC: -+ return "DSC (Descriptor, used for arrays of dyn strings)"; -+ case DSC__K_DTYPE_OU: -+ return "OU (Octaword logical)"; -+ case DSC__K_DTYPE_O: -+ return "O (Octaword integer)"; -+ case DSC__K_DTYPE_G: -+ return "G (Double precision G floating, 64 bit)"; -+ case DSC__K_DTYPE_H: -+ return "H (Quadruple precision floating, 128 bit)"; -+ case DSC__K_DTYPE_GC: -+ return "GC (Double precision complex, G floating)"; -+ case DSC__K_DTYPE_HC: -+ return "HC (Quadruple precision complex, H floating)"; -+ case DSC__K_DTYPE_CIT: -+ return "CIT (COBOL intermediate temporary)"; -+ case DSC__K_DTYPE_BPV: -+ return "BPV (Bound Procedure Value)"; -+ case DSC__K_DTYPE_BLV: -+ return "BLV (Bound Label Value)"; -+ case DSC__K_DTYPE_VU: -+ return "VU (Bit Unaligned)"; -+ case DSC__K_DTYPE_ADT: -+ return "ADT (Absolute Date-Time)"; -+ case DSC__K_DTYPE_VT: -+ return "VT (Varying Text)"; -+ case DSC__K_DTYPE_T2: -+ return "T2 (16-bit char)"; -+ case DSC__K_DTYPE_VT2: -+ return "VT2 (16-bit varying char)"; -+ default: -+ return "?? (unknown)"; -+ } -+} -+ -+static void -+//evax_bfd_print_desc (const unsigned char *buf, int indent, FILE *file) -+evax_bfd_print_desc (const unsigned char *buf, unsigned int bufsize, -+ int indent, FILE *file) -+{ -+ if (bufsize < 8) -+ return; -+ -+ unsigned char bclass = buf[3]; -+ unsigned char dtype = buf[2]; -+ unsigned int len = (unsigned)bfd_getl16 (buf); -+ unsigned int pointer = (unsigned)bfd_getl32 (buf + 4); -+ -+ evax_bfd_print_indent (indent, file); -+ -+ if (len == 1 && pointer == 0xffffffffUL) -+ { -+ /* 64 bits. */ -+ fprintf (file, _("64 bits *unhandled*\n")); -+ } -+ else -+ { -+ /* xgettext:c-format */ -+ fprintf (file, _("class: %u, dtype: %u, length: %u, pointer: 0x%08x\n"), -+ bclass, dtype, len, pointer); -+ switch (bclass) -+ { -+ case DSC__K_CLASS_NCA: -+ { -+ const struct vms_dsc_nca *dsc = (const void *)buf; -+ unsigned int i; -+ const unsigned char *b; -+ -+ evax_bfd_print_indent (indent, file); -+ fprintf (file, _("non-contiguous array of %s\n"), -+ evax_bfd_get_dsc_name (dsc->dtype)); -+ if (bufsize >= sizeof (*dsc)) -+ { -+ evax_bfd_print_indent (indent + 1, file); -+ fprintf (file, -+ /* xgettext:c-format */ -+ _("dimct: %u, aflags: 0x%02x, digits: %u, scale: %u\n"), -+ dsc->dimct, dsc->aflags, dsc->digits, dsc->scale); -+ evax_bfd_print_indent (indent + 1, file); -+ fprintf (file, -+ /* xgettext:c-format */ -+ _("arsize: %u, a0: 0x%08x\n"), -+ (unsigned) bfd_getl32 (dsc->arsize), -+ (unsigned) bfd_getl32 (dsc->a0)); -+ evax_bfd_print_indent (indent + 1, file); -+ fprintf (file, _("Strides:\n")); -+ b = buf + sizeof (*dsc); -+ bufsize -= sizeof (*dsc); -+ for (i = 0; i < dsc->dimct; i++) -+ { -+ if (bufsize < 4) -+ break; -+ } -+ } -+ break; -+ case DSC__K_CLASS_UBS: -+ { -+ const struct vms_dsc_ubs *ubs = (const void *)buf; -+ -+ evax_bfd_print_indent (indent, file); -+ fprintf (file, _("unaligned bit-string of %s\n"), -+ evax_bfd_get_dsc_name (ubs->dtype)); -+ if (bufsize >= sizeof (*ubs)) -+ { -+ evax_bfd_print_indent (indent + 1, file); -+ fprintf (file, -+ /* xgettext:c-format */ -+ _("base: %u, pos: %u\n"), -+ (unsigned) bfd_getl32 (ubs->base), -+ (unsigned) bfd_getl32 (ubs->pos)); -+ } -+ } -+ break; -+ default: -+ fprintf (file, _("*unhandled*\n")); -+ break; -+ } -+ } -+} -+ -+static unsigned int -+//evax_bfd_print_valspec (const unsigned char *buf, int indent, FILE *file) -+evax_bfd_print_valspec (const unsigned char *buf, unsigned int bufsize, -+ int indent, FILE *file) -+{ -+ if (bufsize < 5) -+ return bufsize; -+ -+ unsigned int vflags = buf[0]; -+ unsigned int value = (unsigned) bfd_getl32 (buf + 1); -+ unsigned int len = 5; -+ -+ evax_bfd_print_indent (indent, file); -+ /* xgettext:c-format */ -+ fprintf (file, _("vflags: 0x%02x, value: 0x%08x "), vflags, value); -+ buf += 5; -+ bufsize -= 5; -+ -+ switch (vflags) -+ { -+ case DST__K_VFLAGS_NOVAL: -+ fprintf (file, _("(no value)\n")); -+ break; -+ case DST__K_VFLAGS_NOTACTIVE: -+ fprintf (file, _("(not active)\n")); -+ break; -+ case DST__K_VFLAGS_UNALLOC: -+ fprintf (file, _("(not allocated)\n")); -+ break; -+ case DST__K_VFLAGS_DSC: -+ fprintf (file, _("(descriptor)\n")); -+ //evax_bfd_print_desc (buf + value, indent + 1, file); -+ if (value <= bufsize) -+ evax_bfd_print_desc (buf + value, bufsize - value, indent + 1, file); -+ break; -+ case DST__K_VFLAGS_TVS: -+ fprintf (file, _("(trailing value)\n")); -+ break; -+ case DST__K_VS_FOLLOWS: -+ fprintf (file, _("(value spec follows)\n")); -+ break; -+ case DST__K_VFLAGS_BITOFFS: -+ fprintf (file, _("(at bit offset %u)\n"), value); -+ break; -+ default: -+ /* xgettext:c-format */ -+ fprintf (file, _("(reg: %u, disp: %u, indir: %u, kind: "), -+ (vflags & DST__K_REGNUM_MASK) >> DST__K_REGNUM_SHIFT, -+ vflags & DST__K_DISP ? 1 : 0, -+ vflags & DST__K_INDIR ? 1 : 0); -+ switch (vflags & DST__K_VALKIND_MASK) -+ { -+ case DST__K_VALKIND_LITERAL: -+ fputs (_("literal"), file); -+ break; -+ case DST__K_VALKIND_ADDR: -+ fputs (_("address"), file); -+ break; -+ case DST__K_VALKIND_DESC: -+ fputs (_("desc"), file); -+ break; -+ case DST__K_VALKIND_REG: -+ fputs (_("reg"), file); -+ break; -+ } -+ fputs (")\n", file); -+ break; -+ } -+ return len; -+} -+ -+static void -+//evax_bfd_print_typspec (const unsigned char *buf, int indent, FILE *file) -+evax_bfd_print_typspec (const unsigned char *buf, unsigned int bufsize, -+ int indent, FILE *file) -+{ -+ if (bufsize < 3) -+ return; -+ -+ unsigned char kind = buf[2]; -+ unsigned int len = (unsigned) bfd_getl16 (buf); -+ -+ evax_bfd_print_indent (indent, file); -+ /* xgettext:c-format */ -+ fprintf (file, _("len: %2u, kind: %2u "), len, kind); -+ buf += 3; -+ bufsize -= 3; -+ switch (kind) -+ { -+ case DST__K_TS_ATOM: -+ /* xgettext:c-format */ -+ //fprintf (file, _("atomic, type=0x%02x %s\n"), -+ // buf[0], evax_bfd_get_dsc_name (buf[0])); -+ if (bufsize >= 1) -+ fprintf (file, _("atomic, type=0x%02x %s\n"), -+ buf[0], evax_bfd_get_dsc_name (buf[0])); -+ break; -+ case DST__K_TS_IND: -+ //fprintf (file, _("indirect, defined at 0x%08x\n"), -+ // (unsigned)bfd_getl32 (buf)); -+ if (bufsize >= 4) -+ fprintf (file, _("indirect, defined at 0x%08x\n"), -+ (unsigned) bfd_getl32 (buf)); -+ break; -+ case DST__K_TS_TPTR: -+ fprintf (file, _("typed pointer\n")); -+ //evax_bfd_print_typspec (buf, indent + 1, file); -+ evax_bfd_print_typspec (buf, bufsize, indent + 1, file); -+ break; -+ case DST__K_TS_PTR: -+ fprintf (file, _("pointer\n")); -+ break; -+ case DST__K_TS_ARRAY: -+ { -+ const unsigned char *vs; -+ unsigned int vs_len; -+ unsigned int vec_len; -+ unsigned int i; -+ -+ if (bufsize == 0) -+ return; -+ fprintf (file, _("array, dim: %u, bitmap: "), buf[0]); -+ --bufsize; -+ vec_len = (buf[0] + 1 + 7) / 8; -+ for (i = 0; i < vec_len; i++) -+ //fprintf (file, " %02x", buf[i + 1]); -+ { -+ if (bufsize == 0) -+ break; -+ fprintf (file, " %02x", buf[i + 1]); -+ --bufsize; -+ } -+ fputc ('\n', file); -+ if (bufsize == 0) -+ return; -+ vs = buf + 1 + vec_len; -+ evax_bfd_print_indent (indent, file); -+ fprintf (file, _("array descriptor:\n")); -+ vs_len = evax_bfd_print_valspec (vs, bufsize, indent + 1, file); -+ vs += vs_len; -+ if (bufsize > vs_len) -+ { -+ bufsize -= vs_len; -+ for (i = 0; i < buf[0] + 1U; i++) -+ if (buf[1 + i / 8] & (1 << (i % 8))) -+ { -+ evax_bfd_print_indent (indent, file); -+ if (i == 0) -+ fprintf (file, _("type spec for element:\n")); -+ else -+ fprintf (file, _("type spec for subscript %u:\n"), i); -+ evax_bfd_print_typspec (vs, bufsize, indent + 1, file); -+ if (bufsize < 2) -+ break; -+ vs_len = bfd_getl16 (vs); -+ if (bufsize <= vs_len) -+ break; -+ vs += vs_len; -+ bufsize -= vs_len; -+ } -+ } -+ } -+ break; -+ default: -+ fprintf (file, _("*unhandled*\n")); -+ } -+} -+ -+static void -+evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file) -+{ -+ unsigned int off = 0; -+ unsigned int pc = 0; -+ unsigned int line = 0; -+ -+ fprintf (file, _("Debug symbol table:\n")); -+ -+ while (dst_size > 0) -+ { -+ struct vms_dst_header dsth; -+ unsigned int len; -+ unsigned int type; -+ unsigned char *buf; -+ -+ if (bfd_bread (&dsth, sizeof (dsth), abfd) != sizeof (dsth)) -+ { -+ fprintf (file, _("cannot read DST header\n")); -+ return; -+ } -+ len = bfd_getl16 (dsth.length); -+ type = bfd_getl16 (dsth.type); -+ /* xgettext:c-format */ -+ fprintf (file, _(" type: %3u, len: %3u (at 0x%08x): "), -+ type, len, off); -+ //if (len == 0) -+ if (len < sizeof (dsth)) -+ { -+ fputc ('\n', file); -+ break; -+ } -+ //len++; -+ dst_size -= len; -+ off += len; -+ len -= sizeof (dsth); -+ //buf = bfd_malloc (len); -+ //if (bfd_bread (buf, len, abfd) != len) -+ if (len == 0) -+ buf = NULL; -+ else -+ { -+ buf = _bfd_malloc_and_read (abfd, len, len); -+ if (buf == NULL) -+ { -+ fprintf (file, _("cannot read DST symbol\n")); -+ return; -+ } -+ } -+ switch (type) -+ { -+ case DSC__K_DTYPE_V: -+ case DSC__K_DTYPE_BU: -+ case DSC__K_DTYPE_WU: -+ case DSC__K_DTYPE_LU: -+ case DSC__K_DTYPE_QU: -+ case DSC__K_DTYPE_B: -+ case DSC__K_DTYPE_W: -+ case DSC__K_DTYPE_L: -+ case DSC__K_DTYPE_Q: -+ case DSC__K_DTYPE_F: -+ case DSC__K_DTYPE_D: -+ case DSC__K_DTYPE_FC: -+ case DSC__K_DTYPE_DC: -+ case DSC__K_DTYPE_T: -+ case DSC__K_DTYPE_NU: -+ case DSC__K_DTYPE_NL: -+ case DSC__K_DTYPE_NLO: -+ case DSC__K_DTYPE_NR: -+ case DSC__K_DTYPE_NRO: -+ case DSC__K_DTYPE_NZ: -+ case DSC__K_DTYPE_P: -+ case DSC__K_DTYPE_ZI: -+ case DSC__K_DTYPE_ZEM: -+ case DSC__K_DTYPE_DSC: -+ case DSC__K_DTYPE_OU: -+ case DSC__K_DTYPE_O: -+ case DSC__K_DTYPE_G: -+ case DSC__K_DTYPE_H: -+ case DSC__K_DTYPE_GC: -+ case DSC__K_DTYPE_HC: -+ case DSC__K_DTYPE_CIT: -+ case DSC__K_DTYPE_BPV: -+ case DSC__K_DTYPE_BLV: -+ case DSC__K_DTYPE_VU: -+ case DSC__K_DTYPE_ADT: -+ case DSC__K_DTYPE_VT: -+ case DSC__K_DTYPE_T2: -+ case DSC__K_DTYPE_VT2: -+ fprintf (file, _("standard data: %s\n"), -+ evax_bfd_get_dsc_name (type)); -+ evax_bfd_print_valspec (buf, len, 4, file); -+ fprintf (file, _(" name: %.*s\n"), buf[5], buf + 6); -+ break; -+ case DST__K_MODBEG: -+ { -+ struct vms_dst_modbeg *dst = (void *)buf; -+ const char *name = (const char *)buf + sizeof (*dst); -+ -+ fprintf (file, _("modbeg\n")); -+ if (len < sizeof (*dst)) -+ break; -+ /* xgettext:c-format */ -+ fprintf (file, _(" flags: %d, language: %u, " -+ "major: %u, minor: %u\n"), -+ dst->flags, -+ (unsigned)bfd_getl32 (dst->language), -+ (unsigned)bfd_getl16 (dst->major), -+ (unsigned)bfd_getl16 (dst->minor)); -+ len -= sizeof (*dst); -+ if (len > 0) -+ { -+ int nlen = len - 1; -+ fprintf (file, _(" module name: %.*s\n"), -+ name[0] > nlen ? nlen : name[0], name + 1); -+ if (name[0] < nlen) -+ { -+ len -= name[0] + 1; -+ name += name[0] + 1; -+ nlen = len - 1; -+ fprintf (file, _(" compiler : %.*s\n"), -+ name[0] > nlen ? nlen: name[0], name + 1); -+ } -+ } -+ } -+ break; -+ case DST__K_MODEND: -+ fprintf (file, _("modend\n")); -+ break; -+ case DST__K_RTNBEG: -+ { -+ struct vms_dst_rtnbeg *dst = (void *)buf; -+ const char *name = (const char *)buf + sizeof (*dst); -+ -+ fputs (_("rtnbeg\n"), file); -+ if (len >= sizeof (*dst)) -+ { -+ /* xgettext:c-format */ -+ fprintf (file, _(" flags: %u, address: 0x%08x, " -+ "pd-address: 0x%08x\n"), -+ dst->flags, -+ (unsigned) bfd_getl32 (dst->address), -+ (unsigned) bfd_getl32 (dst->pd_address)); -+ len -= sizeof (*dst); -+ if (len > 0) -+ { -+ int nlen = len - 1; -+ fprintf (file, _(" routine name: %.*s\n"), -+ name[0] > nlen ? nlen : name[0], name + 1); -+ } -+ } -+ } -+ break; -+ case DST__K_RTNEND: -+ { -+ struct vms_dst_rtnend *dst = (void *)buf; -+ -+ if (len >= sizeof (*dst)) -+ fprintf (file, _("rtnend: size 0x%08x\n"), -+ (unsigned) bfd_getl32 (dst->size)); -+ } -+ break; -+ case DST__K_PROLOG: -+ { -+ struct vms_dst_prolog *dst = (void *)buf; -+ -+ if (len >= sizeof (*dst)) -+ /* xgettext:c-format */ -+ fprintf (file, _("prolog: bkpt address 0x%08x\n"), -+ (unsigned) bfd_getl32 (dst->bkpt_addr)); -+ } -+ break; -+ case DST__K_EPILOG: -+ { -+ struct vms_dst_epilog *dst = (void *)buf; -+ -+ if (len >= sizeof (*dst)) -+ /* xgettext:c-format */ -+ fprintf (file, _("epilog: flags: %u, count: %u\n"), -+ dst->flags, (unsigned) bfd_getl32 (dst->count)); -+ } -+ break; -+ case DST__K_BLKBEG: -+ { -+ struct vms_dst_blkbeg *dst = (void *)buf; -+ const char *name = (const char *)buf + sizeof (*dst); -+ -+ if (len > sizeof (*dst)) -+ { -+ int nlen; -+ len -= sizeof (*dst); -+ nlen = len - 1; -+ /* xgettext:c-format */ -+ fprintf (file, _("blkbeg: address: 0x%08x, name: %.*s\n"), -+ (unsigned) bfd_getl32 (dst->address), -+ name[0] > nlen ? nlen : name[0], name + 1); -+ } -+ } -+ break; -+ case DST__K_BLKEND: -+ { -+ struct vms_dst_blkend *dst = (void *)buf; -+ -+ if (len >= sizeof (*dst)) -+ /* xgettext:c-format */ -+ fprintf (file, _("blkend: size: 0x%08x\n"), -+ (unsigned) bfd_getl32 (dst->size)); -+ } -+ break; -+ case DST__K_TYPSPEC: -+ { -+ fprintf (file, _("typspec (len: %u)\n"), len); -+ if (len >= 1) -+ { -+ int nlen = len - 1; -+ fprintf (file, _(" name: %.*s\n"), -+ buf[0] > nlen ? nlen : buf[0], buf + 1); -+ if (nlen > buf[0]) -+ evax_bfd_print_typspec (buf + 1 + buf[0], len - (1 + buf[0]), -+ 5, file); -+ } -+ } -+ break; -+ case DST__K_SEPTYP: -+ { -+ if (len >= 6) -+ { -+ fprintf (file, _("septyp, name: %.*s\n"), -+ buf[5] > len - 6 ? len - 6 : buf[5], buf + 6); -+ evax_bfd_print_valspec (buf, len, 4, file); -+ } -+ } -+ break; -+ case DST__K_RECBEG: -+ { -+ struct vms_dst_recbeg *recbeg = (void *)buf; -+ const char *name = (const char *)buf + sizeof (*recbeg); -+ -+ if (len > sizeof (*recbeg)) -+ { -+ int nlen = len - sizeof (*recbeg) - 1; -+ if (name[0] < nlen) -+ nlen = name[0]; -+ fprintf (file, _("recbeg: name: %.*s\n"), nlen, name + 1); -+ evax_bfd_print_valspec (buf, len, 4, file); -+ len -= 1 + nlen; -+ if (len >= 4) -+ fprintf (file, _(" len: %u bits\n"), -+ (unsigned) bfd_getl32 (name + 1 + nlen)); -+ } -+ } -+ break; -+ case DST__K_RECEND: -+ fprintf (file, _("recend\n")); -+ break; -+ case DST__K_ENUMBEG: -+ if (len >= 2) -+ /* xgettext:c-format */ -+ fprintf (file, _("enumbeg, len: %u, name: %.*s\n"), -+ buf[0], buf[1] > len - 2 ? len - 2 : buf[1], buf + 2); -+ break; -+ case DST__K_ENUMELT: -+ if (len >= 6) -+ { -+ fprintf (file, _("enumelt, name: %.*s\n"), -+ buf[5] > len - 6 ? len - 6 : buf[5], buf + 6); -+ evax_bfd_print_valspec (buf, len, 4, file); -+ } -+ break; -+ case DST__K_ENUMEND: -+ fprintf (file, _("enumend\n")); -+ break; -+ case DST__K_LABEL: -+ { -+ struct vms_dst_label *lab = (void *)buf; -+ if (len >= sizeof (*lab)) -+ { -+ fprintf (file, _("label, name: %.*s\n"), -+ lab->name[0] > len - 1 ? len - 1 : lab->name[0], -+ lab->name + 1); -+ fprintf (file, _(" address: 0x%08x\n"), -+ (unsigned) bfd_getl32 (lab->value)); -+ } -+ } -+ break; -+ case DST__K_DIS_RANGE: -+ if (len >= 4) -+ { -+ unsigned int cnt = bfd_getl32 (buf); -+ unsigned char *rng = buf + 4; -+ unsigned int i; -+ -+ fprintf (file, _("discontiguous range (nbr: %u)\n"), cnt); -+ len -= 4; -+ for (i = 0; i < cnt; i++, rng += 8) -+ { -+ if (len < 8) -+ break; -+ /* xgettext:c-format */ -+ fprintf (file, _(" address: 0x%08x, size: %u\n"), -+ (unsigned) bfd_getl32 (rng), -+ (unsigned) bfd_getl32 (rng + 4)); -+ len -= 8; -+ } -+ } -+ break; -+ case DST__K_LINE_NUM: -+ { -+ unsigned char *buf_orig = buf; -+ -+ fprintf (file, _("line num (len: %u)\n"), len); -+ -+ while (len > 0) -+ { -+ int cmd; -+ unsigned int val; -+ int cmdlen = -1; -+ -+ cmd = *buf++; -+ len--; -+ -+ fputs (" ", file); -+ -+ switch (cmd) -+ { -+ case DST__K_DELTA_PC_W: -+ if (len < 2) -+ break; -+ val = bfd_getl16 (buf); -+ fprintf (file, _("delta_pc_w %u\n"), val); -+ pc += val; -+ line++; -+ cmdlen = 2; -+ break; -+ case DST__K_INCR_LINUM: -+ if (len < 1) -+ break; -+ val = *buf; -+ fprintf (file, _("incr_linum(b): +%u\n"), val); -+ line += val; -+ cmdlen = 1; -+ break; -+ case DST__K_INCR_LINUM_W: -+ if (len < 2) -+ break; -+ val = bfd_getl16 (buf); -+ fprintf (file, _("incr_linum_w: +%u\n"), val); -+ line += val; -+ cmdlen = 2; -+ break; -+ case DST__K_INCR_LINUM_L: -+ if (len < 4) -+ break; -+ val = bfd_getl32 (buf); -+ fprintf (file, _("incr_linum_l: +%u\n"), val); -+ line += val; -+ cmdlen = 4; -+ break; -+ case DST__K_SET_LINUM: -+ if (len < 2) -+ break; -+ line = bfd_getl16 (buf); -+ fprintf (file, _("set_line_num(w) %u\n"), line); -+ cmdlen = 2; -+ break; -+ case DST__K_SET_LINUM_B: -+ if (len < 1) -+ break; -+ line = *buf; -+ fprintf (file, _("set_line_num_b %u\n"), line); -+ cmdlen = 1; -+ break; -+ case DST__K_SET_LINUM_L: -+ if (len < 4) -+ break; -+ line = bfd_getl32 (buf); -+ fprintf (file, _("set_line_num_l %u\n"), line); -+ cmdlen = 4; -+ break; -+ case DST__K_SET_ABS_PC: -+ if (len < 4) -+ break; -+ pc = bfd_getl32 (buf); -+ fprintf (file, _("set_abs_pc: 0x%08x\n"), pc); -+ cmdlen = 4; -+ break; -+ case DST__K_DELTA_PC_L: -+ if (len < 4) -+ break; -+ fprintf (file, _("delta_pc_l: +0x%08x\n"), -+ (unsigned) bfd_getl32 (buf)); -+ cmdlen = 4; -+ break; -+ case DST__K_TERM: -+ if (len < 1) -+ break; -+ fprintf (file, _("term(b): 0x%02x"), *buf); -+ pc += *buf; -+ fprintf (file, _(" pc: 0x%08x\n"), pc); -+ cmdlen = 1; -+ break; -+ case DST__K_TERM_W: -+ if (len < 2) -+ break; -+ val = bfd_getl16 (buf); -+ fprintf (file, _("term_w: 0x%04x"), val); -+ pc += val; -+ fprintf (file, _(" pc: 0x%08x\n"), pc); -+ cmdlen = 2; -+ break; -+ default: -+ if (cmd <= 0) -+ { -+ fprintf (file, _("delta pc +%-4d"), -cmd); -+ line++; /* FIXME: curr increment. */ -+ pc += -cmd; -+ /* xgettext:c-format */ -+ fprintf (file, _(" pc: 0x%08x line: %5u\n"), -+ pc, line); -+ cmdlen = 0; -+ } -+ else -+ fprintf (file, _(" *unhandled* cmd %u\n"), cmd); -+ break; -+ } -+ if (cmdlen < 0) -+ break; -+ len -= cmdlen; -+ buf += cmdlen; -+ } -+ buf = buf_orig; -+ } -+ break; -+ case DST__K_SOURCE: -+ { -+ unsigned char *buf_orig = buf; -+ -+ fprintf (file, _("source (len: %u)\n"), len); -+ -+ while (len > 0) -+ { -+ int cmd = *buf++; -+ int cmdlen = -1; -+ -+ len--; -+ switch (cmd) -+ { -+ case DST__K_SRC_DECLFILE: -+ { -+ struct vms_dst_src_decl_src *src = (void *) buf; -+ const char *name; -+ int nlen; -+ -+ if (len < sizeof (*src)) -+ break; -+ /* xgettext:c-format */ -+ fprintf (file, _(" declfile: len: %u, flags: %u, " -+ "fileid: %u\n"), -+ src->length, src->flags, -+ (unsigned)bfd_getl16 (src->fileid)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" rms: cdt: 0x%08x %08x, " -+ "ebk: 0x%08x, ffb: 0x%04x, " -+ "rfo: %u\n"), -+ (unsigned)bfd_getl32 (src->rms_cdt + 4), -+ (unsigned)bfd_getl32 (src->rms_cdt + 0), -+ (unsigned)bfd_getl32 (src->rms_ebk), -+ (unsigned)bfd_getl16 (src->rms_ffb), -+ src->rms_rfo); -+ if (src->length > len || src->length <= sizeof (*src)) -+ break; -+ nlen = src->length - sizeof (*src) - 1; -+ name = (const char *) buf + sizeof (*src); -+ fprintf (file, _(" filename : %.*s\n"), -+ name[0] > nlen ? nlen : name[0], name + 1); -+ if (name[0] >= nlen) -+ break; -+ nlen -= name[0] + 1; -+ name += name[0] + 1; -+ fprintf (file, _(" module name: %.*s\n"), -+ name[0] > nlen ? nlen : name[0], name + 1); -+ if (name[0] > nlen) -+ break; -+ cmdlen = src->length; -+ } -+ break; -+ case DST__K_SRC_SETFILE: -+ if (len < 2) -+ break; -+ fprintf (file, _(" setfile %u\n"), -+ (unsigned) bfd_getl16 (buf)); -+ cmdlen = 2; -+ break; -+ case DST__K_SRC_SETREC_W: -+ if (len < 2) -+ break; -+ fprintf (file, _(" setrec %u\n"), -+ (unsigned) bfd_getl16 (buf)); -+ cmdlen = 2; -+ break; -+ case DST__K_SRC_SETREC_L: -+ if (len < 4) -+ break; -+ fprintf (file, _(" setrec %u\n"), -+ (unsigned) bfd_getl32 (buf)); -+ cmdlen = 4; -+ break; -+ case DST__K_SRC_SETLNUM_W: -+ if (len < 2) -+ break; -+ fprintf (file, _(" setlnum %u\n"), -+ (unsigned) bfd_getl16 (buf)); -+ cmdlen = 2; -+ break; -+ case DST__K_SRC_SETLNUM_L: -+ if (len < 4) -+ break; -+ fprintf (file, _(" setlnum %u\n"), -+ (unsigned) bfd_getl32 (buf)); -+ cmdlen = 4; -+ break; -+ case DST__K_SRC_DEFLINES_W: -+ if (len < 2) -+ break; -+ fprintf (file, _(" deflines %u\n"), -+ (unsigned) bfd_getl16 (buf)); -+ cmdlen = 2; -+ break; -+ case DST__K_SRC_DEFLINES_B: -+ if (len < 1) -+ break; -+ fprintf (file, _(" deflines %u\n"), *buf); -+ cmdlen = 1; -+ break; -+ case DST__K_SRC_FORMFEED: -+ fprintf (file, _(" formfeed\n")); -+ cmdlen = 0; -+ break; -+ default: -+ fprintf (file, _(" *unhandled* cmd %u\n"), cmd); -+ break; -+ } -+ if (cmdlen < 0) -+ break; -+ len -= cmdlen; -+ buf += cmdlen; -+ } -+ buf = buf_orig; -+ } -+ break; -+ default: -+ fprintf (file, _("*unhandled* dst type %u\n"), type); -+ break; -+ } -+ free (buf); -+ } -+} -+ -+static void -+evax_bfd_print_image (bfd *abfd, FILE *file) -+{ -+ struct vms_eihd eihd; -+ const char *name; -+ unsigned int val; -+ unsigned int eiha_off; -+ unsigned int eihi_off; -+ unsigned int eihs_off; -+ unsigned int eisd_off; -+ unsigned int eihef_off = 0; -+ unsigned int eihnp_off = 0; -+ unsigned int dmt_vbn = 0; -+ unsigned int dmt_size = 0; -+ unsigned int dst_vbn = 0; -+ unsigned int dst_size = 0; -+ unsigned int gst_vbn = 0; -+ unsigned int gst_size = 0; -+ unsigned int eiaf_vbn = 0; -+ unsigned int eiaf_size = 0; -+ unsigned int eihvn_off; -+ -+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) -+ || bfd_bread (&eihd, sizeof (eihd), abfd) != sizeof (eihd)) -+ { -+ fprintf (file, _("cannot read EIHD\n")); -+ return; -+ } -+ /* xgettext:c-format */ -+ fprintf (file, _("EIHD: (size: %u, nbr blocks: %u)\n"), -+ (unsigned)bfd_getl32 (eihd.size), -+ (unsigned)bfd_getl32 (eihd.hdrblkcnt)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" majorid: %u, minorid: %u\n"), -+ (unsigned)bfd_getl32 (eihd.majorid), -+ (unsigned)bfd_getl32 (eihd.minorid)); -+ -+ val = (unsigned)bfd_getl32 (eihd.imgtype); -+ switch (val) -+ { -+ case EIHD__K_EXE: -+ name = _("executable"); -+ break; -+ case EIHD__K_LIM: -+ name = _("linkable image"); -+ break; -+ default: -+ name = _("unknown"); -+ break; -+ } -+ /* xgettext:c-format */ -+ fprintf (file, _(" image type: %u (%s)"), val, name); -+ -+ val = (unsigned)bfd_getl32 (eihd.subtype); -+ switch (val) -+ { -+ case EIHD__C_NATIVE: -+ name = _("native"); -+ break; -+ case EIHD__C_CLI: -+ name = _("CLI"); -+ break; -+ default: -+ name = _("unknown"); -+ break; -+ } -+ /* xgettext:c-format */ -+ fprintf (file, _(", subtype: %u (%s)\n"), val, name); -+ -+ eisd_off = bfd_getl32 (eihd.isdoff); -+ eiha_off = bfd_getl32 (eihd.activoff); -+ eihi_off = bfd_getl32 (eihd.imgidoff); -+ eihs_off = bfd_getl32 (eihd.symdbgoff); -+ /* xgettext:c-format */ -+ fprintf (file, _(" offsets: isd: %u, activ: %u, symdbg: %u, " -+ "imgid: %u, patch: %u\n"), -+ eisd_off, eiha_off, eihs_off, eihi_off, -+ (unsigned)bfd_getl32 (eihd.patchoff)); -+ fprintf (file, _(" fixup info rva: ")); -+ bfd_fprintf_vma (abfd, file, bfd_getl64 (eihd.iafva)); -+ fprintf (file, _(", symbol vector rva: ")); -+ bfd_fprintf_vma (abfd, file, bfd_getl64 (eihd.symvva)); -+ eihvn_off = bfd_getl32 (eihd.version_array_off); -+ fprintf (file, _("\n" -+ " version array off: %u\n"), -+ eihvn_off); -+ fprintf (file, -+ /* xgettext:c-format */ -+ _(" img I/O count: %u, nbr channels: %u, req pri: %08x%08x\n"), -+ (unsigned)bfd_getl32 (eihd.imgiocnt), -+ (unsigned)bfd_getl32 (eihd.iochancnt), -+ (unsigned)bfd_getl32 (eihd.privreqs + 4), -+ (unsigned)bfd_getl32 (eihd.privreqs + 0)); -+ val = (unsigned)bfd_getl32 (eihd.lnkflags); -+ fprintf (file, _(" linker flags: %08x:"), val); -+ if (val & EIHD__M_LNKDEBUG) -+ fprintf (file, " LNKDEBUG"); -+ if (val & EIHD__M_LNKNOTFR) -+ fprintf (file, " LNKNOTFR"); -+ if (val & EIHD__M_NOP0BUFS) -+ fprintf (file, " NOP0BUFS"); -+ if (val & EIHD__M_PICIMG) -+ fprintf (file, " PICIMG"); -+ if (val & EIHD__M_P0IMAGE) -+ fprintf (file, " P0IMAGE"); -+ if (val & EIHD__M_DBGDMT) -+ fprintf (file, " DBGDMT"); -+ if (val & EIHD__M_INISHR) -+ fprintf (file, " INISHR"); -+ if (val & EIHD__M_XLATED) -+ fprintf (file, " XLATED"); -+ if (val & EIHD__M_BIND_CODE_SEC) -+ fprintf (file, " BIND_CODE_SEC"); -+ if (val & EIHD__M_BIND_DATA_SEC) -+ fprintf (file, " BIND_DATA_SEC"); -+ if (val & EIHD__M_MKTHREADS) -+ fprintf (file, " MKTHREADS"); -+ if (val & EIHD__M_UPCALLS) -+ fprintf (file, " UPCALLS"); -+ if (val & EIHD__M_OMV_READY) -+ fprintf (file, " OMV_READY"); -+ if (val & EIHD__M_EXT_BIND_SECT) -+ fprintf (file, " EXT_BIND_SECT"); -+ fprintf (file, "\n"); -+ /* xgettext:c-format */ -+ fprintf (file, _(" ident: 0x%08x, sysver: 0x%08x, " -+ "match ctrl: %u, symvect_size: %u\n"), -+ (unsigned)bfd_getl32 (eihd.ident), -+ (unsigned)bfd_getl32 (eihd.sysver), -+ eihd.matchctl, -+ (unsigned)bfd_getl32 (eihd.symvect_size)); -+ fprintf (file, _(" BPAGE: %u"), -+ (unsigned)bfd_getl32 (eihd.virt_mem_block_size)); -+ if (val & (EIHD__M_OMV_READY | EIHD__M_EXT_BIND_SECT)) -+ { -+ eihef_off = bfd_getl32 (eihd.ext_fixup_off); -+ eihnp_off = bfd_getl32 (eihd.noopt_psect_off); -+ /* xgettext:c-format */ -+ fprintf (file, _(", ext fixup offset: %u, no_opt psect off: %u"), -+ eihef_off, eihnp_off); -+ } -+ fprintf (file, _(", alias: %u\n"), (unsigned)bfd_getl16 (eihd.alias)); -+ -+ if (eihvn_off != 0) -+ { -+ struct vms_eihvn eihvn; -+ unsigned int mask; -+ unsigned int j; -+ -+ fprintf (file, _("system version array information:\n")); -+ if (bfd_seek (abfd, (file_ptr) eihvn_off, SEEK_SET) -+ || bfd_bread (&eihvn, sizeof (eihvn), abfd) != sizeof (eihvn)) -+ { -+ fprintf (file, _("cannot read EIHVN header\n")); -+ return; -+ } -+ mask = bfd_getl32 (eihvn.subsystem_mask); -+ for (j = 0; j < 32; j++) -+ if (mask & (1u << j)) -+ { -+ struct vms_eihvn_subversion ver; -+ if (bfd_bread (&ver, sizeof (ver), abfd) != sizeof (ver)) -+ { -+ fprintf (file, _("cannot read EIHVN version\n")); -+ return; -+ } -+ fprintf (file, _(" %02u "), j); -+ switch (j) -+ { -+ case EIHVN__BASE_IMAGE_BIT: -+ fputs (_("BASE_IMAGE "), file); -+ break; -+ case EIHVN__MEMORY_MANAGEMENT_BIT: -+ fputs (_("MEMORY_MANAGEMENT"), file); -+ break; -+ case EIHVN__IO_BIT: -+ fputs (_("IO "), file); -+ break; -+ case EIHVN__FILES_VOLUMES_BIT: -+ fputs (_("FILES_VOLUMES "), file); -+ break; -+ case EIHVN__PROCESS_SCHED_BIT: -+ fputs (_("PROCESS_SCHED "), file); -+ break; -+ case EIHVN__SYSGEN_BIT: -+ fputs (_("SYSGEN "), file); -+ break; -+ case EIHVN__CLUSTERS_LOCKMGR_BIT: -+ fputs (_("CLUSTERS_LOCKMGR "), file); -+ break; -+ case EIHVN__LOGICAL_NAMES_BIT: -+ fputs (_("LOGICAL_NAMES "), file); -+ break; -+ case EIHVN__SECURITY_BIT: -+ fputs (_("SECURITY "), file); -+ break; -+ case EIHVN__IMAGE_ACTIVATOR_BIT: -+ fputs (_("IMAGE_ACTIVATOR "), file); -+ break; -+ case EIHVN__NETWORKS_BIT: -+ fputs (_("NETWORKS "), file); -+ break; -+ case EIHVN__COUNTERS_BIT: -+ fputs (_("COUNTERS "), file); -+ break; -+ case EIHVN__STABLE_BIT: -+ fputs (_("STABLE "), file); -+ break; -+ case EIHVN__MISC_BIT: -+ fputs (_("MISC "), file); -+ break; -+ case EIHVN__CPU_BIT: -+ fputs (_("CPU "), file); -+ break; -+ case EIHVN__VOLATILE_BIT: -+ fputs (_("VOLATILE "), file); -+ break; -+ case EIHVN__SHELL_BIT: -+ fputs (_("SHELL "), file); -+ break; -+ case EIHVN__POSIX_BIT: -+ fputs (_("POSIX "), file); -+ break; -+ case EIHVN__MULTI_PROCESSING_BIT: -+ fputs (_("MULTI_PROCESSING "), file); -+ break; -+ case EIHVN__GALAXY_BIT: -+ fputs (_("GALAXY "), file); -+ break; -+ default: -+ fputs (_("*unknown* "), file); -+ break; -+ } -+ fprintf (file, ": %u.%u\n", -+ (unsigned)bfd_getl16 (ver.major), -+ (unsigned)bfd_getl16 (ver.minor)); -+ } -+ } -+ -+ if (eiha_off != 0) -+ { -+ struct vms_eiha eiha; -+ -+ if (bfd_seek (abfd, (file_ptr) eiha_off, SEEK_SET) -+ || bfd_bread (&eiha, sizeof (eiha), abfd) != sizeof (eiha)) -+ { -+ fprintf (file, _("cannot read EIHA\n")); -+ return; -+ } -+ fprintf (file, _("Image activation: (size=%u)\n"), -+ (unsigned)bfd_getl32 (eiha.size)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" First address : 0x%08x 0x%08x\n"), -+ (unsigned)bfd_getl32 (eiha.tfradr1_h), -+ (unsigned)bfd_getl32 (eiha.tfradr1)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" Second address: 0x%08x 0x%08x\n"), -+ (unsigned)bfd_getl32 (eiha.tfradr2_h), -+ (unsigned)bfd_getl32 (eiha.tfradr2)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" Third address : 0x%08x 0x%08x\n"), -+ (unsigned)bfd_getl32 (eiha.tfradr3_h), -+ (unsigned)bfd_getl32 (eiha.tfradr3)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" Fourth address: 0x%08x 0x%08x\n"), -+ (unsigned)bfd_getl32 (eiha.tfradr4_h), -+ (unsigned)bfd_getl32 (eiha.tfradr4)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" Shared image : 0x%08x 0x%08x\n"), -+ (unsigned)bfd_getl32 (eiha.inishr_h), -+ (unsigned)bfd_getl32 (eiha.inishr)); -+ } -+ if (eihi_off != 0) -+ { -+ struct vms_eihi eihi; -+ -+ if (bfd_seek (abfd, (file_ptr) eihi_off, SEEK_SET) -+ || bfd_bread (&eihi, sizeof (eihi), abfd) != sizeof (eihi)) -+ { -+ fprintf (file, _("cannot read EIHI\n")); -+ return; -+ } -+ /* xgettext:c-format */ -+ fprintf (file, _("Image identification: (major: %u, minor: %u)\n"), -+ (unsigned)bfd_getl32 (eihi.majorid), -+ (unsigned)bfd_getl32 (eihi.minorid)); -+ fprintf (file, _(" image name : %.*s\n"), -+ eihi.imgnam[0], eihi.imgnam + 1); -+ fprintf (file, _(" link time : %s\n"), -+ vms_time_to_str (eihi.linktime)); -+ fprintf (file, _(" image ident : %.*s\n"), -+ eihi.imgid[0], eihi.imgid + 1); -+ fprintf (file, _(" linker ident : %.*s\n"), -+ eihi.linkid[0], eihi.linkid + 1); -+ fprintf (file, _(" image build ident: %.*s\n"), -+ eihi.imgbid[0], eihi.imgbid + 1); -+ } -+ if (eihs_off != 0) -+ { -+ struct vms_eihs eihs; -+ -+ if (bfd_seek (abfd, (file_ptr) eihs_off, SEEK_SET) -+ || bfd_bread (&eihs, sizeof (eihs), abfd) != sizeof (eihs)) -+ { -+ fprintf (file, _("cannot read EIHS\n")); -+ return; -+ } -+ /* xgettext:c-format */ -+ fprintf (file, _("Image symbol & debug table: (major: %u, minor: %u)\n"), -+ (unsigned)bfd_getl32 (eihs.majorid), -+ (unsigned)bfd_getl32 (eihs.minorid)); -+ dst_vbn = bfd_getl32 (eihs.dstvbn); -+ dst_size = bfd_getl32 (eihs.dstsize); -+ /* xgettext:c-format */ -+ fprintf (file, _(" debug symbol table : vbn: %u, size: %u (0x%x)\n"), -+ dst_vbn, dst_size, dst_size); -+ gst_vbn = bfd_getl32 (eihs.gstvbn); -+ gst_size = bfd_getl32 (eihs.gstsize); -+ /* xgettext:c-format */ -+ fprintf (file, _(" global symbol table: vbn: %u, records: %u\n"), -+ gst_vbn, gst_size); -+ dmt_vbn = bfd_getl32 (eihs.dmtvbn); -+ dmt_size = bfd_getl32 (eihs.dmtsize); -+ /* xgettext:c-format */ -+ fprintf (file, _(" debug module table : vbn: %u, size: %u\n"), -+ dmt_vbn, dmt_size); -+ } -+ while (eisd_off != 0) -+ { -+ struct vms_eisd eisd; -+ unsigned int len; -+ -+ while (1) -+ { -+ if (bfd_seek (abfd, (file_ptr) eisd_off, SEEK_SET) -+ || bfd_bread (&eisd, sizeof (eisd), abfd) != sizeof (eisd)) -+ { -+ fprintf (file, _("cannot read EISD\n")); -+ return; -+ } -+ len = (unsigned)bfd_getl32 (eisd.eisdsize); -+ if (len != (unsigned)-1) -+ break; -+ -+ /* Next block. */ -+ eisd_off = (eisd_off + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1); -+ } -+ /* xgettext:c-format */ -+ fprintf (file, _("Image section descriptor: (major: %u, minor: %u, " -+ "size: %u, offset: %u)\n"), -+ (unsigned)bfd_getl32 (eisd.majorid), -+ (unsigned)bfd_getl32 (eisd.minorid), -+ len, eisd_off); -+ if (len == 0) -+ break; -+ /* xgettext:c-format */ -+ fprintf (file, _(" section: base: 0x%08x%08x size: 0x%08x\n"), -+ (unsigned)bfd_getl32 (eisd.virt_addr + 4), -+ (unsigned)bfd_getl32 (eisd.virt_addr + 0), -+ (unsigned)bfd_getl32 (eisd.secsize)); -+ val = (unsigned)bfd_getl32 (eisd.flags); -+ fprintf (file, _(" flags: 0x%04x"), val); -+ if (val & EISD__M_GBL) -+ fprintf (file, " GBL"); -+ if (val & EISD__M_CRF) -+ fprintf (file, " CRF"); -+ if (val & EISD__M_DZRO) -+ fprintf (file, " DZRO"); -+ if (val & EISD__M_WRT) -+ fprintf (file, " WRT"); -+ if (val & EISD__M_INITALCODE) -+ fprintf (file, " INITALCODE"); -+ if (val & EISD__M_BASED) -+ fprintf (file, " BASED"); -+ if (val & EISD__M_FIXUPVEC) -+ fprintf (file, " FIXUPVEC"); -+ if (val & EISD__M_RESIDENT) -+ fprintf (file, " RESIDENT"); -+ if (val & EISD__M_VECTOR) -+ fprintf (file, " VECTOR"); -+ if (val & EISD__M_PROTECT) -+ fprintf (file, " PROTECT"); -+ if (val & EISD__M_LASTCLU) -+ fprintf (file, " LASTCLU"); -+ if (val & EISD__M_EXE) -+ fprintf (file, " EXE"); -+ if (val & EISD__M_NONSHRADR) -+ fprintf (file, " NONSHRADR"); -+ if (val & EISD__M_QUAD_LENGTH) -+ fprintf (file, " QUAD_LENGTH"); -+ if (val & EISD__M_ALLOC_64BIT) -+ fprintf (file, " ALLOC_64BIT"); -+ fprintf (file, "\n"); -+ if (val & EISD__M_FIXUPVEC) -+ { -+ eiaf_vbn = bfd_getl32 (eisd.vbn); -+ eiaf_size = bfd_getl32 (eisd.secsize); -+ } -+ /* xgettext:c-format */ -+ fprintf (file, _(" vbn: %u, pfc: %u, matchctl: %u type: %u ("), -+ (unsigned)bfd_getl32 (eisd.vbn), -+ eisd.pfc, eisd.matchctl, eisd.type); -+ switch (eisd.type) -+ { -+ case EISD__K_NORMAL: -+ fputs (_("NORMAL"), file); -+ break; -+ case EISD__K_SHRFXD: -+ fputs (_("SHRFXD"), file); -+ break; -+ case EISD__K_PRVFXD: -+ fputs (_("PRVFXD"), file); -+ break; -+ case EISD__K_SHRPIC: -+ fputs (_("SHRPIC"), file); -+ break; -+ case EISD__K_PRVPIC: -+ fputs (_("PRVPIC"), file); -+ break; -+ case EISD__K_USRSTACK: -+ fputs (_("USRSTACK"), file); -+ break; -+ default: -+ fputs (_("*unknown*"), file); -+ break; -+ } -+ fputs (_(")\n"), file); -+ if (val & EISD__M_GBL) -+ /* xgettext:c-format */ -+ fprintf (file, _(" ident: 0x%08x, name: %.*s\n"), -+ (unsigned)bfd_getl32 (eisd.ident), -+ eisd.gblnam[0], eisd.gblnam + 1); -+ eisd_off += len; -+ } -+ -+ if (dmt_vbn != 0) -+ { -+ if (bfd_seek (abfd, (file_ptr) (dmt_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET)) -+ { -+ fprintf (file, _("cannot read DMT\n")); -+ return; -+ } -+ -+ fprintf (file, _("Debug module table:\n")); -+ -+ while (dmt_size > 0) -+ { -+ struct vms_dmt_header dmth; -+ unsigned int count; -+ -+ if (bfd_bread (&dmth, sizeof (dmth), abfd) != sizeof (dmth)) -+ { -+ fprintf (file, _("cannot read DMT header\n")); -+ return; -+ } -+ count = bfd_getl16 (dmth.psect_count); -+ fprintf (file, -+ /* xgettext:c-format */ -+ _(" module offset: 0x%08x, size: 0x%08x, (%u psects)\n"), -+ (unsigned)bfd_getl32 (dmth.modbeg), -+ (unsigned)bfd_getl32 (dmth.size), count); -+ dmt_size -= sizeof (dmth); -+ while (count > 0) -+ { -+ struct vms_dmt_psect dmtp; -+ -+ if (bfd_bread (&dmtp, sizeof (dmtp), abfd) != sizeof (dmtp)) -+ { -+ fprintf (file, _("cannot read DMT psect\n")); -+ return; -+ } -+ /* xgettext:c-format */ -+ fprintf (file, _(" psect start: 0x%08x, length: %u\n"), -+ (unsigned)bfd_getl32 (dmtp.start), -+ (unsigned)bfd_getl32 (dmtp.length)); -+ count--; -+ dmt_size -= sizeof (dmtp); -+ } -+ } -+ } -+ -+ if (dst_vbn != 0) -+ { -+ if (bfd_seek (abfd, (file_ptr) (dst_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET)) -+ { -+ fprintf (file, _("cannot read DST\n")); -+ return; -+ } -+ -+ evax_bfd_print_dst (abfd, dst_size, file); -+ } -+ if (gst_vbn != 0) -+ { -+ if (bfd_seek (abfd, (file_ptr) (gst_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET)) -+ { -+ fprintf (file, _("cannot read GST\n")); -+ return; -+ } -+ -+ fprintf (file, _("Global symbol table:\n")); -+ evax_bfd_print_eobj (abfd, file); -+ } -+ if (eiaf_vbn != 0 && eiaf_size >= sizeof (struct vms_eiaf)) -+ { -+ unsigned char *buf; -+ struct vms_eiaf *eiaf; -+ unsigned int qrelfixoff; -+ unsigned int lrelfixoff; -+ unsigned int qdotadroff; -+ unsigned int ldotadroff; -+ unsigned int shrimgcnt; -+ unsigned int shlstoff; -+ unsigned int codeadroff; -+ unsigned int lpfixoff; -+ unsigned int chgprtoff; -+ -+ buf = bfd_malloc (eiaf_size); -+ -+ if (bfd_seek (abfd, (file_ptr) (eiaf_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET) -+ || bfd_bread (buf, eiaf_size, abfd) != eiaf_size) -+ { -+ fprintf (file, _("cannot read EIHA\n")); -+ free (buf); -+ return; -+ } -+ eiaf = (struct vms_eiaf *)buf; -+ fprintf (file, -+ /* xgettext:c-format */ -+ _("Image activator fixup: (major: %u, minor: %u)\n"), -+ (unsigned)bfd_getl32 (eiaf->majorid), -+ (unsigned)bfd_getl32 (eiaf->minorid)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" iaflink : 0x%08x %08x\n"), -+ (unsigned)bfd_getl32 (eiaf->iaflink + 0), -+ (unsigned)bfd_getl32 (eiaf->iaflink + 4)); -+ /* xgettext:c-format */ -+ fprintf (file, _(" fixuplnk: 0x%08x %08x\n"), -+ (unsigned)bfd_getl32 (eiaf->fixuplnk + 0), -+ (unsigned)bfd_getl32 (eiaf->fixuplnk + 4)); -+ fprintf (file, _(" size : %u\n"), -+ (unsigned)bfd_getl32 (eiaf->size)); -+ fprintf (file, _(" flags: 0x%08x\n"), -+ (unsigned)bfd_getl32 (eiaf->flags)); -+ qrelfixoff = bfd_getl32 (eiaf->qrelfixoff); -+ lrelfixoff = bfd_getl32 (eiaf->lrelfixoff); -+ /* xgettext:c-format */ -+ fprintf (file, _(" qrelfixoff: %5u, lrelfixoff: %5u\n"), -+ qrelfixoff, lrelfixoff); -+ qdotadroff = bfd_getl32 (eiaf->qdotadroff); -+ ldotadroff = bfd_getl32 (eiaf->ldotadroff); -+ /* xgettext:c-format */ -+ fprintf (file, _(" qdotadroff: %5u, ldotadroff: %5u\n"), -+ qdotadroff, ldotadroff); -+ codeadroff = bfd_getl32 (eiaf->codeadroff); -+ lpfixoff = bfd_getl32 (eiaf->lpfixoff); -+ /* xgettext:c-format */ -+ fprintf (file, _(" codeadroff: %5u, lpfixoff : %5u\n"), -+ codeadroff, lpfixoff); -+ chgprtoff = bfd_getl32 (eiaf->chgprtoff); -+ fprintf (file, _(" chgprtoff : %5u\n"), chgprtoff); -+ shrimgcnt = bfd_getl32 (eiaf->shrimgcnt); -+ shlstoff = bfd_getl32 (eiaf->shlstoff); -+ /* xgettext:c-format */ -+ fprintf (file, _(" shlstoff : %5u, shrimgcnt : %5u\n"), -+ shlstoff, shrimgcnt); -+ /* xgettext:c-format */ -+ fprintf (file, _(" shlextra : %5u, permctx : %5u\n"), -+ (unsigned)bfd_getl32 (eiaf->shlextra), -+ (unsigned)bfd_getl32 (eiaf->permctx)); -+ fprintf (file, _(" base_va : 0x%08x\n"), -+ (unsigned)bfd_getl32 (eiaf->base_va)); -+ fprintf (file, _(" lppsbfixoff: %5u\n"), -+ (unsigned)bfd_getl32 (eiaf->lppsbfixoff)); -+ -+ if (shlstoff) -+ { -+ //struct vms_shl *shl = (struct vms_shl *)(buf + shlstoff); -+ unsigned int j; -+ -+ fprintf (file, _(" Shareable images:\n")); -+ for (j = 0; -+ j < shrimgcnt && shlstoff <= eiaf_size - sizeof (struct vms_shl); -+ j++, shlstoff += sizeof (struct vms_shl)) -+ { -+ struct vms_shl *shl = (struct vms_shl *) (buf + shlstoff); -+ fprintf (file, -+ /* xgettext:c-format */ -+ _(" %u: size: %u, flags: 0x%02x, name: %.*s\n"), -+ j, shl->size, shl->flags, -+ shl->imgnam[0], shl->imgnam + 1); -+ } -+ } -+ if (qrelfixoff != 0) -+ { -+ fprintf (file, _(" quad-word relocation fixups:\n")); -+ evax_bfd_print_relocation_records (file, buf, eiaf_size, -+ qrelfixoff, 8); -+ } -+ if (lrelfixoff != 0) -+ { -+ fprintf (file, _(" long-word relocation fixups:\n")); -+ evax_bfd_print_relocation_records (file, buf, eiaf_size, -+ lrelfixoff, 4); -+ } -+ if (qdotadroff != 0) -+ { -+ fprintf (file, _(" quad-word .address reference fixups:\n")); -+ evax_bfd_print_address_fixups (file, buf, eiaf_size, qdotadroff); -+ } -+ if (ldotadroff != 0) -+ { -+ fprintf (file, _(" long-word .address reference fixups:\n")); -+ evax_bfd_print_address_fixups (file, buf, eiaf_size, ldotadroff); -+ } -+ if (codeadroff != 0) -+ { -+ fprintf (file, _(" Code Address Reference Fixups:\n")); -+ evax_bfd_print_reference_fixups (file, buf, eiaf_size, codeadroff); -+ } -+ if (lpfixoff != 0) -+ { -+ fprintf (file, _(" Linkage Pairs Reference Fixups:\n")); -+ evax_bfd_print_reference_fixups (file, buf, eiaf_size, lpfixoff); -+ } -+ if (chgprtoff && chgprtoff <= eiaf_size - 4) -+ { -+ unsigned int count = (unsigned) bfd_getl32 (buf + chgprtoff); -+ unsigned int j; -+ -+ fprintf (file, _(" Change Protection (%u entries):\n"), count); -+ for (j = 0, chgprtoff += 4; -+ j < count && chgprtoff <= eiaf_size - sizeof (struct vms_eicp); -+ j++, chgprtoff += sizeof (struct vms_eicp)) -+ { -+ struct vms_eicp *eicp = (struct vms_eicp *) (buf + chgprtoff); -+ unsigned int prot = bfd_getl32 (eicp->newprt); -+ fprintf (file, -+ /* xgettext:c-format */ -+ _(" base: 0x%08x %08x, size: 0x%08x, prot: 0x%08x "), -+ (unsigned) bfd_getl32 (eicp->baseva + 4), -+ (unsigned) bfd_getl32 (eicp->baseva + 0), -+ (unsigned) bfd_getl32 (eicp->size), -+ (unsigned) bfd_getl32 (eicp->newprt)); -+ switch (prot) -+ { -+ case PRT__C_NA: -+ fprintf (file, "NA"); -+ break; -+ case PRT__C_RESERVED: -+ fprintf (file, "RES"); -+ break; -+ case PRT__C_KW: -+ fprintf (file, "KW"); -+ break; -+ case PRT__C_KR: -+ fprintf (file, "KR"); -+ break; -+ case PRT__C_UW: -+ fprintf (file, "UW"); -+ break; -+ case PRT__C_EW: -+ fprintf (file, "EW"); -+ break; -+ case PRT__C_ERKW: -+ fprintf (file, "ERKW"); -+ break; -+ case PRT__C_ER: -+ fprintf (file, "ER"); -+ break; -+ case PRT__C_SW: -+ fprintf (file, "SW"); -+ break; -+ case PRT__C_SREW: -+ fprintf (file, "SREW"); -+ break; -+ case PRT__C_SRKW: -+ fprintf (file, "SRKW"); -+ break; -+ case PRT__C_SR: -+ fprintf (file, "SR"); -+ break; -+ case PRT__C_URSW: -+ fprintf (file, "URSW"); -+ break; -+ case PRT__C_UREW: -+ fprintf (file, "UREW"); -+ break; -+ case PRT__C_URKW: -+ fprintf (file, "URKW"); -+ break; -+ case PRT__C_UR: -+ fprintf (file, "UR"); -+ break; -+ default: -+ fputs ("??", file); -+ break; -+ } -+ fputc ('\n', file); -+ } -+ } -+ free (buf); -+ } -+} -+ -+static bfd_boolean -+vms_bfd_print_private_bfd_data (bfd *abfd, void *ptr) -+{ -+ FILE *file = (FILE *)ptr; -+ -+ if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) -+ evax_bfd_print_image (abfd, file); -+ else -+ { -+ if (bfd_seek (abfd, 0, SEEK_SET)) -+ return FALSE; -+ evax_bfd_print_eobj (abfd, file); -+ } -+ return TRUE; -+} -+ -+/* Linking. */ -+ -+/* Slurp ETIR/EDBG/ETBT VMS object records. */ -+ -+static bfd_boolean -+sw_64_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info) -+{ -+ asection *cur_section; -+ file_ptr cur_offset; -+ asection *dst_section; -+ file_ptr dst_offset; -+ -+ if (bfd_seek (abfd, 0, SEEK_SET) != 0) -+ return FALSE; -+ -+ cur_section = NULL; -+ cur_offset = 0; -+ -+ dst_section = PRIV (dst_section); -+ dst_offset = 0; -+ if (info) -+ { -+ if (info->strip == strip_all || info->strip == strip_debugger) -+ { -+ /* Discard the DST section. */ -+ dst_offset = 0; -+ dst_section = NULL; -+ } -+ else if (dst_section) -+ { -+ dst_offset = dst_section->output_offset; -+ dst_section = dst_section->output_section; -+ } -+ } -+ -+ while (1) -+ { -+ int type; -+ bfd_boolean res; -+ -+ type = _bfd_vms_get_object_record (abfd); -+ if (type < 0) -+ { -+ vms_debug2 ((2, "next_record failed\n")); -+ return FALSE; -+ } -+ switch (type) -+ { -+ case EOBJ__C_ETIR: -+ PRIV (image_section) = cur_section; -+ PRIV (image_offset) = cur_offset; -+ res = _bfd_vms_slurp_etir (abfd, info); -+ cur_section = PRIV (image_section); -+ cur_offset = PRIV (image_offset); -+ break; -+ case EOBJ__C_EDBG: -+ case EOBJ__C_ETBT: -+ if (dst_section == NULL) -+ continue; -+ PRIV (image_section) = dst_section; -+ PRIV (image_offset) = dst_offset; -+ res = _bfd_vms_slurp_etir (abfd, info); -+ dst_offset = PRIV (image_offset); -+ break; -+ case EOBJ__C_EEOM: -+ return TRUE; -+ default: -+ continue; -+ } -+ if (!res) -+ { -+ vms_debug2 ((2, "slurp eobj type %d failed\n", type)); -+ return FALSE; -+ } -+ } -+} -+ -+static int -+sw_64_vms_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info ATTRIBUTE_UNUSED) -+{ -+ return 0; -+} -+ -+/* Add a linkage pair fixup at address SECT + OFFSET to SHLIB. */ -+ -+static void -+sw_64_vms_add_fixup_lp (struct bfd_link_info *info, bfd *src, bfd *shlib) -+{ -+ struct sw_64_vms_shlib_el *sl; -+ asection *sect = PRIV2 (src, image_section); -+ file_ptr offset = PRIV2 (src, image_offset); -+ -+ sl = &VEC_EL (sw_64_vms_link_hash (info)->shrlibs, -+ struct sw_64_vms_shlib_el, PRIV2 (shlib, shr_index)); -+ sl->has_fixups = TRUE; -+ VEC_APPEND_EL (sl->lp, bfd_vma, -+ sect->output_section->vma + sect->output_offset + offset); -+ sect->output_section->flags |= SEC_RELOC; -+} -+ -+/* Add a code address fixup at address SECT + OFFSET to SHLIB. */ -+ -+static void -+sw_64_vms_add_fixup_ca (struct bfd_link_info *info, bfd *src, bfd *shlib) -+{ -+ struct sw_64_vms_shlib_el *sl; -+ asection *sect = PRIV2 (src, image_section); -+ file_ptr offset = PRIV2 (src, image_offset); -+ -+ sl = &VEC_EL (sw_64_vms_link_hash (info)->shrlibs, -+ struct sw_64_vms_shlib_el, PRIV2 (shlib, shr_index)); -+ sl->has_fixups = TRUE; -+ VEC_APPEND_EL (sl->ca, bfd_vma, -+ sect->output_section->vma + sect->output_offset + offset); -+ sect->output_section->flags |= SEC_RELOC; -+} -+ -+/* Add a quad word relocation fixup at address SECT + OFFSET to SHLIB. */ -+ -+static void -+sw_64_vms_add_fixup_qr (struct bfd_link_info *info, bfd *src, -+ bfd *shlib, bfd_vma vec) -+{ -+ struct sw_64_vms_shlib_el *sl; -+ struct sw_64_vms_vma_ref *r; -+ asection *sect = PRIV2 (src, image_section); -+ file_ptr offset = PRIV2 (src, image_offset); -+ -+ sl = &VEC_EL (sw_64_vms_link_hash (info)->shrlibs, -+ struct sw_64_vms_shlib_el, PRIV2 (shlib, shr_index)); -+ sl->has_fixups = TRUE; -+ r = VEC_APPEND (sl->qr, struct sw_64_vms_vma_ref); -+ r->vma = sect->output_section->vma + sect->output_offset + offset; -+ r->ref = vec; -+ sect->output_section->flags |= SEC_RELOC; -+} -+ -+static void -+sw_64_vms_add_fixup_lr (struct bfd_link_info *info ATTRIBUTE_UNUSED, -+ unsigned int shr ATTRIBUTE_UNUSED, -+ bfd_vma vec ATTRIBUTE_UNUSED) -+{ -+ /* Not yet supported. */ -+ abort (); -+} -+ -+/* Add relocation. FIXME: Not yet emitted. */ -+ -+static void -+sw_64_vms_add_lw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED) -+{ -+} -+ -+static void -+sw_64_vms_add_qw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED) -+{ -+} -+ -+static struct bfd_hash_entry * -+sw_64_vms_link_hash_newfunc (struct bfd_hash_entry *entry, -+ struct bfd_hash_table *table, -+ const char *string) -+{ -+ struct sw_64_vms_link_hash_entry *ret = -+ (struct sw_64_vms_link_hash_entry *) entry; -+ -+ /* Allocate the structure if it has not already been allocated by a -+ subclass. */ -+ if (ret == NULL) -+ ret = ((struct sw_64_vms_link_hash_entry *) -+ bfd_hash_allocate (table, -+ sizeof (struct sw_64_vms_link_hash_entry))); -+ if (ret == NULL) -+ return NULL; -+ -+ /* Call the allocation method of the superclass. */ -+ ret = ((struct sw_64_vms_link_hash_entry *) -+ _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, -+ table, string)); -+ -+ ret->sym = NULL; -+ -+ return (struct bfd_hash_entry *) ret; -+} -+ -+static void -+sw_64_vms_bfd_link_hash_table_free (bfd *abfd) -+{ -+ struct sw_64_vms_link_hash_table *t; -+ unsigned i; -+ -+ t = (struct sw_64_vms_link_hash_table *) abfd->link.hash; -+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -+ { -+ struct sw_64_vms_shlib_el *shlib; -+ -+ shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -+ free (&VEC_EL (shlib->ca, bfd_vma, 0)); -+ free (&VEC_EL (shlib->lp, bfd_vma, 0)); -+ free (&VEC_EL (shlib->qr, struct sw_64_vms_vma_ref, 0)); -+ } -+ free (&VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, 0)); -+ -+ _bfd_generic_link_hash_table_free (abfd); -+} -+ -+/* Create an Sw_64/VMS link hash table. */ -+ -+static struct bfd_link_hash_table * -+sw_64_vms_bfd_link_hash_table_create (bfd *abfd) -+{ -+ struct sw_64_vms_link_hash_table *ret; -+ bfd_size_type amt = sizeof (struct sw_64_vms_link_hash_table); -+ -+ ret = (struct sw_64_vms_link_hash_table *) bfd_malloc (amt); -+ if (ret == NULL) -+ return NULL; -+ if (!_bfd_link_hash_table_init (&ret->root, abfd, -+ sw_64_vms_link_hash_newfunc, -+ sizeof (struct sw_64_vms_link_hash_entry))) -+ { -+ free (ret); -+ return NULL; -+ } -+ -+ VEC_INIT (ret->shrlibs); -+ ret->fixup = NULL; -+ ret->root.hash_table_free = sw_64_vms_bfd_link_hash_table_free; -+ -+ return &ret->root; -+} -+ -+static bfd_boolean -+sw_64_vms_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < PRIV (gsd_sym_count); i++) -+ { -+ struct vms_symbol_entry *e = PRIV (syms)[i]; -+ struct sw_64_vms_link_hash_entry *h; -+ struct bfd_link_hash_entry *h_root; -+ asymbol sym; -+ -+ if (!sw_64_vms_convert_symbol (abfd, e, &sym)) -+ return FALSE; -+ -+ if ((e->flags & EGSY__V_DEF) && abfd->selective_search) -+ { -+ /* In selective_search mode, only add definition that are -+ required. */ -+ h = (struct sw_64_vms_link_hash_entry *)bfd_link_hash_lookup -+ (info->hash, sym.name, FALSE, FALSE, FALSE); -+ if (h == NULL || h->root.type != bfd_link_hash_undefined) -+ continue; -+ } -+ else -+ h = NULL; -+ -+ h_root = (struct bfd_link_hash_entry *) h; -+ if (!_bfd_generic_link_add_one_symbol (info, abfd, sym.name, sym.flags, -+ sym.section, sym.value, NULL, -+ FALSE, FALSE, &h_root)) -+ return FALSE; -+ h = (struct sw_64_vms_link_hash_entry *) h_root; -+ -+ if ((e->flags & EGSY__V_DEF) -+ && h->sym == NULL -+ && abfd->xvec == info->output_bfd->xvec) -+ h->sym = e; -+ } -+ -+ if (abfd->flags & DYNAMIC) -+ { -+ struct sw_64_vms_shlib_el *shlib; -+ -+ /* We do not want to include any of the sections in a dynamic -+ object in the output file. See comment in elflink.c. */ -+ bfd_section_list_clear (abfd); -+ -+ shlib = VEC_APPEND (sw_64_vms_link_hash (info)->shrlibs, -+ struct sw_64_vms_shlib_el); -+ shlib->abfd = abfd; -+ VEC_INIT (shlib->ca); -+ VEC_INIT (shlib->lp); -+ VEC_INIT (shlib->qr); -+ PRIV (shr_index) = VEC_COUNT (sw_64_vms_link_hash (info)->shrlibs) - 1; -+ } -+ -+ return TRUE; -+} -+ -+static bfd_boolean -+sw_64_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) -+{ -+ int pass; -+ struct bfd_link_hash_entry **pundef; -+ struct bfd_link_hash_entry **next_pundef; -+ -+ /* We only accept VMS libraries. */ -+ if (info->output_bfd->xvec != abfd->xvec) -+ { -+ bfd_set_error (bfd_error_wrong_format); -+ return FALSE; -+ } -+ -+ /* The archive_pass field in the archive itself is used to -+ initialize PASS, since we may search the same archive multiple -+ times. */ -+ pass = ++abfd->archive_pass; -+ -+ /* Look through the list of undefined symbols. */ -+ for (pundef = &info->hash->undefs; *pundef != NULL; pundef = next_pundef) -+ { -+ struct bfd_link_hash_entry *h; -+ symindex symidx; -+ bfd *element; -+ bfd *orig_element; -+ -+ h = *pundef; -+ next_pundef = &(*pundef)->u.undef.next; -+ -+ /* 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 = *next_pundef; -+ next_pundef = pundef; -+ } -+ continue; -+ } -+ -+ /* Look for this symbol in the archive hash table. */ -+ symidx = _bfd_vms_lib_find_symbol (abfd, h->root.string); -+ if (symidx == BFD_NO_MORE_SYMBOLS) -+ { -+ /* Nothing in this slot. */ -+ continue; -+ } -+ -+ element = bfd_get_elt_at_index (abfd, symidx); -+ if (element == NULL) -+ return FALSE; -+ -+ if (element->archive_pass == -1 || element->archive_pass == pass) -+ { -+ /* Next symbol if this archive is wrong or already handled. */ -+ continue; -+ } -+ -+ if (! bfd_check_format (element, bfd_object)) -+ { -+ element->archive_pass = -1; -+ return FALSE; -+ } -+ -+ orig_element = element; -+ if (bfd_is_thin_archive (abfd)) -+ { -+ element = _bfd_vms_lib_get_imagelib_file (element); -+ if (element == NULL || !bfd_check_format (element, bfd_object)) -+ { -+ orig_element->archive_pass = -1; -+ 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, h->root.string, &element)) -+ continue; -+ if (!sw_64_vms_link_add_object_symbols (element, info)) -+ return FALSE; -+ -+ orig_element->archive_pass = pass; -+ } -+ -+ return TRUE; -+} -+ -+static bfd_boolean -+sw_64_vms_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info) -+{ -+ switch (bfd_get_format (abfd)) -+ { -+ case bfd_object: -+ vms_debug2 ((2, "vms_link_add_symbols for object %s\n", -+ abfd->filename)); -+ return sw_64_vms_link_add_object_symbols (abfd, info); -+ break; -+ case bfd_archive: -+ vms_debug2 ((2, "vms_link_add_symbols for archive %s\n", -+ abfd->filename)); -+ return sw_64_vms_link_add_archive_symbols (abfd, info); -+ break; -+ default: -+ bfd_set_error (bfd_error_wrong_format); -+ return FALSE; -+ } -+} -+ -+static bfd_boolean -+sw_64_vms_build_fixups (struct bfd_link_info *info) -+{ -+ struct sw_64_vms_link_hash_table *t = sw_64_vms_link_hash (info); -+ unsigned char *content; -+ unsigned int i; -+ unsigned int sz = 0; -+ unsigned int lp_sz = 0; -+ unsigned int ca_sz = 0; -+ unsigned int qr_sz = 0; -+ unsigned int shrimg_cnt = 0; -+ unsigned int chgprt_num = 0; -+ unsigned int chgprt_sz = 0; -+ struct vms_eiaf *eiaf; -+ unsigned int off; -+ asection *sec; -+ -+ /* Shared libraries. */ -+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -+ { -+ struct sw_64_vms_shlib_el *shlib; -+ -+ shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -+ -+ if (!shlib->has_fixups) -+ continue; -+ -+ shrimg_cnt++; -+ -+ if (VEC_COUNT (shlib->ca) > 0) -+ { -+ /* Header + entries. */ -+ ca_sz += 8; -+ ca_sz += VEC_COUNT (shlib->ca) * 4; -+ } -+ if (VEC_COUNT (shlib->lp) > 0) -+ { -+ /* Header + entries. */ -+ lp_sz += 8; -+ lp_sz += VEC_COUNT (shlib->lp) * 4; -+ } -+ if (VEC_COUNT (shlib->qr) > 0) -+ { -+ /* Header + entries. */ -+ qr_sz += 8; -+ qr_sz += VEC_COUNT (shlib->qr) * 8; -+ } -+ } -+ /* Add markers. */ -+ if (ca_sz > 0) -+ ca_sz += 8; -+ if (lp_sz > 0) -+ lp_sz += 8; -+ if (qr_sz > 0) -+ qr_sz += 8; -+ -+ /* Finish now if there is no content. */ -+ if (ca_sz + lp_sz + qr_sz == 0) -+ return TRUE; -+ -+ /* Add an eicp entry for the fixup itself. */ -+ chgprt_num = 1; -+ for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next) -+ { -+ /* This isect could be made RO or EXE after relocations are applied. */ -+ if ((sec->flags & SEC_RELOC) != 0 -+ && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) -+ chgprt_num++; -+ } -+ chgprt_sz = 4 + chgprt_num * sizeof (struct vms_eicp); -+ -+ /* Allocate section content (round-up size) */ -+ sz = sizeof (struct vms_eiaf) + shrimg_cnt * sizeof (struct vms_shl) -+ + ca_sz + lp_sz + qr_sz + chgprt_sz; -+ sz = (sz + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1); -+ content = bfd_zalloc (info->output_bfd, sz); -+ if (content == NULL) -+ return FALSE; -+ -+ sec = sw_64_vms_link_hash (info)->fixup; -+ sec->contents = content; -+ sec->size = sz; -+ -+ eiaf = (struct vms_eiaf *)content; -+ off = sizeof (struct vms_eiaf); -+ bfd_putl32 (0, eiaf->majorid); -+ bfd_putl32 (0, eiaf->minorid); -+ bfd_putl32 (0, eiaf->iaflink); -+ bfd_putl32 (0, eiaf->fixuplnk); -+ bfd_putl32 (sizeof (struct vms_eiaf), eiaf->size); -+ bfd_putl32 (0, eiaf->flags); -+ bfd_putl32 (0, eiaf->qrelfixoff); -+ bfd_putl32 (0, eiaf->lrelfixoff); -+ bfd_putl32 (0, eiaf->qdotadroff); -+ bfd_putl32 (0, eiaf->ldotadroff); -+ bfd_putl32 (0, eiaf->codeadroff); -+ bfd_putl32 (0, eiaf->lpfixoff); -+ bfd_putl32 (0, eiaf->chgprtoff); -+ bfd_putl32 (shrimg_cnt ? off : 0, eiaf->shlstoff); -+ bfd_putl32 (shrimg_cnt, eiaf->shrimgcnt); -+ bfd_putl32 (0, eiaf->shlextra); -+ bfd_putl32 (0, eiaf->permctx); -+ bfd_putl32 (0, eiaf->base_va); -+ bfd_putl32 (0, eiaf->lppsbfixoff); -+ -+ if (shrimg_cnt) -+ { -+ shrimg_cnt = 0; -+ -+ /* Write shl. */ -+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -+ { -+ struct sw_64_vms_shlib_el *shlib; -+ struct vms_shl *shl; -+ -+ shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -+ -+ if (!shlib->has_fixups) -+ continue; -+ -+ /* Renumber shared images. */ -+ PRIV2 (shlib->abfd, shr_index) = shrimg_cnt++; -+ -+ shl = (struct vms_shl *)(content + off); -+ bfd_putl32 (0, shl->baseva); -+ bfd_putl32 (0, shl->shlptr); -+ bfd_putl32 (0, shl->ident); -+ bfd_putl32 (0, shl->permctx); -+ shl->size = sizeof (struct vms_shl); -+ bfd_putl16 (0, shl->fill_1); -+ shl->flags = 0; -+ bfd_putl32 (0, shl->icb); -+ shl->imgnam[0] = strlen (PRIV2 (shlib->abfd, hdr_data.hdr_t_name)); -+ memcpy (shl->imgnam + 1, PRIV2 (shlib->abfd, hdr_data.hdr_t_name), -+ shl->imgnam[0]); -+ -+ off += sizeof (struct vms_shl); -+ } -+ -+ /* CA fixups. */ -+ if (ca_sz != 0) -+ { -+ bfd_putl32 (off, eiaf->codeadroff); -+ -+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -+ { -+ struct sw_64_vms_shlib_el *shlib; -+ unsigned int j; -+ -+ shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -+ -+ if (VEC_COUNT (shlib->ca) == 0) -+ continue; -+ -+ bfd_putl32 (VEC_COUNT (shlib->ca), content + off); -+ bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4); -+ off += 8; -+ -+ for (j = 0; j < VEC_COUNT (shlib->ca); j++) -+ { -+ bfd_putl32 (VEC_EL (shlib->ca, bfd_vma, j) - t->base_addr, -+ content + off); -+ off += 4; -+ } -+ } -+ -+ bfd_putl32 (0, content + off); -+ bfd_putl32 (0, content + off + 4); -+ off += 8; -+ } -+ -+ /* LP fixups. */ -+ if (lp_sz != 0) -+ { -+ bfd_putl32 (off, eiaf->lpfixoff); -+ -+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -+ { -+ struct sw_64_vms_shlib_el *shlib; -+ unsigned int j; -+ -+ shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -+ -+ if (VEC_COUNT (shlib->lp) == 0) -+ continue; -+ -+ bfd_putl32 (VEC_COUNT (shlib->lp), content + off); -+ bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4); -+ off += 8; -+ -+ for (j = 0; j < VEC_COUNT (shlib->lp); j++) -+ { -+ bfd_putl32 (VEC_EL (shlib->lp, bfd_vma, j) - t->base_addr, -+ content + off); -+ off += 4; -+ } -+ } -+ -+ bfd_putl32 (0, content + off); -+ bfd_putl32 (0, content + off + 4); -+ off += 8; -+ } -+ -+ /* QR fixups. */ -+ if (qr_sz != 0) -+ { -+ bfd_putl32 (off, eiaf->qdotadroff); -+ -+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++) -+ { -+ struct sw_64_vms_shlib_el *shlib; -+ unsigned int j; -+ -+ shlib = &VEC_EL (t->shrlibs, struct sw_64_vms_shlib_el, i); -+ -+ if (VEC_COUNT (shlib->qr) == 0) -+ continue; -+ -+ bfd_putl32 (VEC_COUNT (shlib->qr), content + off); -+ bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4); -+ off += 8; -+ -+ for (j = 0; j < VEC_COUNT (shlib->qr); j++) -+ { -+ struct sw_64_vms_vma_ref *r; -+ r = &VEC_EL (shlib->qr, struct sw_64_vms_vma_ref, j); -+ bfd_putl32 (r->vma - t->base_addr, content + off); -+ bfd_putl32 (r->ref, content + off + 4); -+ off += 8; -+ } -+ } -+ -+ bfd_putl32 (0, content + off); -+ bfd_putl32 (0, content + off + 4); -+ off += 8; -+ } -+ } -+ -+ /* Write the change protection table. */ -+ bfd_putl32 (off, eiaf->chgprtoff); -+ bfd_putl32 (chgprt_num, content + off); -+ off += 4; -+ -+ for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next) -+ { -+ struct vms_eicp *eicp; -+ unsigned int prot; -+ -+ if ((sec->flags & SEC_LINKER_CREATED) != 0 && -+ strcmp (sec->name, "$FIXUP$") == 0) -+ prot = PRT__C_UREW; -+ else if ((sec->flags & SEC_RELOC) != 0 -+ && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) -+ prot = PRT__C_UR; -+ else -+ continue; -+ -+ eicp = (struct vms_eicp *)(content + off); -+ bfd_putl64 (sec->vma - t->base_addr, eicp->baseva); -+ bfd_putl32 ((sec->size + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1), -+ eicp->size); -+ bfd_putl32 (prot, eicp->newprt); -+ off += sizeof (struct vms_eicp); -+ } -+ -+ return TRUE; -+} -+ -+/* Called by bfd_hash_traverse to fill the symbol table. -+ Return FALSE in case of failure. */ -+ -+static bfd_boolean -+sw_64_vms_link_output_symbol (struct bfd_hash_entry *bh, void *infov) -+{ -+ struct bfd_link_hash_entry *hc = (struct bfd_link_hash_entry *) bh; -+ struct bfd_link_info *info = (struct bfd_link_info *)infov; -+ struct sw_64_vms_link_hash_entry *h; -+ struct vms_symbol_entry *sym; -+ -+ if (hc->type == bfd_link_hash_warning) -+ { -+ hc = hc->u.i.link; -+ if (hc->type == bfd_link_hash_new) -+ return TRUE; -+ } -+ h = (struct sw_64_vms_link_hash_entry *) hc; -+ -+ switch (h->root.type) -+ { -+ case bfd_link_hash_undefined: -+ return TRUE; -+ case bfd_link_hash_new: -+ case bfd_link_hash_warning: -+ abort (); -+ case bfd_link_hash_undefweak: -+ return TRUE; -+ case bfd_link_hash_defined: -+ case bfd_link_hash_defweak: -+ { -+ asection *sec = h->root.u.def.section; -+ -+ /* FIXME: this is certainly a symbol from a dynamic library. */ -+ if (bfd_is_abs_section (sec)) -+ return TRUE; -+ -+ if (sec->owner->flags & DYNAMIC) -+ return TRUE; -+ } -+ break; -+ case bfd_link_hash_common: -+ break; -+ case bfd_link_hash_indirect: -+ return TRUE; -+ } -+ -+ /* Do not write not kept symbols. */ -+ if (info->strip == strip_some -+ && bfd_hash_lookup (info->keep_hash, h->root.root.string, -+ FALSE, FALSE) != NULL) -+ return TRUE; -+ -+ if (h->sym == NULL) -+ { -+ /* This symbol doesn't come from a VMS object. So we suppose it is -+ a data. */ -+ int len = strlen (h->root.root.string); -+ -+ sym = (struct vms_symbol_entry *)bfd_zalloc (info->output_bfd, -+ sizeof (*sym) + len); -+ if (sym == NULL) -+ abort (); -+ sym->namelen = len; -+ memcpy (sym->name, h->root.root.string, len); -+ sym->name[len] = 0; -+ sym->owner = info->output_bfd; -+ -+ sym->typ = EGSD__C_SYMG; -+ sym->data_type = 0; -+ sym->flags = EGSY__V_DEF | EGSY__V_REL; -+ sym->symbol_vector = h->root.u.def.value; -+ sym->section = h->root.u.def.section; -+ sym->value = h->root.u.def.value; -+ } -+ else -+ sym = h->sym; -+ -+ if (!add_symbol_entry (info->output_bfd, sym)) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+static bfd_boolean -+sw_64_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) -+{ -+ asection *o; -+ struct bfd_link_order *p; -+ bfd *sub; -+ asection *fixupsec; -+ bfd_vma base_addr; -+ bfd_vma last_addr; -+ asection *dst; -+ asection *dmt; -+ -+ if (bfd_link_relocatable (info)) -+ { -+ /* FIXME: we do not yet support relocatable link. It is not obvious -+ how to do it for debug infos. */ -+ (*info->callbacks->einfo)(_("%P: relocatable link is not supported\n")); -+ return FALSE; -+ } -+ -+ abfd->outsymbols = NULL; -+ abfd->symcount = 0; -+ -+ /* Mark all sections which will be included in the output file. */ -+ for (o = abfd->sections; o != NULL; o = o->next) -+ for (p = o->map_head.link_order; p != NULL; p = p->next) -+ if (p->type == bfd_indirect_link_order) -+ p->u.indirect.section->linker_mark = TRUE; -+ -+#if 0 -+ /* Handle all the link order information for the sections. */ -+ for (o = abfd->sections; o != NULL; o = o->next) -+ { -+ printf ("For section %s (at 0x%08x, flags=0x%08x):\n", -+ o->name, (unsigned)o->vma, (unsigned)o->flags); -+ -+ for (p = o->map_head.link_order; p != NULL; p = p->next) -+ { -+ printf (" at 0x%08x - 0x%08x: ", -+ (unsigned)p->offset, (unsigned)(p->offset + p->size - 1)); -+ switch (p->type) -+ { -+ case bfd_section_reloc_link_order: -+ case bfd_symbol_reloc_link_order: -+ printf (" section/symbol reloc\n"); -+ break; -+ case bfd_indirect_link_order: -+ printf (" section %s of %s\n", -+ p->u.indirect.section->name, -+ p->u.indirect.section->owner->filename); -+ break; -+ case bfd_data_link_order: -+ printf (" explicit data\n"); -+ break; -+ default: -+ printf (" *unknown* type %u\n", p->type); -+ break; -+ } -+ } -+ } -+#endif -+ -+ /* Generate the symbol table. */ -+ BFD_ASSERT (PRIV (syms) == NULL); -+ if (info->strip != strip_all) -+ bfd_hash_traverse (&info->hash->table, sw_64_vms_link_output_symbol, info); -+ -+ /* Find the entry point. */ -+ if (bfd_get_start_address (abfd) == 0) -+ { -+ bfd *startbfd = NULL; -+ -+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) -+ { -+ /* Consider only VMS object files. */ -+ if (sub->xvec != abfd->xvec) -+ continue; -+ -+ if (!PRIV2 (sub, eom_data).eom_has_transfer) -+ continue; -+ if ((PRIV2 (sub, eom_data).eom_b_tfrflg & EEOM__M_WKTFR) && startbfd) -+ continue; -+ if (startbfd != NULL -+ && !(PRIV2 (sub, eom_data).eom_b_tfrflg & EEOM__M_WKTFR)) -+ { -+ (*info->callbacks->einfo) -+ /* xgettext:c-format */ -+ (_("%P: multiple entry points: in modules %pB and %pB\n"), -+ startbfd, sub); -+ continue; -+ } -+ startbfd = sub; -+ } -+ -+ if (startbfd) -+ { -+ unsigned int ps_idx = PRIV2 (startbfd, eom_data).eom_l_psindx; -+ bfd_vma tfradr = PRIV2 (startbfd, eom_data).eom_l_tfradr; -+ asection *sec; -+ -+ sec = PRIV2 (startbfd, sections)[ps_idx]; -+ -+ bfd_set_start_address -+ (abfd, sec->output_section->vma + sec->output_offset + tfradr); -+ } -+ } -+ -+ /* Set transfer addresses. */ -+ { -+ int i; -+ struct bfd_link_hash_entry *h; -+ -+ i = 0; -+ PRIV (transfer_address[i++]) = 0xffffffff00000340ULL; /* SYS$IMGACT */ -+ h = bfd_link_hash_lookup (info->hash, "LIB$INITIALIZE", FALSE, FALSE, TRUE); -+ if (h != NULL && h->type == bfd_link_hash_defined) -+ PRIV (transfer_address[i++]) = -+ sw_64_vms_get_sym_value (h->u.def.section, h->u.def.value); -+ PRIV (transfer_address[i++]) = bfd_get_start_address (abfd); -+ while (i < 4) -+ PRIV (transfer_address[i++]) = 0; -+ } -+ -+ /* Allocate contents. -+ Also compute the virtual base address. */ -+ base_addr = (bfd_vma)-1; -+ last_addr = 0; -+ for (o = abfd->sections; o != NULL; o = o->next) -+ { -+ if (o->flags & SEC_HAS_CONTENTS) -+ { -+ o->contents = bfd_alloc (abfd, o->size); -+ if (o->contents == NULL) -+ return FALSE; -+ } -+ if (o->flags & SEC_LOAD) -+ { -+ if (o->vma < base_addr) -+ base_addr = o->vma; -+ if (o->vma + o->size > last_addr) -+ last_addr = o->vma + o->size; -+ } -+ /* Clear the RELOC flags. Currently we don't support incremental -+ linking. We use the RELOC flag for computing the eicp entries. */ -+ o->flags &= ~SEC_RELOC; -+ } -+ -+ /* Create the fixup section. */ -+ fixupsec = bfd_make_section_anyway_with_flags -+ (info->output_bfd, "$FIXUP$", -+ SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_LINKER_CREATED); -+ if (fixupsec == NULL) -+ return FALSE; -+ last_addr = (last_addr + 0xffff) & ~0xffff; -+ fixupsec->vma = last_addr; -+ -+ sw_64_vms_link_hash (info)->fixup = fixupsec; -+ sw_64_vms_link_hash (info)->base_addr = base_addr; -+ -+ /* Create the DMT section, if necessary. */ -+ BFD_ASSERT (PRIV (dst_section) == NULL); -+ dst = bfd_get_section_by_name (abfd, "$DST$"); -+ if (dst != NULL && dst->size == 0) -+ dst = NULL; -+ if (dst != NULL) -+ { -+ PRIV (dst_section) = dst; -+ dmt = bfd_make_section_anyway_with_flags -+ (info->output_bfd, "$DMT$", -+ SEC_DEBUGGING | SEC_HAS_CONTENTS | SEC_LINKER_CREATED); -+ if (dmt == NULL) -+ return FALSE; -+ } -+ else -+ dmt = NULL; -+ -+ /* Read all sections from the inputs. */ -+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) -+ { -+ if (sub->flags & DYNAMIC) -+ { -+ sw_64_vms_create_eisd_for_shared (abfd, sub); -+ continue; -+ } -+ -+ if (!sw_64_vms_read_sections_content (sub, info)) -+ return FALSE; -+ } -+ -+ /* Handle all the link order information for the sections. -+ Note: past this point, it is not possible to create new sections. */ -+ for (o = abfd->sections; o != NULL; o = o->next) -+ { -+ for (p = o->map_head.link_order; p != NULL; p = p->next) -+ { -+ switch (p->type) -+ { -+ case bfd_section_reloc_link_order: -+ case bfd_symbol_reloc_link_order: -+ abort (); -+ return FALSE; -+ case bfd_indirect_link_order: -+ /* Already done. */ -+ break; -+ default: -+ if (! _bfd_default_link_order (abfd, info, o, p)) -+ return FALSE; -+ break; -+ } -+ } -+ } -+ -+ /* Compute fixups. */ -+ if (!sw_64_vms_build_fixups (info)) -+ return FALSE; -+ -+ /* Compute the DMT. */ -+ if (dmt != NULL) -+ { -+ int pass; -+ unsigned char *contents = NULL; -+ -+ /* In pass 1, compute the size. In pass 2, write the DMT contents. */ -+ for (pass = 0; pass < 2; pass++) -+ { -+ unsigned int off = 0; -+ -+ /* For each object file (ie for each module). */ -+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) -+ { -+ asection *sub_dst; -+ struct vms_dmt_header *dmth = NULL; -+ unsigned int psect_count; -+ -+ /* Skip this module if it has no DST. */ -+ sub_dst = PRIV2 (sub, dst_section); -+ if (sub_dst == NULL || sub_dst->size == 0) -+ continue; -+ -+ if (pass == 1) -+ { -+ /* Write the header. */ -+ dmth = (struct vms_dmt_header *)(contents + off); -+ bfd_putl32 (sub_dst->output_offset, dmth->modbeg); -+ bfd_putl32 (sub_dst->size, dmth->size); -+ } -+ -+ off += sizeof (struct vms_dmt_header); -+ psect_count = 0; -+ -+ /* For each section (ie for each psect). */ -+ for (o = sub->sections; o != NULL; o = o->next) -+ { -+ /* Only consider interesting sections. */ -+ if (!(o->flags & SEC_ALLOC)) -+ continue; -+ if (o->flags & SEC_LINKER_CREATED) -+ continue; -+ -+ if (pass == 1) -+ { -+ /* Write an entry. */ -+ struct vms_dmt_psect *dmtp; -+ -+ dmtp = (struct vms_dmt_psect *)(contents + off); -+ bfd_putl32 (o->output_offset + o->output_section->vma, -+ dmtp->start); -+ bfd_putl32 (o->size, dmtp->length); -+ psect_count++; -+ } -+ off += sizeof (struct vms_dmt_psect); -+ } -+ if (pass == 1) -+ bfd_putl32 (psect_count, dmth->psect_count); -+ } -+ -+ if (pass == 0) -+ { -+ contents = bfd_zalloc (info->output_bfd, off); -+ if (contents == NULL) -+ return FALSE; -+ dmt->contents = contents; -+ dmt->size = off; -+ } -+ else -+ { -+ BFD_ASSERT (off == dmt->size); -+ } -+ } -+ } -+ -+ return TRUE; -+} -+ -+/* Read the contents of a section. -+ buf points to a buffer of buf_size bytes to be filled with -+ section data (starting at offset into section) */ -+ -+static bfd_boolean -+sw_64_vms_get_section_contents (bfd *abfd, asection *section, -+ void *buf, file_ptr offset, -+ bfd_size_type count) -+{ -+ asection *sec; -+ -+ /* Image are easy. */ -+ if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) -+ return _bfd_generic_get_section_contents (abfd, section, -+ buf, offset, count); -+ -+ /* Safety check. */ -+ if (offset + count < count -+ || offset + count > section->size) -+ { -+ bfd_set_error (bfd_error_invalid_operation); -+ return FALSE; -+ } -+ -+ /* If the section is already in memory, just copy it. */ -+ if (section->flags & SEC_IN_MEMORY) -+ { -+ BFD_ASSERT (section->contents != NULL); -+ memcpy (buf, section->contents + offset, count); -+ return TRUE; -+ } -+ if (section->size == 0) -+ return TRUE; -+ -+ /* Alloc in memory and read ETIRs. */ -+ for (sec = abfd->sections; sec; sec = sec->next) -+ { -+ BFD_ASSERT (sec->contents == NULL); -+ -+ if (sec->size != 0 && (sec->flags & SEC_HAS_CONTENTS)) -+ { -+ sec->contents = bfd_alloc (abfd, sec->size); -+ if (sec->contents == NULL) -+ return FALSE; -+ } -+ } -+ if (!sw_64_vms_read_sections_content (abfd, NULL)) -+ return FALSE; -+ for (sec = abfd->sections; sec; sec = sec->next) -+ if (sec->contents) -+ sec->flags |= SEC_IN_MEMORY; -+ memcpy (buf, section->contents + offset, count); -+ return TRUE; -+} -+ -+ -+/* Set the format of a file being written. */ -+ -+static bfd_boolean -+sw_64_vms_mkobject (bfd * abfd) -+{ -+ const bfd_arch_info_type *arch; -+ -+ vms_debug2 ((1, "sw_64_vms_mkobject (%p)\n", abfd)); -+ -+ if (!vms_initialize (abfd)) -+ return FALSE; -+ -+ PRIV (recwr.buf) = bfd_alloc (abfd, MAX_OUTREC_SIZE); -+ if (PRIV (recwr.buf) == NULL) -+ return FALSE; -+ -+ arch = bfd_scan_arch ("sw_64"); -+ -+ if (arch == 0) -+ { -+ bfd_set_error (bfd_error_wrong_format); -+ return FALSE; -+ } -+ -+ abfd->arch_info = arch; -+ return TRUE; -+} -+ -+ -+/* 4.1, generic. */ -+ -+/* Called when the BFD is being closed to do any necessary cleanup. */ -+ -+static bfd_boolean -+vms_close_and_cleanup (bfd * abfd) -+{ -+ vms_debug2 ((1, "vms_close_and_cleanup (%p)\n", abfd)); -+ -+ if (abfd == NULL || abfd->tdata.any == NULL) -+ return TRUE; -+ -+ if (abfd->format == bfd_object) -+ { -+ sw_64_vms_free_private (abfd); -+ -+#ifdef VMS -+ if (abfd->direction == write_direction) -+ { -+ /* Last step on VMS is to convert the file to variable record length -+ format. */ -+ if (!bfd_cache_close (abfd)) -+ return FALSE; -+ if (!_bfd_vms_convert_to_var_unix_filename (abfd->filename)) -+ return FALSE; -+ } -+#endif -+ } -+ -+ return _bfd_generic_close_and_cleanup (abfd); -+} -+ -+/* Called when a new section is created. */ -+ -+static bfd_boolean -+vms_new_section_hook (bfd * abfd, asection *section) -+{ -+ bfd_size_type amt; -+ -+ vms_debug2 ((1, "vms_new_section_hook (%p, [%u]%s)\n", -+ abfd, section->index, section->name)); -+ -+ if (!bfd_set_section_alignment (section, 0)) -+ return FALSE; -+ -+ vms_debug2 ((7, "%u: %s\n", section->index, section->name)); -+ -+ amt = sizeof (struct vms_section_data_struct); -+ section->used_by_bfd = bfd_zalloc (abfd, amt); -+ if (section->used_by_bfd == NULL) -+ return FALSE; -+ -+ /* Create the section symbol. */ -+ return _bfd_generic_new_section_hook (abfd, section); -+} -+ -+/* Part 4.5, symbols. */ -+ -+/* Print symbol to file according to how. how is one of -+ bfd_print_symbol_name just print the name -+ bfd_print_symbol_more print more (???) -+ bfd_print_symbol_all print all we know, which is not much right now :-). */ -+ -+static void -+vms_print_symbol (bfd * abfd, -+ void * file, -+ asymbol *symbol, -+ bfd_print_symbol_type how) -+{ -+ vms_debug2 ((1, "vms_print_symbol (%p, %p, %p, %d)\n", -+ abfd, file, symbol, how)); -+ -+ switch (how) -+ { -+ case bfd_print_symbol_name: -+ case bfd_print_symbol_more: -+ fprintf ((FILE *)file," %s", symbol->name); -+ break; -+ -+ case bfd_print_symbol_all: -+ { -+ const char *section_name = symbol->section->name; -+ -+ bfd_print_symbol_vandf (abfd, file, symbol); -+ -+ fprintf ((FILE *) file," %-8s %s", section_name, symbol->name); -+ } -+ break; -+ } -+} -+ -+/* Return information about symbol in ret. -+ -+ fill type, value and name -+ type: -+ A absolute -+ B bss segment symbol -+ C common symbol -+ D data segment symbol -+ f filename -+ t a static function symbol -+ T text segment symbol -+ U undefined -+ - debug. */ -+ -+static void -+vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED, -+ asymbol *symbol, -+ symbol_info *ret) -+{ -+ asection *sec; -+ -+ vms_debug2 ((1, "vms_get_symbol_info (%p, %p, %p)\n", abfd, symbol, ret)); -+ -+ sec = symbol->section; -+ -+ if (ret == NULL) -+ return; -+ -+ if (sec == NULL) -+ ret->type = 'U'; -+ else if (bfd_is_com_section (sec)) -+ ret->type = 'C'; -+ else if (bfd_is_abs_section (sec)) -+ ret->type = 'A'; -+ else if (bfd_is_und_section (sec)) -+ ret->type = 'U'; -+ else if (bfd_is_ind_section (sec)) -+ ret->type = 'I'; -+ else if ((symbol->flags & BSF_FUNCTION) -+ || (bfd_section_flags (sec) & SEC_CODE)) -+ ret->type = 'T'; -+ else if (bfd_section_flags (sec) & SEC_DATA) -+ ret->type = 'D'; -+ else if (bfd_section_flags (sec) & SEC_ALLOC) -+ ret->type = 'B'; -+ else -+ ret->type = '?'; -+ -+ if (ret->type != 'U') -+ ret->value = symbol->value + symbol->section->vma; -+ else -+ ret->value = 0; -+ ret->name = symbol->name; -+} -+ -+/* Return TRUE if the given symbol sym in the BFD abfd is -+ a compiler generated local label, else return FALSE. */ -+ -+static bfd_boolean -+vms_bfd_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED, -+ const char *name) -+{ -+ return name[0] == '$'; -+} -+ -+/* Part 4.7, writing an object file. */ -+ -+/* Sets the contents of the section section in BFD abfd to the data starting -+ in memory at LOCATION. The data is written to the output section starting -+ at offset offset for count bytes. -+ -+ Normally TRUE is returned, else FALSE. Possible error returns are: -+ o bfd_error_no_contents - The output section does not have the -+ SEC_HAS_CONTENTS attribute, so nothing can be written to it. -+ o and some more too */ -+ -+static bfd_boolean -+_bfd_vms_set_section_contents (bfd * abfd, -+ asection *section, -+ const void * location, -+ file_ptr offset, -+ bfd_size_type count) -+{ -+ if (section->contents == NULL) -+ { -+ section->contents = bfd_alloc (abfd, section->size); -+ if (section->contents == NULL) -+ return FALSE; -+ -+ memcpy (section->contents + offset, location, (size_t) count); -+ } -+ -+ return TRUE; -+} -+ -+/* Set the architecture and machine type in BFD abfd to arch and mach. -+ Find the correct pointer to a structure and insert it into the arch_info -+ pointer. */ -+ -+static bfd_boolean -+sw_64_vms_set_arch_mach (bfd *abfd, -+ enum bfd_architecture arch, unsigned long mach) -+{ -+ if (arch != bfd_arch_sw_64 -+ && arch != bfd_arch_unknown) -+ return FALSE; -+ -+ return bfd_default_set_arch_mach (abfd, arch, mach); -+} -+ -+/* Set section VMS flags. Clear NO_FLAGS and set FLAGS. */ -+ -+void -+bfd_vms_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED, -+ asection *sec, flagword no_flags, flagword flags) -+{ -+ vms_section_data (sec)->no_flags = no_flags; -+ vms_section_data (sec)->flags = flags; -+} -+ -+struct vms_private_data_struct * -+bfd_vms_get_data (bfd *abfd) -+{ -+ return (struct vms_private_data_struct *)abfd->tdata.any; -+} -+ -+#define vms_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false -+#define vms_bfd_link_just_syms _bfd_generic_link_just_syms -+#define vms_bfd_copy_link_hash_symbol_type \ -+ _bfd_generic_copy_link_hash_symbol_type -+#define vms_bfd_is_group_section bfd_generic_is_group_section -+#define vms_bfd_group_name bfd_generic_group_name -+#define vms_bfd_discard_group bfd_generic_discard_group -+#define vms_section_already_linked _bfd_generic_section_already_linked -+#define vms_bfd_define_common_symbol bfd_generic_define_common_symbol -+#define vms_bfd_link_hide_symbol _bfd_generic_link_hide_symbol -+#define vms_bfd_define_start_stop bfd_generic_define_start_stop -+#define vms_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data -+ -+#define vms_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data -+#define vms_bfd_free_cached_info _bfd_generic_bfd_free_cached_info -+#define vms_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data -+#define vms_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data -+#define vms_bfd_set_private_flags _bfd_generic_bfd_set_private_flags -+#define vms_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data -+ -+/* Symbols table. */ -+#define sw_64_vms_make_empty_symbol _bfd_generic_make_empty_symbol -+#define sw_64_vms_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false -+#define sw_64_vms_print_symbol vms_print_symbol -+#define sw_64_vms_get_symbol_info vms_get_symbol_info -+#define sw_64_vms_get_symbol_version_string \ -+ _bfd_nosymbols_get_symbol_version_string -+ -+#define sw_64_vms_read_minisymbols _bfd_generic_read_minisymbols -+#define sw_64_vms_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol -+#define sw_64_vms_get_lineno _bfd_nosymbols_get_lineno -+#define sw_64_vms_find_inliner_info _bfd_nosymbols_find_inliner_info -+#define sw_64_vms_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol -+#define sw_64_vms_find_nearest_line _bfd_vms_find_nearest_line -+#define sw_64_vms_find_line _bfd_nosymbols_find_line -+#define sw_64_vms_bfd_is_local_label_name vms_bfd_is_local_label_name -+ -+/* Generic table. */ -+#define sw_64_vms_close_and_cleanup vms_close_and_cleanup -+#define sw_64_vms_bfd_free_cached_info vms_bfd_free_cached_info -+#define sw_64_vms_new_section_hook vms_new_section_hook -+#define sw_64_vms_set_section_contents _bfd_vms_set_section_contents -+#define sw_64_vms_get_section_contents_in_window _bfd_generic_get_section_contents_in_window -+ -+#define sw_64_vms_bfd_get_relocated_section_contents \ -+ bfd_generic_get_relocated_section_contents -+ -+#define sw_64_vms_bfd_relax_section bfd_generic_relax_section -+#define sw_64_vms_bfd_gc_sections bfd_generic_gc_sections -+#define sw_64_vms_bfd_lookup_section_flags bfd_generic_lookup_section_flags -+#define sw_64_vms_bfd_merge_sections bfd_generic_merge_sections -+#define sw_64_vms_bfd_is_group_section bfd_generic_is_group_section -+#define sw_64_vms_bfd_group_name bfd_generic_group_name -+#define sw_64_vms_bfd_discard_group bfd_generic_discard_group -+#define sw_64_vms_section_already_linked \ -+ _bfd_generic_section_already_linked -+ -+#define sw_64_vms_bfd_define_common_symbol bfd_generic_define_common_symbol -+#define sw_64_vms_bfd_link_hide_symbol _bfd_generic_link_hide_symbol -+#define sw_64_vms_bfd_define_start_stop bfd_generic_define_start_stop -+#define sw_64_vms_bfd_link_just_syms _bfd_generic_link_just_syms -+#define sw_64_vms_bfd_copy_link_hash_symbol_type \ -+ _bfd_generic_copy_link_hash_symbol_type -+ -+#define sw_64_vms_bfd_link_split_section _bfd_generic_link_split_section -+ -+#define sw_64_vms_get_dynamic_symtab_upper_bound \ -+ _bfd_nodynamic_get_dynamic_symtab_upper_bound -+#define sw_64_vms_canonicalize_dynamic_symtab \ -+ _bfd_nodynamic_canonicalize_dynamic_symtab -+#define sw_64_vms_get_dynamic_reloc_upper_bound \ -+ _bfd_nodynamic_get_dynamic_reloc_upper_bound -+#define sw_64_vms_canonicalize_dynamic_reloc \ -+ _bfd_nodynamic_canonicalize_dynamic_reloc -+#define sw_64_vms_bfd_link_check_relocs _bfd_generic_link_check_relocs -+ -+const bfd_target sw_64_vms_vec = -+{ -+ "vms-sw_64", /* Name. */ -+ bfd_target_evax_flavour, -+ BFD_ENDIAN_LITTLE, /* Data byte order is little. */ -+ BFD_ENDIAN_LITTLE, /* Header byte order is little. */ -+ -+ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS -+ | WP_TEXT | D_PAGED), /* Object flags. */ -+ (SEC_ALLOC | SEC_LOAD | SEC_RELOC -+ | SEC_READONLY | SEC_CODE | SEC_DATA -+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */ -+ 0, /* symbol_leading_char. */ -+ ' ', /* ar_pad_char. */ -+ 15, /* ar_max_namelen. */ -+ 0, /* match priority. */ -+ 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_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. */ -+ _bfd_dummy_target, -+ sw_64_vms_object_p, -+ _bfd_vms_lib_sw_64_archive_p, -+ _bfd_dummy_target -+ }, -+ { /* bfd_set_format. */ -+ _bfd_bool_bfd_false_error, -+ sw_64_vms_mkobject, -+ _bfd_vms_lib_sw_64_mkarchive, -+ _bfd_bool_bfd_false_error -+ }, -+ { /* bfd_write_contents. */ -+ _bfd_bool_bfd_false_error, -+ sw_64_vms_write_object_contents, -+ _bfd_vms_lib_write_archive_contents, -+ _bfd_bool_bfd_false_error -+ }, -+ -+ BFD_JUMP_TABLE_GENERIC (sw_64_vms), -+ BFD_JUMP_TABLE_COPY (vms), -+ BFD_JUMP_TABLE_CORE (_bfd_nocore), -+ BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib), -+ BFD_JUMP_TABLE_SYMBOLS (sw_64_vms), -+ BFD_JUMP_TABLE_RELOCS (sw_64_vms), -+ BFD_JUMP_TABLE_WRITE (sw_64_vms), -+ BFD_JUMP_TABLE_LINK (sw_64_vms), -+ BFD_JUMP_TABLE_DYNAMIC (sw_64_vms), -+ -+ NULL, -+ -+ NULL -+}; -diff --git a/elfcpp/sw_64.def.h b/elfcpp/sw_64.def.h -new file mode 100644 -index 00000000..cc384293 ---- /dev/null -+++ b/elfcpp/sw_64.def.h -@@ -0,0 +1,39 @@ -+#ifndef ELF_RELOC -+#error "ELF_RELOC must be defined" -+#endif -+ -+ELF_RELOC(R_SW_64_NONE , 0) /* No reloc */ -+ELF_RELOC(R_SW_64_REFLONG , 1) /* Direct 32 bit */ -+ELF_RELOC(R_SW_64_REFQUAD , 2) /* Direct 64 bit */ -+ELF_RELOC(R_SW_64_GPREL32 , 3) /* GP relative 32 bit */ -+ELF_RELOC(R_SW_64_LITERAL , 4) /* GP relative 16 bit w/optimization */ -+ELF_RELOC(R_SW_64_LITUSE , 5) /* Optimization hint for LITERAL */ -+ELF_RELOC(R_SW_64_GPDISP , 6) /* Add displacement to GP */ -+ELF_RELOC(R_SW_64_BRADDR , 7) /* PC+4 relative 23 bit shifted */ -+ELF_RELOC(R_SW_64_HINT , 8) /* PC+4 relative 16 bit shifted */ -+ELF_RELOC(R_SW_64_SREL16 , 9) /* PC relative 16 bit */ -+ELF_RELOC(R_SW_64_SREL32 , 10) /* PC relative 32 bit */ -+ELF_RELOC(R_SW_64_SREL64 , 11) /* PC relative 64 bit */ -+ELF_RELOC(R_SW_64_GPRELHIGH , 17) /* GP relative 32 bit, high 16 bits */ -+ELF_RELOC(R_SW_64_GPRELLOW , 18) /* GP relative 32 bit, low 16 bits */ -+ELF_RELOC(R_SW_64_GPREL16 , 19) /* GP relative 16 bit */ -+ELF_RELOC(R_SW_64_COPY , 24) /* Copy symbol at runtime */ -+ELF_RELOC(R_SW_64_GLOB_DAT , 25) /* Create GOT entry */ -+ELF_RELOC(R_SW_64_JMP_SLOT , 26) /* Create PLT entry */ -+ELF_RELOC(R_SW_64_RELATIVE , 27) /* Adjust by program base */ -+ELF_RELOC(R_SW_64_BRSGP , 28) /* Like BRADDR, but assert that the source and target object file share the same GP value, and adjust the target address for STO_SW64_STD_GPLOAD. */ -+ELF_RELOC(R_SW_64_TLSGD , 29) -+ELF_RELOC(R_SW_64_TLS_LDM , 30) -+ELF_RELOC(R_SW_64_DTPMOD64 , 31) -+ELF_RELOC(R_SW_64_GOTDTPREL , 32) -+ELF_RELOC(R_SW_64_DTPREL64 , 33) -+ELF_RELOC(R_SW_64_DTPRELHI , 34) -+ELF_RELOC(R_SW_64_DTPRELLO , 35) -+ELF_RELOC(R_SW_64_DTPREL16 , 36) -+ELF_RELOC(R_SW_64_GOTTPREL , 37) -+ELF_RELOC(R_SW_64_TPREL64 , 38) -+ELF_RELOC(R_SW_64_TPRELHI , 39) -+ELF_RELOC(R_SW_64_TPRELLO , 40) -+ELF_RELOC(R_SW_64_TPREL16 , 41) -+ELF_RELOC(R_SW_64_BR26ADDR , 42) -+ELF_RELOC(R_SW_64_LITERAL_GOT , 43) -diff --git a/elfcpp/sw_64.h b/elfcpp/sw_64.h -new file mode 100644 -index 00000000..7950249b ---- /dev/null -+++ b/elfcpp/sw_64.h -@@ -0,0 +1,15 @@ -+// sw_64.h -+ -+// Copyright (C) 2021-2021 LiNaKeSi Ltd. -+// Written by Kid Lee . -+ -+#ifndef ELFCPP_SW_64_H -+namespace elfcpp{ -+enum SwRelType{ -+# define ELF_RELOC(name, value) name = value, -+# include "sw_64.def.h" -+# undef ELF_RELOC -+}; -+} // namespace elfcpp -+#define ELFCPP_SW_64_H -+#endif // !defined(ELFCPP_SW_64_H) -diff --git a/gas/config/tc-sw_64.c b/gas/config/tc-sw_64.c -new file mode 100644 -index 00000000..05dca375 ---- /dev/null -+++ b/gas/config/tc-sw_64.c -@@ -0,0 +1,6585 @@ -+/* tc-sw_64.c - Processor-specific code for the Sw_64 AXP CPU. -+ Copyright (C) 1989-2018 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. -+ Modified by Richard Henderson for ELF support. -+ Modified by Klaus K"ampf for EVAX (OpenVMS/Sw_64) 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA -+ 02110-1301, 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. */ -+ -+#include "as.h" -+#include "subsegs.h" -+#include "ecoff.h" -+ -+#include "opcode/sw_64.h" -+ -+#ifdef OBJ_ELF -+#include "elf/sw_64.h" -+#endif -+ -+#ifdef OBJ_EVAX -+#include "vms.h" -+#include "vms/egps.h" -+#endif -+ -+#include "dwarf2dbg.h" -+#include "dw2gencfi.h" -+#include "safe-ctype.h" -+ -+/* Local types. */ -+ -+#define TOKENIZE_ERROR -1 -+#define TOKENIZE_ERROR_REPORT -2 -+#define MAX_INSN_FIXUPS 2 -+#define MAX_INSN_ARGS 5 -+ -+/* Used since new relocation types are introduced in this -+ file (DUMMY_RELOC_LITUSE_*) */ -+typedef int extended_bfd_reloc_code_real_type; -+ -+struct sw_64_fixup -+{ -+ expressionS exp; -+ /* bfd_reloc_code_real_type reloc; */ -+ extended_bfd_reloc_code_real_type reloc; -+#ifdef OBJ_EVAX -+ /* The symbol of the item in the linkage section. */ -+ symbolS *xtrasym; -+ -+ /* The symbol of the procedure descriptor. */ -+ symbolS *procsym; -+#endif -+}; -+ -+struct sw_64_insn -+{ -+ unsigned insn; -+ int nfixups; -+ struct sw_64_fixup fixups[MAX_INSN_FIXUPS]; -+ long sequence; -+}; -+ -+enum sw_64_macro_arg -+ { -+ MACRO_EOA = 1, -+ MACRO_IR, -+ MACRO_PIR, -+ MACRO_OPIR, -+ MACRO_CPIR, -+ MACRO_FPR, -+ MACRO_EXP -+ }; -+ -+struct sw_64_macro -+{ -+ const char *name; -+ void (*emit) (const expressionS *, int, const void *); -+ const void * arg; -+ enum sw_64_macro_arg argsets[16]; -+}; -+ -+/* Extra expression types. */ -+ -+#define O_pregister O_md1 /* O_register, in parentheses. */ -+#define O_cpregister O_md2 /* + a leading comma. */ -+ -+/* The sw_64_reloc_op table below depends on the ordering of these. */ -+#define O_literal O_md3 /* !literal relocation. */ -+#define O_lituse_addr O_md4 /* !lituse_addr relocation. */ -+#define O_lituse_base O_md5 /* !lituse_base relocation. */ -+#define O_lituse_bytoff O_md6 /* !lituse_bytoff relocation. */ -+#define O_lituse_jsr O_md7 /* !lituse_jsr relocation. */ -+#define O_lituse_tlsgd O_md8 /* !lituse_tlsgd relocation. */ -+#define O_lituse_tlsldm O_md9 /* !lituse_tlsldm relocation. */ -+#define O_lituse_jsrdirect O_md10 /* !lituse_jsrdirect relocation. */ -+#define O_gpdisp O_md11 /* !gpdisp relocation. */ -+#define O_gprelhigh O_md12 /* !gprelhigh relocation. */ -+#define O_gprellow O_md13 /* !gprellow relocation. */ -+#define O_gprel O_md14 /* !gprel relocation. */ -+#define O_samegp O_md15 /* !samegp relocation. */ -+#define O_tlsgd O_md16 /* !tlsgd relocation. */ -+#define O_tlsldm O_md17 /* !tlsldm relocation. */ -+#define O_gotdtprel O_md18 /* !gotdtprel relocation. */ -+#define O_dtprelhi O_md19 /* !dtprelhi relocation. */ -+#define O_dtprello O_md20 /* !dtprello relocation. */ -+#define O_dtprel O_md21 /* !dtprel relocation. */ -+#define O_gottprel O_md22 /* !gottprel relocation. */ -+#define O_tprelhi O_md23 /* !tprelhi relocation. */ -+#define O_tprello O_md24 /* !tprello relocation. */ -+#define O_tprel O_md25 /* !tprel relocation. */ -+ -+#define DUMMY_RELOC_LITUSE_ADDR (BFD_RELOC_UNUSED + 1) -+#define DUMMY_RELOC_LITUSE_BASE (BFD_RELOC_UNUSED + 2) -+#define DUMMY_RELOC_LITUSE_BYTOFF (BFD_RELOC_UNUSED + 3) -+#define DUMMY_RELOC_LITUSE_JSR (BFD_RELOC_UNUSED + 4) -+#define DUMMY_RELOC_LITUSE_TLSGD (BFD_RELOC_UNUSED + 5) -+#define DUMMY_RELOC_LITUSE_TLSLDM (BFD_RELOC_UNUSED + 6) -+#define DUMMY_RELOC_LITUSE_JSRDIRECT (BFD_RELOC_UNUSED + 7) -+ -+#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_tprel) -+ -+/* Macros for extracting the type and number of encoded register tokens. */ -+ -+#define is_ir_num(x) (((x) & 32) == 0) -+#define is_fpr_num(x) (((x) & 32) != 0) -+#define regno(x) ((x) & 31) -+ -+/* Something odd inherited from the old assembler. */ -+ -+#define note_gpreg(R) (sw_64_gprmask |= (1 << (R))) -+#define note_fpreg(R) (sw_64_fprmask |= (1 << (R))) -+ -+/* Predicates for 16- and 32-bit ranges */ -+/* XXX: The non-shift version appears to trigger a compiler bug when -+ cross-assembling from x86 w/ gcc 2.7.2. */ -+ -+#if 1 -+#define range_signed_16(x) \ -+ (((offsetT) (x) >> 15) == 0 || ((offsetT) (x) >> 15) == -1) -+#define range_signed_32(x) \ -+ (((offsetT) (x) >> 31) == 0 || ((offsetT) (x) >> 31) == -1) -+#else -+#define range_signed_16(x) ((offsetT) (x) >= -(offsetT) 0x8000 && \ -+ (offsetT) (x) <= (offsetT) 0x7FFF) -+#define range_signed_32(x) ((offsetT) (x) >= -(offsetT) 0x80000000 && \ -+ (offsetT) (x) <= (offsetT) 0x7FFFFFFF) -+#endif -+ -+/* Macros for sign extending from 16- and 32-bits. */ -+/* XXX: The cast macros will work on all the systems that I care about, -+ but really a predicate should be found to use the non-cast forms. */ -+ -+#if 1 -+#define sign_extend_16(x) ((short) (x)) -+#define sign_extend_32(x) ((int) (x)) -+#else -+#define sign_extend_16(x) ((offsetT) (((x) & 0xFFFF) ^ 0x8000) - 0x8000) -+#define sign_extend_32(x) ((offsetT) (((x) & 0xFFFFFFFF) \ -+ ^ 0x80000000) - 0x80000000) -+#endif -+ -+/* Macros to build tokens. */ -+ -+#define set_tok_reg(t, r) (memset (&(t), 0, sizeof (t)), \ -+ (t).X_op = O_register, \ -+ (t).X_add_number = (r)) -+#define set_tok_preg(t, r) (memset (&(t), 0, sizeof (t)), \ -+ (t).X_op = O_pregister, \ -+ (t).X_add_number = (r)) -+#define set_tok_cpreg(t, r) (memset (&(t), 0, sizeof (t)), \ -+ (t).X_op = O_cpregister, \ -+ (t).X_add_number = (r)) -+#define set_tok_freg(t, r) (memset (&(t), 0, sizeof (t)), \ -+ (t).X_op = O_register, \ -+ (t).X_add_number = (r) + 32) -+#define set_tok_sym(t, s, a) (memset (&(t), 0, sizeof (t)), \ -+ (t).X_op = O_symbol, \ -+ (t).X_add_symbol = (s), \ -+ (t).X_add_number = (a)) -+#define set_tok_const(t, n) (memset (&(t), 0, sizeof (t)), \ -+ (t).X_op = O_constant, \ -+ (t).X_add_number = (n)) -+ -+/* Generic assembler global variables which must be defined by all -+ targets. */ -+ -+/* Characters which always start a comment. */ -+const char comment_chars[] = "#"; -+ -+/* Characters which start a comment at the beginning of a line. */ -+const char line_comment_chars[] = "#"; -+ -+/* Characters which may be used to separate multiple commands on a -+ single line. */ -+const char line_separator_chars[] = ";"; -+ -+/* Characters which are used to indicate an exponent in a floating -+ point number. */ -+const char EXP_CHARS[] = "eE"; -+ -+/* Characters which mean that a number is a floating point constant, -+ as in 0d1.0. */ -+/* XXX: Do all of these really get used on the sw_64?? */ -+const char FLT_CHARS[] = "rRsSfFdDxXpP"; -+ -+/* The argument of the -march= flag. The architecture we are assembling. */ -+static int file_sw_64_arch = CPU_UNKNOWN; -+static const char *sw_64_arch_string; -+ -+struct sw_64_cpu_info -+{ -+ const char *name; /* CPU or ISA name. */ -+ int flags; /* SW_64_CPU_* flags. */ -+ int ase; /* Set of ASEs implemented by the CPU. */ -+ int isa; /* ISA level. */ -+ int cpu; /* CPU number (default CPU if ISA). */ -+}; -+ -+#define SW_64_CPU_IS_ISA 0x0001 /* Is this an ISA? (If 0, a CPU.) */ -+ -+struct sw_64_set_options -+{ -+ int isa; -+ int ase; -+ int sw_64_tmp; -+ int micromips; -+ int noreorder; -+ unsigned int at; -+ int warn_about_macros; -+ int nomove; -+ int nobopt; -+ int noautoextend; -+ bfd_boolean insn32; -+ int gp32; -+ int fp32; -+ int arch; -+ bfd_boolean sym32; -+ bfd_boolean soft_float; -+ bfd_boolean single_float; -+}; -+ -+static struct sw_64_set_options sw_64_opts = -+{ -+ /* isa */ ISA_UNKNOWN, /* ase */ 0, /* sw_64_tmp */ -1, /* micromips */ -1, -+ /* noreorder */ 0, /* at */ FALSE, /* warn_about_macros */ 0, -+ /* nomove */ 0, /* nobopt */ 0, /* noautoextend */ 0, /* insn32 */ FALSE, -+ /* gp32 */ 0, /* fp32 */ 0, /* arch */ CPU_UNKNOWN, /* sym32 */ FALSE, -+ /* soft_float */ FALSE, /* single_float */ FALSE -+}; -+ -+static const struct sw_64_cpu_info *sw_64_parse_cpu (const char *, const char *); -+static const struct sw_64_cpu_info *sw_64_cpu_info_from_isa (int); -+static const struct sw_64_cpu_info *sw_64_cpu_info_from_arch (int); -+ -+#ifdef OBJ_EVAX -+const char *md_shortopts = "Fm:g+1h:HG:"; -+#else -+const char *md_shortopts = "Fm:gG:"; -+#endif -+ -+struct option md_longopts[] = -+ { -+#define OPTION_32ADDR (OPTION_MD_BASE) -+ { "32addr", no_argument, NULL, OPTION_32ADDR }, -+#define OPTION_NOCHECK_SAMEREG (OPTION_32ADDR + 1) -+ { "nocheck-samereg", no_argument, NULL, OPTION_NOCHECK_SAMEREG}, -+#define OPTION_RELAX (OPTION_NOCHECK_SAMEREG + 1) -+ { "relax", no_argument, NULL, OPTION_RELAX }, -+#ifdef OBJ_ELF -+#define OPTION_MDEBUG (OPTION_RELAX + 1) -+#define OPTION_NO_MDEBUG (OPTION_MDEBUG + 1) -+ { "mdebug", no_argument, NULL, OPTION_MDEBUG }, -+ { "no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG }, -+#endif -+#ifdef OBJ_EVAX -+#define OPTION_REPLACE (OPTION_RELAX + 1) -+#define OPTION_NOREPLACE (OPTION_REPLACE+1) -+ { "replace", no_argument, NULL, OPTION_REPLACE }, -+ { "noreplace", no_argument, NULL, OPTION_NOREPLACE }, -+#endif -+ { NULL, no_argument, NULL, 0 } -+ }; -+ -+size_t md_longopts_size = sizeof (md_longopts); -+ -+#ifdef OBJ_EVAX -+#define AXP_REG_R0 0 -+#define AXP_REG_R16 16 -+#define AXP_REG_R17 17 -+#undef AXP_REG_T9 -+#define AXP_REG_T9 22 -+#undef AXP_REG_T10 -+#define AXP_REG_T10 23 -+#undef AXP_REG_T11 -+#define AXP_REG_T11 24 -+#undef AXP_REG_T12 -+#define AXP_REG_T12 25 -+#define AXP_REG_AI 25 -+#undef AXP_REG_FP -+#define AXP_REG_FP 29 -+ -+#undef AXP_REG_GP -+#define AXP_REG_GP AXP_REG_PV -+ -+#endif /* OBJ_EVAX */ -+ -+/* The cpu for which we are generating code. */ -+static unsigned sw_64_target; -+static const char *sw_64_target_name; -+ -+/* The hash table of instruction opcodes. */ -+static htab_t sw_64_opcode_hash; -+ -+/* The hash table of macro opcodes. */ -+static htab_t sw_64_macro_hash; -+ -+#ifdef OBJ_ECOFF -+/* The $gp relocation symbol. */ -+static symbolS *sw_64_gp_symbol; -+ -+/* XXX: what is this, and why is it exported? */ -+valueT sw_64_gp_value; -+#endif -+ -+/* The current $gp register. */ -+static int sw_64_gp_register = AXP_REG_GP; -+ -+/* A table of the register symbols. */ -+static symbolS *sw_64_register_table[64]; -+ -+/* Constant sections, or sections of constants. */ -+#ifdef OBJ_ECOFF -+static segT sw_64_lita_section; -+#endif -+#ifdef OBJ_EVAX -+segT sw_64_link_section; -+#endif -+#ifndef OBJ_EVAX -+static segT sw_64_lit8_section; -+#endif -+ -+/* Symbols referring to said sections. */ -+#ifdef OBJ_ECOFF -+static symbolS *sw_64_lita_symbol; -+#endif -+#ifdef OBJ_EVAX -+static symbolS *sw_64_link_symbol; -+#endif -+#ifndef OBJ_EVAX -+static symbolS *sw_64_lit8_symbol; -+#endif -+ -+/* Literal for .litX+0x8000 within .lita. */ -+#ifdef OBJ_ECOFF -+static offsetT sw_64_lit8_literal; -+#endif -+ -+/* Is the assembler not allowed to use $at? */ -+static int sw_64_noat_on = 0; -+ -+/* Are macros enabled? */ -+static int sw_64_macros_on = 1; -+ -+/* Are floats disabled? */ -+static int sw_64_nofloats_on = 0; -+ -+/* Are addresses 32 bit? */ -+static int sw_64_addr32_on = 0; -+ -+/* Symbol labelling the current insn. When the Sw_64 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 *sw_64_insn_label; -+#if defined(OBJ_ELF) || defined (OBJ_EVAX) -+static symbolS *sw_64_prologue_label; -+#endif -+ -+#ifdef OBJ_EVAX -+/* Symbol associate with the current call instruction. */ -+static symbolS *sw_64_linkage_symbol; -+#endif -+ -+/* Whether we should automatically align data generation pseudo-ops. -+ .align 0 will turn this off. */ -+static int sw_64_auto_align_on = 1; -+ -+/* The known current alignment of the current section. */ -+static int sw_64_current_align; -+ -+/* These are exported to ECOFF code. */ -+unsigned long sw_64_gprmask, sw_64_fprmask; -+ -+/* Whether the debugging option was seen. */ -+static int sw_64_debug; -+ -+#ifdef OBJ_ELF -+/* Whether we are emitting an mdebug section. */ -+int sw_64_flag_mdebug = -1; -+#endif -+ -+#ifdef OBJ_EVAX -+/* Whether to perform the VMS procedure call optimization. */ -+int sw_64_flag_replace = 1; -+#endif -+ -+/* Don't fully resolve relocations, allowing code movement in the linker. */ -+static int sw_64_flag_relax; -+ -+/* What value to give to bfd_set_gp_size. */ -+static int g_switch_value = 8; -+ -+static int sw_64_flag_nocheck_samereg = 0; -+ -+#ifdef OBJ_EVAX -+/* Collect information about current procedure here. */ -+struct sw_64_evax_procs -+{ -+ symbolS *symbol; /* Proc pdesc symbol. */ -+ int pdsckind; -+ int framereg; /* Register for frame pointer. */ -+ int framesize; /* Size of frame. */ -+ int rsa_offset; -+ int ra_save; -+ int fp_save; -+ long imask; -+ long fmask; -+ int type; -+ int prologue; -+ symbolS *handler; -+ int handler_data; -+}; -+ -+/* Linked list of .linkage fixups. */ -+struct sw_64_linkage_fixups *sw_64_linkage_fixup_root; -+static struct sw_64_linkage_fixups *sw_64_linkage_fixup_tail; -+ -+/* Current procedure descriptor. */ -+static struct sw_64_evax_procs *sw_64_evax_proc; -+static struct sw_64_evax_procs sw_64_evax_proc_data; -+ -+static int sw_64_flag_hash_long_names = 0; /* -+ */ -+static int sw_64_flag_show_after_trunc = 0; /* -H */ -+ -+/* If the -+ switch is given, then a hash is appended to any name that is -+ longer than 64 characters, else longer symbol names are truncated. */ -+ -+#endif -+ -+#ifdef RELOC_OP_P -+/* A table to map the spelling of a relocation operand into an appropriate -+ bfd_reloc_code_real_type type. The table is assumed to be ordered such -+ that op-O_literal indexes into it. */ -+ -+#define SW_64_RELOC_TABLE(op) \ -+(&sw_64_reloc_op[ ((!USER_RELOC_P (op)) \ -+ ? (abort (), 0) \ -+ : (int) (op) - (int) O_literal) ]) -+ -+#define DEF(NAME, RELOC, REQ, ALLOW) \ -+ { #NAME, sizeof(#NAME)-1, O_##NAME, RELOC, REQ, ALLOW} -+ -+static const struct sw_64_reloc_op_tag -+{ -+ const char *name; /* String to lookup. */ -+ size_t length; /* Size of the string. */ -+ operatorT op; /* Which operator to use. */ -+ extended_bfd_reloc_code_real_type reloc; -+ unsigned int require_seq : 1; /* Require a sequence number. */ -+ unsigned int allow_seq : 1; /* Allow a sequence number. */ -+} -+sw_64_reloc_op[] = -+{ -+ DEF (literal, BFD_RELOC_SW_64_ELF_LITERAL, 0, 1), -+ DEF (lituse_addr, DUMMY_RELOC_LITUSE_ADDR, 1, 1), -+ DEF (lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1), -+ DEF (lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1), -+ DEF (lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1), -+ DEF (lituse_tlsgd, DUMMY_RELOC_LITUSE_TLSGD, 1, 1), -+ DEF (lituse_tlsldm, DUMMY_RELOC_LITUSE_TLSLDM, 1, 1), -+ DEF (lituse_jsrdirect, DUMMY_RELOC_LITUSE_JSRDIRECT, 1, 1), -+ DEF (gpdisp, BFD_RELOC_SW_64_GPDISP, 1, 1), -+ DEF (gprelhigh, BFD_RELOC_SW_64_GPREL_HI16, 0, 0), -+ DEF (gprellow, BFD_RELOC_SW_64_GPREL_LO16, 0, 0), -+ DEF (gprel, BFD_RELOC_GPREL16, 0, 0), -+ DEF (samegp, BFD_RELOC_SW_64_BRSGP, 0, 0), -+ DEF (tlsgd, BFD_RELOC_SW_64_TLSGD, 0, 1), -+ DEF (tlsldm, BFD_RELOC_SW_64_TLSLDM, 0, 1), -+ DEF (gotdtprel, BFD_RELOC_SW_64_GOTDTPREL16, 0, 0), -+ DEF (dtprelhi, BFD_RELOC_SW_64_DTPREL_HI16, 0, 0), -+ DEF (dtprello, BFD_RELOC_SW_64_DTPREL_LO16, 0, 0), -+ DEF (dtprel, BFD_RELOC_SW_64_DTPREL16, 0, 0), -+ DEF (gottprel, BFD_RELOC_SW_64_GOTTPREL16, 0, 0), -+ DEF (tprelhi, BFD_RELOC_SW_64_TPREL_HI16, 0, 0), -+ DEF (tprello, BFD_RELOC_SW_64_TPREL_LO16, 0, 0), -+ DEF (tprel, BFD_RELOC_SW_64_TPREL16, 0, 0), -+}; -+ -+#undef DEF -+ -+static const int sw_64_num_reloc_op -+ = sizeof (sw_64_reloc_op) / sizeof (*sw_64_reloc_op); -+#endif /* RELOC_OP_P */ -+ -+/* Maximum # digits needed to hold the largest sequence #. */ -+#define SW_64_RELOC_DIGITS 25 -+ -+/* Structure to hold explicit sequence information. */ -+struct sw_64_reloc_tag -+{ -+ fixS *master; /* The literal reloc. */ -+#ifdef OBJ_EVAX -+ struct symbol *sym; /* Linkage section item symbol. */ -+ struct symbol *psym; /* Pdesc symbol. */ -+#endif -+ fixS *slaves; /* Head of linked list of lituses. */ -+ segT segment; /* Segment relocs are in or undefined_section. */ -+ long sequence; /* Sequence #. */ -+ unsigned n_master; /* # of literals. */ -+ unsigned n_slaves; /* # of lituses. */ -+ unsigned saw_tlsgd : 1; /* True if ... */ -+ unsigned saw_tlsldm : 1; -+ unsigned saw_lu_tlsgd : 1; -+ unsigned saw_lu_tlsldm : 1; -+ unsigned multi_section_p : 1; /* True if more than one section was used. */ -+ char string[1]; /* Printable form of sequence to hash with. */ -+}; -+ -+/* Hash table to link up literals with the appropriate lituse. */ -+static htab_t sw_64_literal_hash; -+ -+/* Sequence numbers for internal use by macros. */ -+static long next_sequence_num = -1; -+ -+/* A table of CPU names and opcode sets. */ -+ -+static const struct cpu_type -+{ -+ const char *name; -+ unsigned flags; -+} -+cpu_types[] = -+{ -+ { "sw6a", AXP_OPCODE_SW6|AXP_OPCODE_SW6A}, -+ { "sw6b", AXP_OPCODE_SW6|AXP_OPCODE_SW6B}, -+ { 0, 0 } -+}; -+ -+/* Some instruction sets indexed by lg(size). */ -+static const char * const sextX_op[] = { "sextb", "sexth", "sextw", NULL }; -+static const char * const insXl_op[] = { "ins0b", "ins1b", "ins2b", "ins3b" }; -+static const char * const insXh_op[] = { NULL, "ins5b", "ins6b", "ins7b" }; -+static const char * const extXl_op[] = { "ext0b", "ext1b", "ext2b", "ext3b" }; -+static const char * const extXh_op[] = { NULL, "ext5b", "ext6b", "ext7b" }; -+static const char * const mskXl_op[] = { "mask0b", "mask1b", "mask2b", "mask3b" }; -+static const char * const mskXh_op[] = { NULL, "mask5b", "mask6b", "mask7b" }; -+static const char * const stX_op[] = { "stb", "stb", "stw", "stl" }; -+static const char * const ldXu_op[] = { "ldbu", "ldhu", NULL, NULL }; -+ -+static void assemble_insn (const struct sw_64_opcode *, const expressionS *, int, struct sw_64_insn *, extended_bfd_reloc_code_real_type); -+static void emit_insn (struct sw_64_insn *); -+static void assemble_tokens (const char *, const expressionS *, int, int); -+#ifdef OBJ_EVAX -+static const char *s_sw_64_section_name (void); -+static symbolS *add_to_link_pool (symbolS *, offsetT); -+#endif -+ -+static struct sw_64_reloc_tag * -+get_sw_64_reloc_tag (long sequence) -+{ -+ char buffer[SW_64_RELOC_DIGITS]; -+ struct sw_64_reloc_tag *info; -+ -+ sprintf (buffer, "!%ld", sequence); -+ -+ info = (struct sw_64_reloc_tag *) str_hash_find (sw_64_literal_hash, buffer); -+ if (! info) -+ { -+ size_t len = strlen (buffer); -+ -+ info = (struct sw_64_reloc_tag *) -+ xcalloc (sizeof (struct sw_64_reloc_tag) + len, 1); -+ -+ info->segment = now_seg; -+ info->sequence = sequence; -+ strcpy (info->string, buffer); -+ str_hash_insert (sw_64_literal_hash, info->string, info, 0); -+ -+#ifdef OBJ_EVAX -+ info->sym = 0; -+ info->psym = 0; -+#endif -+ } -+ -+ return info; -+} -+ -+#ifndef OBJ_EVAX -+ -+static void -+sw_64_adjust_relocs (bfd *abfd ATTRIBUTE_UNUSED, -+ asection *sec, -+ void * ptr ATTRIBUTE_UNUSED) -+{ -+ segment_info_type *seginfo = seg_info (sec); -+ fixS **prevP; -+ fixS *fixp; -+ fixS *next; -+ fixS *slave; -+ -+ /* If seginfo is NULL, we did not create this section; don't do -+ anything with it. By using a pointer to a pointer, we can update -+ the links in place. */ -+ if (seginfo == NULL) -+ return; -+ -+ /* If there are no relocations, skip the section. */ -+ if (! seginfo->fix_root) -+ return; -+ -+ /* First rebuild the fixup chain without the explicit lituse and -+ gpdisp_lo16 relocs. */ -+ prevP = &seginfo->fix_root; -+ for (fixp = seginfo->fix_root; fixp; fixp = next) -+ { -+ next = fixp->fx_next; -+ fixp->fx_next = (fixS *) 0; -+ -+ switch (fixp->fx_r_type) -+ { -+ case BFD_RELOC_SW_64_LITUSE: -+ if (fixp->tc_fix_data.info->n_master == 0) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("No !literal!%ld was found"), -+ fixp->tc_fix_data.info->sequence); -+#ifdef RELOC_OP_P -+ if (fixp->fx_offset == LITUSE_SW_64_TLSGD) -+ { -+ if (! fixp->tc_fix_data.info->saw_tlsgd) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("No !tlsgd!%ld was found"), -+ fixp->tc_fix_data.info->sequence); -+ } -+ else if (fixp->fx_offset == LITUSE_SW_64_TLSLDM) -+ { -+ if (! fixp->tc_fix_data.info->saw_tlsldm) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("No !tlsldm!%ld was found"), -+ fixp->tc_fix_data.info->sequence); -+ } -+#endif -+ break; -+ -+ case BFD_RELOC_SW_64_GPDISP_LO16: -+ if (fixp->tc_fix_data.info->n_master == 0) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("No ldih !gpdisp!%ld was found"), -+ fixp->tc_fix_data.info->sequence); -+ break; -+ -+ case BFD_RELOC_SW_64_ELF_LITERAL: -+ if (fixp->tc_fix_data.info -+ && (fixp->tc_fix_data.info->saw_tlsgd -+ || fixp->tc_fix_data.info->saw_tlsldm)) -+ break; -+ /* FALLTHRU */ -+ -+ default: -+ *prevP = fixp; -+ prevP = &fixp->fx_next; -+ break; -+ } -+ } -+ -+ /* Go back and re-chain dependent relocations. They are currently -+ linked through the next_reloc field in reverse order, so as we -+ go through the next_reloc chain, we effectively reverse the chain -+ once again. -+ -+ Except if there is more than one !literal for a given sequence -+ number. In that case, the programmer and/or compiler is not sure -+ how control flows from literal to lituse, and we can't be sure to -+ get the relaxation correct. -+ -+ ??? Well, actually we could, if there are enough lituses such that -+ we can make each literal have at least one of each lituse type -+ present. Not implemented. -+ -+ Also suppress the optimization if the !literals/!lituses are spread -+ in different segments. This can happen with "interesting" uses of -+ inline assembly; examples are present in the Linux kernel semaphores. */ -+ -+ for (fixp = seginfo->fix_root; fixp; fixp = next) -+ { -+ next = fixp->fx_next; -+ switch (fixp->fx_r_type) -+ { -+ case BFD_RELOC_SW_64_TLSGD: -+ case BFD_RELOC_SW_64_TLSLDM: -+ if (!fixp->tc_fix_data.info) -+ break; -+ if (fixp->tc_fix_data.info->n_master == 0) -+ break; -+ else if (fixp->tc_fix_data.info->n_master > 1) -+ { -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("too many !literal!%ld for %s"), -+ fixp->tc_fix_data.info->sequence, -+ (fixp->fx_r_type == BFD_RELOC_SW_64_TLSGD -+ ? "!tlsgd" : "!tlsldm")); -+ break; -+ } -+ -+ fixp->tc_fix_data.info->master->fx_next = fixp->fx_next; -+ fixp->fx_next = fixp->tc_fix_data.info->master; -+ fixp = fixp->fx_next; -+ /* Fall through. */ -+ -+ case BFD_RELOC_SW_64_ELF_LITERAL: -+ if (fixp->tc_fix_data.info -+ && fixp->tc_fix_data.info->n_master == 1 -+ && ! fixp->tc_fix_data.info->multi_section_p) -+ { -+ for (slave = fixp->tc_fix_data.info->slaves; -+ slave != (fixS *) 0; -+ slave = slave->tc_fix_data.next_reloc) -+ { -+ slave->fx_next = fixp->fx_next; -+ fixp->fx_next = slave; -+ } -+ } -+ break; -+ -+ case BFD_RELOC_SW_64_GPDISP_HI16: -+ if (fixp->tc_fix_data.info->n_slaves == 0) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("No ldi !gpdisp!%ld was found"), -+ fixp->tc_fix_data.info->sequence); -+ else -+ { -+ slave = fixp->tc_fix_data.info->slaves; -+ slave->fx_next = next; -+ fixp->fx_next = slave; -+ } -+ break; -+ -+ default: -+ break; -+ } -+ } -+} -+ -+/* Before the relocations are written, reorder them, so that user -+ supplied !lituse relocations follow the appropriate !literal -+ relocations, and similarly for !gpdisp relocations. */ -+ -+void -+sw_64_before_fix (void) -+{ -+ if (sw_64_literal_hash) -+ bfd_map_over_sections (stdoutput, sw_64_adjust_relocs, NULL); -+} -+ -+#endif -+ -+#ifdef DEBUG_SW_64 -+static void -+debug_exp (expressionS tok[], int ntok) -+{ -+ int i; -+ -+ fprintf (stderr, "debug_exp: %d tokens", ntok); -+ for (i = 0; i < ntok; i++) -+ { -+ expressionS *t = &tok[i]; -+ const char *name; -+ -+ switch (t->X_op) -+ { -+ default: name = "unknown"; break; -+ case O_illegal: name = "O_illegal"; break; -+ case O_absent: name = "O_absent"; break; -+ case O_constant: name = "O_constant"; break; -+ case O_symbol: name = "O_symbol"; break; -+ case O_symbol_rva: name = "O_symbol_rva"; break; -+ case O_register: name = "O_register"; break; -+ case O_big: name = "O_big"; break; -+ case O_uminus: name = "O_uminus"; break; -+ case O_bit_not: name = "O_bit_not"; break; -+ case O_logical_not: name = "O_logical_not"; break; -+ case O_multiply: name = "O_multiply"; break; -+ case O_divide: name = "O_divide"; break; -+ case O_modulus: name = "O_modulus"; break; -+ case O_left_shift: name = "O_left_shift"; break; -+ case O_right_shift: name = "O_right_shift"; break; -+ case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break; -+ case O_bit_or_not: name = "O_bit_or_not"; break; -+ case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break; -+ case O_bit_and: name = "O_bit_and"; break; -+ case O_add: name = "O_add"; break; -+ case O_subtract: name = "O_subtract"; break; -+ case O_eq: name = "O_eq"; break; -+ case O_ne: name = "O_ne"; break; -+ case O_lt: name = "O_lt"; break; -+ case O_le: name = "O_le"; break; -+ case O_ge: name = "O_ge"; break; -+ case O_gt: name = "O_gt"; break; -+ case O_logical_and: name = "O_logical_and"; break; -+ case O_logical_or: name = "O_logical_or"; break; -+ case O_index: name = "O_index"; break; -+ case O_pregister: name = "O_pregister"; break; -+ case O_cpregister: name = "O_cpregister"; break; -+ case O_literal: name = "O_literal"; break; -+ case O_lituse_addr: name = "O_lituse_addr"; break; -+ case O_lituse_base: name = "O_lituse_base"; break; -+ case O_lituse_bytoff: name = "O_lituse_bytoff"; break; -+ case O_lituse_jsr: name = "O_lituse_jsr"; break; -+ case O_lituse_tlsgd: name = "O_lituse_tlsgd"; break; -+ case O_lituse_tlsldm: name = "O_lituse_tlsldm"; break; -+ case O_lituse_jsrdirect: name = "O_lituse_jsrdirect"; break; -+ case O_gpdisp: name = "O_gpdisp"; break; -+ case O_gprelhigh: name = "O_gprelhigh"; break; -+ case O_gprellow: name = "O_gprellow"; break; -+ case O_gprel: name = "O_gprel"; break; -+ case O_samegp: name = "O_samegp"; break; -+ case O_tlsgd: name = "O_tlsgd"; break; -+ case O_tlsldm: name = "O_tlsldm"; break; -+ case O_gotdtprel: name = "O_gotdtprel"; break; -+ case O_dtprelhi: name = "O_dtprelhi"; break; -+ case O_dtprello: name = "O_dtprello"; break; -+ case O_dtprel: name = "O_dtprel"; break; -+ case O_gottprel: name = "O_gottprel"; break; -+ case O_tprelhi: name = "O_tprelhi"; break; -+ case O_tprello: name = "O_tprello"; break; -+ case O_tprel: name = "O_tprel"; break; -+ } -+ -+ fprintf (stderr, ", %s(%s, %s, %d)", name, -+ (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--", -+ (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--", -+ (int) t->X_add_number); -+ } -+ fprintf (stderr, "\n"); -+ fflush (stderr); -+} -+#endif -+ -+/* Parse the arguments to an opcode. */ -+ -+static int -+tokenize_arguments (char *str, -+ expressionS tok[], -+ int ntok) -+{ -+ expressionS *end_tok = tok + ntok; -+ char *old_input_line_pointer; -+ int saw_comma = 0, saw_arg = 0; -+#ifdef DEBUG_SW_64 -+ expressionS *orig_tok = tok; -+#endif -+#ifdef RELOC_OP_P -+ char *p; -+ const struct sw_64_reloc_op_tag *r; -+ int c, i; -+ size_t len; -+ int reloc_found_p = 0; -+#endif -+ -+ memset (tok, 0, sizeof (*tok) * ntok); -+ -+ /* Save and restore input_line_pointer around this function. */ -+ old_input_line_pointer = input_line_pointer; -+ input_line_pointer = str; -+ -+#ifdef RELOC_OP_P -+ /* ??? Wrest control of ! away from the regular expression parser. */ -+ is_end_of_line[(unsigned char) '!'] = 1; -+#endif -+ -+ while (tok < end_tok && *input_line_pointer) -+ { -+ SKIP_WHITESPACE (); -+ switch (*input_line_pointer) -+ { -+ case '\0': -+ goto fini; -+ -+#ifdef RELOC_OP_P -+ case '!': -+ /* A relocation operand can be placed after the normal operand on an -+ assembly language statement, and has the following form: -+ !relocation_type!sequence_number. */ -+ if (reloc_found_p) -+ { -+ /* Only support one relocation op per insn. */ -+ as_bad (_("More than one relocation op per insn")); -+ goto err_report; -+ } -+ -+ if (!saw_arg) -+ goto err; -+ -+ ++input_line_pointer; -+ SKIP_WHITESPACE (); -+ c = get_symbol_name (&p); -+ -+ /* Parse !relocation_type. */ -+ len = input_line_pointer - p; -+ if (len == 0) -+ { -+ as_bad (_("No relocation operand")); -+ goto err_report; -+ } -+ -+ r = &sw_64_reloc_op[0]; -+ for (i = sw_64_num_reloc_op - 1; i >= 0; i--, r++) -+ if (len == r->length && memcmp (p, r->name, len) == 0) -+ break; -+ if (i < 0) -+ { -+ as_bad (_("Unknown relocation operand: !%s"), p); -+ goto err_report; -+ } -+ -+ *input_line_pointer = c; -+ SKIP_WHITESPACE_AFTER_NAME (); -+ if (*input_line_pointer != '!') -+ { -+ if (r->require_seq) -+ { -+ as_bad (_("no sequence number after !%s"), p); -+ goto err_report; -+ } -+ -+ tok->X_add_number = 0; -+ } -+ else -+ { -+ if (! r->allow_seq) -+ { -+ as_bad (_("!%s does not use a sequence number"), p); -+ goto err_report; -+ } -+ -+ input_line_pointer++; -+ -+ /* Parse !sequence_number. */ -+ expression (tok); -+ if (tok->X_op != O_constant || tok->X_add_number <= 0) -+ { -+ as_bad (_("Bad sequence number: !%s!%s"), -+ r->name, input_line_pointer); -+ goto err_report; -+ } -+ } -+ -+ tok->X_op = r->op; -+ reloc_found_p = 1; -+ ++tok; -+ break; -+#endif /* RELOC_OP_P */ -+ -+ case ',': -+ ++input_line_pointer; -+ if (saw_comma || !saw_arg) -+ goto err; -+ saw_comma = 1; -+ break; -+ -+ case '(': -+ { -+ char *hold = input_line_pointer++; -+ -+ /* First try for parenthesized register ... */ -+ expression (tok); -+ if (*input_line_pointer == ')' && tok->X_op == O_register) -+ { -+ tok->X_op = (saw_comma ? O_cpregister : O_pregister); -+ saw_comma = 0; -+ saw_arg = 1; -+ ++input_line_pointer; -+ ++tok; -+ break; -+ } -+ -+ /* ... then fall through to plain expression. */ -+ input_line_pointer = hold; -+ } -+ /* Fall through. */ -+ -+ default: -+ if (saw_arg && !saw_comma) -+ goto err; -+ -+ expression (tok); -+ if (tok->X_op == O_illegal || tok->X_op == O_absent) -+ goto err; -+ -+ saw_comma = 0; -+ saw_arg = 1; -+ ++tok; -+ break; -+ } -+ } -+ -+fini: -+ if (saw_comma) -+ goto err; -+ input_line_pointer = old_input_line_pointer; -+ -+#ifdef DEBUG_SW_64 -+ debug_exp (orig_tok, ntok - (end_tok - tok)); -+#endif -+#ifdef RELOC_OP_P -+ is_end_of_line[(unsigned char) '!'] = 0; -+#endif -+ -+ return ntok - (end_tok - tok); -+ -+err: -+#ifdef RELOC_OP_P -+ is_end_of_line[(unsigned char) '!'] = 0; -+#endif -+ input_line_pointer = old_input_line_pointer; -+ return TOKENIZE_ERROR; -+ -+#ifdef RELOC_OP_P -+err_report: -+ is_end_of_line[(unsigned char) '!'] = 0; -+#endif -+ input_line_pointer = old_input_line_pointer; -+ return TOKENIZE_ERROR_REPORT; -+} -+ -+/* Search forward through all variants of an opcode looking for a -+ syntax match. */ -+ -+static const struct sw_64_opcode * -+find_opcode_match (const struct sw_64_opcode *first_opcode, -+ const expressionS *tok, -+ int *pntok, -+ int *pcpumatch) -+{ -+ const struct sw_64_opcode *opcode = first_opcode; -+ int ntok = *pntok; -+ int got_cpu_match = 0; -+ -+ do -+ { -+ const unsigned char *opidx; -+ int tokidx = 0; -+ -+ /* Don't match opcodes that don't exist on this architecture. */ -+ if (!(opcode->flags & sw_64_target)) -+ goto match_failed; -+ -+ got_cpu_match = 1; -+ -+ for (opidx = opcode->operands; *opidx; ++opidx) -+ { -+ const struct sw_64_operand *operand = &sw_64_operands[*opidx]; -+ -+ /* Only take input from real operands. */ -+ if (operand->flags & AXP_OPERAND_FAKE) -+ continue; -+ -+ /* When we expect input, make sure we have it. */ -+ if (tokidx >= ntok) -+ { -+ /* -pal: don't allowed to use default result register. */ -+ if (pal_org_backwrards) -+ goto match_failed; -+ else -+ if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0) -+ goto match_failed; -+ continue; -+ } -+ -+ /* Match operand type with expression type. */ -+ switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK) -+ { -+ case AXP_OPERAND_IR: -+ if (tok[tokidx].X_op != O_register -+ || !is_ir_num (tok[tokidx].X_add_number)) -+ goto match_failed; -+ break; -+ case AXP_OPERAND_FPR: -+ if (tok[tokidx].X_op != O_register -+ || !is_fpr_num (tok[tokidx].X_add_number)) -+ goto match_failed; -+ break; -+ case AXP_OPERAND_IR | AXP_OPERAND_PARENS: -+ if (tok[tokidx].X_op != O_pregister -+ || !is_ir_num (tok[tokidx].X_add_number)) -+ goto match_failed; -+ break; -+ case AXP_OPERAND_IR | AXP_OPERAND_PARENS | AXP_OPERAND_COMMA: -+ if (tok[tokidx].X_op != O_cpregister -+ || !is_ir_num (tok[tokidx].X_add_number)) -+ goto match_failed; -+ break; -+ -+ case AXP_OPERAND_RELATIVE: -+ case AXP_OPERAND_SIGNED: -+ case AXP_OPERAND_UNSIGNED: -+ switch (tok[tokidx].X_op) -+ { -+ case O_illegal: -+ case O_absent: -+ case O_register: -+ case O_pregister: -+ case O_cpregister: -+ goto match_failed; -+ -+ default: -+ break; -+ } -+ break; -+ -+ default: -+ /* Everything else should have been fake. */ -+ abort (); -+ } -+ ++tokidx; -+ } -+ -+ /* Possible match -- did we use all of our input? */ -+ if (tokidx == ntok) -+ { -+ *pntok = ntok; -+ return opcode; -+ } -+ -+ match_failed:; -+ } -+ while (++opcode - sw_64_opcodes < (int) sw_64_num_opcodes -+ && !strcmp (opcode->name, first_opcode->name)); -+ -+ if (*pcpumatch) -+ *pcpumatch = got_cpu_match; -+ -+ return NULL; -+} -+ -+/* Given an opcode name and a pre-tokenized set of arguments, assemble -+ the insn, but do not emit it. -+ -+ Note that this implies no macros allowed, since we can't store more -+ than one insn in an insn structure. */ -+ -+static void -+assemble_tokens_to_insn (const char *opname, -+ const expressionS *tok, -+ int ntok, -+ struct sw_64_insn *insn) -+{ -+ const struct sw_64_opcode *opcode; -+ -+ /* Search opcodes. */ -+ opcode = (const struct sw_64_opcode *) str_hash_find (sw_64_opcode_hash, opname); -+ if (opcode) -+ { -+ int cpumatch; -+ opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch); -+ if (opcode) -+ { -+ assemble_insn (opcode, tok, ntok, insn, BFD_RELOC_UNUSED); -+ return; -+ } -+ else if (cpumatch) -+ as_bad (_("inappropriate arguments for opcode `%s'"), opname); -+ else -+ as_bad (_("opcode `%s' not supported for target %s"), opname, -+ sw_64_target_name); -+ } -+ else -+ as_bad (_("unknown opcode `%s'"), opname); -+} -+ -+/* Build a BFD section with its flags set appropriately for the .lita, -+ .lit8, or .lit4 sections. */ -+ -+static void -+create_literal_section (const char *name, -+ segT *secp, -+ symbolS **symp) -+{ -+ 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 (new_sec, 4); -+ bfd_set_section_flags (new_sec, (SEC_RELOC | SEC_ALLOC | SEC_LOAD -+ | SEC_READONLY | SEC_DATA)); -+ -+ S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec)); -+} -+ -+/* Load a (partial) expression into a target register. -+ -+ If poffset is not null, after the call it will either contain -+ O_constant 0, or a 16-bit offset appropriate for any MEM format -+ instruction. In addition, pbasereg will be modified to point to -+ the base register to use in that MEM format instruction. -+ -+ In any case, *pbasereg should contain a base register to add to the -+ expression. This will normally be either AXP_REG_ZERO or -+ sw_64_gp_register. Symbol addresses will always be loaded via $gp, -+ so "foo($0)" is interpreted as adding the address of foo to $0; -+ i.e. "ldl $targ, LIT($gp); addl $targ, $0, $targ". Odd, perhaps, -+ but this is what OSF/1 does. -+ -+ If explicit relocations of the form !literal! are allowed, -+ and used, then explicit_reloc with be an expression pointer. -+ -+ Finally, the return value is nonzero if the calling macro may emit -+ a LITUSE reloc if otherwise appropriate; the return value is the -+ sequence number to use. */ -+ -+static long -+load_expression (int targreg, -+ const expressionS *exp, -+ int *pbasereg, -+ expressionS *poffset, -+ const char *opname) -+{ -+ long emit_lituse = 0; -+ offsetT addend = exp->X_add_number; -+ int basereg = *pbasereg; -+ struct sw_64_insn insn; -+ expressionS newtok[3]; -+ -+ switch (exp->X_op) -+ { -+ case O_symbol: -+ { -+#ifdef OBJ_ECOFF -+ offsetT lit; -+ -+ /* Attempt to reduce .lit load by splitting the offset from -+ its symbol when possible, but don't create a situation in -+ which we'd fail. */ -+ if (!range_signed_32 (addend) && -+ (sw_64_noat_on || targreg == AXP_REG_AT)) -+ { -+ lit = add_to_literal_pool (exp->X_add_symbol, addend, -+ sw_64_lita_section, 8); -+ addend = 0; -+ } -+ else -+ lit = add_to_literal_pool (exp->X_add_symbol, 0, -+ sw_64_lita_section, 8); -+ -+ if (lit >= 0x8000) -+ as_fatal (_("overflow in literal (.lita) table")); -+ -+ /* Emit "ldl r, lit(gp)". */ -+ -+ if (basereg != sw_64_gp_register && targreg == basereg) -+ { -+ if (sw_64_noat_on) -+ as_warn (_("macro requires $at register while noat in effect")); -+ if (targreg == AXP_REG_AT) -+ as_warn (_("macro requires $at while $at in use")); -+ -+ set_tok_reg (newtok[0], AXP_REG_AT); -+ } -+ else -+ set_tok_reg (newtok[0], targreg); -+ -+ set_tok_sym (newtok[1], sw_64_lita_symbol, lit); -+ set_tok_preg (newtok[2], sw_64_gp_register); -+ -+ -+ assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -+ -+ gas_assert (insn.nfixups == 1); -+ insn.fixups[0].reloc = BFD_RELOC_SW_64_LITERAL; -+ insn.sequence = emit_lituse = next_sequence_num--; -+#endif /* OBJ_ECOFF */ -+#ifdef OBJ_ELF -+ /* Emit "ldl r, gotoff(gp)". */ -+ -+ if (basereg != sw_64_gp_register && targreg == basereg) -+ { -+ if (sw_64_noat_on) -+ as_bad (_("macro requires $at register while noat in effect")); -+ if (targreg == AXP_REG_AT) -+ as_bad (_("macro requires $at while $at in use")); -+ -+ set_tok_reg (newtok[0], AXP_REG_AT); -+ } -+ else -+ set_tok_reg (newtok[0], targreg); -+ -+ /* XXX: Disable this .got minimizing optimization so that we can get -+ better instruction offset knowledge in the compiler. This happens -+ very infrequently anyway. */ -+ if (1 -+ || (!range_signed_32 (addend) -+ && (sw_64_noat_on || targreg == AXP_REG_AT))) -+ { -+ newtok[1] = *exp; -+ addend = 0; -+ } -+ else -+ set_tok_sym (newtok[1], exp->X_add_symbol, 0); -+ -+ set_tok_preg (newtok[2], sw_64_gp_register); -+ -+ assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -+ -+ gas_assert (insn.nfixups == 1); -+ insn.fixups[0].reloc = BFD_RELOC_SW_64_ELF_LITERAL; -+ insn.sequence = emit_lituse = next_sequence_num--; -+#endif /* OBJ_ELF */ -+#ifdef OBJ_EVAX -+ /* Find symbol or symbol pointer in link section. */ -+ -+ if (exp->X_add_symbol == sw_64_evax_proc->symbol) -+ { -+ /* Linkage-relative expression. */ -+ set_tok_reg (newtok[0], targreg); -+ -+ if (range_signed_16 (addend)) -+ { -+ set_tok_const (newtok[1], addend); -+ addend = 0; -+ } -+ else -+ { -+ set_tok_const (newtok[1], 0); -+ } -+ set_tok_preg (newtok[2], basereg); -+ assemble_tokens_to_insn ("ldi", newtok, 3, &insn); -+ } -+ else -+ { -+ const char *symname = S_GET_NAME (exp->X_add_symbol); -+ const char *ptr1, *ptr2; -+ int symlen = strlen (symname); -+ -+ if ((symlen > 4 && -+ strcmp (ptr2 = &symname [symlen - 4], "..lk") == 0)) -+ { -+ /* Access to an item whose address is stored in the linkage -+ section. Just read the address. */ -+ set_tok_reg (newtok[0], targreg); -+ -+ newtok[1] = *exp; -+ newtok[1].X_op = O_subtract; -+ newtok[1].X_op_symbol = sw_64_evax_proc->symbol; -+ -+ set_tok_preg (newtok[2], basereg); -+ assemble_tokens_to_insn ("ldi", newtok, 3, &insn); -+ sw_64_linkage_symbol = exp->X_add_symbol; -+ -+ if (poffset) -+ set_tok_const (*poffset, 0); -+ -+ if (sw_64_flag_replace && targreg == 26) -+ { -+ /* Add a NOP fixup for 'ldX $26,YYY..NAME..lk'. */ -+ char *ensymname; -+ symbolS *ensym; -+ -+ /* Build the entry name as 'NAME..en'. */ -+ ptr1 = strstr (symname, "..") + 2; -+ if (ptr1 > ptr2) -+ ptr1 = symname; -+ ensymname = XNEWVEC (char, ptr2 - ptr1 + 5); -+ memcpy (ensymname, ptr1, ptr2 - ptr1); -+ memcpy (ensymname + (ptr2 - ptr1), "..en", 5); -+ -+ gas_assert (insn.nfixups + 1 <= MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = BFD_RELOC_SW_64_NOP; -+ ensym = symbol_find_or_make (ensymname); -+ free (ensymname); -+ symbol_mark_used (ensym); -+ /* The fixup must be the same as the BFD_RELOC_SW_64_BOH -+ case in emit_jsrjmp. See B.4.5.2 of the OpenVMS Linker -+ Utility Manual. */ -+ insn.fixups[insn.nfixups].exp.X_op = O_symbol; -+ insn.fixups[insn.nfixups].exp.X_add_symbol = ensym; -+ insn.fixups[insn.nfixups].exp.X_add_number = 0; -+ insn.fixups[insn.nfixups].xtrasym = sw_64_linkage_symbol; -+ insn.fixups[insn.nfixups].procsym = sw_64_evax_proc->symbol; -+ insn.nfixups++; -+ -+ /* ??? Force bsym to be instantiated now, as it will be -+ too late to do so in tc_gen_reloc. */ -+ symbol_get_bfdsym (exp->X_add_symbol); -+ } -+ else if (sw_64_flag_replace && targreg == 27) -+ { -+ /* Add a ldi fixup for 'ldX $27,YYY.NAME..lk+8'. */ -+ char *psymname; -+ symbolS *psym; -+ -+ /* Extract NAME. */ -+ ptr1 = strstr (symname, "..") + 2; -+ if (ptr1 > ptr2) -+ ptr1 = symname; -+ psymname = xmemdup0 (ptr1, ptr2 - ptr1); -+ -+ gas_assert (insn.nfixups + 1 <= MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = BFD_RELOC_SW_64_LDA; -+ psym = symbol_find_or_make (psymname); -+ free (psymname); -+ symbol_mark_used (psym); -+ insn.fixups[insn.nfixups].exp.X_op = O_subtract; -+ insn.fixups[insn.nfixups].exp.X_add_symbol = psym; -+ insn.fixups[insn.nfixups].exp.X_op_symbol = sw_64_evax_proc->symbol; -+ insn.fixups[insn.nfixups].exp.X_add_number = 0; -+ insn.fixups[insn.nfixups].xtrasym = sw_64_linkage_symbol; -+ insn.fixups[insn.nfixups].procsym = sw_64_evax_proc->symbol; -+ insn.nfixups++; -+ } -+ -+ emit_insn (&insn); -+ return 0; -+ } -+ else -+ { -+ /* Not in the linkage section. Put the value into the linkage -+ section. */ -+ symbolS *linkexp; -+ -+ if (!range_signed_32 (addend)) -+ addend = sign_extend_32 (addend); -+ linkexp = add_to_link_pool (exp->X_add_symbol, 0); -+ set_tok_reg (newtok[0], targreg); -+ set_tok_sym (newtok[1], linkexp, 0); -+ set_tok_preg (newtok[2], basereg); -+ assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -+ } -+ } -+#endif /* OBJ_EVAX */ -+ -+ emit_insn (&insn); -+ -+#ifndef OBJ_EVAX -+ if (basereg != sw_64_gp_register && basereg != AXP_REG_ZERO) -+ { -+ /* Emit "addl r, base, r". */ -+ -+ set_tok_reg (newtok[1], basereg); -+ set_tok_reg (newtok[2], targreg); -+ assemble_tokens ("addl", newtok, 3, 0); -+ } -+#endif -+ basereg = targreg; -+ } -+ break; -+ -+ case O_constant: -+ break; -+/* -+ * .text -+ * call_hmc__tbi_addr: -+ * ldi $4, ((tbi_tbl - call_hmc__tbi_addr) & 0xFFFF)($4) -+ * tbi_tbl: -+ * -+ * the value of label tbi_tbl can't be calculated,so the op of the expression "((tbi_tbl - call_hmc__tbi_addr) & 0xFFFF)" -+ * is "O_bit_and" but not "O_constant", so we must pass it ! -+ * */ -+ case O_bit_and: -+ set_tok_reg (newtok[0], targreg); -+ newtok[1] = *exp; -+ set_tok_preg (newtok[2], basereg); -+ assemble_tokens ("ldi", newtok, 3, 0); -+ break; -+ -+ case O_subtract: -+ /* Assume that this difference expression will be resolved to an -+ absolute value and that that value will fit in 16 bits. */ -+ -+ set_tok_reg (newtok[0], targreg); -+ newtok[1] = *exp; -+ set_tok_preg (newtok[2], basereg); -+ assemble_tokens (opname, newtok, 3, 0); -+ -+ if (poffset) -+ set_tok_const (*poffset, 0); -+ return 0; -+ -+ case O_big: -+ if (exp->X_add_number > 0) -+ as_bad (_("bignum invalid; zero assumed")); -+ else -+ as_bad (_("floating point number invalid; zero assumed")); -+ addend = 0; -+ break; -+ -+ default: -+ as_bad (_("can't handle expression")); -+ addend = 0; -+ break; -+ } -+ -+ if (!range_signed_32 (addend)) -+ { -+#ifdef OBJ_EVAX -+ symbolS *litexp; -+#else -+ offsetT lit; -+ long seq_num = next_sequence_num--; -+#endif -+ -+ /* For 64-bit addends, just put it in the literal pool. */ -+#ifdef OBJ_EVAX -+ /* Emit "ldl targreg, lit(basereg)". */ -+ litexp = add_to_link_pool (section_symbol (absolute_section), addend); -+ set_tok_reg (newtok[0], targreg); -+ set_tok_sym (newtok[1], litexp, 0); -+ set_tok_preg (newtok[2], sw_64_gp_register); -+ assemble_tokens ("ldl", newtok, 3, 0); -+#else -+ -+ if (sw_64_lit8_section == NULL) -+ { -+ create_literal_section (".lit8", -+ &sw_64_lit8_section, -+ &sw_64_lit8_symbol); -+ -+#ifdef OBJ_ECOFF -+ sw_64_lit8_literal = add_to_literal_pool (sw_64_lit8_symbol, 0x8000, -+ sw_64_lita_section, 8); -+ if (sw_64_lit8_literal >= 0x8000) -+ as_fatal (_("overflow in literal (.lita) table")); -+#endif -+ } -+ -+ lit = add_to_literal_pool (NULL, addend, sw_64_lit8_section, 8) - 0x8000; -+ if (lit >= 0x8000) -+ as_fatal (_("overflow in literal (.lit8) table")); -+ -+ /* Emit "ldi litreg, .lit8+0x8000". */ -+ -+ if (targreg == basereg) -+ { -+ if (sw_64_noat_on) -+ as_bad (_("macro requires $at register while noat in effect")); -+ if (targreg == AXP_REG_AT) -+ as_bad (_("macro requires $at while $at in use")); -+ -+ set_tok_reg (newtok[0], AXP_REG_AT); -+ } -+ else -+ set_tok_reg (newtok[0], targreg); -+#ifdef OBJ_ECOFF -+ set_tok_sym (newtok[1], sw_64_lita_symbol, sw_64_lit8_literal); -+#endif -+#ifdef OBJ_ELF -+ set_tok_sym (newtok[1], sw_64_lit8_symbol, 0x8000); -+#endif -+ set_tok_preg (newtok[2], sw_64_gp_register); -+ -+ assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -+ -+ gas_assert (insn.nfixups == 1); -+#ifdef OBJ_ECOFF -+ insn.fixups[0].reloc = BFD_RELOC_SW_64_LITERAL; -+#endif -+#ifdef OBJ_ELF -+ insn.fixups[0].reloc = BFD_RELOC_SW_64_ELF_LITERAL; -+#endif -+ insn.sequence = seq_num; -+ -+ emit_insn (&insn); -+ -+ /* Emit "ldl litreg, lit(litreg)". */ -+ -+ set_tok_const (newtok[1], lit); -+ set_tok_preg (newtok[2], newtok[0].X_add_number); -+ -+ assemble_tokens_to_insn ("ldl", newtok, 3, &insn); -+ -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = seq_num; -+ emit_lituse = 0; -+ -+ emit_insn (&insn); -+ -+ /* Emit "addl litreg, base, target". */ -+ -+ if (basereg != AXP_REG_ZERO) -+ { -+ set_tok_reg (newtok[1], basereg); -+ set_tok_reg (newtok[2], targreg); -+ assemble_tokens ("addl", newtok, 3, 0); -+ } -+#endif /* !OBJ_EVAX */ -+ -+ if (poffset) -+ set_tok_const (*poffset, 0); -+ *pbasereg = targreg; -+ } -+ else -+ { -+ offsetT low, high, extra, tmp; -+ -+ /* For 32-bit operands, break up the addend. */ -+ -+ low = sign_extend_16 (addend); -+ tmp = addend - low; -+ high = sign_extend_16 (tmp >> 16); -+ -+ if (tmp - (high << 16)) -+ { -+ extra = 0x4000; -+ tmp -= 0x40000000; -+ high = sign_extend_16 (tmp >> 16); -+ } -+ else -+ extra = 0; -+ -+ set_tok_reg (newtok[0], targreg); -+ set_tok_preg (newtok[2], basereg); -+ -+ if (extra) -+ { -+ /* Emit "ldih r, extra(r). */ -+ set_tok_const (newtok[1], extra); -+ assemble_tokens ("ldih", newtok, 3, 0); -+ set_tok_preg (newtok[2], basereg = targreg); -+ } -+ -+ if (high) -+ { -+ /* Emit "ldih r, high(r). */ -+ set_tok_const (newtok[1], high); -+ if (newtok[0].X_add_number==31 && newtok[0].X_op == O_register) -+ as_warn (_(" the disp is out of range ,may be incorrect !")); -+ else -+ assemble_tokens ("ldih", newtok, 3, 0); -+ basereg = targreg; -+ set_tok_preg (newtok[2], basereg); -+ } -+ -+ if ((low && !poffset) || (!poffset && basereg != targreg)) -+ { -+ /* Emit "ldi r, low(base)". */ -+ set_tok_const (newtok[1], low); -+ assemble_tokens ("ldi", newtok, 3, 0); -+ basereg = targreg; -+ low = 0; -+ } -+ -+ if (poffset) -+ set_tok_const (*poffset, low); -+ *pbasereg = basereg; -+ } -+ -+ return emit_lituse; -+} -+ -+/* The ldi macro differs from the ldi instruction in that it handles -+ most simple expressions, particularly symbol address loads and -+ large constants. */ -+ -+static void -+emit_ldi (const expressionS *tok, -+ int ntok, -+ const void * unused ATTRIBUTE_UNUSED) -+{ -+ int basereg; -+ -+ if (ntok == 2) -+ basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : sw_64_gp_register); -+ else -+ basereg = tok[2].X_add_number; -+ -+ (void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL, "ldi"); -+} -+ -+/* The ldih macro differs from the ldih instruction in that it has $31 -+ as an implied base register. */ -+ -+static void -+emit_ldih (const expressionS *tok, -+ int ntok ATTRIBUTE_UNUSED, -+ const void * unused ATTRIBUTE_UNUSED) -+{ -+ expressionS newtok[3]; -+ -+ newtok[0] = tok[0]; -+ newtok[1] = tok[1]; -+ set_tok_preg (newtok[2], AXP_REG_ZERO); -+ -+ assemble_tokens ("ldih", newtok, 3, 0); -+} -+ -+/* Called internally to handle all alignment needs. This takes care -+ of eliding calls to frag_align if'n the cached current alignment -+ says we've already got it, as well as taking care of the auto-align -+ feature wrt labels. */ -+ -+static void -+sw_64_align (int n, -+ char *pfill, -+ symbolS *label, -+ int force ATTRIBUTE_UNUSED) -+{ -+ if (sw_64_current_align >= n) -+ return; -+ -+ if (pfill == NULL) -+ { -+ if (subseg_text_p (now_seg)) -+ frag_align_code (n, 0); -+ else -+ frag_align (n, 0, 0); -+ } -+ else -+ frag_align (n, *pfill, 0); -+ -+ sw_64_current_align = n; -+ -+ if (label != NULL && S_GET_SEGMENT (label) == now_seg) -+ { -+ symbol_set_frag (label, frag_now); -+ S_SET_VALUE (label, (valueT) frag_now_fix ()); -+ } -+ -+ record_alignment (now_seg, n); -+ -+ /* ??? If sw_64_flag_relax && force && elf, record the requested alignment -+ in a reloc for the linker to see. */ -+} -+ -+/* Actually output an instruction with its fixup. */ -+ -+static void -+emit_insn (struct sw_64_insn *insn) -+{ -+ char *f; -+ int i; -+ -+ /* Take care of alignment duties. */ -+ if (sw_64_auto_align_on && sw_64_current_align < 2) -+ sw_64_align (2, (char *) NULL, sw_64_insn_label, 0); -+ if (sw_64_current_align > 2) -+ sw_64_current_align = 2; -+ sw_64_insn_label = NULL; -+ -+ /* Write out the instruction. */ -+ f = frag_more (4); -+ md_number_to_chars (f, insn->insn, 4); -+ -+#ifdef OBJ_ELF -+ dwarf2_emit_insn (4); -+#endif -+ -+ /* Apply the fixups in order. */ -+ for (i = 0; i < insn->nfixups; ++i) -+ { -+ const struct sw_64_operand *operand = (const struct sw_64_operand *) 0; -+ struct sw_64_fixup *fixup = &insn->fixups[i]; -+ struct sw_64_reloc_tag *info = NULL; -+ int size, pcrel; -+ fixS *fixP; -+ -+ /* Some fixups are only used internally and so have no howto. */ -+ if ((int) fixup->reloc < 0) -+ { -+ operand = &sw_64_operands[-(int) fixup->reloc]; -+ size = 4; -+ pcrel = ((operand->flags & AXP_OPERAND_RELATIVE) != 0); -+ } -+ else if (fixup->reloc > BFD_RELOC_UNUSED -+ || fixup->reloc == BFD_RELOC_SW_64_GPDISP_HI16 -+ || fixup->reloc == BFD_RELOC_SW_64_GPDISP_LO16) -+ { -+ size = 2; -+ pcrel = 0; -+ } -+ else -+ { -+ reloc_howto_type *reloc_howto = -+ bfd_reloc_type_lookup (stdoutput, -+ (bfd_reloc_code_real_type) fixup->reloc); -+ gas_assert (reloc_howto); -+ -+ size = bfd_get_reloc_size (reloc_howto); -+ -+ switch (fixup->reloc) -+ { -+#ifdef OBJ_EVAX -+ case BFD_RELOC_SW_64_NOP: -+ case BFD_RELOC_SW_64_BSR: -+ case BFD_RELOC_SW_64_LDA: -+ case BFD_RELOC_SW_64_BOH: -+ break; -+#endif -+ default: -+ gas_assert (size >= 1 && size <= 4); -+ } -+ -+ pcrel = reloc_howto->pc_relative; -+ } -+ -+ fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size, -+ &fixup->exp, pcrel, (bfd_reloc_code_real_type) fixup->reloc); -+ -+ /* Turn off complaints that the addend is too large for some fixups, -+ and copy in the sequence number for the explicit relocations. */ -+ switch (fixup->reloc) -+ { -+ case BFD_RELOC_SW_64_HINT: -+ case BFD_RELOC_GPREL32: -+ case BFD_RELOC_GPREL16: -+ case BFD_RELOC_SW_64_GPREL_HI16: -+ case BFD_RELOC_SW_64_GPREL_LO16: -+ case BFD_RELOC_SW_64_GOTDTPREL16: -+ case BFD_RELOC_SW_64_DTPREL_HI16: -+ case BFD_RELOC_SW_64_DTPREL_LO16: -+ case BFD_RELOC_SW_64_DTPREL16: -+ case BFD_RELOC_SW_64_GOTTPREL16: -+ case BFD_RELOC_SW_64_TPREL_HI16: -+ case BFD_RELOC_SW_64_TPREL_LO16: -+ case BFD_RELOC_SW_64_TPREL16: -+ fixP->fx_no_overflow = 1; -+ break; -+ -+ case BFD_RELOC_SW_64_GPDISP_HI16: -+ fixP->fx_no_overflow = 1; -+ fixP->fx_addsy = section_symbol (now_seg); -+ fixP->fx_offset = 0; -+ -+ info = get_sw_64_reloc_tag (insn->sequence); -+ if (++info->n_master > 1) -+ as_bad (_("too many ldih insns for !gpdisp!%ld"), insn->sequence); -+ if (info->segment != now_seg) -+ as_bad (_("both insns for !gpdisp!%ld must be in the same section"), -+ insn->sequence); -+ fixP->tc_fix_data.info = info; -+ break; -+ -+ case BFD_RELOC_SW_64_GPDISP_LO16: -+ fixP->fx_no_overflow = 1; -+ -+ info = get_sw_64_reloc_tag (insn->sequence); -+ if (++info->n_slaves > 1) -+ as_bad (_("too many ldi insns for !gpdisp!%ld"), insn->sequence); -+ if (info->segment != now_seg) -+ as_bad (_("both insns for !gpdisp!%ld must be in the same section"), -+ insn->sequence); -+ fixP->tc_fix_data.info = info; -+ info->slaves = fixP; -+ break; -+ -+ case BFD_RELOC_SW_64_LITERAL: -+ case BFD_RELOC_SW_64_ELF_LITERAL: -+ fixP->fx_no_overflow = 1; -+ -+ if (insn->sequence == 0) -+ break; -+ info = get_sw_64_reloc_tag (insn->sequence); -+ info->master = fixP; -+ info->n_master++; -+ if (info->segment != now_seg) -+ info->multi_section_p = 1; -+ fixP->tc_fix_data.info = info; -+ break; -+ -+#ifdef RELOC_OP_P -+ case DUMMY_RELOC_LITUSE_ADDR: -+ fixP->fx_offset = LITUSE_SW_64_ADDR; -+ goto do_lituse; -+ case DUMMY_RELOC_LITUSE_BASE: -+ fixP->fx_offset = LITUSE_SW_64_BASE; -+ goto do_lituse; -+ case DUMMY_RELOC_LITUSE_BYTOFF: -+ fixP->fx_offset = LITUSE_SW_64_BYTOFF; -+ goto do_lituse; -+ case DUMMY_RELOC_LITUSE_JSR: -+ fixP->fx_offset = LITUSE_SW_64_JSR; -+ goto do_lituse; -+ case DUMMY_RELOC_LITUSE_TLSGD: -+ fixP->fx_offset = LITUSE_SW_64_TLSGD; -+ goto do_lituse; -+ case DUMMY_RELOC_LITUSE_TLSLDM: -+ fixP->fx_offset = LITUSE_SW_64_TLSLDM; -+ goto do_lituse; -+ case DUMMY_RELOC_LITUSE_JSRDIRECT: -+ fixP->fx_offset = LITUSE_SW_64_JSRDIRECT; -+ goto do_lituse; -+ do_lituse: -+ fixP->fx_addsy = section_symbol (now_seg); -+ fixP->fx_r_type = BFD_RELOC_SW_64_LITUSE; -+ -+ info = get_sw_64_reloc_tag (insn->sequence); -+ if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSGD) -+ info->saw_lu_tlsgd = 1; -+ else if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSLDM) -+ info->saw_lu_tlsldm = 1; -+ if (++info->n_slaves > 1) -+ { -+ if (info->saw_lu_tlsgd) -+ as_bad (_("too many lituse insns for !lituse_tlsgd!%ld"), -+ insn->sequence); -+ else if (info->saw_lu_tlsldm) -+ as_bad (_("too many lituse insns for !lituse_tlsldm!%ld"), -+ insn->sequence); -+ } -+ fixP->tc_fix_data.info = info; -+ fixP->tc_fix_data.next_reloc = info->slaves; -+ info->slaves = fixP; -+ if (info->segment != now_seg) -+ info->multi_section_p = 1; -+ break; -+ -+ case BFD_RELOC_SW_64_TLSGD: -+ fixP->fx_no_overflow = 1; -+ -+ if (insn->sequence == 0) -+ break; -+ info = get_sw_64_reloc_tag (insn->sequence); -+ if (info->saw_tlsgd) -+ as_bad (_("duplicate !tlsgd!%ld"), insn->sequence); -+ else if (info->saw_tlsldm) -+ as_bad (_("sequence number in use for !tlsldm!%ld"), -+ insn->sequence); -+ else -+ info->saw_tlsgd = 1; -+ fixP->tc_fix_data.info = info; -+ break; -+ -+ case BFD_RELOC_SW_64_TLSLDM: -+ fixP->fx_no_overflow = 1; -+ -+ if (insn->sequence == 0) -+ break; -+ info = get_sw_64_reloc_tag (insn->sequence); -+ if (info->saw_tlsldm) -+ as_bad (_("duplicate !tlsldm!%ld"), insn->sequence); -+ else if (info->saw_tlsgd) -+ as_bad (_("sequence number in use for !tlsgd!%ld"), -+ insn->sequence); -+ else -+ info->saw_tlsldm = 1; -+ fixP->tc_fix_data.info = info; -+ break; -+#endif -+#ifdef OBJ_EVAX -+ case BFD_RELOC_SW_64_NOP: -+ case BFD_RELOC_SW_64_LDA: -+ case BFD_RELOC_SW_64_BSR: -+ case BFD_RELOC_SW_64_BOH: -+ info = get_sw_64_reloc_tag (next_sequence_num--); -+ fixP->tc_fix_data.info = info; -+ fixP->tc_fix_data.info->sym = fixup->xtrasym; -+ fixP->tc_fix_data.info->psym = fixup->procsym; -+ break; -+#endif -+ -+ default: -+ if ((int) fixup->reloc < 0) -+ { -+ if (operand->flags & AXP_OPERAND_NOOVERFLOW) -+ fixP->fx_no_overflow = 1; -+ } -+ break; -+ } -+ } -+} -+ -+/* Insert an operand value into an instruction. */ -+ -+static unsigned -+insert_operand (unsigned insn, -+ const struct sw_64_operand *operand, -+ offsetT val, -+ const char *file, -+ unsigned line) -+{ -+ if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW)) -+ { -+ offsetT min, max; -+ -+ if (operand->flags & AXP_OPERAND_SIGNED) -+ { -+ max = (1 << (operand->bits - 1)) - 1; -+ min = -(1 << (operand->bits - 1)); -+ } -+ else -+ { -+ max = (1 << operand->bits) - 1; -+ min = 0; -+ } -+ -+ if (val < min || val > max) -+ as_warn_value_out_of_range (_("operand"), val, min, max, file, line); -+ } -+ -+ if (operand->insert) -+ { -+ const char *errmsg = NULL; -+ -+ insn = (*operand->insert) (insn, val, &errmsg); -+ if (errmsg) -+ as_warn ("%s", errmsg); -+ } -+ else -+ insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift); -+ -+ return insn; -+} -+ -+ static unsigned int need_rd_f = 0; -+ static unsigned int next_insn = 0; -+ -+/* Turn an opcode description and a set of arguments into -+ an instruction and a fixup. */ -+ -+static void -+assemble_insn (const struct sw_64_opcode *opcode, -+ const expressionS *tok, -+ int ntok, -+ struct sw_64_insn *insn, -+ extended_bfd_reloc_code_real_type reloc) -+{ -+ const struct sw_64_operand *reloc_operand = NULL; -+ const expressionS *reloc_exp = NULL; -+ const unsigned char *argidx; -+ unsigned image; -+ int tokidx = 0; -+ next_insn++; -+ -+ memset (insn, 0, sizeof (*insn)); -+ image = opcode->opcode; -+ -+ for (argidx = opcode->operands; *argidx; ++argidx) -+ { -+ const struct sw_64_operand *operand = &sw_64_operands[*argidx]; -+ const expressionS *t = (const expressionS *) 0; -+ -+ if (operand->flags & AXP_OPERAND_FAKE) -+ { -+ /* Fake operands take no value and generate no fixup. */ -+ image = insert_operand (image, operand, 0, NULL, 0); -+ continue; -+ } -+ -+ if (tokidx >= ntok) -+ { -+ switch (operand->flags & AXP_OPERAND_OPTIONAL_MASK) -+ { -+ case AXP_OPERAND_DEFAULT_FIRST: -+ t = &tok[0]; -+ break; -+ case AXP_OPERAND_DEFAULT_SECOND: -+ t = &tok[1]; -+ break; -+ case AXP_OPERAND_DEFAULT_THIRD: -+ t = &tok[2]; -+ break; -+ case AXP_OPERAND_DEFAULT_ZERO: -+ { -+ static expressionS zero_exp; -+ t = &zero_exp; -+ zero_exp.X_op = O_constant; -+ zero_exp.X_unsigned = 1; -+ } -+ break; -+ default: -+ abort (); -+ } -+ } -+ else -+ t = &tok[tokidx++]; -+ -+ switch (t->X_op) -+ { -+ case O_register: -+ case O_pregister: -+ case O_cpregister: -+ image = insert_operand (image, operand, regno (t->X_add_number), -+ NULL, 0); -+ break; -+ -+ case O_constant: -+ image = insert_operand (image, operand, t->X_add_number, NULL, 0); -+ gas_assert (reloc_operand == NULL); -+ reloc_operand = operand; -+ reloc_exp = t; -+ break; -+ -+ default: -+ /* This is only 0 for fields that should contain registers, -+ which means this pattern shouldn't have matched. */ -+ if (operand->default_reloc == 0) -+ abort (); -+ -+ /* There is one special case for which an insn receives two -+ relocations, and thus the user-supplied reloc does not -+ override the operand reloc. */ -+ if (operand->default_reloc == BFD_RELOC_SW_64_HINT) -+ { -+ struct sw_64_fixup *fixup; -+ -+ if (insn->nfixups >= MAX_INSN_FIXUPS) -+ as_fatal (_("too many fixups")); -+ -+ fixup = &insn->fixups[insn->nfixups++]; -+ fixup->exp = *t; -+ fixup->reloc = BFD_RELOC_SW_64_HINT; -+ } -+ else -+ { -+ if (reloc == BFD_RELOC_UNUSED) -+ reloc = operand->default_reloc; -+ -+ gas_assert (reloc_operand == NULL); -+ reloc_operand = operand; -+ reloc_exp = t; -+ } -+ break; -+ } -+ } -+ -+ if (reloc != BFD_RELOC_UNUSED) -+ { -+ struct sw_64_fixup *fixup; -+ -+ if (insn->nfixups >= MAX_INSN_FIXUPS) -+ as_fatal (_("too many fixups")); -+ -+ /* ??? My but this is hacky. But the OSF/1 assembler uses the same -+ relocation tag for both ldih and ldi with gpdisp. Choose the -+ correct internal relocation based on the opcode. */ -+ if (reloc == BFD_RELOC_SW_64_GPDISP) -+ { -+ if (strcmp (opcode->name, "ldih") == 0) -+ reloc = BFD_RELOC_SW_64_GPDISP_HI16; -+ else if (strcmp (opcode->name, "ldi") == 0) -+ reloc = BFD_RELOC_SW_64_GPDISP_LO16; -+ else -+ as_bad (_("invalid relocation for instruction")); -+ } -+ -+ /* If this is a real relocation (as opposed to a lituse hint), then -+ the relocation width should match the operand width. -+ Take care of -MDISP in operand table. */ -+ else if (reloc < BFD_RELOC_UNUSED && reloc > 0) -+ { -+ reloc_howto_type *reloc_howto -+ = bfd_reloc_type_lookup (stdoutput, -+ (bfd_reloc_code_real_type) reloc); -+ if (reloc_operand == NULL -+ || reloc_howto->bitsize != reloc_operand->bits) -+ { -+ as_bad (_("invalid relocation for field")); -+ return; -+ } -+ } -+ -+ fixup = &insn->fixups[insn->nfixups++]; -+ if (reloc_exp) -+ fixup->exp = *reloc_exp; -+ else -+ fixup->exp.X_op = O_absent; -+ fixup->reloc = reloc; -+ } -+ -+ insn->insn = image; -+ -+ if (!strcmp(sw_64_target_name, "sw6a") -+ || !strcmp(sw_64_target_name, "sw6b")) -+ { -+ if (!strcmp (opcode->name, "lstw") || !strcmp (opcode->name,"lstl") -+ || !strcmp (opcode->name,"stl_c") || !strcmp (opcode->name,"stq_c")) -+ { -+ sw_64_align (3, (char *) NULL, sw_64_insn_label, 0); -+ need_rd_f = 1; -+ next_insn = 0; -+ } -+ if (strcmp (opcode->name, "rd_f") && need_rd_f && (next_insn == 1) ) -+ as_bad (_("missing \"rd_f\" before \"%s\" !!"), (char *)opcode->name); -+ } -+} -+ -+/* Handle all "simple" integer register loads -- ldl, ldl_l, ldl_u, -+ etc. They differ from the real instructions in that they do simple -+ expressions like the ldi macro. */ -+ -+static void -+emit_ir_load (const expressionS *tok, -+ int ntok, -+ const void * opname) -+{ -+ int basereg; -+ long lituse; -+ expressionS newtok[3]; -+ struct sw_64_insn insn; -+ const char *symname -+ = tok[1].X_add_symbol ? S_GET_NAME (tok[1].X_add_symbol): ""; -+ int symlen = strlen (symname); -+ -+ if (ntok == 2) -+ basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : sw_64_gp_register); -+ else -+ basereg = tok[2].X_add_number; -+ -+ lituse = load_expression (tok[0].X_add_number, &tok[1], -+ &basereg, &newtok[1], (const char *) opname); -+ -+ if (basereg == sw_64_gp_register && -+ (symlen > 4 && strcmp (&symname [symlen - 4], "..lk") == 0)) -+ return; -+ -+ newtok[0] = tok[0]; -+ set_tok_preg (newtok[2], basereg); -+ -+ assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); -+ -+ if (lituse) -+ { -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = lituse; -+ } -+ -+ emit_insn (&insn); -+} -+ -+/* Handle fp register loads, and both integer and fp register stores. -+ Again, we handle simple expressions. */ -+ -+static void -+emit_loadstore (const expressionS *tok, -+ int ntok, -+ const void * opname) -+{ -+ int basereg; -+ long lituse; -+ expressionS newtok[3]; -+ struct sw_64_insn insn; -+ -+ if (ntok == 2) -+ basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : sw_64_gp_register); -+ else -+ basereg = tok[2].X_add_number; -+ -+ if (tok[1].X_op != O_constant || !range_signed_16 (tok[1].X_add_number)) -+ { -+ if (sw_64_noat_on) -+ as_bad (_("macro requires $at register while noat in effect")); -+ else -+ as_warn (_("assembler requires $28 register for the marco !")); -+ -+ lituse = load_expression (AXP_REG_AT, &tok[1], -+ &basereg, &newtok[1], (const char *) opname); -+ } -+ else -+ { -+ newtok[1] = tok[1]; -+ lituse = 0; -+ } -+ -+ newtok[0] = tok[0]; -+ set_tok_preg (newtok[2], basereg); -+ -+ assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); -+ -+ if (lituse) -+ { -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = lituse; -+ } -+ -+ emit_insn (&insn); -+} -+ -+/* Load a half-word or byte as an unsigned value. */ -+ -+static void -+emit_ldXu (const expressionS *tok, -+ int ntok, -+ const void * vlgsize) -+{ -+ if (sw_64_target & AXP_OPCODE_SW6) -+ emit_ir_load (tok, ntok, ldXu_op[(long) vlgsize]); -+ else -+ { -+ expressionS newtok[3]; -+ struct sw_64_insn insn; -+ int basereg; -+ long lituse; -+ -+ if (sw_64_noat_on) -+ as_bad (_("macro requires $at register while noat in effect")); -+ -+ if (ntok == 2) -+ basereg = (tok[1].X_op == O_constant -+ ? AXP_REG_ZERO : sw_64_gp_register); -+ else -+ basereg = tok[2].X_add_number; -+ -+ /* Emit "ldi $at, exp". */ -+ lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL, "ldi"); -+ -+ /* Emit "ldl_u targ, 0($at)". */ -+ newtok[0] = tok[0]; -+ set_tok_const (newtok[1], 0); -+ set_tok_preg (newtok[2], basereg); -+ assemble_tokens_to_insn ("ldl_u", newtok, 3, &insn); -+ -+ if (lituse) -+ { -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = lituse; -+ } -+ -+ emit_insn (&insn); -+ -+ /* Emit "extXl targ, $at, targ". */ -+ set_tok_reg (newtok[1], basereg); -+ newtok[2] = newtok[0]; -+ assemble_tokens_to_insn (extXl_op[(long) vlgsize], newtok, 3, &insn); -+ -+ if (lituse) -+ { -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = lituse; -+ } -+ -+ emit_insn (&insn); -+ } -+} -+ -+/* Load a half-word or byte as a signed value. */ -+ -+static void -+emit_ldX (const expressionS *tok, -+ int ntok, -+ const void * vlgsize) -+{ -+ emit_ldXu (tok, ntok, vlgsize); -+ assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1); -+} -+ -+/* Load an integral value from an unaligned address as an unsigned -+ value. */ -+ -+static void -+emit_uldXu (const expressionS *tok, -+ int ntok, -+ const void * vlgsize) -+{ -+ long lgsize = (long) vlgsize; -+ expressionS newtok[3]; -+ -+ if (sw_64_noat_on) -+ as_bad (_("macro requires $at register while noat in effect")); -+ -+ /* Emit "ldi $at, exp". */ -+ memcpy (newtok, tok, sizeof (expressionS) * ntok); -+ newtok[0].X_add_number = AXP_REG_AT; -+ assemble_tokens ("ldi", newtok, ntok, 1); -+ -+ /* Emit "ldl_u $t9, 0($at)". */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ set_tok_const (newtok[1], 0); -+ set_tok_preg (newtok[2], AXP_REG_AT); -+ assemble_tokens ("ldl_u", newtok, 3, 1); -+ -+ /* Emit "ldl_u $t10, size-1($at)". */ -+ set_tok_reg (newtok[0], AXP_REG_T10); -+ set_tok_const (newtok[1], (1 << lgsize) - 1); -+ assemble_tokens ("ldl_u", newtok, 3, 1); -+ -+ /* Emit "extXl $t9, $at, $t9". */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ set_tok_reg (newtok[1], AXP_REG_AT); -+ set_tok_reg (newtok[2], AXP_REG_T9); -+ assemble_tokens (extXl_op[lgsize], newtok, 3, 1); -+ -+ /* Emit "extXh $t10, $at, $t10". */ -+ set_tok_reg (newtok[0], AXP_REG_T10); -+ set_tok_reg (newtok[2], AXP_REG_T10); -+ assemble_tokens (extXh_op[lgsize], newtok, 3, 1); -+ -+ /* Emit "or $t9, $t10, targ". */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ set_tok_reg (newtok[1], AXP_REG_T10); -+ newtok[2] = tok[0]; -+ assemble_tokens ("or", newtok, 3, 1); -+} -+ -+/* Load an integral value from an unaligned address as a signed value. -+ Note that quads should get funneled to the unsigned load since we -+ don't have to do the sign extension. */ -+ -+static void -+emit_uldX (const expressionS *tok, -+ int ntok, -+ const void * vlgsize) -+{ -+ emit_uldXu (tok, ntok, vlgsize); -+ assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1); -+} -+ -+/* Implement the ldil macro. */ -+ -+static void -+emit_ldil (const expressionS *tok, -+ int ntok, -+ const void * unused ATTRIBUTE_UNUSED) -+{ -+ expressionS newtok[2]; -+ -+ memcpy (newtok, tok, sizeof (newtok)); -+ newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number); -+ -+ assemble_tokens ("ldi", newtok, ntok, 1); -+} -+ -+/* Store a half-word or byte. */ -+ -+static void -+emit_stX (const expressionS *tok, -+ int ntok, -+ const void * vlgsize) -+{ -+ int lgsize = (int) (long) vlgsize; -+ -+ -+ if (sw_64_target & AXP_OPCODE_SW6) -+ emit_loadstore (tok, ntok, stX_op[lgsize]); -+ else -+ { -+ expressionS newtok[3]; -+ struct sw_64_insn insn; -+ int basereg; -+ long lituse; -+ -+ if (sw_64_noat_on) -+ as_bad (_("macro requires $at register while noat in effect")); -+ -+ if (ntok == 2) -+ basereg = (tok[1].X_op == O_constant -+ ? AXP_REG_ZERO : sw_64_gp_register); -+ else -+ basereg = tok[2].X_add_number; -+ -+ /* Emit "ldi $at, exp". */ -+ lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL, "ldi"); -+ -+ /* Emit "ldl_u $t9, 0($at)". */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ set_tok_const (newtok[1], 0); -+ set_tok_preg (newtok[2], basereg); -+ assemble_tokens_to_insn ("ldl_u", newtok, 3, &insn); -+ -+ if (lituse) -+ { -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = lituse; -+ } -+ -+ emit_insn (&insn); -+ -+ /* Emit "insXl src, $at, $t10". */ -+ newtok[0] = tok[0]; -+ set_tok_reg (newtok[1], basereg); -+ set_tok_reg (newtok[2], AXP_REG_T10); -+ assemble_tokens_to_insn (insXl_op[lgsize], newtok, 3, &insn); -+ -+ if (lituse) -+ { -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = lituse; -+ } -+ -+ emit_insn (&insn); -+ -+ /* Emit "mskXl $t9, $at, $t9". */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ newtok[2] = newtok[0]; -+ assemble_tokens_to_insn (mskXl_op[lgsize], newtok, 3, &insn); -+ -+ if (lituse) -+ { -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = lituse; -+ } -+ -+ emit_insn (&insn); -+ -+ /* Emit "or $t9, $t10, $t9". */ -+ set_tok_reg (newtok[1], AXP_REG_T10); -+ assemble_tokens ("or", newtok, 3, 1); -+ -+ /* Emit "stq_u $t9, 0($at). */ -+ set_tok_const(newtok[1], 0); -+ set_tok_preg (newtok[2], AXP_REG_AT); -+ assemble_tokens_to_insn ("stl_u", newtok, 3, &insn); -+ -+ if (lituse) -+ { -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = lituse; -+ } -+ -+ emit_insn (&insn); -+ } -+} -+ -+/* Store an integer to an unaligned address. */ -+ -+static void -+emit_ustX (const expressionS *tok, -+ int ntok, -+ const void * vlgsize) -+{ -+ int lgsize = (int) (long) vlgsize; -+ expressionS newtok[3]; -+ -+ /* Emit "ldi $at, exp". */ -+ memcpy (newtok, tok, sizeof (expressionS) * ntok); -+ newtok[0].X_add_number = AXP_REG_AT; -+ assemble_tokens ("ldi", newtok, ntok, 1); -+ -+ /* Emit "ldl_u $9, 0($at)". */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ set_tok_const (newtok[1], 0); -+ set_tok_preg (newtok[2], AXP_REG_AT); -+ assemble_tokens ("ldl_u", newtok, 3, 1); -+ -+ /* Emit "ldl_u $10, size-1($at)". */ -+ set_tok_reg (newtok[0], AXP_REG_T10); -+ set_tok_const (newtok[1], (1 << lgsize) - 1); -+ assemble_tokens ("ldl_u", newtok, 3, 1); -+ -+ /* Emit "insXl src, $at, $t11". */ -+ newtok[0] = tok[0]; -+ set_tok_reg (newtok[1], AXP_REG_AT); -+ set_tok_reg (newtok[2], AXP_REG_T11); -+ assemble_tokens (insXl_op[lgsize], newtok, 3, 1); -+ -+ /* Emit "insXh src, $at, $t12". */ -+ set_tok_reg (newtok[2], AXP_REG_T12); -+ assemble_tokens (insXh_op[lgsize], newtok, 3, 1); -+ -+ /* Emit "mskXl $t9, $at, $t9". */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ newtok[2] = newtok[0]; -+ assemble_tokens (mskXl_op[lgsize], newtok, 3, 1); -+ -+ /* Emit "mskXh $t10, $at, $t10". */ -+ set_tok_reg (newtok[0], AXP_REG_T10); -+ newtok[2] = newtok[0]; -+ assemble_tokens (mskXh_op[lgsize], newtok, 3, 1); -+ -+ /* Emit "or $t9, $t11, $t9". */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ set_tok_reg (newtok[1], AXP_REG_T11); -+ newtok[2] = newtok[0]; -+ assemble_tokens ("or", newtok, 3, 1); -+ -+ /* Emit "or $t10, $t12, $t10". */ -+ set_tok_reg (newtok[0], AXP_REG_T10); -+ set_tok_reg (newtok[1], AXP_REG_T12); -+ newtok[2] = newtok[0]; -+ assemble_tokens ("or", newtok, 3, 1); -+ -+ /* Emit "stq_u $t10, size-1($at)". */ -+ set_tok_reg (newtok[0], AXP_REG_T10); -+ set_tok_const (newtok[1], (1 << lgsize) - 1); -+ set_tok_preg (newtok[2], AXP_REG_AT); -+ assemble_tokens ("stl_u", newtok, 3, 1); -+ -+ /* Emit "stq_u $t9, 0($at)". */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ set_tok_const (newtok[1], 0); -+ assemble_tokens ("stl_u", newtok, 3, 1); -+} -+ -+/* Sign extend a half-word or byte. The 32-bit sign extend is -+ implemented as "addl $31, $r, $t" in the opcode table. */ -+ -+static void -+emit_sextX (const expressionS *tok, -+ int ntok, -+ const void * vlgsize) -+{ -+ long lgsize = (long) vlgsize; -+ -+ if (sw_64_target & AXP_OPCODE_SW6) -+ assemble_tokens (sextX_op[lgsize], tok, ntok, 0); -+ else -+ { -+ int bitshift = 64 - 8 * (1 << lgsize); -+ expressionS newtok[3]; -+ -+ /* Emit "sll src,bits,dst". */ -+ newtok[0] = tok[0]; -+ set_tok_const (newtok[1], bitshift); -+ newtok[2] = tok[ntok - 1]; -+ assemble_tokens ("sll", newtok, 3, 1); -+ -+ /* Emit "sra dst,bits,dst". */ -+ newtok[0] = newtok[2]; -+ assemble_tokens ("sra", newtok, 3, 1); -+ } -+} -+ -+static void -+emit_vlogx(const expressionS *tok, -+ int ntok, -+ const void * unused ATTRIBUTE_UNUSED) -+{ -+ unsigned int mask=0; -+ struct sw_64_insn insn; -+ assemble_tokens_to_insn("vlog",tok,ntok-1,&insn); -+ mask=(tok[4].X_add_number>>6)<<26; -+ mask+=(tok[4].X_add_number & 0x3f)<<10; -+ insn.insn|=mask; -+ emit_insn(&insn); -+} -+ -+/* Implement the division and modulus macros. */ -+ -+#ifdef OBJ_EVAX -+ -+/* Make register usage like in normal procedure call. -+ Don't clobber PV and RA. */ -+ -+static void -+emit_division (const expressionS *tok, -+ int ntok, -+ const void * symname) -+{ -+ /* DIVISION and MODULUS. Yech. -+ -+ Convert -+ OP x,y,result -+ to -+ mov x,R16 # if x != R16 -+ mov y,R17 # if y != R17 -+ ldi AT,__OP -+ call AT,(AT),0 -+ mov R0,result -+ -+ with appropriate optimizations if R0,R16,R17 are the registers -+ specified by the compiler. */ -+ -+ int xr, yr, rr; -+ symbolS *sym; -+ expressionS newtok[3]; -+ -+ xr = regno (tok[0].X_add_number); -+ yr = regno (tok[1].X_add_number); -+ -+ if (ntok < 3) -+ rr = xr; -+ else -+ rr = regno (tok[2].X_add_number); -+ -+ /* Move the operands into the right place. */ -+ if (yr == AXP_REG_R16 && xr == AXP_REG_R17) -+ { -+ /* They are in exactly the wrong order -- swap through AT. */ -+ if (sw_64_noat_on) -+ as_bad (_("macro requires $at register while noat in effect")); -+ -+ set_tok_reg (newtok[0], AXP_REG_R16); -+ set_tok_reg (newtok[1], AXP_REG_AT); -+ assemble_tokens ("mov", newtok, 2, 1); -+ -+ set_tok_reg (newtok[0], AXP_REG_R17); -+ set_tok_reg (newtok[1], AXP_REG_R16); -+ assemble_tokens ("mov", newtok, 2, 1); -+ -+ set_tok_reg (newtok[0], AXP_REG_AT); -+ set_tok_reg (newtok[1], AXP_REG_R17); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+ else -+ { -+ if (yr == AXP_REG_R16) -+ { -+ set_tok_reg (newtok[0], AXP_REG_R16); -+ set_tok_reg (newtok[1], AXP_REG_R17); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+ -+ if (xr != AXP_REG_R16) -+ { -+ set_tok_reg (newtok[0], xr); -+ set_tok_reg (newtok[1], AXP_REG_R16); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+ -+ if (yr != AXP_REG_R16 && yr != AXP_REG_R17) -+ { -+ set_tok_reg (newtok[0], yr); -+ set_tok_reg (newtok[1], AXP_REG_R17); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+ } -+ -+ sym = symbol_find_or_make ((const char *) symname); -+ -+ set_tok_reg (newtok[0], AXP_REG_AT); -+ set_tok_sym (newtok[1], sym, 0); -+ assemble_tokens ("ldi", newtok, 2, 1); -+ -+ /* Call the division routine. */ -+ set_tok_reg (newtok[0], AXP_REG_AT); -+ set_tok_cpreg (newtok[1], AXP_REG_AT); -+ set_tok_const (newtok[2], 0); -+ assemble_tokens ("call", newtok, 3, 1); -+ -+ /* Move the result to the right place. */ -+ if (rr != AXP_REG_R0) -+ { -+ set_tok_reg (newtok[0], AXP_REG_R0); -+ set_tok_reg (newtok[1], rr); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+} -+ -+#else /* !OBJ_EVAX */ -+ -+static void -+emit_division (const expressionS *tok, -+ int ntok, -+ const void * symname) -+{ -+ /* DIVISION and MODULUS. Yech. -+ Convert -+ OP x,y,result -+ to -+ ldi pv,__OP -+ mov x,t10 -+ mov y,t11 -+ call t9,(pv),__OP -+ mov t12,result -+ -+ with appropriate optimizations if t10,t11,t12 are the registers -+ specified by the compiler. */ -+ -+ int xr, yr, rr; -+ symbolS *sym; -+ expressionS newtok[3]; -+ -+ xr = regno (tok[0].X_add_number); -+ yr = regno (tok[1].X_add_number); -+ -+ if (ntok < 3) -+ rr = xr; -+ else -+ rr = regno (tok[2].X_add_number); -+ -+ sym = symbol_find_or_make ((const char *) symname); -+ -+ /* Move the operands into the right place. */ -+ if (yr == AXP_REG_T10 && xr == AXP_REG_T11) -+ { -+ /* They are in exactly the wrong order -- swap through AT. */ -+ if (sw_64_noat_on) -+ as_bad (_("macro requires $at register while noat in effect")); -+ -+ set_tok_reg (newtok[0], AXP_REG_T10); -+ set_tok_reg (newtok[1], AXP_REG_AT); -+ assemble_tokens ("mov", newtok, 2, 1); -+ -+ set_tok_reg (newtok[0], AXP_REG_T11); -+ set_tok_reg (newtok[1], AXP_REG_T10); -+ assemble_tokens ("mov", newtok, 2, 1); -+ -+ set_tok_reg (newtok[0], AXP_REG_AT); -+ set_tok_reg (newtok[1], AXP_REG_T11); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+ else -+ { -+ if (yr == AXP_REG_T10) -+ { -+ set_tok_reg (newtok[0], AXP_REG_T10); -+ set_tok_reg (newtok[1], AXP_REG_T11); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+ -+ if (xr != AXP_REG_T10) -+ { -+ set_tok_reg (newtok[0], xr); -+ set_tok_reg (newtok[1], AXP_REG_T10); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+ -+ if (yr != AXP_REG_T10 && yr != AXP_REG_T11) -+ { -+ set_tok_reg (newtok[0], yr); -+ set_tok_reg (newtok[1], AXP_REG_T11); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+ } -+ -+ /* Call the division routine. */ -+ set_tok_reg (newtok[0], AXP_REG_T9); -+ set_tok_sym (newtok[1], sym, 0); -+ assemble_tokens ("call", newtok, 2, 1); -+ -+ /* Reload the GP register. */ -+#ifdef OBJ_AOUT -+FIXME -+#endif -+#if defined(OBJ_ECOFF) || defined(OBJ_ELF) -+ set_tok_reg (newtok[0], sw_64_gp_register); -+ set_tok_const (newtok[1], 0); -+ set_tok_preg (newtok[2], AXP_REG_T9); -+ assemble_tokens ("ldgp", newtok, 3, 1); -+#endif -+ -+ /* Move the result to the right place. */ -+ if (rr != AXP_REG_T12) -+ { -+ set_tok_reg (newtok[0], AXP_REG_T12); -+ set_tok_reg (newtok[1], rr); -+ assemble_tokens ("mov", newtok, 2, 1); -+ } -+} -+ -+#endif /* !OBJ_EVAX */ -+ -+/* The call and jmp macros differ from their instruction counterparts -+ in that they can load the target address and default most -+ everything. */ -+ -+static void -+emit_jsrjmp (const expressionS *tok, -+ int ntok, -+ const void * vopname) -+{ -+ const char *opname = (const char *) vopname; -+ struct sw_64_insn insn; -+ expressionS newtok[3]; -+ int r, tokidx = 0; -+ long lituse = 0; -+ -+ if (tokidx < ntok && tok[tokidx].X_op == O_register) -+ r = regno (tok[tokidx++].X_add_number); -+ else -+ r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA; -+ -+ set_tok_reg (newtok[0], r); -+ -+ if (tokidx < ntok && -+ (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister)) -+ r = regno (tok[tokidx++].X_add_number); -+#ifdef OBJ_EVAX -+ /* Keep register if call $n.. */ -+#else -+ else -+ { -+ int basereg = sw_64_gp_register; -+ lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], -+ &basereg, NULL, opname); -+ } -+#endif -+ -+ set_tok_cpreg (newtok[1], r); -+ -+#ifndef OBJ_EVAX -+ if (tokidx < ntok) -+ newtok[2] = tok[tokidx]; -+ else -+#endif -+ set_tok_const (newtok[2], 0); -+ -+ assemble_tokens_to_insn (opname, newtok, 3, &insn); -+ -+ if (lituse) -+ { -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_JSR; -+ insn.fixups[insn.nfixups].exp.X_op = O_absent; -+ insn.nfixups++; -+ insn.sequence = lituse; -+ } -+ -+#ifdef OBJ_EVAX -+ if (sw_64_flag_replace -+ && r == AXP_REG_RA -+ && tok[tokidx].X_add_symbol -+ && sw_64_linkage_symbol) -+ { -+ /* Create a BOH reloc for 'call $27,NAME'. */ -+ const char *symname = S_GET_NAME (tok[tokidx].X_add_symbol); -+ int symlen = strlen (symname); -+ char *ensymname; -+ -+ /* Build the entry name as 'NAME..en'. */ -+ ensymname = XNEWVEC (char, symlen + 5); -+ memcpy (ensymname, symname, symlen); -+ memcpy (ensymname + symlen, "..en", 5); -+ -+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS); -+ if (insn.nfixups > 0) -+ { -+ memmove (&insn.fixups[1], &insn.fixups[0], -+ sizeof(struct sw_64_fixup) * insn.nfixups); -+ } -+ -+ /* The fixup must be the same as the BFD_RELOC_SW_64_NOP -+ case in load_expression. See B.4.5.2 of the OpenVMS -+ Linker Utility Manual. */ -+ insn.fixups[0].reloc = BFD_RELOC_SW_64_BOH; -+ insn.fixups[0].exp.X_op = O_symbol; -+ insn.fixups[0].exp.X_add_symbol = symbol_find_or_make (ensymname); -+ insn.fixups[0].exp.X_add_number = 0; -+ insn.fixups[0].xtrasym = sw_64_linkage_symbol; -+ insn.fixups[0].procsym = sw_64_evax_proc->symbol; -+ insn.nfixups++; -+ sw_64_linkage_symbol = 0; -+ free (ensymname); -+ } -+#endif -+ -+ emit_insn (&insn); -+} -+ -+/* The ret and jcr instructions differ from their instruction -+ counterparts in that everything can be defaulted. */ -+ -+static void -+emit_retjcr (const expressionS *tok, -+ int ntok, -+ const void * vopname) -+{ -+ const char *opname = (const char *) vopname; -+ expressionS newtok[3]; -+ int r, tokidx = 0; -+ -+ if (tokidx < ntok && tok[tokidx].X_op == O_register) -+ r = regno (tok[tokidx++].X_add_number); -+ else -+ r = AXP_REG_ZERO; -+ -+ set_tok_reg (newtok[0], r); -+ -+ if (tokidx < ntok && -+ (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister)) -+ r = regno (tok[tokidx++].X_add_number); -+ else -+ r = AXP_REG_RA; -+ -+ set_tok_cpreg (newtok[1], r); -+ -+ if (tokidx < ntok) -+ newtok[2] = tok[tokidx]; -+ else -+ set_tok_const (newtok[2], strcmp (opname, "ret") == 0); -+ -+ assemble_tokens (opname, newtok, 3, 0); -+} -+ -+/* Implement the ldgp macro. */ -+ -+static void -+emit_ldgp (const expressionS *tok ATTRIBUTE_UNUSED, -+ int ntok ATTRIBUTE_UNUSED, -+ const void * unused ATTRIBUTE_UNUSED) -+{ -+#ifdef OBJ_AOUT -+FIXME -+#endif -+#if defined(OBJ_ECOFF) || defined(OBJ_ELF) -+ /* from "ldgp r1,n(r2)", generate "ldih r1,X(R2); ldi r1,Y(r1)" -+ with appropriate constants and relocations. */ -+ struct sw_64_insn insn; -+ expressionS newtok[3]; -+ expressionS addend; -+ -+#ifdef OBJ_ECOFF -+ if (regno (tok[2].X_add_number) == AXP_REG_PV) -+ ecoff_set_gp_prolog_size (0); -+#endif -+ -+ newtok[0] = tok[0]; -+ set_tok_const (newtok[1], 0); -+ newtok[2] = tok[2]; -+ -+ assemble_tokens_to_insn ("ldih", newtok, 3, &insn); -+ -+ addend = tok[1]; -+ -+#ifdef OBJ_ECOFF -+ if (addend.X_op != O_constant) -+ as_bad (_("can not resolve expression")); -+ addend.X_op = O_symbol; -+ addend.X_add_symbol = sw_64_gp_symbol; -+#endif -+ -+ insn.nfixups = 1; -+ insn.fixups[0].exp = addend; -+ insn.fixups[0].reloc = BFD_RELOC_SW_64_GPDISP_HI16; -+ insn.sequence = next_sequence_num; -+ -+ emit_insn (&insn); -+ -+ set_tok_preg (newtok[2], tok[0].X_add_number); -+ -+ assemble_tokens_to_insn ("ldi", newtok, 3, &insn); -+ -+#ifdef OBJ_ECOFF -+ addend.X_add_number += 4; -+#endif -+ -+ insn.nfixups = 1; -+ insn.fixups[0].exp = addend; -+ insn.fixups[0].reloc = BFD_RELOC_SW_64_GPDISP_LO16; -+ insn.sequence = next_sequence_num--; -+ -+ emit_insn (&insn); -+#endif /* OBJ_ECOFF || OBJ_ELF */ -+} -+ -+/* The macro table. */ -+ -+static const struct sw_64_macro sw_64_macros[] = -+{ -+ { "vlog", emit_vlogx, NULL, -+ { MACRO_FPR, MACRO_FPR, MACRO_FPR, MACRO_FPR, MACRO_EOA } }, -+/* Load/Store macros. */ -+ { "ldi", emit_ldi, NULL, -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldih", emit_ldih, NULL, -+ { MACRO_IR, MACRO_EXP, MACRO_EOA } }, -+ -+ { "ldw", emit_ir_load, "ldw", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldl", emit_ir_load, "ldl", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldl_u", emit_ir_load, "ldl_u", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldw_inc", emit_ir_load, "ldw_inc", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldl_inc", emit_ir_load, "ldl_inc", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldw_dec", emit_ir_load, "ldw_dec", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldl_dec", emit_ir_load, "ldl_dec", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldw_set", emit_ir_load, "ldw_set", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldl_set", emit_ir_load, "ldl_set", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "flds", emit_loadstore, "flds", -+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "fldd", emit_loadstore, "fldd", -+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ -+ { "ldb", emit_ldX, (void *) 0, -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "ldh", emit_ldX, (void *) 1, -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ -+ { "ldgp", emit_ldgp, NULL, -+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } }, -+ { "stw", emit_loadstore, "stw", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "stl", emit_loadstore, "stl", -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "fsts", emit_loadstore, "fsts", -+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "fstd", emit_loadstore, "fstd", -+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ { "stb", emit_stX, (void *) 0, -+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -+ -+/* Arithmetic macros. */ -+ { "sextb", emit_sextX, (void *) 0, -+ { MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EOA, -+ /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, -+ { "sexth", emit_sextX, (void *) 1, -+ { MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EOA, -+ /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, -+ -+ { "divw", emit_division, "__divw", -+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_IR, MACRO_EOA, -+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -+ { "divwu", emit_division, "__divwu", -+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_IR, MACRO_EOA, -+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -+ { "divl", emit_division, "__divl", -+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_IR, MACRO_EOA, -+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -+ { "divlu", emit_division, "__divlu", -+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_IR, MACRO_EOA, -+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -+ { "remw", emit_division, "__remw", -+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_IR, MACRO_EOA, -+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -+ { "remwu", emit_division, "__remwu", -+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_IR, MACRO_EOA, -+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -+ { "reml", emit_division, "__reml", -+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_IR, MACRO_EOA, -+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -+ { "remlu", emit_division, "__remlu", -+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_IR, MACRO_EOA, -+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, -+ -+ { "call", emit_jsrjmp, "call", -+ { MACRO_PIR, MACRO_EXP, MACRO_EOA, -+ MACRO_PIR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA, -+ MACRO_EXP, MACRO_EOA } }, -+ { "jmp", emit_jsrjmp, "jmp", -+ { MACRO_PIR, MACRO_EXP, MACRO_EOA, -+ MACRO_PIR, MACRO_EOA, -+ MACRO_IR, MACRO_EXP, MACRO_EOA, -+ MACRO_EXP, MACRO_EOA } }, -+ { "ret", emit_retjcr, "ret", -+ { MACRO_IR, MACRO_EXP, MACRO_EOA, -+ MACRO_IR, MACRO_EOA, -+ MACRO_PIR, MACRO_EXP, MACRO_EOA, -+ MACRO_PIR, MACRO_EOA, -+ MACRO_EXP, MACRO_EOA, -+ MACRO_EOA } }, -+}; -+ -+static const unsigned int sw_64_num_macros -+ = sizeof (sw_64_macros) / sizeof (*sw_64_macros); -+ -+/* Search forward through all variants of a macro looking for a syntax -+ match. */ -+ -+static const struct sw_64_macro * -+find_macro_match (const struct sw_64_macro *first_macro, -+ const expressionS *tok, -+ int *pntok) -+ -+{ -+ const struct sw_64_macro *macro = first_macro; -+ int ntok = *pntok; -+ -+ do -+ { -+ const enum sw_64_macro_arg *arg = macro->argsets; -+ int tokidx = 0; -+ -+ while (*arg) -+ { -+ switch (*arg) -+ { -+ case MACRO_EOA: -+ if (tokidx == ntok) -+ return macro; -+ else -+ tokidx = 0; -+ break; -+ -+ /* Index register. */ -+ case MACRO_IR: -+ if (tokidx >= ntok || tok[tokidx].X_op != O_register -+ || !is_ir_num (tok[tokidx].X_add_number)) -+ goto match_failed; -+ ++tokidx; -+ break; -+ -+ /* Parenthesized index register. */ -+ case MACRO_PIR: -+ if (tokidx >= ntok || tok[tokidx].X_op != O_pregister -+ || !is_ir_num (tok[tokidx].X_add_number)) -+ goto match_failed; -+ ++tokidx; -+ break; -+ -+ /* Optional parenthesized index register. */ -+ case MACRO_OPIR: -+ if (tokidx < ntok && tok[tokidx].X_op == O_pregister -+ && is_ir_num (tok[tokidx].X_add_number)) -+ ++tokidx; -+ break; -+ -+ /* Leading comma with a parenthesized index register. */ -+ case MACRO_CPIR: -+ if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister -+ || !is_ir_num (tok[tokidx].X_add_number)) -+ goto match_failed; -+ ++tokidx; -+ break; -+ -+ /* Floating point register. */ -+ case MACRO_FPR: -+ if (tokidx >= ntok || tok[tokidx].X_op != O_register -+ || !is_fpr_num (tok[tokidx].X_add_number)) -+ goto match_failed; -+ ++tokidx; -+ break; -+ -+ /* Normal expression. */ -+ case MACRO_EXP: -+ if (tokidx >= ntok) -+ goto match_failed; -+ switch (tok[tokidx].X_op) -+ { -+ case O_illegal: -+ case O_absent: -+ case O_register: -+ case O_pregister: -+ case O_cpregister: -+ case O_literal: -+ case O_lituse_base: -+ case O_lituse_bytoff: -+ case O_lituse_jsr: -+ case O_gpdisp: -+ case O_gprelhigh: -+ case O_gprellow: -+ case O_gprel: -+ case O_samegp: -+ goto match_failed; -+ -+ default: -+ break; -+ } -+ ++tokidx; -+ break; -+ -+ match_failed: -+ while (*arg != MACRO_EOA) -+ ++arg; -+ tokidx = 0; -+ break; -+ } -+ ++arg; -+ } -+ } -+ while (++macro - sw_64_macros < (int) sw_64_num_macros -+ && !strcmp (macro->name, first_macro->name)); -+ -+ return NULL; -+} -+ -+/* Given an opcode name and a pre-tokenized set of arguments, take the -+ opcode all the way through emission. */ -+ -+static void -+assemble_tokens (const char *opname, -+ const expressionS *tok, -+ int ntok, -+ int local_macros_on) -+{ -+ int found_something = 0; -+ const struct sw_64_opcode *opcode; -+ const struct sw_64_macro *macro; -+ int cpumatch = 1; -+ extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED; -+ -+#ifdef RELOC_OP_P -+ /* If a user-specified relocation is present, this is not a macro. */ -+ if (ntok && USER_RELOC_P (tok[ntok - 1].X_op)) -+ { -+ if (tok[ntok - 1].X_op == O_md3) -+ { -+ struct sw_64_insn insn; -+ expressionS newtok[3]; -+ newtok[0] = tok[0]; -+ set_tok_const (newtok[1], 0); -+ set_tok_preg (newtok[2], sw_64_gp_register); -+ assemble_tokens_to_insn ("ldih", newtok, 3, &insn); -+ insn.nfixups = 1; -+ insn.fixups[0].reloc = BFD_RELOC_SW_64_ELF_LITERAL_GOT; -+ emit_insn (&insn); -+ } -+ reloc = SW_64_RELOC_TABLE (tok[ntok - 1].X_op)->reloc; -+ ntok--; -+ } -+ else -+#endif -+ if (local_macros_on) -+ { -+ macro = ((const struct sw_64_macro *) -+ str_hash_find (sw_64_macro_hash, opname)); -+ if (macro) -+ { -+ found_something = 1; -+ macro = find_macro_match (macro, tok, &ntok); -+ if (macro) -+ { -+ (*macro->emit) (tok, ntok, macro->arg); -+ return; -+ } -+ } -+ } -+ -+ if (memcmp (opname, "vlog", 4)==0) -+ { -+ unsigned long value; -+ unsigned long length = strchr (opname,'g') - opname + 1; -+ value=strtol (opname + length, NULL, 16); -+ if (opname[length + 2] != '\0') -+ as_bad (_("%s, wrong truth number!!"), opname); -+ else if (value > 0xFF) -+ as_bad (_("%s, wrong truth number!!"), opname); -+ else if (value == 0 && (opname[length] != '0' || opname[length + 1] != '0')) -+ as_bad (_("%s, wrong truth number!!"), opname); -+ macro = ((const struct sw_64_macro *) -+ str_hash_find (sw_64_macro_hash, "vlog")); -+ if (macro) -+ { -+ found_something = 1; -+ macro = find_macro_match (macro, tok, &ntok); -+ if (macro) -+ { -+ -+ expressionS newtok[5]; -+ newtok[0] = tok[0]; -+ newtok[1] = tok[1]; -+ newtok[2] = tok[2]; -+ newtok[3] = tok[3]; -+ set_tok_const (newtok[4], value); -+ (*macro->emit) (newtok, ntok+1, macro->arg); -+ return; -+ } -+ } -+ } -+ -+ /* Search opcodes. */ -+ opcode = (const struct sw_64_opcode *) str_hash_find (sw_64_opcode_hash, opname); -+ if (opcode) -+ { -+ found_something = 1; -+ opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch); -+ if (opcode) -+ { -+ struct sw_64_insn insn; -+ assemble_insn (opcode, tok, ntok, &insn, reloc); -+ -+ /* Copy the sequence number for the reloc from the reloc token. */ -+ if (reloc != BFD_RELOC_UNUSED) -+ insn.sequence = tok[ntok].X_add_number; -+ -+ emit_insn (&insn); -+ return; -+ } -+ } -+ -+ if (found_something) -+ { -+ if (cpumatch) -+ as_bad (_("inappropriate arguments for opcode `%s'"), opname); -+ else -+ as_bad (_("opcode `%s' not supported for target %s"), opname, -+ sw_64_target_name); -+ } -+ else -+ as_bad (_("unknown opcode `%s'"), opname); -+} -+ -+#ifdef OBJ_EVAX -+ -+/* Add sym+addend to link pool. -+ Return offset from current procedure value (pv) to entry in link pool. -+ -+ Add new fixup only if offset isn't 16bit. */ -+ -+static symbolS * -+add_to_link_pool (symbolS *sym, offsetT addend) -+{ -+ symbolS *basesym; -+ segT current_section = now_seg; -+ int current_subsec = now_subseg; -+ char *p; -+ segment_info_type *seginfo = seg_info (sw_64_link_section); -+ fixS *fixp; -+ symbolS *linksym, *expsym; -+ expressionS e; -+ -+ basesym = sw_64_evax_proc->symbol; -+ -+ /* @@ This assumes all entries in a given section will be of the same -+ size... Probably correct, but unwise to rely on. */ -+ /* This must always be called with the same subsegment. */ -+ -+ if (seginfo->frchainP) -+ for (fixp = seginfo->frchainP->fix_root; -+ fixp != (fixS *) NULL; -+ fixp = fixp->fx_next) -+ { -+ if (fixp->fx_addsy == sym -+ && fixp->fx_offset == (valueT)addend -+ && fixp->tc_fix_data.info -+ && fixp->tc_fix_data.info->sym -+ && symbol_symbolS (fixp->tc_fix_data.info->sym) -+ && (symbol_get_value_expression (fixp->tc_fix_data.info->sym) -+ ->X_op_symbol == basesym)) -+ return fixp->tc_fix_data.info->sym; -+ } -+ -+ /* Not found, add a new entry. */ -+ subseg_set (sw_64_link_section, 0); -+ linksym = symbol_new (FAKE_LABEL_NAME, now_seg, frag_now, frag_now_fix ()); -+ p = frag_more (8); -+ memset (p, 0, 8); -+ -+ /* Create a symbol for 'basesym - linksym' (offset of the added entry). */ -+ e.X_op = O_subtract; -+ e.X_add_symbol = linksym; -+ e.X_op_symbol = basesym; -+ e.X_add_number = 0; -+ expsym = make_expr_symbol (&e); -+ -+ /* Create a fixup for the entry. */ -+ fixp = fix_new -+ (frag_now, p - frag_now->fr_literal, 8, sym, addend, 0, BFD_RELOC_64); -+ fixp->tc_fix_data.info = get_sw_64_reloc_tag (next_sequence_num--); -+ fixp->tc_fix_data.info->sym = expsym; -+ -+ subseg_set (current_section, current_subsec); -+ -+ /* Return the symbol. */ -+ return expsym; -+} -+#endif /* OBJ_EVAX */ -+ -+/* Assembler directives. */ -+ -+/* Handle the .text pseudo-op. This is like the usual one, but it -+ clears sw_64_insn_label and restores auto alignment. */ -+ -+static void -+s_sw_64_text (int i) -+{ -+#ifdef OBJ_ELF -+ obj_elf_text (i); -+#else -+ s_text (i); -+#endif -+#ifdef OBJ_EVAX -+ { -+ symbolS * symbolP; -+ -+ symbolP = symbol_find (".text"); -+ if (symbolP == NULL) -+ { -+ symbolP = symbol_make (".text"); -+ S_SET_SEGMENT (symbolP, text_section); -+ symbol_table_insert (symbolP); -+ } -+ } -+#endif -+ sw_64_insn_label = NULL; -+ sw_64_auto_align_on = 1; -+ sw_64_current_align = 0; -+} -+ -+/* Handle the .data pseudo-op. This is like the usual one, but it -+ clears sw_64_insn_label and restores auto alignment. */ -+ -+static void -+s_sw_64_data (int i) -+{ -+#ifdef OBJ_ELF -+ obj_elf_data (i); -+#else -+ s_data (i); -+#endif -+ sw_64_insn_label = NULL; -+ sw_64_auto_align_on = 1; -+ sw_64_current_align = 0; -+} -+ -+#if defined (OBJ_ECOFF) || defined (OBJ_EVAX) -+ -+/* Handle the OSF/1 and openVMS .comm pseudo quirks. */ -+ -+static void -+s_sw_64_comm (int ignore ATTRIBUTE_UNUSED) -+{ -+ char *name; -+ char c; -+ char *p; -+ offsetT size; -+ symbolS *symbolP; -+#ifdef OBJ_EVAX -+ offsetT temp; -+ int log_align = 0; -+#endif -+ -+ c = get_symbol_name (&name); -+ -+ /* Just after name is now '\0'. */ -+ p = input_line_pointer; -+ *p = c; -+ -+ SKIP_WHITESPACE_AFTER_NAME (); -+ -+ /* Sw_64 OSF/1 compiler doesn't provide the comma, gcc does. */ -+ if (*input_line_pointer == ',') -+ { -+ input_line_pointer++; -+ SKIP_WHITESPACE (); -+ } -+ if ((size = get_absolute_expression ()) < 0) -+ { -+ as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size); -+ ignore_rest_of_line (); -+ return; -+ } -+ -+ *p = 0; -+ symbolP = symbol_find_or_make (name); -+ *p = c; -+ -+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) -+ { -+ as_bad (_("Ignoring attempt to re-define symbol")); -+ ignore_rest_of_line (); -+ return; -+ } -+ -+#ifdef OBJ_EVAX -+ if (*input_line_pointer != ',') -+ temp = 8; /* Default alignment. */ -+ else -+ { -+ input_line_pointer++; -+ SKIP_WHITESPACE (); -+ temp = get_absolute_expression (); -+ } -+ -+ /* ??? Unlike on OSF/1, the alignment factor is not in log units. */ -+ while ((temp >>= 1) != 0) -+ ++log_align; -+ -+ if (*input_line_pointer == ',') -+ { -+ /* Extended form of the directive -+ -+ .comm symbol, size, alignment, section -+ -+ where the "common" semantics is transferred to the section. -+ The symbol is effectively an alias for the section name. */ -+ -+ segT sec; -+ const char *sec_name; -+ symbolS *sec_symbol; -+ segT current_seg = now_seg; -+ subsegT current_subseg = now_subseg; -+ int cur_size; -+ -+ input_line_pointer++; -+ SKIP_WHITESPACE (); -+ sec_name = s_sw_64_section_name (); -+ sec_symbol = symbol_find_or_make (sec_name); -+ sec = subseg_new (sec_name, 0); -+ S_SET_SEGMENT (sec_symbol, sec); -+ symbol_get_bfdsym (sec_symbol)->flags |= BSF_SECTION_SYM; -+ bfd_vms_set_section_flags (stdoutput, sec, 0, -+ EGPS__V_OVR | EGPS__V_GBL | EGPS__V_NOMOD); -+ record_alignment (sec, log_align); -+ -+ /* Reuse stab_string_size to store the size of the section. */ -+ cur_size = seg_info (sec)->stabu.stab_string_size; -+ if ((int) size > cur_size) -+ { -+ char *pfrag -+ = frag_var (rs_fill, 1, 1, (relax_substateT)0, NULL, -+ (valueT)size - (valueT)cur_size, NULL); -+ *pfrag = 0; -+ seg_info (sec)->stabu.stab_string_size = (int)size; -+ } -+ -+ S_SET_SEGMENT (symbolP, sec); -+ -+ subseg_set (current_seg, current_subseg); -+ } -+ else -+ { -+ /* Regular form of the directive -+ -+ .comm symbol, size, alignment -+ -+ where the "common" semantics in on the symbol. -+ These symbols are assembled in the .bss section. */ -+ -+ char *pfrag; -+ segT current_seg = now_seg; -+ subsegT current_subseg = now_subseg; -+ -+ subseg_set (bss_section, 1); -+ frag_align (log_align, 0, 0); -+ record_alignment (bss_section, log_align); -+ -+ symbol_set_frag (symbolP, frag_now); -+ pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP, -+ size, NULL); -+ *pfrag = 0; -+ -+ S_SET_SEGMENT (symbolP, bss_section); -+ -+ subseg_set (current_seg, current_subseg); -+ } -+#endif -+ -+ if (S_GET_VALUE (symbolP)) -+ { -+ if (S_GET_VALUE (symbolP) != (valueT) size) -+ as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."), -+ S_GET_NAME (symbolP), -+ (long) S_GET_VALUE (symbolP), -+ (long) size); -+ } -+ else -+ { -+#ifndef OBJ_EVAX -+ S_SET_VALUE (symbolP, (valueT) size); -+#endif -+ S_SET_EXTERNAL (symbolP); -+ } -+ -+#ifndef OBJ_EVAX -+ know (symbol_get_frag (symbolP) == &zero_address_frag); -+#endif -+ demand_empty_rest_of_line (); -+} -+ -+#endif /* ! OBJ_ELF */ -+ -+#ifdef OBJ_ECOFF -+ -+/* Handle the .rdata pseudo-op. This is like the usual one, but it -+ clears sw_64_insn_label and restores auto alignment. */ -+ -+static void -+s_sw_64_rdata (int ignore ATTRIBUTE_UNUSED) -+{ -+ get_absolute_expression (); -+ subseg_new (".rdata", 0); -+ demand_empty_rest_of_line (); -+ sw_64_insn_label = NULL; -+ sw_64_auto_align_on = 1; -+ sw_64_current_align = 0; -+} -+ -+#endif -+ -+#ifdef OBJ_ECOFF -+ -+/* Handle the .sdata pseudo-op. This is like the usual one, but it -+ clears sw_64_insn_label and restores auto alignment. */ -+ -+static void -+s_sw_64_sdata (int ignore ATTRIBUTE_UNUSED) -+{ -+ get_absolute_expression (); -+ subseg_new (".sdata", 0); -+ demand_empty_rest_of_line (); -+ sw_64_insn_label = NULL; -+ sw_64_auto_align_on = 1; -+ sw_64_current_align = 0; -+} -+#endif -+ -+#ifdef OBJ_ELF -+struct sw_64_elf_frame_data -+{ -+ symbolS *func_sym; -+ symbolS *func_end_sym; -+ symbolS *prologue_sym; -+ unsigned int mask; -+ unsigned int fmask; -+ int fp_regno; -+ int ra_regno; -+ offsetT frame_size; -+ offsetT mask_offset; -+ offsetT fmask_offset; -+ -+ struct sw_64_elf_frame_data *next; -+}; -+ -+static struct sw_64_elf_frame_data *all_frame_data; -+static struct sw_64_elf_frame_data **plast_frame_data = &all_frame_data; -+static struct sw_64_elf_frame_data *cur_frame_data; -+ -+extern int all_cfi_sections; -+ -+/* Handle the .section pseudo-op. This is like the usual one, but it -+ clears sw_64_insn_label and restores auto alignment. */ -+ -+static void -+s_sw_64_section (int ignore ATTRIBUTE_UNUSED) -+{ -+ obj_elf_section (ignore); -+ -+ sw_64_insn_label = NULL; -+ sw_64_auto_align_on = 1; -+ sw_64_current_align = 0; -+} -+ -+static void -+s_sw_64_ent (int dummy ATTRIBUTE_UNUSED) -+{ -+ if (ECOFF_DEBUGGING) -+ ecoff_directive_ent (0); -+ else -+ { -+ char *name, name_end; -+ -+ name_end = get_symbol_name (&name); -+ /* CFI_EMIT_eh_frame is the default. */ -+ all_cfi_sections = CFI_EMIT_eh_frame; -+ -+ if (! is_name_beginner (*name)) -+ { -+ as_warn (_(".ent directive has no name")); -+ (void) restore_line_pointer (name_end); -+ } -+ else -+ { -+ symbolS *sym; -+ -+ if (cur_frame_data) -+ as_warn (_("nested .ent directives")); -+ -+ sym = symbol_find_or_make (name); -+ symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION; -+ -+ cur_frame_data = XCNEW (struct sw_64_elf_frame_data); -+ cur_frame_data->func_sym = sym; -+ -+ /* Provide sensible defaults. */ -+ cur_frame_data->fp_regno = 30; /* sp */ -+ cur_frame_data->ra_regno = 26; /* ra */ -+ -+ *plast_frame_data = cur_frame_data; -+ plast_frame_data = &cur_frame_data->next; -+ -+ /* The .ent directive is sometimes followed by a number. Not sure -+ what it really means, but ignore it. */ -+ *input_line_pointer = name_end; -+ SKIP_WHITESPACE_AFTER_NAME (); -+ if (*input_line_pointer == ',') -+ { -+ input_line_pointer++; -+ SKIP_WHITESPACE (); -+ } -+ if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') -+ (void) get_absolute_expression (); -+ } -+ demand_empty_rest_of_line (); -+ } -+} -+ -+static void -+s_sw_64_end (int dummy ATTRIBUTE_UNUSED) -+{ -+ if (ECOFF_DEBUGGING) -+ ecoff_directive_end (0); -+ else -+ { -+ char *name, name_end; -+ -+ name_end = get_symbol_name (&name); -+ -+ if (! is_name_beginner (*name)) -+ { -+ as_warn (_(".end directive has no name")); -+ } -+ else -+ { -+ symbolS *sym; -+ -+ sym = symbol_find (name); -+ if (!cur_frame_data) -+ as_warn (_(".end directive without matching .ent")); -+ else if (sym != cur_frame_data->func_sym) -+ as_warn (_(".end directive names different symbol than .ent")); -+ -+ /* Create an expression to calculate the size of the function. */ -+ if (sym && cur_frame_data) -+ { -+ OBJ_SYMFIELD_TYPE *obj = symbol_get_obj (sym); -+ expressionS *exp = XNEW (expressionS); -+ -+ obj->size = exp; -+ exp->X_op = O_subtract; -+ exp->X_add_symbol = symbol_temp_new_now (); -+ exp->X_op_symbol = sym; -+ exp->X_add_number = 0; -+ -+ cur_frame_data->func_end_sym = exp->X_add_symbol; -+ } -+ -+ cur_frame_data = NULL; -+ } -+ -+ (void) restore_line_pointer (name_end); -+ demand_empty_rest_of_line (); -+ } -+} -+ -+static void -+s_sw_64_mask (int fp) -+{ -+ if (ECOFF_DEBUGGING) -+ { -+ if (fp) -+ ecoff_directive_fmask (0); -+ else -+ ecoff_directive_mask (0); -+ } -+ else -+ { -+ long val; -+ offsetT offset; -+ -+ if (!cur_frame_data) -+ { -+ if (fp) -+ as_warn (_(".fmask outside of .ent")); -+ else -+ as_warn (_(".mask outside of .ent")); -+ discard_rest_of_line (); -+ return; -+ } -+ -+ if (get_absolute_expression_and_terminator (&val) != ',') -+ { -+ if (fp) -+ as_warn (_("bad .fmask directive")); -+ else -+ as_warn (_("bad .mask directive")); -+ --input_line_pointer; -+ discard_rest_of_line (); -+ return; -+ } -+ -+ offset = get_absolute_expression (); -+ demand_empty_rest_of_line (); -+ -+ if (fp) -+ { -+ cur_frame_data->fmask = val; -+ cur_frame_data->fmask_offset = offset; -+ } -+ else -+ { -+ cur_frame_data->mask = val; -+ cur_frame_data->mask_offset = offset; -+ } -+ } -+} -+ -+static void -+s_sw_64_frame (int dummy ATTRIBUTE_UNUSED) -+{ -+ if (ECOFF_DEBUGGING) -+ ecoff_directive_frame (0); -+ else -+ { -+ long val; -+ -+ if (!cur_frame_data) -+ { -+ as_warn (_(".frame outside of .ent")); -+ discard_rest_of_line (); -+ return; -+ } -+ -+ cur_frame_data->fp_regno = tc_get_register (1); -+ -+ SKIP_WHITESPACE (); -+ if (*input_line_pointer++ != ',' -+ || get_absolute_expression_and_terminator (&val) != ',') -+ { -+ as_warn (_("bad .frame directive")); -+ --input_line_pointer; -+ discard_rest_of_line (); -+ return; -+ } -+ cur_frame_data->frame_size = val; -+ -+ cur_frame_data->ra_regno = tc_get_register (0); -+ -+ /* Next comes the "offset of saved $a0 from $sp". In gcc terms -+ this is current_function_pretend_args_size. There's no place -+ to put this value, so ignore it. */ -+ s_ignore (42); -+ } -+} -+ -+static void -+s_sw_64_prologue (int ignore ATTRIBUTE_UNUSED) -+{ -+ symbolS *sym; -+ int arg; -+ -+ arg = get_absolute_expression (); -+ demand_empty_rest_of_line (); -+ sw_64_prologue_label = symbol_new -+ (FAKE_LABEL_NAME, now_seg, frag_now, frag_now_fix ()); -+ -+ if (ECOFF_DEBUGGING) -+ sym = ecoff_get_cur_proc_sym (); -+ else -+ sym = cur_frame_data ? cur_frame_data->func_sym : NULL; -+ -+ if (sym == NULL) -+ { -+ as_bad (_(".prologue directive without a preceding .ent directive")); -+ return; -+ } -+ -+ switch (arg) -+ { -+ case 0: /* No PV required. */ -+ S_SET_OTHER (sym, STO_SW_64_NOPV -+ | (S_GET_OTHER (sym) & ~STO_SW_64_STD_GPLOAD)); -+ break; -+ case 1: /* Std GP load. */ -+ S_SET_OTHER (sym, STO_SW_64_STD_GPLOAD -+ | (S_GET_OTHER (sym) & ~STO_SW_64_STD_GPLOAD)); -+ break; -+ case 2: /* Non-std use of PV. */ -+ break; -+ -+ default: -+ as_bad (_("Invalid argument %d to .prologue."), arg); -+ break; -+ } -+ -+ if (cur_frame_data) -+ cur_frame_data->prologue_sym = symbol_temp_new_now (); -+} -+ -+static char *first_file_directive; -+ -+static void -+s_sw_64_file (int ignore ATTRIBUTE_UNUSED) -+{ -+ /* Save the first .file directive we see, so that we can change our -+ minds about whether ecoff debugging should or shouldn't be enabled. */ -+ if (sw_64_flag_mdebug < 0 && ! first_file_directive) -+ { -+ char *start = input_line_pointer; -+ size_t len; -+ -+ discard_rest_of_line (); -+ -+ len = input_line_pointer - start; -+ first_file_directive = xmemdup0 (start, len); -+ -+ input_line_pointer = start; -+ } -+ -+ if (ECOFF_DEBUGGING) -+ ecoff_directive_file (0); -+ else -+ dwarf2_directive_file (0); -+} -+ -+static void -+s_sw_64_loc (int ignore ATTRIBUTE_UNUSED) -+{ -+ if (ECOFF_DEBUGGING) -+ ecoff_directive_loc (0); -+ else -+ dwarf2_directive_loc (0); -+} -+ -+static void -+s_sw_64_stab (int n) -+{ -+ /* If we've been undecided about mdebug, make up our minds in favour. */ -+ if (sw_64_flag_mdebug < 0) -+ { -+ segT sec = subseg_new (".mdebug", 0); -+ bfd_set_section_flags (sec, SEC_HAS_CONTENTS | SEC_READONLY); -+ bfd_set_section_alignment (sec, 3); -+ ecoff_read_begin_hook (); -+ -+ if (first_file_directive) -+ { -+ char *save_ilp = input_line_pointer; -+ input_line_pointer = first_file_directive; -+ ecoff_directive_file (0); -+ input_line_pointer = save_ilp; -+ free (first_file_directive); -+ } -+ -+ sw_64_flag_mdebug = 1; -+ } -+ s_stab (n); -+} -+ -+static void -+s_sw_64_coff_wrapper (int which) -+{ -+ static void (* const fns[]) (int) = { -+ ecoff_directive_begin, -+ ecoff_directive_bend, -+ ecoff_directive_def, -+ ecoff_directive_dim, -+ ecoff_directive_endef, -+ ecoff_directive_scl, -+ ecoff_directive_tag, -+ ecoff_directive_val, -+ }; -+ -+ gas_assert (which >= 0 && which < (int) (sizeof (fns)/sizeof (*fns))); -+ -+ if (ECOFF_DEBUGGING) -+ (*fns[which]) (0); -+ else -+ { -+ as_bad (_("ECOFF debugging is disabled.")); -+ ignore_rest_of_line (); -+ } -+} -+ -+/* Called at the end of assembly. Here we emit unwind info for frames -+ unless the compiler has done it for us. */ -+ -+void -+sw_64_elf_md_end (void) -+{ -+ struct sw_64_elf_frame_data *p; -+ -+ if (cur_frame_data) -+ as_warn (_(".ent directive without matching .end")); -+ -+ /* If someone has generated the unwind info themselves, great. */ -+ if (bfd_get_section_by_name (stdoutput, ".eh_frame") != NULL) -+ return; -+ -+ /* ??? In theory we could look for functions for which we have -+ generated unwind info via CFI directives, and those we have not. -+ Those we have not could still get their unwind info from here. -+ For now, do nothing if we've seen any CFI directives. Note that -+ the above test will not trigger, as we've not emitted data yet. */ -+ if (all_fde_data != NULL) -+ return; -+ -+ /* Generate .eh_frame data for the unwind directives specified. */ -+ for (p = all_frame_data; p ; p = p->next) -+ if (p->prologue_sym) -+ { -+ /* Create a temporary symbol at the same location as our -+ function symbol. This prevents problems with globals. */ -+ cfi_new_fde (symbol_temp_new (S_GET_SEGMENT (p->func_sym), -+ symbol_get_frag (p->func_sym), -+ S_GET_VALUE (p->func_sym))); -+ -+ cfi_set_sections (); -+ cfi_set_return_column (p->ra_regno); -+ cfi_add_CFA_def_cfa_register (30); -+ if (p->fp_regno != 30 || p->mask || p->fmask || p->frame_size) -+ { -+ unsigned int mask; -+ offsetT offset; -+ -+ cfi_add_advance_loc (p->prologue_sym); -+ -+ if (p->fp_regno != 30) -+ if (p->frame_size != 0) -+ cfi_add_CFA_def_cfa (p->fp_regno, p->frame_size); -+ else -+ cfi_add_CFA_def_cfa_register (p->fp_regno); -+ else if (p->frame_size != 0) -+ cfi_add_CFA_def_cfa_offset (p->frame_size); -+ -+ mask = p->mask; -+ offset = p->mask_offset; -+ -+ /* Recall that $26 is special-cased and stored first. */ -+ if ((mask >> 26) & 1) -+ { -+ cfi_add_CFA_offset (26, offset); -+ offset += 8; -+ mask &= ~(1 << 26); -+ } -+ while (mask) -+ { -+ unsigned int i; -+ i = mask & -mask; -+ mask ^= i; -+ i = ffs (i) - 1; -+ -+ cfi_add_CFA_offset (i, offset); -+ offset += 8; -+ } -+ -+ mask = p->fmask; -+ offset = p->fmask_offset; -+ while (mask) -+ { -+ unsigned int i; -+ i = mask & -mask; -+ mask ^= i; -+ i = ffs (i) - 1; -+ -+ cfi_add_CFA_offset (i + 32, offset); -+ offset += 8; -+ } -+ } -+ -+ cfi_end_fde (p->func_end_sym); -+ } -+} -+ -+static void -+s_sw_64_usepv (int unused ATTRIBUTE_UNUSED) -+{ -+ char *name, name_end; -+ char *which, which_end; -+ symbolS *sym; -+ int other; -+ -+ name_end = get_symbol_name (&name); -+ -+ if (! is_name_beginner (*name)) -+ { -+ as_bad (_(".usepv directive has no name")); -+ (void) restore_line_pointer (name_end); -+ ignore_rest_of_line (); -+ return; -+ } -+ -+ sym = symbol_find_or_make (name); -+ name_end = restore_line_pointer (name_end); -+ if (! is_end_of_line[(unsigned char) name_end]) -+ input_line_pointer++; -+ -+ if (name_end != ',') -+ { -+ as_bad (_(".usepv directive has no type")); -+ ignore_rest_of_line (); -+ return; -+ } -+ -+ SKIP_WHITESPACE (); -+ -+ which_end = get_symbol_name (&which); -+ -+ if (strcmp (which, "no") == 0) -+ other = STO_SW_64_NOPV; -+ else if (strcmp (which, "std") == 0) -+ other = STO_SW_64_STD_GPLOAD; -+ else -+ { -+ as_bad (_("unknown argument for .usepv")); -+ other = 0; -+ } -+ -+ (void) restore_line_pointer (which_end); -+ demand_empty_rest_of_line (); -+ -+ S_SET_OTHER (sym, other | (S_GET_OTHER (sym) & ~STO_SW_64_STD_GPLOAD)); -+} -+#endif /* OBJ_ELF */ -+ -+/* Standard calling conventions leaves the CFA at $30 on entry. */ -+ -+void -+sw_64_cfi_frame_initial_instructions (void) -+{ -+ cfi_add_CFA_def_cfa_register (30); -+} -+ -+#ifdef OBJ_EVAX -+ -+/* Get name of section. */ -+static const char * -+s_sw_64_section_name (void) -+{ -+ char *name; -+ -+ SKIP_WHITESPACE (); -+ if (*input_line_pointer == '"') -+ { -+ int dummy; -+ -+ name = demand_copy_C_string (&dummy); -+ if (name == NULL) -+ { -+ ignore_rest_of_line (); -+ return NULL; -+ } -+ } -+ else -+ { -+ char *end = input_line_pointer; -+ -+ while (0 == strchr ("\n\t,; ", *end)) -+ end++; -+ if (end == input_line_pointer) -+ { -+ as_warn (_("missing name")); -+ ignore_rest_of_line (); -+ return NULL; -+ } -+ -+ name = xmemdup0 (input_line_pointer, end - input_line_pointer); -+ input_line_pointer = end; -+ } -+ SKIP_WHITESPACE (); -+ return name; -+} -+ -+/* Put clear/set flags in one flagword. The LSBs are flags to be set, -+ the MSBs are the flags to be cleared. */ -+ -+#define EGPS__V_NO_SHIFT 16 -+#define EGPS__V_MASK 0xffff -+ -+/* Parse one VMS section flag. */ -+ -+static flagword -+s_sw_64_section_word (char *str, size_t len) -+{ -+ int no = 0; -+ flagword flag = 0; -+ -+ if (len == 5 && strncmp (str, "NO", 2) == 0) -+ { -+ no = 1; -+ str += 2; -+ len -= 2; -+ } -+ -+ if (len == 3) -+ { -+ if (strncmp (str, "PIC", 3) == 0) -+ flag = EGPS__V_PIC; -+ else if (strncmp (str, "LIB", 3) == 0) -+ flag = EGPS__V_LIB; -+ else if (strncmp (str, "OVR", 3) == 0) -+ flag = EGPS__V_OVR; -+ else if (strncmp (str, "REL", 3) == 0) -+ flag = EGPS__V_REL; -+ else if (strncmp (str, "GBL", 3) == 0) -+ flag = EGPS__V_GBL; -+ else if (strncmp (str, "SHR", 3) == 0) -+ flag = EGPS__V_SHR; -+ else if (strncmp (str, "EXE", 3) == 0) -+ flag = EGPS__V_EXE; -+ else if (strncmp (str, "WRT", 3) == 0) -+ flag = EGPS__V_WRT; -+ else if (strncmp (str, "VEC", 3) == 0) -+ flag = EGPS__V_VEC; -+ else if (strncmp (str, "MOD", 3) == 0) -+ { -+ flag = no ? EGPS__V_NOMOD : EGPS__V_NOMOD << EGPS__V_NO_SHIFT; -+ no = 0; -+ } -+ else if (strncmp (str, "COM", 3) == 0) -+ flag = EGPS__V_COM; -+ } -+ -+ if (flag == 0) -+ { -+ char c = str[len]; -+ str[len] = 0; -+ as_warn (_("unknown section attribute %s"), str); -+ str[len] = c; -+ return 0; -+ } -+ -+ if (no) -+ return flag << EGPS__V_NO_SHIFT; -+ else -+ return flag; -+} -+ -+/* Handle the section specific pseudo-op. */ -+ -+#define EVAX_SECTION_COUNT 5 -+ -+static const char *section_name[EVAX_SECTION_COUNT + 1] = -+ { "NULL", ".rdata", ".comm", ".link", ".ctors", ".dtors" }; -+ -+static void -+s_sw_64_section (int secid) -+{ -+ const char *name; -+ char *beg; -+ segT sec; -+ flagword vms_flags = 0; -+ symbolS *symbol; -+ -+ if (secid == 0) -+ { -+ name = s_sw_64_section_name (); -+ if (name == NULL) -+ return; -+ sec = subseg_new (name, 0); -+ if (*input_line_pointer == ',') -+ { -+ /* Skip the comma. */ -+ ++input_line_pointer; -+ SKIP_WHITESPACE (); -+ -+ do -+ { -+ char c; -+ -+ SKIP_WHITESPACE (); -+ c = get_symbol_name (&beg); -+ *input_line_pointer = c; -+ -+ vms_flags |= s_sw_64_section_word (beg, input_line_pointer - beg); -+ -+ SKIP_WHITESPACE_AFTER_NAME (); -+ } -+ while (*input_line_pointer++ == ','); -+ -+ --input_line_pointer; -+ } -+ -+ symbol = symbol_find_or_make (name); -+ S_SET_SEGMENT (symbol, sec); -+ symbol_get_bfdsym (symbol)->flags |= BSF_SECTION_SYM; -+ bfd_vms_set_section_flags -+ (stdoutput, sec, -+ (vms_flags >> EGPS__V_NO_SHIFT) & EGPS__V_MASK, -+ vms_flags & EGPS__V_MASK); -+ } -+ else -+ { -+ get_absolute_expression (); -+ subseg_new (section_name[secid], 0); -+ } -+ -+ demand_empty_rest_of_line (); -+ sw_64_insn_label = NULL; -+ sw_64_auto_align_on = 1; -+ sw_64_current_align = 0; -+} -+ -+static void -+s_sw_64_literals (int ignore ATTRIBUTE_UNUSED) -+{ -+ subseg_new (".literals", 0); -+ demand_empty_rest_of_line (); -+ sw_64_insn_label = NULL; -+ sw_64_auto_align_on = 1; -+ sw_64_current_align = 0; -+} -+ -+/* Parse .ent directives. */ -+ -+static void -+s_sw_64_ent (int ignore ATTRIBUTE_UNUSED) -+{ -+ symbolS *symbol; -+ expressionS symexpr; -+ -+ if (sw_64_evax_proc != NULL) -+ as_bad (_("previous .ent not closed by a .end")); -+ -+ sw_64_evax_proc = &sw_64_evax_proc_data; -+ -+ sw_64_evax_proc->pdsckind = 0; -+ sw_64_evax_proc->framereg = -1; -+ sw_64_evax_proc->framesize = 0; -+ sw_64_evax_proc->rsa_offset = 0; -+ sw_64_evax_proc->ra_save = AXP_REG_RA; -+ sw_64_evax_proc->fp_save = -1; -+ sw_64_evax_proc->imask = 0; -+ sw_64_evax_proc->fmask = 0; -+ sw_64_evax_proc->prologue = 0; -+ sw_64_evax_proc->type = 0; -+ sw_64_evax_proc->handler = 0; -+ sw_64_evax_proc->handler_data = 0; -+ -+ expression (&symexpr); -+ -+ if (symexpr.X_op != O_symbol) -+ { -+ as_fatal (_(".ent directive has no symbol")); -+ demand_empty_rest_of_line (); -+ return; -+ } -+ -+ symbol = make_expr_symbol (&symexpr); -+ symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION; -+ sw_64_evax_proc->symbol = symbol; -+ -+ demand_empty_rest_of_line (); -+} -+ -+static void -+s_sw_64_handler (int is_data) -+{ -+ if (is_data) -+ sw_64_evax_proc->handler_data = get_absolute_expression (); -+ else -+ { -+ char *name, name_end; -+ -+ name_end = get_symbol_name (&name); -+ -+ if (! is_name_beginner (*name)) -+ { -+ as_warn (_(".handler directive has no name")); -+ } -+ else -+ { -+ symbolS *sym; -+ -+ sym = symbol_find_or_make (name); -+ symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION; -+ sw_64_evax_proc->handler = sym; -+ } -+ -+ (void) restore_line_pointer (name_end); -+ } -+ -+ demand_empty_rest_of_line (); -+} -+ -+/* Parse .frame ,,RA, directives. */ -+ -+static void -+s_sw_64_frame (int ignore ATTRIBUTE_UNUSED) -+{ -+ long val; -+ int ra; -+ -+ sw_64_evax_proc->framereg = tc_get_register (1); -+ -+ SKIP_WHITESPACE (); -+ if (*input_line_pointer++ != ',' -+ || get_absolute_expression_and_terminator (&val) != ',') -+ { -+ as_warn (_("Bad .frame directive 1./2. param")); -+ --input_line_pointer; -+ demand_empty_rest_of_line (); -+ return; -+ } -+ -+ sw_64_evax_proc->framesize = val; -+ -+ ra = tc_get_register (1); -+ if (ra != AXP_REG_RA) -+ as_warn (_("Bad RA (%d) register for .frame"), ra); -+ -+ SKIP_WHITESPACE (); -+ if (*input_line_pointer++ != ',') -+ { -+ as_warn (_("Bad .frame directive 3./4. param")); -+ --input_line_pointer; -+ demand_empty_rest_of_line (); -+ return; -+ } -+ sw_64_evax_proc->rsa_offset = get_absolute_expression (); -+} -+ -+/* Parse .prologue. */ -+ -+static void -+s_sw_64_prologue (int ignore ATTRIBUTE_UNUSED) -+{ -+ demand_empty_rest_of_line (); -+ sw_64_prologue_label = symbol_new -+ (FAKE_LABEL_NAME, now_seg, frag_now, frag_now_fix ()); -+} -+ -+/* Parse .pdesc ,{null|stack|reg} -+ Insert a procedure descriptor. */ -+ -+static void -+s_sw_64_pdesc (int ignore ATTRIBUTE_UNUSED) -+{ -+ char *name; -+ char name_end; -+ char *p; -+ expressionS exp; -+ symbolS *entry_sym; -+ const char *entry_sym_name; -+ const char *pdesc_sym_name; -+ fixS *fixp; -+ size_t len; -+ -+ if (now_seg != sw_64_link_section) -+ { -+ as_bad (_(".pdesc directive not in link (.link) section")); -+ return; -+ } -+ -+ expression (&exp); -+ if (exp.X_op != O_symbol) -+ { -+ as_bad (_(".pdesc directive has no entry symbol")); -+ return; -+ } -+ -+ entry_sym = make_expr_symbol (&exp); -+ entry_sym_name = S_GET_NAME (entry_sym); -+ -+ /* Strip "..en". */ -+ len = strlen (entry_sym_name); -+ if (len < 4 || strcmp (entry_sym_name + len - 4, "..en") != 0) -+ { -+ as_bad (_(".pdesc has a bad entry symbol")); -+ return; -+ } -+ len -= 4; -+ pdesc_sym_name = S_GET_NAME (sw_64_evax_proc->symbol); -+ -+ if (!sw_64_evax_proc -+ || !S_IS_DEFINED (sw_64_evax_proc->symbol) -+ || strlen (pdesc_sym_name) != len -+ || memcmp (entry_sym_name, pdesc_sym_name, len) != 0) -+ { -+ as_fatal (_(".pdesc doesn't match with last .ent")); -+ return; -+ } -+ -+ /* Define pdesc symbol. */ -+ symbol_set_value_now (sw_64_evax_proc->symbol); -+ -+ /* Save bfd symbol of proc entry in function symbol. */ -+ ((struct evax_private_udata_struct *) -+ symbol_get_bfdsym (sw_64_evax_proc->symbol)->udata.p)->enbsym -+ = symbol_get_bfdsym (entry_sym); -+ -+ SKIP_WHITESPACE (); -+ if (*input_line_pointer++ != ',') -+ { -+ as_warn (_("No comma after .pdesc ")); -+ demand_empty_rest_of_line (); -+ return; -+ } -+ -+ SKIP_WHITESPACE (); -+ name_end = get_symbol_name (&name); -+ -+ if (strncmp (name, "stack", 5) == 0) -+ sw_64_evax_proc->pdsckind = PDSC_S_K_KIND_FP_STACK; -+ -+ else if (strncmp (name, "reg", 3) == 0) -+ sw_64_evax_proc->pdsckind = PDSC_S_K_KIND_FP_REGISTER; -+ -+ else if (strncmp (name, "null", 4) == 0) -+ sw_64_evax_proc->pdsckind = PDSC_S_K_KIND_NULL; -+ -+ else -+ { -+ (void) restore_line_pointer (name_end); -+ as_fatal (_("unknown procedure kind")); -+ demand_empty_rest_of_line (); -+ return; -+ } -+ -+ (void) restore_line_pointer (name_end); -+ demand_empty_rest_of_line (); -+ -+#ifdef md_flush_pending_output -+ md_flush_pending_output (); -+#endif -+ -+ frag_align (3, 0, 0); -+ p = frag_more (16); -+ fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0); -+ fixp->fx_done = 1; -+ -+ *p = sw_64_evax_proc->pdsckind -+ | ((sw_64_evax_proc->framereg == 29) ? PDSC_S_M_BASE_REG_IS_FP : 0) -+ | ((sw_64_evax_proc->handler) ? PDSC_S_M_HANDLER_VALID : 0) -+ | ((sw_64_evax_proc->handler_data) ? PDSC_S_M_HANDLER_DATA_VALID : 0); -+ *(p + 1) = PDSC_S_M_NATIVE | PDSC_S_M_NO_JACKET; -+ -+ switch (sw_64_evax_proc->pdsckind) -+ { -+ case PDSC_S_K_KIND_NULL: -+ *(p + 2) = 0; -+ *(p + 3) = 0; -+ break; -+ case PDSC_S_K_KIND_FP_REGISTER: -+ *(p + 2) = sw_64_evax_proc->fp_save; -+ *(p + 3) = sw_64_evax_proc->ra_save; -+ break; -+ case PDSC_S_K_KIND_FP_STACK: -+ md_number_to_chars (p + 2, (valueT) sw_64_evax_proc->rsa_offset, 2); -+ break; -+ default: /* impossible */ -+ break; -+ } -+ -+ *(p + 4) = 0; -+ *(p + 5) = sw_64_evax_proc->type & 0x0f; -+ -+ /* Signature offset. */ -+ md_number_to_chars (p + 6, (valueT) 0, 2); -+ -+ fix_new_exp (frag_now, p - frag_now->fr_literal + 8, -+ 8, &exp, 0, BFD_RELOC_64); -+ -+ if (sw_64_evax_proc->pdsckind == PDSC_S_K_KIND_NULL) -+ return; -+ -+ /* pdesc+16: Size. */ -+ p = frag_more (6); -+ md_number_to_chars (p, (valueT) sw_64_evax_proc->framesize, 4); -+ md_number_to_chars (p + 4, (valueT) 0, 2); -+ -+ /* Entry length. */ -+ exp.X_op = O_subtract; -+ exp.X_add_symbol = sw_64_prologue_label; -+ exp.X_op_symbol = entry_sym; -+ emit_expr (&exp, 2); -+ -+ if (sw_64_evax_proc->pdsckind == PDSC_S_K_KIND_FP_REGISTER) -+ return; -+ -+ /* pdesc+24: register masks. */ -+ p = frag_more (8); -+ md_number_to_chars (p, sw_64_evax_proc->imask, 4); -+ md_number_to_chars (p + 4, sw_64_evax_proc->fmask, 4); -+ -+ if (sw_64_evax_proc->handler) -+ { -+ p = frag_more (8); -+ fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, -+ sw_64_evax_proc->handler, 0, 0, BFD_RELOC_64); -+ } -+ -+ if (sw_64_evax_proc->handler_data) -+ { -+ p = frag_more (8); -+ md_number_to_chars (p, sw_64_evax_proc->handler_data, 8); -+ } -+} -+ -+/* Support for crash debug on vms. */ -+ -+static void -+s_sw_64_name (int ignore ATTRIBUTE_UNUSED) -+{ -+ char *p; -+ expressionS exp; -+ -+ if (now_seg != sw_64_link_section) -+ { -+ as_bad (_(".name directive not in link (.link) section")); -+ demand_empty_rest_of_line (); -+ return; -+ } -+ -+ expression (&exp); -+ if (exp.X_op != O_symbol) -+ { -+ as_warn (_(".name directive has no symbol")); -+ demand_empty_rest_of_line (); -+ return; -+ } -+ -+ demand_empty_rest_of_line (); -+ -+#ifdef md_flush_pending_output -+ md_flush_pending_output (); -+#endif -+ -+ frag_align (3, 0, 0); -+ p = frag_more (8); -+ -+ fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0, BFD_RELOC_64); -+} -+ -+/* Parse .linkage . -+ Create a linkage pair relocation. */ -+ -+static void -+s_sw_64_linkage (int ignore ATTRIBUTE_UNUSED) -+{ -+ expressionS exp; -+ char *p; -+ fixS *fixp; -+ -+#ifdef md_flush_pending_output -+ md_flush_pending_output (); -+#endif -+ -+ expression (&exp); -+ if (exp.X_op != O_symbol) -+ { -+ as_fatal (_("No symbol after .linkage")); -+ } -+ else -+ { -+ struct sw_64_linkage_fixups *linkage_fixup; -+ -+ p = frag_more (LKP_S_K_SIZE); -+ memset (p, 0, LKP_S_K_SIZE); -+ fixp = fix_new_exp -+ (frag_now, p - frag_now->fr_literal, LKP_S_K_SIZE, &exp, 0, -+ BFD_RELOC_SW_64_LINKAGE); -+ -+ if (sw_64_insn_label == NULL) -+ sw_64_insn_label = symbol_new -+ (FAKE_LABEL_NAME, now_seg, frag_now, frag_now_fix ()); -+ -+ /* Create a linkage element. */ -+ linkage_fixup = XNEW (struct sw_64_linkage_fixups); -+ linkage_fixup->fixp = fixp; -+ linkage_fixup->next = NULL; -+ linkage_fixup->label = sw_64_insn_label; -+ -+ /* Append it to the list. */ -+ if (sw_64_linkage_fixup_root == NULL) -+ sw_64_linkage_fixup_root = linkage_fixup; -+ else -+ sw_64_linkage_fixup_tail->next = linkage_fixup; -+ sw_64_linkage_fixup_tail = linkage_fixup; -+ } -+ demand_empty_rest_of_line (); -+} -+ -+/* Parse .code_address . -+ Create a code address relocation. */ -+ -+static void -+s_sw_64_code_address (int ignore ATTRIBUTE_UNUSED) -+{ -+ expressionS exp; -+ char *p; -+ -+#ifdef md_flush_pending_output -+ md_flush_pending_output (); -+#endif -+ -+ expression (&exp); -+ if (exp.X_op != O_symbol) -+ as_fatal (_("No symbol after .code_address")); -+ else -+ { -+ p = frag_more (8); -+ memset (p, 0, 8); -+ fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0,\ -+ BFD_RELOC_SW_64_CODEADDR); -+ } -+ demand_empty_rest_of_line (); -+} -+ -+static void -+s_sw_64_fp_save (int ignore ATTRIBUTE_UNUSED) -+{ -+ sw_64_evax_proc->fp_save = tc_get_register (1); -+ -+ demand_empty_rest_of_line (); -+} -+ -+static void -+s_sw_64_mask (int ignore ATTRIBUTE_UNUSED) -+{ -+ long val; -+ -+ if (get_absolute_expression_and_terminator (&val) != ',') -+ { -+ as_warn (_("Bad .mask directive")); -+ --input_line_pointer; -+ } -+ else -+ { -+ sw_64_evax_proc->imask = val; -+ (void) get_absolute_expression (); -+ } -+ demand_empty_rest_of_line (); -+} -+ -+static void -+s_sw_64_fmask (int ignore ATTRIBUTE_UNUSED) -+{ -+ long val; -+ -+ if (get_absolute_expression_and_terminator (&val) != ',') -+ { -+ as_warn (_("Bad .fmask directive")); -+ --input_line_pointer; -+ } -+ else -+ { -+ sw_64_evax_proc->fmask = val; -+ (void) get_absolute_expression (); -+ } -+ demand_empty_rest_of_line (); -+} -+ -+static void -+s_sw_64_end (int ignore ATTRIBUTE_UNUSED) -+{ -+ char *name; -+ char c; -+ -+ c = get_symbol_name (&name); -+ (void) restore_line_pointer (c); -+ demand_empty_rest_of_line (); -+ sw_64_evax_proc = NULL; -+} -+ -+static void -+s_sw_64_file (int ignore ATTRIBUTE_UNUSED) -+{ -+ symbolS *s; -+ int length; -+ static char case_hack[32]; -+ -+ sprintf (case_hack, "", -+ sw_64_flag_hash_long_names, sw_64_flag_show_after_trunc); -+ -+ s = symbol_find_or_make (case_hack); -+ symbol_get_bfdsym (s)->flags |= BSF_FILE; -+ -+ get_absolute_expression (); -+ s = symbol_find_or_make (demand_copy_string (&length)); -+ symbol_get_bfdsym (s)->flags |= BSF_FILE; -+ demand_empty_rest_of_line (); -+} -+#endif /* OBJ_EVAX */ -+ -+/* Handle the .gprel32 pseudo op. */ -+ -+static void -+s_sw_64_gprel32 (int ignore ATTRIBUTE_UNUSED) -+{ -+ expressionS e; -+ char *p; -+ -+ SKIP_WHITESPACE (); -+ expression (&e); -+ -+#ifdef OBJ_ELF -+ switch (e.X_op) -+ { -+ case O_constant: -+ e.X_add_symbol = section_symbol (absolute_section); -+ e.X_op = O_symbol; -+ /* FALLTHRU */ -+ case O_symbol: -+ break; -+ default: -+ abort (); -+ } -+#else -+#ifdef OBJ_ECOFF -+ 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 = sw_64_gp_symbol; -+ break; -+ default: -+ abort (); -+ } -+#endif -+#endif -+ -+ if (sw_64_auto_align_on && sw_64_current_align < 2) -+ sw_64_align (2, (char *) NULL, sw_64_insn_label, 0); -+ if (sw_64_current_align > 2) -+ sw_64_current_align = 2; -+ sw_64_insn_label = NULL; -+ -+ p = frag_more (4); -+ memset (p, 0, 4); -+ fix_new_exp (frag_now, p - frag_now->fr_literal, 4, -+ &e, 0, BFD_RELOC_GPREL32); -+} -+ -+/* Handle floating point allocation pseudo-ops. This is like the -+ generic version, but it makes sure the current label, if any, is -+ correctly aligned. */ -+ -+static void -+s_sw_64_float_cons (int type) -+{ -+ 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; -+ } -+ -+ if (sw_64_auto_align_on && sw_64_current_align < log_size) -+ sw_64_align (log_size, (char *) NULL, sw_64_insn_label, 0); -+ if (sw_64_current_align > log_size) -+ sw_64_current_align = log_size; -+ sw_64_insn_label = NULL; -+ -+ float_cons (type); -+} -+ -+/* Handle the .proc pseudo op. We don't really do much with it except -+ parse it. */ -+ -+static void -+s_sw_64_proc (int is_static ATTRIBUTE_UNUSED) -+{ -+ char *name; -+ char c; -+ char *p; -+ symbolS *symbolP; -+ int temp; -+ -+ /* Takes ".proc name,nargs". */ -+ SKIP_WHITESPACE (); -+ c = get_symbol_name (&name); -+ p = input_line_pointer; -+ symbolP = symbol_find_or_make (name); -+ *p = c; -+ SKIP_WHITESPACE_AFTER_NAME (); -+ 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 (); -+ } -+ /* *symbol_get_obj (symbolP) = (signed char) temp; */ -+ (void) symbolP; -+ as_warn (_("unhandled: .proc %s,%d"), name, temp); -+ demand_empty_rest_of_line (); -+} -+ -+/* Handle the .set pseudo op. This is used to turn on and off most of -+ the assembler features. */ -+ -+static void -+s_sw_64_set (int x ATTRIBUTE_UNUSED) -+{ -+ char *name, ch, *s; -+ int yesno = 1; -+ -+ SKIP_WHITESPACE (); -+ -+ ch = get_symbol_name (&name); -+ s = name; -+ if (s[0] == 'n' && s[1] == 'o') -+ { -+ yesno = 0; -+ s += 2; -+ } -+ if (!strcmp ("reorder", s)) -+ /* ignore */ ; -+ else if (!strcmp ("at", s)) -+ sw_64_noat_on = !yesno; -+ else if (!strcmp ("macro", s)) -+ sw_64_macros_on = yesno; -+ else if (!strcmp ("move", s)) -+ /* ignore */ ; -+ else if (!strcmp ("volatile", s)) -+ /* ignore */ ; -+ else -+ as_warn (_("Tried to .set unrecognized mode `%s'"), name); -+ -+ (void) restore_line_pointer (ch); -+ demand_empty_rest_of_line (); -+} -+ -+/* Handle the .base pseudo op. This changes the assembler's notion of -+ the $gp register. */ -+ -+static void -+s_sw_64_base (int ignore ATTRIBUTE_UNUSED) -+{ -+ SKIP_WHITESPACE (); -+ -+ if (*input_line_pointer == '$') -+ { -+ /* $rNN form. */ -+ input_line_pointer++; -+ if (*input_line_pointer == 'r') -+ input_line_pointer++; -+ } -+ -+ sw_64_gp_register = get_absolute_expression (); -+ if (sw_64_gp_register < 0 || sw_64_gp_register > 31) -+ { -+ sw_64_gp_register = AXP_REG_GP; -+ as_warn (_("Bad base register, using $%d."), sw_64_gp_register); -+ } -+ -+ demand_empty_rest_of_line (); -+} -+ -+/* 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_sw_64_align (int ignore ATTRIBUTE_UNUSED) -+{ -+ int align; -+ char fill, *pfill; -+ long max_alignment = 16; -+ -+ align = get_absolute_expression (); -+ if (align > max_alignment) -+ { -+ align = max_alignment; -+ as_bad (_("Alignment too large: %d. assumed"), align); -+ } -+ else if (align < 0) -+ { -+ as_warn (_("Alignment negative: 0 assumed")); -+ align = 0; -+ } -+ -+ if (*input_line_pointer == ',') -+ { -+ input_line_pointer++; -+ fill = get_absolute_expression (); -+ pfill = &fill; -+ } -+ else -+ pfill = NULL; -+ -+ if (align != 0) -+ { -+ sw_64_auto_align_on = 1; -+ sw_64_align (align, pfill, NULL, 1); -+ } -+ else -+ { -+ sw_64_auto_align_on = 0; -+ } -+ sw_64_insn_label = NULL; -+ -+ demand_empty_rest_of_line (); -+} -+ -+/* Hook the normal string processor to reset known alignment. */ -+ -+static void -+s_sw_64_stringer (int terminate) -+{ -+ sw_64_current_align = 0; -+ sw_64_insn_label = NULL; -+ stringer (8 + terminate); -+} -+ -+/* Hook the normal space processing to reset known alignment. */ -+ -+static void -+s_sw_64_space (int ignore) -+{ -+ sw_64_current_align = 0; -+ sw_64_insn_label = NULL; -+ s_space (ignore); -+} -+ -+/* Hook into cons for auto-alignment. */ -+ -+void -+sw_64_cons_align (int size) -+{ -+ int log_size; -+ -+ log_size = 0; -+ while ((size >>= 1) != 0) -+ ++log_size; -+ -+ if (sw_64_auto_align_on && sw_64_current_align < log_size) -+ sw_64_align (log_size, (char *) NULL, sw_64_insn_label, 0); -+ if (sw_64_current_align > log_size) -+ sw_64_current_align = log_size; -+ sw_64_insn_label = NULL; -+} -+ -+/* Here come the .uword, .ulong, and .uquad explicitly unaligned -+ pseudos. We just turn off auto-alignment and call down to cons. */ -+ -+static void -+s_sw_64_ucons (int bytes) -+{ -+ int hold = sw_64_auto_align_on; -+ sw_64_auto_align_on = 0; -+ cons (bytes); -+ sw_64_auto_align_on = hold; -+} -+ -+/* Switch the working cpu type. */ -+ -+static void -+s_sw_64_arch (int ignored ATTRIBUTE_UNUSED) -+{ -+ char *name, ch; -+ const struct cpu_type *p; -+ -+ SKIP_WHITESPACE (); -+ -+ ch = get_symbol_name (&name); -+ -+ for (p = cpu_types; p->name; ++p) -+ if (strcmp (name, p->name) == 0) -+ { -+ sw_64_target_name = p->name, sw_64_target = p->flags; -+ goto found; -+ } -+ as_warn (_("Unknown CPU identifier `%s'"), name); -+ -+found: -+ (void) restore_line_pointer (ch); -+ demand_empty_rest_of_line (); -+} -+ -+#ifdef DEBUG1 -+/* print token expression with sw_64 specific extension. */ -+ -+static void -+sw_64_print_token (FILE *f, const expressionS *exp) -+{ -+ switch (exp->X_op) -+ { -+ case O_cpregister: -+ putc (',', f); -+ /* FALLTHRU */ -+ case O_pregister: -+ putc ('(', f); -+ { -+ expressionS nexp = *exp; -+ nexp.X_op = O_register; -+ print_expr_1 (f, &nexp); -+ } -+ putc (')', f); -+ break; -+ default: -+ print_expr_1 (f, exp); -+ break; -+ } -+} -+#endif -+ -+/* The target specific pseudo-ops which we support. */ -+ -+const pseudo_typeS md_pseudo_table[] = -+{ -+#ifdef OBJ_ECOFF -+ {"comm", s_sw_64_comm, 0}, /* OSF1 compiler does this. */ -+ {"rdata", s_sw_64_rdata, 0}, -+#endif -+ {"text", s_sw_64_text, 0}, -+ {"data", s_sw_64_data, 0}, -+#ifdef OBJ_ECOFF -+ {"sdata", s_sw_64_sdata, 0}, -+#endif -+#ifdef OBJ_ELF -+ {"section", s_sw_64_section, 0}, -+ {"section.s", s_sw_64_section, 0}, -+ {"sect", s_sw_64_section, 0}, -+ {"sect.s", s_sw_64_section, 0}, -+#endif -+#ifdef OBJ_EVAX -+ {"section", s_sw_64_section, 0}, -+ {"literals", s_sw_64_literals, 0}, -+ {"pdesc", s_sw_64_pdesc, 0}, -+ {"name", s_sw_64_name, 0}, -+ {"linkage", s_sw_64_linkage, 0}, -+ {"code_address", s_sw_64_code_address, 0}, -+ {"ent", s_sw_64_ent, 0}, -+ {"frame", s_sw_64_frame, 0}, -+ {"fp_save", s_sw_64_fp_save, 0}, -+ {"mask", s_sw_64_mask, 0}, -+ {"fmask", s_sw_64_fmask, 0}, -+ {"end", s_sw_64_end, 0}, -+ {"file", s_sw_64_file, 0}, -+ {"rdata", s_sw_64_section, 1}, -+ {"comm", s_sw_64_comm, 0}, -+ {"link", s_sw_64_section, 3}, -+ {"ctors", s_sw_64_section, 4}, -+ {"dtors", s_sw_64_section, 5}, -+ {"handler", s_sw_64_handler, 0}, -+ {"handler_data", s_sw_64_handler, 1}, -+#endif -+#ifdef OBJ_ELF -+ /* Frame related pseudos. */ -+ {"ent", s_sw_64_ent, 0}, -+ {"end", s_sw_64_end, 0}, -+ {"mask", s_sw_64_mask, 0}, -+ {"fmask", s_sw_64_mask, 1}, -+ {"frame", s_sw_64_frame, 0}, -+ {"prologue", s_sw_64_prologue, 0}, -+ {"file", s_sw_64_file, 5}, -+ {"loc", s_sw_64_loc, 9}, -+ {"stabs", s_sw_64_stab, 's'}, -+ {"stabn", s_sw_64_stab, 'n'}, -+ {"usepv", s_sw_64_usepv, 0}, -+ /* COFF debugging related pseudos. */ -+ {"begin", s_sw_64_coff_wrapper, 0}, -+ {"bend", s_sw_64_coff_wrapper, 1}, -+ {"def", s_sw_64_coff_wrapper, 2}, -+ {"dim", s_sw_64_coff_wrapper, 3}, -+ {"endef", s_sw_64_coff_wrapper, 4}, -+ {"scl", s_sw_64_coff_wrapper, 5}, -+ {"tag", s_sw_64_coff_wrapper, 6}, -+ {"val", s_sw_64_coff_wrapper, 7}, -+#else -+#ifdef OBJ_EVAX -+ {"prologue", s_sw_64_prologue, 0}, -+#else -+ {"prologue", s_ignore, 0}, -+#endif -+#endif -+ {"gprel32", s_sw_64_gprel32, 0}, -+ {"t_floating", s_sw_64_float_cons, 'd'}, -+ {"s_floating", s_sw_64_float_cons, 'f'}, -+ {"f_floating", s_sw_64_float_cons, 'F'}, -+ {"g_floating", s_sw_64_float_cons, 'G'}, -+ {"d_floating", s_sw_64_float_cons, 'D'}, -+ -+ {"proc", s_sw_64_proc, 0}, -+ {"aproc", s_sw_64_proc, 1}, -+ {"set", s_sw_64_set, 0}, -+ {"reguse", s_ignore, 0}, -+ {"livereg", s_ignore, 0}, -+ {"base", s_sw_64_base, 0}, /*??*/ -+ {"option", s_ignore, 0}, -+ {"aent", s_ignore, 0}, -+ {"ugen", s_ignore, 0}, -+ {"eflag", s_ignore, 0}, -+ -+ {"align", s_sw_64_align, 0}, -+ {"double", s_sw_64_float_cons, 'd'}, -+ {"float", s_sw_64_float_cons, 'f'}, -+ {"single", s_sw_64_float_cons, 'f'}, -+ {"ascii", s_sw_64_stringer, 0}, -+ {"asciz", s_sw_64_stringer, 1}, -+ {"string", s_sw_64_stringer, 1}, -+ {"space", s_sw_64_space, 0}, -+ {"skip", s_sw_64_space, 0}, -+ {"zero", s_sw_64_space, 0}, -+ -+/* Unaligned data pseudos. */ -+ {"uword", s_sw_64_ucons, 2}, -+ {"ulong", s_sw_64_ucons, 4}, -+ {"uquad", s_sw_64_ucons, 8}, -+ -+#ifdef OBJ_ELF -+/* Dwarf wants these versions of unaligned. */ -+ {"2byte", s_sw_64_ucons, 2}, -+ {"4byte", s_sw_64_ucons, 4}, -+ {"8byte", s_sw_64_ucons, 8}, -+#endif -+ -+/* We don't do any optimizing, so we can safely ignore these. */ -+ {"noalias", s_ignore, 0}, -+ {"alias", s_ignore, 0}, -+ -+ {"arch", s_sw_64_arch, 0}, -+ -+ {NULL, 0, 0}, -+}; -+ -+#ifdef OBJ_ECOFF -+ -+/* @@@ GP selection voodoo. All of this seems overly complicated and -+ unnecessary; which is the primary reason it's for ECOFF only. */ -+ -+static inline void -+maybe_set_gp (asection *sec) -+{ -+ bfd_vma vma; -+ -+ if (!sec) -+ return; -+ vma = bfd_section_vma (sec); -+ if (vma && vma < sw_64_gp_value) -+ sw_64_gp_value = vma; -+} -+ -+static void -+select_gp_value (void) -+{ -+ gas_assert (sw_64_gp_value == 0); -+ -+ /* Get minus-one in whatever width... */ -+ sw_64_gp_value = 0; -+ sw_64_gp_value--; -+ -+ /* Select the smallest VMA of these existing sections. */ -+ maybe_set_gp (sw_64_lita_section); -+ -+/* @@ Will a simple 0x8000 work here? If not, why not? */ -+#define GP_ADJUSTMENT (0x8000 - 0x10) -+ -+ sw_64_gp_value += GP_ADJUSTMENT; -+ -+ S_SET_VALUE (sw_64_gp_symbol, sw_64_gp_value); -+ -+#ifdef DEBUG1 -+ printf (_("Chose GP value of %lx\n"), sw_64_gp_value); -+#endif -+} -+#endif /* OBJ_ECOFF */ -+ -+#ifdef OBJ_ELF -+/* Map 's' to SHF_SW_64_GPREL. */ -+ -+bfd_vma -+sw_64_elf_section_letter (int letter, const char **ptr_msg) -+{ -+ if (letter == 's') -+ return SHF_SW_64_GPREL; -+ -+ *ptr_msg = _("bad .section directive: want a,s,w,x,M,S,G,T in string"); -+ return -1; -+} -+ -+/* Map SHF_SW_64_GPREL to SEC_SMALL_DATA. */ -+ -+flagword -+sw_64_elf_section_flags (flagword flags, bfd_vma attr, int type ATTRIBUTE_UNUSED) -+{ -+ if (attr & SHF_SW_64_GPREL) -+ flags |= SEC_SMALL_DATA; -+ return flags; -+} -+#endif /* OBJ_ELF */ -+ -+/* This is called from HANDLE_ALIGN in write.c. Fill in the contents -+ of an rs_align_code fragment. */ -+ -+void -+sw_64_handle_align (fragS *fragp) -+{ -+ static unsigned char const unop[4] = { 0x00, 0x00, 0xfe, 0xff }; -+ static unsigned char const nopunop[8] = -+ { -+ 0x00, 0x00, 0xfe, 0xff, -+ 0x00, 0x00, 0xfe, 0xff -+ }; -+ -+ int bytes, fix; -+ char *p; -+ -+ if (fragp->fr_type != rs_align_code) -+ return; -+ -+ bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; -+ p = fragp->fr_literal + fragp->fr_fix; -+ fix = 0; -+ -+ if (bytes & 3) -+ { -+ fix = bytes & 3; -+ memset (p, 0, fix); -+ p += fix; -+ bytes -= fix; -+ } -+ -+ if (bytes & 4) -+ { -+ memcpy (p, unop, 4); -+ p += 4; -+ bytes -= 4; -+ fix += 4; -+ } -+ -+ memcpy (p, nopunop, 8); -+ -+ fragp->fr_fix += fix; -+ fragp->fr_var = 8; -+} -+ -+/* Public interface functions. */ -+ -+/* This function is called once, at assembler startup time. It sets -+ 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 (void) -+{ -+ unsigned int i; -+ -+ /* Verify that X_op field is wide enough. */ -+ { -+ expressionS e; -+ -+ e.X_op = O_max; -+ gas_assert (e.X_op == O_max); -+ } -+ -+ if (! bfd_set_arch_mach (stdoutput, bfd_arch_sw_64, file_sw_64_arch)) -+ as_warn (_("could not set architecture and machine")); -+ -+ /* Create the opcode hash table. */ -+ sw_64_opcode_hash = str_htab_create (); -+ -+ for (i = 0; i < sw_64_num_opcodes;) -+ { -+ const char *name, *slash; -+ -+ name = sw_64_opcodes[i].name; -+ if(str_hash_insert (sw_64_opcode_hash, name, &sw_64_opcodes[i], 0)) -+ as_fatal (_("internal error: can't hash opcode `%s': %s"),name); -+ -+ /* Some opcodes include modifiers of various sorts with a "/mod" -+ syntax, like the architecture manual suggests. However, for -+ use with gcc at least, we also need access to those same opcodes -+ without the "/". */ -+ -+ if ((slash = strchr (name, '/')) != NULL) -+ { -+ char *p = XNEWVEC (char, strlen (name)); -+ -+ memcpy (p, name, slash - name); -+ strcpy (p + (slash - name), slash + 1); -+ -+ (void) str_hash_insert (sw_64_opcode_hash, p, &sw_64_opcodes[i], 0); -+ /* Ignore failures -- the opcode table does duplicate some -+ variants in different forms, like "hw_stq" and "hw_st/q". */ -+ } -+ -+ while (++i < sw_64_num_opcodes -+ && (sw_64_opcodes[i].name == name -+ || !strcmp (sw_64_opcodes[i].name, name))) -+ continue; -+ } -+ -+ /* Create the macro hash table. */ -+ sw_64_macro_hash = str_htab_create (); -+ -+ for (i = 0; i < sw_64_num_macros;) -+ { -+ const char *name, *retval; -+ -+ name = sw_64_macros[i].name; -+ if(str_hash_insert (sw_64_macro_hash, name, &sw_64_macros[i], 0)) -+ as_fatal (_("internal error: can't hash macro `%s': %s"), -+ name); -+ -+ while (++i < sw_64_num_macros -+ && (sw_64_macros[i].name == name -+ || !strcmp (sw_64_macros[i].name, name))) -+ continue; -+ } -+ -+ /* Construct symbols for each of the registers. */ -+ for (i = 0; i < 32; ++i) -+ { -+ char name[4]; -+ -+ sprintf (name, "$%d", i); -+ sw_64_register_table[i] = symbol_create (name, reg_section, -+ &zero_address_frag, i); -+ } -+ -+ for (; i < 64; ++i) -+ { -+ char name[5]; -+ -+ sprintf (name, "$f%d", i - 32); -+ sw_64_register_table[i] = symbol_create (name, reg_section, -+ &zero_address_frag, i); -+ } -+ -+ /* Create the special symbols and sections we'll be using. */ -+ -+ /* So .sbss will get used for tiny objects. */ -+ bfd_set_gp_size (stdoutput, g_switch_value); -+ -+#ifdef OBJ_ECOFF -+ create_literal_section (".lita", &sw_64_lita_section, &sw_64_lita_symbol); -+ -+ /* For handling the GP, create a symbol that won't be output in the -+ symbol table. We'll edit it out of relocs later. */ -+ sw_64_gp_symbol = symbol_create ("", sw_64_lita_section, -+ &zero_address_frag, 0x8000); -+#endif -+ -+#ifdef OBJ_EVAX -+ create_literal_section (".link", &sw_64_link_section, &sw_64_link_symbol); -+#endif -+ -+#ifdef OBJ_ELF -+ if (ECOFF_DEBUGGING) -+ { -+ segT sec = subseg_new (".mdebug", (subsegT) 0); -+ bfd_set_section_flags (sec, SEC_HAS_CONTENTS | SEC_READONLY); -+ bfd_set_section_alignment (sec, 3); -+ } -+#endif -+ -+ /* Create literal lookup hash table. */ -+ sw_64_literal_hash = str_htab_create (); -+ -+ subseg_set (text_section, 0); -+} -+ -+/* The public interface to the instruction assembler. */ -+ -+void -+md_assemble (char *str) -+{ -+ /* Current maximum is 13. */ -+ char opname[32]; -+ expressionS tok[MAX_INSN_ARGS]; -+ int ntok, trunclen; -+ size_t opnamelen; -+ -+ /* Split off the opcode. */ -+ opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/0123456789"); -+ trunclen = (opnamelen < sizeof (opname) - 1 -+ ? opnamelen -+ : sizeof (opname) - 1); -+ memcpy (opname, str, trunclen); -+ opname[trunclen] = '\0'; -+ -+if (!strcmp (opname, "ldw_inc") || !strcmp (opname, "ldl_inc") -+ || !strcmp (opname, "ldw_dec") || !strcmp (opname, "ldl_dec") -+ || !strcmp (opname, "ldw_set") || !strcmp (opname, "ldl_set")) -+ { -+ if (!strcmp (sw_64_target_name, "sw6a")) -+ as_warn (_("The %s is only 6A instruction, you better change it!"), opname); -+ if (!strcmp (sw_64_target_name, "sw6b")) -+ as_bad (_("sw6b don't have \"%s\" !!"),(char *)opname); -+ } -+ -+ /* Tokenize the rest of the line. */ -+ if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0) -+ { -+ if (ntok != TOKENIZE_ERROR_REPORT) -+ as_bad (_("syntax error")); -+ -+ return; -+ } -+ -+#define REG_NUM 64 -+ int i, j; -+ char float_insn[REG_NUM][REG_NUM] = -+ { "fadds", "faddd", "fsubs", "fsubd", "fmuls", "fmuld", -+ "fdivs", "fdivd", "fsqrts", "fsqrtd", "fcmpeq", -+ "fcmple", "fcmplt", "fcmpun", "fcvtsd", "fcvtds", -+ "fcvtdl_g", "fcvtdl_p", "fcvtdl_z", "fcvtdl_n", -+ "fcvtdl", "fcvtlw", "fcvtls", "fcvtld", -+ "fmas","fmad","fmss","fmsd","fnmas","fnmad","fnmss","fnmsd", -+ "vadds","vaddd","vsubs","vsubd","vmuls","vmuld","vdivs","vdivd", -+ "vsqrts","vsqrtd","vmas","vmad","vmss","vmsd","vnmas","vnmad", -+ "vnmss","vnmsd","vfcmpeq","vfcmple", "vfcmplt", "vfcmpun" -+ }; -+ if (!sw_64_flag_nocheck_samereg) -+ { -+ for (i = 0; i < REG_NUM; i++) -+ { -+ if (strcmp (opname, float_insn[i]) == 0) -+ { -+ for (j = 0; j < ntok-1; j++) -+ { -+ if (tok[j].X_add_number == tok[ntok-1].X_add_number ) -+ as_bad (_("SRC and DST register of '%s' must be different!"), opname); -+ } -+ } -+ } -+ } -+ -+ /* Finish it off. */ -+ assemble_tokens (opname, tok, ntok, sw_64_macros_on); -+} -+ -+/* Round up a section's size to the appropriate boundary. */ -+ -+valueT -+md_section_align (segT seg, valueT size) -+{ -+ int align = bfd_section_alignment (seg); -+ valueT mask = ((valueT) 1 << align) - 1; -+ -+ return (size + mask) & ~mask; -+} -+ -+/* 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. */ -+ -+const char * -+md_atof (int type, char *litP, int *sizeP) -+{ -+ extern const char *vax_md_atof (int, char *, int *); -+ -+ switch (type) -+ { -+ /* VAX floats. */ -+ case 'G': -+ /* vax_md_atof() doesn't like "G" for some reason. */ -+ type = 'g'; -+ /* Fall through. */ -+ case 'F': -+ case 'D': -+ return vax_md_atof (type, litP, sizeP); -+ -+ default: -+ return ieee_md_atof (type, litP, sizeP, FALSE); -+ } -+} -+ -+/* Take care of the target-specific command-line options. */ -+ -+int -+md_parse_option (int c, const char *arg) -+{ -+ switch (c) -+ { -+ case 'F': -+ sw_64_nofloats_on = 1; -+ break; -+ -+ case OPTION_32ADDR: -+ sw_64_addr32_on = 1; -+ break; -+ -+ case 'g': -+ sw_64_debug = 1; -+ break; -+ -+ case 'G': -+ g_switch_value = atoi (arg); -+ break; -+ -+ case 'm': -+ { -+ const struct cpu_type *p; -+ -+ for (p = cpu_types; p->name; ++p) -+ if (strcmp (arg, p->name) == 0) -+ { -+ sw_64_target_name = p->name, sw_64_target = p->flags; -+ goto found; -+ } -+ as_warn (_("Unknown CPU identifier `%s'"), arg); -+ found:; -+ } -+ break; -+ -+#ifdef OBJ_EVAX -+ case '+': /* For g++. Hash any name > 63 chars long. */ -+ sw_64_flag_hash_long_names = 1; -+ break; -+ -+ case 'H': /* Show new symbol after hash truncation. */ -+ sw_64_flag_show_after_trunc = 1; -+ break; -+ -+ case 'h': /* For gnu-c/vax compatibility. */ -+ break; -+ -+ case OPTION_REPLACE: -+ sw_64_flag_replace = 1; -+ break; -+ -+ case OPTION_NOREPLACE: -+ sw_64_flag_replace = 0; -+ break; -+#endif -+ -+ case OPTION_RELAX: -+ sw_64_flag_relax = 1; -+ break; -+ -+#ifdef OBJ_ELF -+ case OPTION_MDEBUG: -+ sw_64_flag_mdebug = 1; -+ break; -+ case OPTION_NO_MDEBUG: -+ sw_64_flag_mdebug = 0; -+ break; -+#endif -+ -+ case OPTION_NOCHECK_SAMEREG: -+ sw_64_flag_nocheck_samereg = 1; -+ break; -+ -+ default: -+ return 0; -+ } -+ -+ return 1; -+} -+ -+/* Print a description of the command-line options that we accept. */ -+ -+void -+md_show_usage (FILE *stream) -+{ -+ fputs (_("\ -+Sw_64 options:\n\ -+-32addr treat addresses as 32-bit values\n\ -+-F lack floating point instructions support\n\ -+-msw6a | -msw6b\n\ -+ these variants include PALcode opcodes\n"), -+ stream); -+#ifdef OBJ_EVAX -+ fputs (_("\ -+VMS options:\n\ -+-+ encode (don't truncate) names longer than 64 characters\n\ -+-H show new symbol after hash truncation\n\ -+-replace/-noreplace enable or disable the optimization of procedure calls\n"), -+ stream); -+#endif -+} -+ -+/* Decide from what point a pc-relative relocation is relative to, -+ relative to the pc-relative fixup. Er, relatively speaking. */ -+ -+long -+md_pcrel_from (fixS *fixP) -+{ -+ valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; -+ -+ switch (fixP->fx_r_type) -+ { -+ case BFD_RELOC_23_PCREL_S2: -+ case BFD_RELOC_SW_64_HINT: -+ case BFD_RELOC_SW_64_BRSGP: -+ return addr + 4; -+ default: -+ return addr; -+ } -+} -+ -+/* Attempt to simplify or even eliminate a fixup. The return value is -+ ignored; perhaps it was once meaningful, but now it is historical. -+ To indicate that a fixup has been eliminated, set fixP->fx_done. -+ -+ For ELF, here it is that we transform the GPDISP_HI16 reloc we used -+ internally into the GPDISP reloc used externally. We had to do -+ this so that we'd have the GPDISP_LO16 reloc as a tag to compute -+ the distance to the "ldi" instruction for setting the addend to -+ GPDISP. */ -+ -+void -+md_apply_fix (fixS *fixP, valueT * valP, segT seg) -+{ -+ char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where; -+ valueT value = * valP; -+ unsigned image, size; -+ -+ switch (fixP->fx_r_type) -+ { -+ /* The GPDISP relocations are processed internally with a symbol -+ referring to the current function's section; 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_SW_64_GPDISP_HI16: -+ { -+ fixS *next = fixP->fx_next; -+ -+ /* With user-specified !gpdisp relocations, we can be missing -+ the matching LO16 reloc. We will have already issued an -+ error message. */ -+ if (next) -+ fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where -+ - fixP->fx_frag->fr_address - fixP->fx_where); -+ -+ value = (value - sign_extend_16 (value)) >> 16; -+ } -+#ifdef OBJ_ELF -+ fixP->fx_r_type = BFD_RELOC_SW_64_GPDISP; -+#endif -+ goto do_reloc_gp; -+ -+ case BFD_RELOC_SW_64_GPDISP_LO16: -+ value = sign_extend_16 (value); -+ fixP->fx_offset = 0; -+#ifdef OBJ_ELF -+ fixP->fx_done = 1; -+#endif -+ -+ do_reloc_gp: -+ fixP->fx_addsy = section_symbol (seg); -+ md_number_to_chars (fixpos, value, 2); -+ break; -+ case BFD_RELOC_8: -+ if (fixP->fx_pcrel) -+ fixP->fx_r_type = BFD_RELOC_8_PCREL; -+ size = 1; -+ goto do_reloc_xx; -+ case BFD_RELOC_16: -+ if (fixP->fx_pcrel) -+ fixP->fx_r_type = BFD_RELOC_16_PCREL; -+ size = 2; -+ goto do_reloc_xx; -+ -+ case BFD_RELOC_32: -+ if (fixP->fx_pcrel) -+ fixP->fx_r_type = BFD_RELOC_32_PCREL; -+ size = 4; -+ goto do_reloc_xx; -+ -+ case BFD_RELOC_64: -+ if (fixP->fx_pcrel) -+ fixP->fx_r_type = BFD_RELOC_64_PCREL; -+ size = 8; -+ -+ do_reloc_xx: -+ if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) -+ { -+ md_number_to_chars (fixpos, value, size); -+ goto done; -+ } -+ return; -+ -+#ifdef OBJ_ECOFF -+ case BFD_RELOC_GPREL32: -+ gas_assert (fixP->fx_subsy == sw_64_gp_symbol); -+ fixP->fx_subsy = 0; -+ /* FIXME: inherited this obliviousness of `value' -- why? */ -+ md_number_to_chars (fixpos, -sw_64_gp_value, 4); -+ break; -+#else -+ case BFD_RELOC_GPREL32: -+#endif -+ case BFD_RELOC_GPREL16: -+ case BFD_RELOC_SW_64_GPREL_HI16: -+ case BFD_RELOC_SW_64_GPREL_LO16: -+ return; -+ -+ case BFD_RELOC_23_PCREL_S2: -+ if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) -+ { -+ image = bfd_getl32 (fixpos); -+ image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF); -+ goto write_done; -+ } -+ return; -+ -+ case BFD_RELOC_SW_64_HINT: -+ if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) -+ { -+ image = bfd_getl32 (fixpos); -+ /* SW6 use 16 bit hint disp,not 14. */ -+ image = (image & ~0xFFFF) | ((value >> 2) & 0xFFFF); -+ goto write_done; -+ } -+ return; -+ -+#ifdef OBJ_ELF -+ case BFD_RELOC_SW_64_BRSGP: -+ return; -+ -+ case BFD_RELOC_SW_64_TLSGD: -+ case BFD_RELOC_SW_64_TLSLDM: -+ case BFD_RELOC_SW_64_GOTDTPREL16: -+ case BFD_RELOC_SW_64_DTPREL_HI16: -+ case BFD_RELOC_SW_64_DTPREL_LO16: -+ case BFD_RELOC_SW_64_DTPREL16: -+ case BFD_RELOC_SW_64_GOTTPREL16: -+ case BFD_RELOC_SW_64_TPREL_HI16: -+ case BFD_RELOC_SW_64_TPREL_LO16: -+ case BFD_RELOC_SW_64_TPREL16: -+ if (fixP->fx_addsy) -+ S_SET_THREAD_LOCAL (fixP->fx_addsy); -+ return; -+#endif -+ -+#ifdef OBJ_ECOFF -+ case BFD_RELOC_SW_64_LITERAL: -+ md_number_to_chars (fixpos, value, 2); -+ return; -+#endif -+ case BFD_RELOC_SW_64_ELF_LITERAL: -+ case BFD_RELOC_SW_64_ELF_LITERAL_GOT: -+ case BFD_RELOC_SW_64_LITUSE: -+ case BFD_RELOC_SW_64_LINKAGE: -+ case BFD_RELOC_SW_64_CODEADDR: -+ return; -+ -+#ifdef OBJ_EVAX -+ case BFD_RELOC_SW_64_NOP: -+ value -= (8 + 4); /* PC-relative, base is call+4. */ -+ -+ /* From B.4.5.2 of the OpenVMS Linker Utility Manual: -+ "Finally, the ETIR$C_STC_BSR command passes the same address -+ as ETIR$C_STC_NOP (so that they will fail or succeed together), -+ and the same test is done again." */ -+ if (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) -+ { -+ fixP->fx_addnumber = -value; -+ return; -+ } -+ if (value + (1u << 22) >= (1u << 23)) -+ goto done; -+ else -+ { -+ /* Change to a nop. */ -+ image = 0x47FF041F; -+ goto write_done; -+ } -+ -+ case BFD_RELOC_SW_64_LDA: -+ /* fixup_segment sets fixP->fx_addsy to NULL when it can pre-compute -+ the value for an O_subtract. */ -+ if (fixP->fx_addsy -+ && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) -+ { -+ fixP->fx_addnumber = symbol_get_bfdsym (fixP->fx_subsy)->value; -+ return; -+ } -+ if (value + (1u << 15) >= (1u << 16)) -+ goto done; -+ else -+ { -+ /* Change to an ldi. */ -+ image = 0x237B0000 | (value & 0xFFFF); -+ goto write_done; -+ } -+ -+ case BFD_RELOC_SW_64_BSR: -+ case BFD_RELOC_SW_64_BOH: -+ value -= 4; /* PC-relative, base is call+4. */ -+ -+ /* See comment in the BFD_RELOC_SW_64_NOP case above. */ -+ if (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) -+ { -+ fixP->fx_addnumber = -value; -+ return; -+ } -+ if (value + (1u << 22) >= (1u << 23)) -+ { -+ /* Out of range. */ -+ if (fixP->fx_r_type == BFD_RELOC_SW_64_BOH) -+ { -+ /* Add a hint. */ -+ image = bfd_getl32(fixpos); -+ image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF); -+ goto write_done; -+ } -+ goto done; -+ } -+ else -+ { -+ /* Change to a branch. */ -+ image = 0xD3400000 | ((value >> 2) & 0x1FFFFF); -+ goto write_done; -+ } -+#endif -+ -+ case BFD_RELOC_VTABLE_INHERIT: -+ case BFD_RELOC_VTABLE_ENTRY: -+ return; -+ -+ default: -+ { -+ const struct sw_64_operand *operand; -+ -+ if ((int) fixP->fx_r_type >= 0) -+ as_fatal (_("unhandled relocation type %s"), -+ bfd_get_reloc_code_name (fixP->fx_r_type)); -+ -+ gas_assert (-(int) fixP->fx_r_type < (int) sw_64_num_operands); -+ operand = &sw_64_operands[-(int) fixP->fx_r_type]; -+ -+ /* The rest of these fixups only exist internally during symbol -+ resolution and have no representation in the object file. -+ Therefore they must be completely resolved as constants. */ -+ -+ if (fixP->fx_addsy != 0 -+ && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section) -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _("non-absolute expression in constant field")); -+ -+ image = bfd_getl32 (fixpos); -+ image = insert_operand (image, operand, (offsetT) value, -+ fixP->fx_file, fixP->fx_line); -+ } -+ goto write_done; -+ } -+ -+ if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0) -+ return; -+ else -+ { -+ as_warn_where (fixP->fx_file, fixP->fx_line, -+ _("type %d reloc done?\n"), (int) fixP->fx_r_type); -+ goto done; -+ } -+ -+write_done: -+ md_number_to_chars (fixpos, image, 4); -+ -+done: -+ fixP->fx_done = 1; -+} -+ -+/* Look for a register name in the given symbol. */ -+ -+symbolS * -+md_undefined_symbol (char *name) -+{ -+ if (*name == '$') -+ { -+ int is_float = 0, num; -+ -+ switch (*++name) -+ { -+ case 'f': -+ if (name[1] == 'p' && name[2] == '\0') -+ return sw_64_register_table[AXP_REG_FP]; -+ is_float = 32; -+ /* Fall through. */ -+ -+ case 'r': -+ if (!ISDIGIT (*++name)) -+ break; -+ /* Fall through. */ -+ -+ case '0': case '1': case '2': case '3': case '4': -+ case '5': case '6': case '7': case '8': case '9': -+ if (name[1] == '\0') -+ num = name[0] - '0'; -+ else if (name[0] != '0' && ISDIGIT (name[1]) && name[2] == '\0') -+ { -+ num = (name[0] - '0') * 10 + name[1] - '0'; -+ if (num >= 32) -+ break; -+ } -+ else -+ break; -+ -+ if (!sw_64_noat_on && (num + is_float) == AXP_REG_AT) -+ as_warn (_("Used $at without \".set noat\"")); -+ return sw_64_register_table[num + is_float]; -+ -+ case 'a': -+ if (name[1] == 't' && name[2] == '\0') -+ { -+ if (!sw_64_noat_on) -+ as_warn (_("Used $at without \".set noat\"")); -+ return sw_64_register_table[AXP_REG_AT]; -+ } -+ break; -+ -+ case 'g': -+ if (name[1] == 'p' && name[2] == '\0') -+ return sw_64_register_table[sw_64_gp_register]; -+ break; -+ -+ case 's': -+ if (name[1] == 'p' && name[2] == '\0') -+ return sw_64_register_table[AXP_REG_SP]; -+ break; -+ } -+ } -+ return NULL; -+} -+ -+#ifdef OBJ_ECOFF -+/* @@@ Magic ECOFF bits. */ -+ -+void -+sw_64_frob_ecoff_data (void) -+{ -+ select_gp_value (); -+ /* $zero and $f31 are read-only. */ -+ sw_64_gprmask &= ~1; -+ sw_64_fprmask &= ~1; -+} -+#endif -+ -+/* Hook to remember a recently defined label so that the auto-align -+ code can adjust the symbol after we know what alignment will be -+ required. */ -+ -+void -+sw_64_define_label (symbolS *sym) -+{ -+ sw_64_insn_label = sym; -+#ifdef OBJ_ELF -+ dwarf2_emit_label (sym); -+#endif -+} -+ -+/* Return true if we must always emit a reloc for a type and false if -+ there is some hope of resolving it at assembly time. */ -+ -+int -+sw_64_force_relocation (fixS *f) -+{ -+ if (sw_64_flag_relax) -+ return 1; -+ -+ switch (f->fx_r_type) -+ { -+ case BFD_RELOC_SW_64_GPDISP_HI16: -+ case BFD_RELOC_SW_64_GPDISP_LO16: -+ case BFD_RELOC_SW_64_GPDISP: -+ case BFD_RELOC_SW_64_LITERAL: -+ case BFD_RELOC_SW_64_ELF_LITERAL: -+ case BFD_RELOC_SW_64_ELF_LITERAL_GOT: -+ case BFD_RELOC_SW_64_LITUSE: -+ case BFD_RELOC_GPREL16: -+ case BFD_RELOC_GPREL32: -+ case BFD_RELOC_SW_64_GPREL_HI16: -+ case BFD_RELOC_SW_64_GPREL_LO16: -+ case BFD_RELOC_SW_64_LINKAGE: -+ case BFD_RELOC_SW_64_CODEADDR: -+ case BFD_RELOC_SW_64_BRSGP: -+ case BFD_RELOC_SW_64_TLSGD: -+ case BFD_RELOC_SW_64_TLSLDM: -+ case BFD_RELOC_SW_64_GOTDTPREL16: -+ case BFD_RELOC_SW_64_DTPREL_HI16: -+ case BFD_RELOC_SW_64_DTPREL_LO16: -+ case BFD_RELOC_SW_64_DTPREL16: -+ case BFD_RELOC_SW_64_GOTTPREL16: -+ case BFD_RELOC_SW_64_TPREL_HI16: -+ case BFD_RELOC_SW_64_TPREL_LO16: -+ case BFD_RELOC_SW_64_TPREL16: -+#ifdef OBJ_EVAX -+ case BFD_RELOC_SW_64_NOP: -+ case BFD_RELOC_SW_64_BSR: -+ case BFD_RELOC_SW_64_LDA: -+ case BFD_RELOC_SW_64_BOH: -+#endif -+ return 1; -+ -+ default: -+ break; -+ } -+ -+ return generic_force_reloc (f); -+} -+ -+/* Return true if we can partially resolve a relocation now. */ -+ -+int -+sw_64_fix_adjustable (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_SW_64_GPDISP_HI16: -+ case BFD_RELOC_SW_64_GPDISP_LO16: -+ case BFD_RELOC_SW_64_GPDISP: -+ return 0; -+ -+ case BFD_RELOC_SW_64_LITERAL: -+ case BFD_RELOC_SW_64_ELF_LITERAL: -+ case BFD_RELOC_SW_64_ELF_LITERAL_GOT: -+ case BFD_RELOC_SW_64_LITUSE: -+ case BFD_RELOC_SW_64_LINKAGE: -+ case BFD_RELOC_SW_64_CODEADDR: -+ return 1; -+ -+ case BFD_RELOC_VTABLE_ENTRY: -+ case BFD_RELOC_VTABLE_INHERIT: -+ return 0; -+ -+ case BFD_RELOC_GPREL16: -+ case BFD_RELOC_GPREL32: -+ case BFD_RELOC_SW_64_GPREL_HI16: -+ case BFD_RELOC_SW_64_GPREL_LO16: -+ case BFD_RELOC_23_PCREL_S2: -+ case BFD_RELOC_16: -+ case BFD_RELOC_32: -+ case BFD_RELOC_64: -+ case BFD_RELOC_SW_64_HINT: -+ return 1; -+ -+ case BFD_RELOC_SW_64_TLSGD: -+ case BFD_RELOC_SW_64_TLSLDM: -+ case BFD_RELOC_SW_64_GOTDTPREL16: -+ case BFD_RELOC_SW_64_DTPREL_HI16: -+ case BFD_RELOC_SW_64_DTPREL_LO16: -+ case BFD_RELOC_SW_64_DTPREL16: -+ case BFD_RELOC_SW_64_GOTTPREL16: -+ case BFD_RELOC_SW_64_TPREL_HI16: -+ case BFD_RELOC_SW_64_TPREL_LO16: -+ case BFD_RELOC_SW_64_TPREL16: -+ /* ??? No idea why we can't return a reference to .tbss+10, but -+ we're preventing this in the other assemblers. Follow for now. */ -+ return 0; -+ -+#ifdef OBJ_ELF -+ case BFD_RELOC_SW_64_BRSGP: -+ /* If we have a BRSGP reloc to a local symbol, adjust it to BRADDR and -+ let it get resolved at assembly time. */ -+ { -+ symbolS *sym = f->fx_addsy; -+ const char *name; -+ int offset = 0; -+ -+ if (generic_force_reloc (f)) -+ return 0; -+ -+ switch (S_GET_OTHER (sym) & STO_SW_64_STD_GPLOAD) -+ { -+ case STO_SW_64_NOPV: -+ break; -+ case STO_SW_64_STD_GPLOAD: -+ offset = 8; -+ break; -+ default: -+ if (S_IS_LOCAL (sym)) -+ name = ""; -+ else -+ name = S_GET_NAME (sym); -+ as_bad_where (f->fx_file, f->fx_line, -+ _("!samegp reloc against symbol without .prologue: %s"), -+ name); -+ break; -+ } -+ f->fx_r_type = BFD_RELOC_23_PCREL_S2; -+ f->fx_offset += offset; -+ return 1; -+ } -+#endif -+#ifdef OBJ_EVAX -+ case BFD_RELOC_SW_64_NOP: -+ case BFD_RELOC_SW_64_BSR: -+ case BFD_RELOC_SW_64_LDA: -+ case BFD_RELOC_SW_64_BOH: -+ return 1; -+#endif -+ -+ default: -+ return 1; -+ } -+} -+ -+/* Generate the BFD reloc to be stuck in the object file from the -+ fixup used internally in the assembler. */ -+ -+arelent * -+tc_gen_reloc (asection *sec ATTRIBUTE_UNUSED, -+ fixS *fixp) -+{ -+ arelent *reloc; -+ -+ reloc = XNEW (arelent); -+ reloc->sym_ptr_ptr = XNEW (asymbol *); -+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); -+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; -+ -+ /* Make sure none of our internal relocations make it this far. -+ They'd better have been fully resolved by this point. */ -+ gas_assert ((int) fixp->fx_r_type > 0); -+ -+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); -+ if (reloc->howto == NULL) -+ { -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("cannot represent `%s' relocation in object file"), -+ bfd_get_reloc_code_name (fixp->fx_r_type)); -+ return NULL; -+ } -+ -+ 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)); -+ -+ gas_assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); -+ -+ reloc->addend = fixp->fx_offset; -+ -+#ifdef OBJ_ECOFF -+ /* Fake out bfd_perform_relocation. sigh. */ -+ /* ??? Better would be to use the special_function hook. */ -+ if (fixp->fx_r_type == BFD_RELOC_SW_64_LITERAL) -+ reloc->addend = -sw_64_gp_value; -+#endif -+ -+#ifdef OBJ_EVAX -+ switch (fixp->fx_r_type) -+ { -+ struct evax_private_udata_struct *udata; -+ const char *pname; -+ int pname_len; -+ -+ case BFD_RELOC_SW_64_LINKAGE: -+ /* Copy the linkage index. */ -+ reloc->addend = fixp->fx_addnumber; -+ break; -+ -+ case BFD_RELOC_SW_64_NOP: -+ case BFD_RELOC_SW_64_BSR: -+ case BFD_RELOC_SW_64_LDA: -+ case BFD_RELOC_SW_64_BOH: -+ pname = symbol_get_bfdsym (fixp->fx_addsy)->name; -+ -+ /* We need the non-suffixed name of the procedure. Beware that -+ the main symbol might be equated so look it up and take its name. */ -+ pname_len = strlen (pname); -+ if (pname_len > 4 && strcmp (pname + pname_len - 4, "..en") == 0) -+ { -+ symbolS *sym; -+ char *my_pname = xmemdup0 (pname, pname_len - 4); -+ sym = symbol_find (my_pname); -+ free (my_pname); -+ if (sym == NULL) -+ abort (); -+ -+ while (symbol_equated_reloc_p (sym)) -+ { -+ symbolS *n = symbol_get_value_expression (sym)->X_add_symbol; -+ -+ /* We must avoid looping, as that can occur with a badly -+ written program. */ -+ if (n == sym) -+ break; -+ sym = n; -+ } -+ pname = symbol_get_bfdsym (sym)->name; -+ } -+ -+ udata = XNEW (struct evax_private_udata_struct); -+ udata->enbsym = symbol_get_bfdsym (fixp->fx_addsy); -+ udata->bsym = symbol_get_bfdsym (fixp->tc_fix_data.info->psym); -+ udata->origname = (char *)pname; -+ udata->lkindex = ((struct evax_private_udata_struct *) -+ symbol_get_bfdsym (fixp->tc_fix_data.info->sym)->udata.p)->lkindex; -+ reloc->sym_ptr_ptr = (void *)udata; -+ reloc->addend = fixp->fx_addnumber; -+ -+ default: -+ break; -+ } -+#endif -+ -+ return reloc; -+} -+ -+/* Parse a register name off of the input_line and return a register -+ number. Gets md_undefined_symbol above to do the register name -+ matching for us. -+ -+ Only called as a part of processing the ECOFF .frame directive. */ -+ -+int -+tc_get_register (int frame ATTRIBUTE_UNUSED) -+{ -+ int framereg = AXP_REG_SP; -+ -+ SKIP_WHITESPACE (); -+ if (*input_line_pointer == '$') -+ { -+ char *s; -+ char c = get_symbol_name (&s); -+ symbolS *sym = md_undefined_symbol (s); -+ -+ *strchr (s, '\0') = c; -+ if (sym && (framereg = S_GET_VALUE (sym)) <= 31) -+ goto found; -+ } -+ as_warn (_("frame reg expected, using $%d."), framereg); -+ -+found: -+ note_gpreg (framereg); -+ return framereg; -+} -+ -+/* This is called before the symbol table is processed. In order to -+ work with gcc when using mips-tfile, we must keep all local labels. -+ However, in other cases, we want to discard them. If we were -+ called with -g, but we didn't see any debugging information, it may -+ mean that gcc is smuggling debugging information through to -+ mips-tfile, in which case we must generate all local labels. */ -+ -+#ifdef OBJ_ECOFF -+ -+void -+sw_64_frob_file_before_adjust (void) -+{ -+ if (sw_64_debug != 0 -+ && ! ecoff_debugging_seen) -+ flag_keep_locals = 1; -+} -+ -+#endif /* OBJ_ECOFF */ -+ -+static const struct sw_64_cpu_info * -+sw_64_parse_cpu (const char *option, const char *cpu_string) -+{ -+ if (strcasecmp (cpu_string, "sw6a") == 0) -+ return sw_64_cpu_info_from_isa (ISA_SW6A); -+ -+ if (strcasecmp (cpu_string, "sw6b") == 0) -+ return sw_64_cpu_info_from_isa (ISA_SW6B); -+ -+ if (strcasecmp (cpu_string, "default") == 0) -+ return 0; -+} -+ -+/* Set up globals to generate code for the ISA or processor -+ * described by INFO. */ -+ -+static void -+sw_64_set_architecture (const struct sw_64_cpu_info *info) -+{ -+ if (info != 0) -+ { -+ file_sw_64_arch = info->cpu; -+ sw_64_opts.arch = info->cpu; -+ sw_64_opts.isa = info->isa; -+ } -+} -+ -+void -+sw_64_after_parse_args (void) -+{ -+ const struct sw_64_cpu_info *arch_info = 0; -+ const struct sw_64_cpu_info *tune_info = 0; -+ -+ const struct cpu_type *p; -+ if (sw_64_target_name == NULL) -+ { -+ for (p = cpu_types; p->name; ++p) -+ if (strcmp (SW_CPU_STRING_DEFAULT, p->name) == 0) -+ { -+ sw_64_target_name = p->name, sw_64_target = p->flags; -+ goto found; -+ } -+ as_bad (_("Unknown CPU default name `%s'"), SW_CPU_STRING_DEFAULT); -+found: -+ arch_info = sw_64_parse_cpu ("default CPU", SW_CPU_STRING_DEFAULT); -+ gas_assert (arch_info); -+ } -+ -+ if (strcmp (sw_64_target_name, "sw6a") == 0) -+ arch_info = sw_64_parse_cpu ("default CPU", "sw6a"); -+ else if (strcmp (sw_64_target_name, "sw6b") == 0) -+ arch_info = sw_64_parse_cpu ("default CPU", "sw6b"); -+ else -+ as_bad (_("Unkonwn CPU target name: `%s'"), sw_64_target_name); -+ sw_64_set_architecture (arch_info); -+} -+ -+static const struct sw_64_cpu_info sw_64_cpu_info_table[] = -+{ -+ /* Entries for generic ISAs */ -+ { "sw6a", SW_64_CPU_IS_ISA, 0, ISA_SW6A, CPU_SW6A }, -+ { "sw6b", SW_64_CPU_IS_ISA, 0, ISA_SW6B, CPU_SW6B }, -+ { NULL, 0, 0, 0, 0 } -+}; -+ -+/* Return the canonical processor information for ISA (a member of the -+ * ISA_SW_64* enumeration). */ -+ -+static const struct sw_64_cpu_info * -+sw_64_cpu_info_from_isa (int isa) -+{ -+ int i; -+ -+ for (i = 0; sw_64_cpu_info_table[i].name != NULL; i++) -+ if ((sw_64_cpu_info_table[i].flags & SW_64_CPU_IS_ISA) -+ && isa == sw_64_cpu_info_table[i].isa) -+ return (&sw_64_cpu_info_table[i]); -+ -+ return NULL; -+} -+ -+/* Some special processing for a SW_64 ELF file. */ -+ -+void -+sw_64_elf_final_processing (void) -+{ -+#ifdef GIT_REVISION -+ elf_elfheader (stdoutput)->e_flags |= GIT_REVISION; -+#else -+ if (file_sw_64_arch == 4) -+ elf_elfheader (stdoutput)->e_flags |= EF_SW6A_FLGAS; -+ else if (file_sw_64_arch == 8) -+ elf_elfheader (stdoutput)->e_flags |= EF_SW6B_FLGAS; -+ else -+ elf_elfheader (stdoutput)->e_flags |= 0; -+#endif -+} -+ -+ -+/* The Sw_64 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. */ -+#include "config/atof-vax.c" -diff --git a/gas/config/tc-sw_64.h b/gas/config/tc-sw_64.h -new file mode 100644 -index 00000000..0c1c3ba0 ---- /dev/null -+++ b/gas/config/tc-sw_64.h -@@ -0,0 +1,197 @@ -+/* This file is tc-sw_64.h -+ Copyright (C) 1994-2018 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA -+ 02110-1301, USA. */ -+ -+#define TC_SW_64 -+ -+#define TARGET_BYTES_BIG_ENDIAN 0 -+ -+#define WORKING_DOT_WORD -+ -+#define TARGET_ARCH bfd_arch_sw_64 -+ -+#ifdef TE_FreeBSD -+#define ELF_TARGET_FORMAT "elf64-sw_64-freebsd" -+#endif -+#ifndef ELF_TARGET_FORMAT -+#define ELF_TARGET_FORMAT "elf64-sw_64" -+#endif -+ -+#define TARGET_FORMAT (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ -+ ? "ecoff-littlesw_64" \ -+ : OUTPUT_FLAVOR == bfd_target_elf_flavour \ -+ ? ELF_TARGET_FORMAT \ -+ : OUTPUT_FLAVOR == bfd_target_evax_flavour \ -+ ? "vms-sw_64" \ -+ : "unknown-format") -+ -+#define NEED_LITERAL_POOL -+#define REPEAT_CONS_EXPRESSIONS -+ -+struct fix; -+struct sw_64_reloc_tag; -+ -+extern int sw_64_force_relocation (struct fix *); -+extern int sw_64_fix_adjustable (struct fix *); -+ -+extern unsigned long sw_64_gprmask, sw_64_fprmask; -+extern valueT sw_64_gp_value; -+ -+#define TC_FORCE_RELOCATION(FIX) sw_64_force_relocation (FIX) -+#define tc_fix_adjustable(FIX) sw_64_fix_adjustable (FIX) -+#define RELOC_REQUIRES_SYMBOL -+ -+/* Values passed to md_apply_fix don't include the symbol value. */ -+#define MD_APPLY_SYM_VALUE(FIX) 0 -+ -+#define md_convert_frag(b,s,f) as_fatal ("sw_64 convert_frag\n") -+#define md_estimate_size_before_relax(f,s) \ -+ (as_fatal ("estimate_size_before_relax called"),1) -+#define md_operand(x) -+ -+#ifdef OBJ_EVAX -+#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1 -+ -+#define tc_canonicalize_symbol_name evax_shorten_name -+ -+#define TC_CONS_FIX_NEW(FRAG,OFF,LEN,EXP,RELOC) \ -+ (void) RELOC, \ -+ fix_new_exp (FRAG, OFF, (int)LEN, EXP, 0, \ -+ LEN == 2 ? BFD_RELOC_16 \ -+ : LEN == 4 ? BFD_RELOC_32 \ -+ : LEN == 8 ? BFD_RELOC_64 \ -+ : BFD_RELOC_SW_64_LINKAGE); -+#endif -+ -+#ifdef OBJ_EVAX -+#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) (P2VAR) = 3 -+#else -+#define TC_IMPLICIT_LCOMM_ALIGNMENT(size, align) \ -+ do \ -+ { \ -+ align = 0; \ -+ if (size > 1) \ -+ { \ -+ addressT temp = 1; \ -+ while ((size & temp) == 0) \ -+ ++align, temp <<= 1; \ -+ } \ -+ } \ -+ while (0) -+#endif -+ -+#define md_number_to_chars number_to_chars_littleendian -+ -+extern int tc_get_register (int); -+extern void sw_64_frob_ecoff_data (void); -+ -+#define tc_frob_label(sym) sw_64_define_label (sym) -+extern void sw_64_define_label (symbolS *); -+ -+#define md_cons_align(nbytes) sw_64_cons_align (nbytes) -+extern void sw_64_cons_align (int); -+ -+#define HANDLE_ALIGN(fragp) sw_64_handle_align (fragp) -+extern void sw_64_handle_align (struct frag *); -+ -+#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4 + 8) -+ -+#ifdef OBJ_ECOFF -+#define tc_frob_file_before_adjust() sw_64_frob_file_before_adjust () -+extern void sw_64_frob_file_before_adjust (void); -+ -+#define TC_VALIDATE_FIX_SUB(FIX, SEG) \ -+ ((md_register_arithmetic || (SEG) != reg_section) \ -+ && ((FIX)->fx_r_type == BFD_RELOC_GPREL32 \ -+ || (FIX)->fx_r_type == BFD_RELOC_GPREL16)) -+#endif -+ -+#define md_after_parse_args() sw_64_after_parse_args() -+extern void sw_64_after_parse_args (void); -+ -+#define elf_tc_final_processing sw_64_elf_final_processing -+extern void sw_64_elf_final_processing (void); -+ -+#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs. */ -+ -+#ifdef OBJ_ELF -+#define md_elf_section_letter sw_64_elf_section_letter -+extern bfd_vma sw_64_elf_section_letter (int, const char **); -+#define md_elf_section_flags sw_64_elf_section_flags -+extern flagword sw_64_elf_section_flags (flagword, bfd_vma, int); -+#endif -+ -+/* Whether to add support for explicit !relocation_op!sequence_number. At the -+ moment, only do this for ELF, though ECOFF could use it as well. */ -+ -+#ifdef OBJ_ELF -+#define RELOC_OP_P -+#endif -+ -+#ifndef OBJ_EVAX -+/* Before the relocations are written, reorder them, so that user -+ supplied !lituse relocations follow the appropriate !literal -+ relocations. Also convert the gas-internal relocations to the -+ appropriate linker relocations. */ -+#define tc_frob_file_before_fix() sw_64_before_fix () -+extern void sw_64_before_fix (void); -+#endif -+ -+#ifdef OBJ_ELF -+#define md_end sw_64_elf_md_end -+extern void sw_64_elf_md_end (void); -+#endif -+ -+/* New fields for supporting explicit relocations (such as !literal to mark -+ where a pointer is loaded from the global table, and !lituse_base to track -+ all of the normal uses of that pointer). */ -+ -+#define TC_FIX_TYPE struct sw_64_fix_tag -+ -+struct sw_64_fix_tag -+{ -+ struct fix *next_reloc; /* Next !lituse or !gpdisp. */ -+ struct sw_64_reloc_tag *info; /* Other members with same sequence. */ -+}; -+ -+/* Initialize the TC_FIX_TYPE field. */ -+#define TC_INIT_FIX_DATA(FIX) \ -+do { \ -+ FIX->tc_fix_data.next_reloc = NULL; \ -+ FIX->tc_fix_data.info = NULL; \ -+} while (0) -+ -+/* Work with DEBUG5 to print fields in tc_fix_type. */ -+#define TC_FIX_DATA_PRINT(STREAM, FIX) \ -+do { \ -+ if (FIX->tc_fix_data.info) \ -+ fprintf (STREAM, "\tinfo = 0x%lx, next_reloc = 0x%lx\n", \ -+ (long) FIX->tc_fix_data.info, \ -+ (long) FIX->tc_fix_data.next_reloc); \ -+} while (0) -+ -+#define TARGET_USE_CFIPOP 1 -+ -+#define tc_cfi_frame_initial_instructions sw_64_cfi_frame_initial_instructions -+extern void sw_64_cfi_frame_initial_instructions (void); -+ -+#define DWARF2_LINE_MIN_INSN_LENGTH 4 -+#define DWARF2_DEFAULT_RETURN_COLUMN 26 -+#define DWARF2_CIE_DATA_ALIGNMENT (-8) -diff --git a/gas/test b/gas/test -new file mode 100644 -index 00000000..4af4899b ---- /dev/null -+++ b/gas/test -@@ -0,0 +1,350 @@ -+# Copyright (C) 2012-2021 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 3 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. -+ -+# -+# elf tests -+# -+ -+proc run_elf_list_test { name suffix opts readelf_opts readelf_pipe } { -+ global READELF -+ global srcdir subdir -+ set testname "elf $name list" -+ set file $srcdir/$subdir/$name -+ gas_run ${name}.s "$opts -o dump.o" ">&dump.out" -+ if { ![string match "" $opts] -+ && [regexp_diff "dump.out" "${file}.l"] } then { -+ fail $testname -+ verbose "output is [file_contents "dump.out"]" 2 -+ return -+ } -+ send_log "$READELF $readelf_opts dump.o $readelf_pipe > dump.out\n" -+ set status [gas_host_run "$READELF $readelf_opts dump.o" ">readelf.out"] -+ if { [lindex $status 0] != 0 || ![string match "" [lindex $status 1]] } then { -+ send_log "[lindex $status 1]\n" -+ fail $testname -+ return -+ } -+ catch "exec cat readelf.out $readelf_pipe > dump.out\n" comp_output -+ if ![string match "" $comp_output] then { -+ send_log "$comp_output\n" -+ fail $testname -+ return -+ } -+ verbose_eval {[file_contents "dump.out"]} 3 -+ if { [regexp_diff "dump.out" "${file}.e${suffix}"] } then { -+ fail $testname -+ verbose "output is [file_contents "dump.out"]" 2 -+ return -+ } -+ pass $testname -+} -+ -+# We're testing bits in obj-elf -- don't run on anything else. -+if { [is_elf_format] } then { -+ if { [is_elf_unused_section_symbols ] } { -+ set target_machine -unused -+ } else { -+ set target_machine "" -+ } -+ set dump_opts "" -+ if {[istarget "arc*-*-*"]} { -+ set target_machine -arc -+ } -+ if {[istarget "arm*-*-*"]} { -+ set target_machine -arm -+ } -+ if {[istarget "avr*-*-*"]} { -+ set dump_opts {{as -mno-link-relax}} -+ } -+ if {[istarget "csky*-*-*"]} { -+ set target_machine -csky -+ } -+ if {[istarget "m32r*-*-*"]} then { -+ set target_machine -m32r -+ } -+ if {[istarget "mips*-*-*"]} then { -+ set target_machine -mips -+ } -+ if {[istarget "msp430-*-*"]} then { -+ set target_machine -msp430 -+ } -+ if {[istarget "pru-*-*"]} { -+ set dump_opts {{as -mno-link-relax}} -+ } -+ if {[istarget "riscv*-*-*"]} then { -+ set target_machine -riscv -+ set dump_opts {{as -mno-relax}} -+ } -+ if {[istarget "rl78-*-*"]} then { -+ set target_machine -rl78 -+ } -+ if {[istarget "rx-*-*"]} then { -+ set target_machine -rx -+ } -+ if {[istarget "score-*-*"]} then { -+ set target_machine -score -+ } -+ if {[istarget "tic6x-*-*"]} then { -+ set target_machine -tic6x -+ } -+ if {[istarget "v850*-*-*"]} then { -+ set target_machine -v850 -+ } -+ if {[istarget "xtensa*-*-*"]} then { -+ set target_machine -xtensa -+ set dump_opts {{as --no-link-relax}} -+ } -+ -+ # The MN10300 and Xtensa ports disable the assembler's call frame -+ # optimization because it interfers with link-time relaxation of -+ # function prologues. -+ if {![istarget "mn10300-*-*"] -+ && ![istarget "am3*-*-*"] -+ && ![istarget "xtensa*-*-*"] -+ && ![istarget "msp430*-*-*"] -+ && ![istarget "nds32*-*-*"] -+ && ![istarget "am3*-*-*"]} then { -+ run_dump_test "ehopt0" -+ } -+ switch -glob $target_triplet { -+ m68k-*-* - -+ m68[03]??-*-* { -+ run_dump_test "file" { { as "--defsym m68k=1" } } -+ } -+ mmix-*-* { -+ run_dump_test "file" { { as "--defsym mmix=1" } } -+ } -+ xtensa*-*-* { -+ run_dump_test "file" { { as "--rename-section file.s=file.c" } } -+ } -+ default { -+ run_dump_test "file" -+ } -+ } -+ run_dump_test "file-2" -+ setup_xfail "nds32*-*-*" -+ run_dump_test "group0a" -+ run_dump_test "group0b" -+ run_dump_test "group0c" -+ run_dump_test "group1a" -+ run_dump_test "group1b" -+ run_dump_test "group2" -+ run_dump_test "group3" -+ -+ run_dump_test "attach-1" -+ run_dump_test "attach-err" -+ -+ switch -glob $target_triplet { -+ hppa64*-*-hpux* { } -+ riscv*-*-* { } -+ default { -+ run_dump_test "groupautoa" -+ } -+ } -+ switch -glob $target_triplet { -+ hppa64*-*-hpux* { } -+ riscv*-*-* { } -+ xtensa*-*-* { } -+ default { -+ run_dump_test "groupautob" -+ } -+ } -+ switch -glob $target_triplet { -+ alpha*-*-* { } -+ am3*-*-* { } -+ *c54x*-*-* { } -+ cr16*-*-* { } -+ crx*-*-* { } -+ h8300-*-* { } -+ hppa*-*-* { } -+ iq2000*-*-* { } -+ mips*-*-* { } -+ mn10200-*-* { } -+ mn10300-*-* { } -+ msp43*-*-* { } -+ rl78-*-* { } -+ riscv*-*-* { } -+ rx-*-* { } -+ loongarch*-*-* { } -+ default { -+ # The next test can fail if the target does not convert fixups -+ # against ordinary symbols into relocations against section symbols. -+ # This is usually revealed by the error message: -+ # symbol `sym' required but not present -+ setup_xfail "m681*-*-*" "m68hc*-*-*" "xgate-*-*" "vax-*-*" "sw_64*-*-*" -+ run_dump_test redef -+ setup_xfail "sw_64*-*-*" -+ run_dump_test equ-reloc -+ } -+ } -+ run_dump_test "pseudo" -+ run_dump_test "section0" -+ run_dump_test "section1" -+ # The h8300 port issues a warning message for -+ # new sections created without atrributes. -+ if {! [istarget "h8300-*-*"]} then { -+ set as_flags "-al --generate-missing-build-notes=no" -+ switch -glob $target_triplet { -+ i*86-*-* - -+ x86_64-*-* { -+ set as_flags "$as_flags -mx86-used-note=no" -+ } -+ riscv*-*-* { -+ set as_flags "$as_flags -march-attr" -+ } -+ } -+ run_elf_list_test "section2" "$target_machine" "$as_flags" "-s" "" -+ } -+ run_dump_test "section3" -+ run_dump_test "section4" -+ if {! [istarget "h8300-*-*"] && ! [istarget "rx-*-*"]} then { -+ # The h8300 port issues a warning message for -+ # new sections created without atrributes. -+ # The RX port does not complain about changing the attributes of the -+ # .data and .bss sections since it does not use those names. -+ run_elf_list_test "section5" "" "-al -Z" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\"" -+ } -+ run_dump_test "struct" -+ if {! [istarget "alpha*-*-*"] && ! [istarget "sw_64*-*-*"]} then { -+ # The alpha port uses .set for state, e.g. nomacro. -+ run_dump_test "symtab" -+ } -+ run_dump_test "symver" -+ run_dump_test "pr21661" -+ run_dump_test "pr14891" -+ -+ # No indirect functions on non-GNU targets. -+ # The Visium and MSP set the ELF header's OSABI field to ELFOSABI_STANDALONE. -+ # The non-eabi ARM ports sets it to ELFOSABI_ARM. -+ # So for these targets we cannot include an IFUNC symbol type -+ # in the symbol type test. -+ # We also need to exclude targets that do not support unique objects. -+ if { [istarget "*-*-hpux*"] -+ || [istarget "arm*-*-*"] -+ || [istarget "mips*-*-*"] -+ || [istarget "msp*-*-*"] -+ || [istarget "visium-*-*"] -+ || ![supports_gnu_unique] -+ } then { -+ # hppa64 has a non-standard common directive -+ if { ![istarget "hppa64*-*-hpux*"] } then { -+ run_elf_list_test "type-noifunc" "" "" "-s" "| grep \"1 *\\\[FONTC\\\]\"" -+ } -+ } else { -+ if {! [istarget "sw_64*-*-*"] } then { -+ run_dump_test ifunc-1 -+ } -+ run_elf_list_test "type" "" "" "-s" "| grep \"1 *\\\[FIONTCU\\\]\"" -+ run_elf_list_test "type-2" "" "--warn" "-s" "| grep \"0 *\\\[FIONT\\\]\"" -+ } -+ -+ run_dump_test "section6" -+ run_dump_test "section7" -+ run_dump_test "section8" -+ run_dump_test "section9" -+ run_dump_test "section10" -+ run_dump_test "section11" -+ run_dump_test "section12a" -+ run_dump_test "section12b" -+ run_dump_test "section13" -+ run_dump_test "section14" -+ run_dump_test "section15" -+ run_dump_test "section16a" -+ run_dump_test "section16b" -+ run_dump_test "section17" -+ run_dump_test "section18" -+ run_dump_test "section19" -+ run_dump_test "section20" -+ run_dump_test "section21" -+ run_dump_test "section22" -+ run_dump_test "section23a" -+ run_dump_test "section23b" -+ run_dump_test "section24a" -+ run_dump_test "section24b" -+ run_dump_test "section25" -+ run_dump_test "section26" -+ run_dump_test "section27" -+ run_dump_test "section28" -+ run_dump_test "section29" -+ run_dump_test "sh-link-zero" -+ run_dump_test "dwarf2-1" $dump_opts -+ run_dump_test "dwarf2-2" $dump_opts -+ run_dump_test "dwarf2-3" $dump_opts -+ run_dump_test "dwarf2-4" $dump_opts -+ run_dump_test "dwarf2-5" $dump_opts -+ run_dump_test "dwarf2-6" $dump_opts -+ run_dump_test "dwarf2-7" $dump_opts -+ run_dump_test "dwarf2-8" $dump_opts -+ run_dump_test "dwarf2-9" $dump_opts -+ run_dump_test "dwarf2-10" $dump_opts -+ run_dump_test "dwarf2-11" $dump_opts -+ run_dump_test "dwarf2-12" $dump_opts -+ run_dump_test "dwarf2-13" $dump_opts -+ run_dump_test "dwarf2-14" $dump_opts -+ run_dump_test "dwarf2-15" $dump_opts -+ run_dump_test "dwarf2-16" $dump_opts -+ run_dump_test "dwarf2-17" $dump_opts -+ run_dump_test "dwarf2-18" $dump_opts -+ run_dump_test "dwarf2-19" $dump_opts -+ run_dump_test "dwarf2-20" $dump_opts -+ run_dump_test "dwarf2-21" $dump_opts -+ run_dump_test "dwarf-5-file0" $dump_opts -+ run_dump_test "dwarf-5-file0-2" $dump_opts -+ run_dump_test "dwarf-5-file0-3" $dump_opts -+ run_dump_test "dwarf-5-dir0" $dump_opts -+ run_dump_test "dwarf-5-loc0" $dump_opts -+ run_dump_test "dwarf-4-cu" $dump_opts -+ run_dump_test "dwarf-5-cu" $dump_opts -+ run_dump_test "dwarf-5-nop-for-line-table" $dump_opts -+ run_dump_test "pr25917" -+ run_dump_test "bss" -+ run_dump_test "bad-bss" -+ run_dump_test "bad-section-flag" -+ run_dump_test "bad-size" -+ run_dump_test "bad-group" -+ run_dump_test "pr27355" -+ -+ if { ![istarget "sw_64*-*-*"]} then { -+ run_dump_test "syms" -+ } -+ run_dump_test "startof" -+ -+ run_dump_test "missing-build-notes" -+ -+ run_dump_test "common1" -+ run_dump_test "common2" -+ -+ # hpux has a non-standard common directive. -+ if { ![istarget "*-*-hpux*"] } then { -+ run_dump_test "common3a" -+ run_dump_test "common3b" -+ run_dump_test "common4a" -+ run_dump_test "common4b" -+ } -+ -+ if { ![istarget "sw_64*-*-*"] && ![istarget "*-*-hpux*"]} then { -+ run_dump_test "common5a" -+ run_dump_test "common5b" -+ run_dump_test "common5c" -+ run_dump_test "common5d" -+ } -+ -+ run_dump_test "strtab" -+ -+ run_dump_test "bignums" -+ run_dump_test "section-symbol-redef" -+ run_dump_test "pr27228" -+} -diff --git a/gas/testsuite/gas/elf/elf.exp.2.37 b/gas/testsuite/gas/elf/elf.exp.2.37 -new file mode 100644 -index 00000000..516075f5 ---- /dev/null -+++ b/gas/testsuite/gas/elf/elf.exp.2.37 -@@ -0,0 +1,344 @@ -+# Copyright (C) 2012-2021 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 3 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. -+ -+# -+# elf tests -+# -+ -+proc run_elf_list_test { name suffix opts readelf_opts readelf_pipe } { -+ global READELF -+ global srcdir subdir -+ set testname "elf $name list" -+ set file $srcdir/$subdir/$name -+ gas_run ${name}.s "$opts -o dump.o" ">&dump.out" -+ if { ![string match "" $opts] -+ && [regexp_diff "dump.out" "${file}.l"] } then { -+ fail $testname -+ verbose "output is [file_contents "dump.out"]" 2 -+ return -+ } -+ send_log "$READELF $readelf_opts dump.o $readelf_pipe > dump.out\n" -+ set status [gas_host_run "$READELF $readelf_opts dump.o" ">readelf.out"] -+ if { [lindex $status 0] != 0 || ![string match "" [lindex $status 1]] } then { -+ send_log "[lindex $status 1]\n" -+ fail $testname -+ return -+ } -+ catch "exec cat readelf.out $readelf_pipe > dump.out\n" comp_output -+ if ![string match "" $comp_output] then { -+ send_log "$comp_output\n" -+ fail $testname -+ return -+ } -+ verbose_eval {[file_contents "dump.out"]} 3 -+ if { [regexp_diff "dump.out" "${file}.e${suffix}"] } then { -+ fail $testname -+ verbose "output is [file_contents "dump.out"]" 2 -+ return -+ } -+ pass $testname -+} -+ -+# We're testing bits in obj-elf -- don't run on anything else. -+if { [is_elf_format] } then { -+ if { [is_elf_unused_section_symbols ] } { -+ set target_machine -unused -+ } else { -+ set target_machine "" -+ } -+ set dump_opts "" -+ if {[istarget "arc*-*-*"]} { -+ set target_machine -arc -+ } -+ if {[istarget "arm*-*-*"]} { -+ set target_machine -arm -+ } -+ if {[istarget "avr*-*-*"]} { -+ set dump_opts {{as -mno-link-relax}} -+ } -+ if {[istarget "csky*-*-*"]} { -+ set target_machine -csky -+ } -+ if {[istarget "m32r*-*-*"]} then { -+ set target_machine -m32r -+ } -+ if {[istarget "mips*-*-*"]} then { -+ set target_machine -mips -+ } -+ if {[istarget "msp430-*-*"]} then { -+ set target_machine -msp430 -+ } -+ if {[istarget "pru-*-*"]} { -+ set dump_opts {{as -mno-link-relax}} -+ } -+ if {[istarget "riscv*-*-*"]} then { -+ set target_machine -riscv -+ set dump_opts {{as -mno-relax}} -+ } -+ if {[istarget "rl78-*-*"]} then { -+ set target_machine -rl78 -+ } -+ if {[istarget "rx-*-*"]} then { -+ set target_machine -rx -+ } -+ if {[istarget "score-*-*"]} then { -+ set target_machine -score -+ } -+ if {[istarget "tic6x-*-*"]} then { -+ set target_machine -tic6x -+ } -+ if {[istarget "v850*-*-*"]} then { -+ set target_machine -v850 -+ } -+ if {[istarget "xtensa*-*-*"]} then { -+ set target_machine -xtensa -+ set dump_opts {{as --no-link-relax}} -+ } -+ -+ # The MN10300 and Xtensa ports disable the assembler's call frame -+ # optimization because it interfers with link-time relaxation of -+ # function prologues. -+ if {![istarget "mn10300-*-*"] -+ && ![istarget "am3*-*-*"] -+ && ![istarget "xtensa*-*-*"] -+ && ![istarget "msp430*-*-*"] -+ && ![istarget "nds32*-*-*"] -+ && ![istarget "am3*-*-*"]} then { -+ run_dump_test "ehopt0" -+ } -+ switch -glob $target_triplet { -+ m68k-*-* - -+ m68[03]??-*-* { -+ run_dump_test "file" { { as "--defsym m68k=1" } } -+ } -+ mmix-*-* { -+ run_dump_test "file" { { as "--defsym mmix=1" } } -+ } -+ xtensa*-*-* { -+ run_dump_test "file" { { as "--rename-section file.s=file.c" } } -+ } -+ default { -+ run_dump_test "file" -+ } -+ } -+ run_dump_test "file-2" -+ setup_xfail "nds32*-*-*" -+ run_dump_test "group0a" -+ run_dump_test "group0b" -+ run_dump_test "group0c" -+ run_dump_test "group1a" -+ run_dump_test "group1b" -+ run_dump_test "group2" -+ run_dump_test "group3" -+ -+ run_dump_test "attach-1" -+ run_dump_test "attach-err" -+ -+ switch -glob $target_triplet { -+ hppa64*-*-hpux* { } -+ riscv*-*-* { } -+ default { -+ run_dump_test "groupautoa" -+ } -+ } -+ switch -glob $target_triplet { -+ hppa64*-*-hpux* { } -+ riscv*-*-* { } -+ xtensa*-*-* { } -+ default { -+ run_dump_test "groupautob" -+ } -+ } -+ switch -glob $target_triplet { -+ alpha*-*-* { } -+ am3*-*-* { } -+ *c54x*-*-* { } -+ cr16*-*-* { } -+ crx*-*-* { } -+ h8300-*-* { } -+ hppa*-*-* { } -+ iq2000*-*-* { } -+ mips*-*-* { } -+ mn10200-*-* { } -+ mn10300-*-* { } -+ msp43*-*-* { } -+ rl78-*-* { } -+ riscv*-*-* { } -+ rx-*-* { } -+ default { -+ # The next test can fail if the target does not convert fixups -+ # against ordinary symbols into relocations against section symbols. -+ # This is usually revealed by the error message: -+ # symbol `sym' required but not present -+ setup_xfail "m681*-*-*" "m68hc*-*-*" "xgate-*-*" "vax-*-*" "sw_64*-*-*" -+ run_dump_test redef -+ setup_xfail "sw_64*-*-*" -+ run_dump_test equ-reloc -+ } -+ } -+ run_dump_test "pseudo" -+ run_dump_test "section0" -+ run_dump_test "section1" -+ # The h8300 port issues a warning message for -+ # new sections created without atrributes. -+ if {! [istarget "h8300-*-*"]} then { -+ set as_flags "-al --generate-missing-build-notes=no" -+ switch -glob $target_triplet { -+ i*86-*-* - -+ x86_64-*-* { -+ set as_flags "$as_flags -mx86-used-note=no" -+ } -+ riscv*-*-* { -+ set as_flags "$as_flags -march-attr" -+ } -+ } -+ run_elf_list_test "section2" "$target_machine" "$as_flags" "-s" "" -+ } -+ run_dump_test "section3" -+ run_dump_test "section4" -+ if {! [istarget "h8300-*-*"] && ! [istarget "rx-*-*"]} then { -+ # The h8300 port issues a warning message for -+ # new sections created without atrributes. -+ # The RX port does not complain about changing the attributes of the -+ # .data and .bss sections since it does not use those names. -+ run_elf_list_test "section5" "" "-al -Z" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\"" -+ } -+ run_dump_test "struct" -+ if {! [istarget "alpha*-*-*"] && ! [istarget "sw_64*-*-*"]} then { -+ # The alpha port uses .set for state, e.g. nomacro. -+ run_dump_test "symtab" -+ } -+ run_dump_test "symver" -+ run_dump_test "pr21661" -+ run_dump_test "pr14891" -+ -+ # No indirect functions on non-GNU targets. -+ # The Visium and MSP set the ELF header's OSABI field to ELFOSABI_STANDALONE. -+ # The non-eabi ARM ports sets it to ELFOSABI_ARM. -+ # So for these targets we cannot include an IFUNC symbol type -+ # in the symbol type test. -+ # We also need to exclude targets that do not support unique objects. -+ if { [istarget "*-*-hpux*"] -+ || [istarget "arm*-*-*"] -+ || [istarget "mips*-*-*"] -+ || [istarget "msp*-*-*"] -+ || [istarget "visium-*-*"] -+ || ![supports_gnu_unique] -+ } then { -+ # hppa64 has a non-standard common directive -+ if { ![istarget "hppa64*-*-hpux*"] } then { -+ run_elf_list_test "type-noifunc" "" "" "-s" "| grep \"1 *\\\[FONTC\\\]\"" -+ } -+ } else { -+ if {! [istarget "sw_64*-*-*"] } then { -+ run_dump_test ifunc-1 -+ } -+ run_elf_list_test "type" "" "" "-s" "| grep \"1 *\\\[FIONTCU\\\]\"" -+ run_elf_list_test "type-2" "" "--warn" "-s" "| grep \"0 *\\\[FIONT\\\]\"" -+ } -+ -+ run_dump_test "section6" -+ run_dump_test "section7" -+ run_dump_test "section8" -+ run_dump_test "section9" -+ run_dump_test "section10" -+ run_dump_test "section11" -+ run_dump_test "section12a" -+ run_dump_test "section12b" -+ run_dump_test "section13" -+ run_dump_test "section14" -+ run_dump_test "section15" -+ run_dump_test "section16a" -+ run_dump_test "section16b" -+ run_dump_test "section17" -+ run_dump_test "section18" -+ run_dump_test "section19" -+ run_dump_test "section20" -+ run_dump_test "section21" -+ run_dump_test "section22" -+ run_dump_test "section23a" -+ run_dump_test "section23b" -+ run_dump_test "section24a" -+ run_dump_test "section24b" -+ run_dump_test "section25" -+ run_dump_test "section26" -+ run_dump_test "section27" -+ run_dump_test "section28" -+ run_dump_test "section29" -+ run_dump_test "sh-link-zero" -+ run_dump_test "dwarf2-1" $dump_opts -+ run_dump_test "dwarf2-2" $dump_opts -+ run_dump_test "dwarf2-3" $dump_opts -+ run_dump_test "dwarf2-4" $dump_opts -+ run_dump_test "dwarf2-5" $dump_opts -+ run_dump_test "dwarf2-6" $dump_opts -+ run_dump_test "dwarf2-7" $dump_opts -+ run_dump_test "dwarf2-8" $dump_opts -+ run_dump_test "dwarf2-9" $dump_opts -+ run_dump_test "dwarf2-10" $dump_opts -+ run_dump_test "dwarf2-11" $dump_opts -+ run_dump_test "dwarf2-12" $dump_opts -+ run_dump_test "dwarf2-13" $dump_opts -+ run_dump_test "dwarf2-14" $dump_opts -+ run_dump_test "dwarf2-15" $dump_opts -+ run_dump_test "dwarf2-16" $dump_opts -+ run_dump_test "dwarf2-17" $dump_opts -+ run_dump_test "dwarf2-18" $dump_opts -+ run_dump_test "dwarf2-19" $dump_opts -+ run_dump_test "dwarf2-20" $dump_opts -+ run_dump_test "dwarf-5-file0" $dump_opts -+ run_dump_test "dwarf-4-cu" $dump_opts -+ run_dump_test "dwarf-5-cu" $dump_opts -+ run_dump_test "dwarf-5-nop-for-line-table" $dump_opts -+ run_dump_test "pr25917" -+ run_dump_test "bss" -+ run_dump_test "bad-bss" -+ run_dump_test "bad-section-flag" -+ run_dump_test "bad-size" -+ run_dump_test "bad-group" -+ run_dump_test "pr27355" -+ -+ if { ![istarget "sw_64*-*-*"]} then { -+ run_dump_test "syms" -+ } -+ run_dump_test "startof" -+ -+ run_dump_test "missing-build-notes" -+ -+ run_dump_test "common1" -+ run_dump_test "common2" -+ -+ # hpux has a non-standard common directive. -+ if { ![istarget "*-*-hpux*"] } then { -+ run_dump_test "common3a" -+ run_dump_test "common3b" -+ run_dump_test "common4a" -+ run_dump_test "common4b" -+ } -+ -+ if { ![istarget "sw_64*-*-*"] && ![istarget "*-*-hpux*"]} then { -+ run_dump_test "common5a" -+ run_dump_test "common5b" -+ run_dump_test "common5c" -+ run_dump_test "common5d" -+ } -+ -+ run_dump_test "strtab" -+ -+ run_dump_test "bignums" -+ run_dump_test "section-symbol-redef" -+ run_dump_test "pr27228" -+} -diff --git a/gas/testsuite/gas/elf/elf.exp.ok b/gas/testsuite/gas/elf/elf.exp.ok -new file mode 100644 -index 00000000..4af4899b ---- /dev/null -+++ b/gas/testsuite/gas/elf/elf.exp.ok -@@ -0,0 +1,350 @@ -+# Copyright (C) 2012-2021 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 3 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. -+ -+# -+# elf tests -+# -+ -+proc run_elf_list_test { name suffix opts readelf_opts readelf_pipe } { -+ global READELF -+ global srcdir subdir -+ set testname "elf $name list" -+ set file $srcdir/$subdir/$name -+ gas_run ${name}.s "$opts -o dump.o" ">&dump.out" -+ if { ![string match "" $opts] -+ && [regexp_diff "dump.out" "${file}.l"] } then { -+ fail $testname -+ verbose "output is [file_contents "dump.out"]" 2 -+ return -+ } -+ send_log "$READELF $readelf_opts dump.o $readelf_pipe > dump.out\n" -+ set status [gas_host_run "$READELF $readelf_opts dump.o" ">readelf.out"] -+ if { [lindex $status 0] != 0 || ![string match "" [lindex $status 1]] } then { -+ send_log "[lindex $status 1]\n" -+ fail $testname -+ return -+ } -+ catch "exec cat readelf.out $readelf_pipe > dump.out\n" comp_output -+ if ![string match "" $comp_output] then { -+ send_log "$comp_output\n" -+ fail $testname -+ return -+ } -+ verbose_eval {[file_contents "dump.out"]} 3 -+ if { [regexp_diff "dump.out" "${file}.e${suffix}"] } then { -+ fail $testname -+ verbose "output is [file_contents "dump.out"]" 2 -+ return -+ } -+ pass $testname -+} -+ -+# We're testing bits in obj-elf -- don't run on anything else. -+if { [is_elf_format] } then { -+ if { [is_elf_unused_section_symbols ] } { -+ set target_machine -unused -+ } else { -+ set target_machine "" -+ } -+ set dump_opts "" -+ if {[istarget "arc*-*-*"]} { -+ set target_machine -arc -+ } -+ if {[istarget "arm*-*-*"]} { -+ set target_machine -arm -+ } -+ if {[istarget "avr*-*-*"]} { -+ set dump_opts {{as -mno-link-relax}} -+ } -+ if {[istarget "csky*-*-*"]} { -+ set target_machine -csky -+ } -+ if {[istarget "m32r*-*-*"]} then { -+ set target_machine -m32r -+ } -+ if {[istarget "mips*-*-*"]} then { -+ set target_machine -mips -+ } -+ if {[istarget "msp430-*-*"]} then { -+ set target_machine -msp430 -+ } -+ if {[istarget "pru-*-*"]} { -+ set dump_opts {{as -mno-link-relax}} -+ } -+ if {[istarget "riscv*-*-*"]} then { -+ set target_machine -riscv -+ set dump_opts {{as -mno-relax}} -+ } -+ if {[istarget "rl78-*-*"]} then { -+ set target_machine -rl78 -+ } -+ if {[istarget "rx-*-*"]} then { -+ set target_machine -rx -+ } -+ if {[istarget "score-*-*"]} then { -+ set target_machine -score -+ } -+ if {[istarget "tic6x-*-*"]} then { -+ set target_machine -tic6x -+ } -+ if {[istarget "v850*-*-*"]} then { -+ set target_machine -v850 -+ } -+ if {[istarget "xtensa*-*-*"]} then { -+ set target_machine -xtensa -+ set dump_opts {{as --no-link-relax}} -+ } -+ -+ # The MN10300 and Xtensa ports disable the assembler's call frame -+ # optimization because it interfers with link-time relaxation of -+ # function prologues. -+ if {![istarget "mn10300-*-*"] -+ && ![istarget "am3*-*-*"] -+ && ![istarget "xtensa*-*-*"] -+ && ![istarget "msp430*-*-*"] -+ && ![istarget "nds32*-*-*"] -+ && ![istarget "am3*-*-*"]} then { -+ run_dump_test "ehopt0" -+ } -+ switch -glob $target_triplet { -+ m68k-*-* - -+ m68[03]??-*-* { -+ run_dump_test "file" { { as "--defsym m68k=1" } } -+ } -+ mmix-*-* { -+ run_dump_test "file" { { as "--defsym mmix=1" } } -+ } -+ xtensa*-*-* { -+ run_dump_test "file" { { as "--rename-section file.s=file.c" } } -+ } -+ default { -+ run_dump_test "file" -+ } -+ } -+ run_dump_test "file-2" -+ setup_xfail "nds32*-*-*" -+ run_dump_test "group0a" -+ run_dump_test "group0b" -+ run_dump_test "group0c" -+ run_dump_test "group1a" -+ run_dump_test "group1b" -+ run_dump_test "group2" -+ run_dump_test "group3" -+ -+ run_dump_test "attach-1" -+ run_dump_test "attach-err" -+ -+ switch -glob $target_triplet { -+ hppa64*-*-hpux* { } -+ riscv*-*-* { } -+ default { -+ run_dump_test "groupautoa" -+ } -+ } -+ switch -glob $target_triplet { -+ hppa64*-*-hpux* { } -+ riscv*-*-* { } -+ xtensa*-*-* { } -+ default { -+ run_dump_test "groupautob" -+ } -+ } -+ switch -glob $target_triplet { -+ alpha*-*-* { } -+ am3*-*-* { } -+ *c54x*-*-* { } -+ cr16*-*-* { } -+ crx*-*-* { } -+ h8300-*-* { } -+ hppa*-*-* { } -+ iq2000*-*-* { } -+ mips*-*-* { } -+ mn10200-*-* { } -+ mn10300-*-* { } -+ msp43*-*-* { } -+ rl78-*-* { } -+ riscv*-*-* { } -+ rx-*-* { } -+ loongarch*-*-* { } -+ default { -+ # The next test can fail if the target does not convert fixups -+ # against ordinary symbols into relocations against section symbols. -+ # This is usually revealed by the error message: -+ # symbol `sym' required but not present -+ setup_xfail "m681*-*-*" "m68hc*-*-*" "xgate-*-*" "vax-*-*" "sw_64*-*-*" -+ run_dump_test redef -+ setup_xfail "sw_64*-*-*" -+ run_dump_test equ-reloc -+ } -+ } -+ run_dump_test "pseudo" -+ run_dump_test "section0" -+ run_dump_test "section1" -+ # The h8300 port issues a warning message for -+ # new sections created without atrributes. -+ if {! [istarget "h8300-*-*"]} then { -+ set as_flags "-al --generate-missing-build-notes=no" -+ switch -glob $target_triplet { -+ i*86-*-* - -+ x86_64-*-* { -+ set as_flags "$as_flags -mx86-used-note=no" -+ } -+ riscv*-*-* { -+ set as_flags "$as_flags -march-attr" -+ } -+ } -+ run_elf_list_test "section2" "$target_machine" "$as_flags" "-s" "" -+ } -+ run_dump_test "section3" -+ run_dump_test "section4" -+ if {! [istarget "h8300-*-*"] && ! [istarget "rx-*-*"]} then { -+ # The h8300 port issues a warning message for -+ # new sections created without atrributes. -+ # The RX port does not complain about changing the attributes of the -+ # .data and .bss sections since it does not use those names. -+ run_elf_list_test "section5" "" "-al -Z" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\"" -+ } -+ run_dump_test "struct" -+ if {! [istarget "alpha*-*-*"] && ! [istarget "sw_64*-*-*"]} then { -+ # The alpha port uses .set for state, e.g. nomacro. -+ run_dump_test "symtab" -+ } -+ run_dump_test "symver" -+ run_dump_test "pr21661" -+ run_dump_test "pr14891" -+ -+ # No indirect functions on non-GNU targets. -+ # The Visium and MSP set the ELF header's OSABI field to ELFOSABI_STANDALONE. -+ # The non-eabi ARM ports sets it to ELFOSABI_ARM. -+ # So for these targets we cannot include an IFUNC symbol type -+ # in the symbol type test. -+ # We also need to exclude targets that do not support unique objects. -+ if { [istarget "*-*-hpux*"] -+ || [istarget "arm*-*-*"] -+ || [istarget "mips*-*-*"] -+ || [istarget "msp*-*-*"] -+ || [istarget "visium-*-*"] -+ || ![supports_gnu_unique] -+ } then { -+ # hppa64 has a non-standard common directive -+ if { ![istarget "hppa64*-*-hpux*"] } then { -+ run_elf_list_test "type-noifunc" "" "" "-s" "| grep \"1 *\\\[FONTC\\\]\"" -+ } -+ } else { -+ if {! [istarget "sw_64*-*-*"] } then { -+ run_dump_test ifunc-1 -+ } -+ run_elf_list_test "type" "" "" "-s" "| grep \"1 *\\\[FIONTCU\\\]\"" -+ run_elf_list_test "type-2" "" "--warn" "-s" "| grep \"0 *\\\[FIONT\\\]\"" -+ } -+ -+ run_dump_test "section6" -+ run_dump_test "section7" -+ run_dump_test "section8" -+ run_dump_test "section9" -+ run_dump_test "section10" -+ run_dump_test "section11" -+ run_dump_test "section12a" -+ run_dump_test "section12b" -+ run_dump_test "section13" -+ run_dump_test "section14" -+ run_dump_test "section15" -+ run_dump_test "section16a" -+ run_dump_test "section16b" -+ run_dump_test "section17" -+ run_dump_test "section18" -+ run_dump_test "section19" -+ run_dump_test "section20" -+ run_dump_test "section21" -+ run_dump_test "section22" -+ run_dump_test "section23a" -+ run_dump_test "section23b" -+ run_dump_test "section24a" -+ run_dump_test "section24b" -+ run_dump_test "section25" -+ run_dump_test "section26" -+ run_dump_test "section27" -+ run_dump_test "section28" -+ run_dump_test "section29" -+ run_dump_test "sh-link-zero" -+ run_dump_test "dwarf2-1" $dump_opts -+ run_dump_test "dwarf2-2" $dump_opts -+ run_dump_test "dwarf2-3" $dump_opts -+ run_dump_test "dwarf2-4" $dump_opts -+ run_dump_test "dwarf2-5" $dump_opts -+ run_dump_test "dwarf2-6" $dump_opts -+ run_dump_test "dwarf2-7" $dump_opts -+ run_dump_test "dwarf2-8" $dump_opts -+ run_dump_test "dwarf2-9" $dump_opts -+ run_dump_test "dwarf2-10" $dump_opts -+ run_dump_test "dwarf2-11" $dump_opts -+ run_dump_test "dwarf2-12" $dump_opts -+ run_dump_test "dwarf2-13" $dump_opts -+ run_dump_test "dwarf2-14" $dump_opts -+ run_dump_test "dwarf2-15" $dump_opts -+ run_dump_test "dwarf2-16" $dump_opts -+ run_dump_test "dwarf2-17" $dump_opts -+ run_dump_test "dwarf2-18" $dump_opts -+ run_dump_test "dwarf2-19" $dump_opts -+ run_dump_test "dwarf2-20" $dump_opts -+ run_dump_test "dwarf2-21" $dump_opts -+ run_dump_test "dwarf-5-file0" $dump_opts -+ run_dump_test "dwarf-5-file0-2" $dump_opts -+ run_dump_test "dwarf-5-file0-3" $dump_opts -+ run_dump_test "dwarf-5-dir0" $dump_opts -+ run_dump_test "dwarf-5-loc0" $dump_opts -+ run_dump_test "dwarf-4-cu" $dump_opts -+ run_dump_test "dwarf-5-cu" $dump_opts -+ run_dump_test "dwarf-5-nop-for-line-table" $dump_opts -+ run_dump_test "pr25917" -+ run_dump_test "bss" -+ run_dump_test "bad-bss" -+ run_dump_test "bad-section-flag" -+ run_dump_test "bad-size" -+ run_dump_test "bad-group" -+ run_dump_test "pr27355" -+ -+ if { ![istarget "sw_64*-*-*"]} then { -+ run_dump_test "syms" -+ } -+ run_dump_test "startof" -+ -+ run_dump_test "missing-build-notes" -+ -+ run_dump_test "common1" -+ run_dump_test "common2" -+ -+ # hpux has a non-standard common directive. -+ if { ![istarget "*-*-hpux*"] } then { -+ run_dump_test "common3a" -+ run_dump_test "common3b" -+ run_dump_test "common4a" -+ run_dump_test "common4b" -+ } -+ -+ if { ![istarget "sw_64*-*-*"] && ![istarget "*-*-hpux*"]} then { -+ run_dump_test "common5a" -+ run_dump_test "common5b" -+ run_dump_test "common5c" -+ run_dump_test "common5d" -+ } -+ -+ run_dump_test "strtab" -+ -+ run_dump_test "bignums" -+ run_dump_test "section-symbol-redef" -+ run_dump_test "pr27228" -+} -diff --git a/gold/sw_64.cc b/gold/sw_64.cc -new file mode 100644 -index 00000000..5dea6061 ---- /dev/null -+++ b/gold/sw_64.cc -@@ -0,0 +1,1787 @@ -+// sw_64.cc -- sw_64 target support for gold. -+ -+// Copyright (C) 2021-2021 LiNaKeSi Ltd. -+// Written by Kid Lee . -+ -+#include "gold.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "elfcpp.h" -+#include "gc.h" -+#include "object.h" -+#include "output.h" -+#include "sw_64.h" -+#include "target.h" -+#include "target-reloc.h" -+#include "target-select.h" -+ -+namespace -+{ -+using namespace gold; -+ -+template -+class Elf{ -+ public: -+ static constexpr int size = _size; -+ static constexpr bool big_endian = _big_endian; -+}; -+ -+typedef Elf<64, false> Elf64le; -+ -+const char* get_relocation_name(unsigned int r_type){ -+ switch(r_type){ -+# define ELF_RELOC(name, value) \ -+ case elfcpp::name: return #name; \ -+ /* end of ELF_RELOC. */ -+# include "sw_64.def.h" -+# undef ELF_RELOC -+ default: { -+ static __thread char str[32]; -+ str[0] = '\0'; -+ snprintf(str, sizeof(str), "Unknown(%d)", r_type); -+ return str; -+ }break; -+ } -+} -+ -+// set_union(A, B) - Compute A := A u B, return whether A changed. -+template -+bool set_union(S1Ty &S1, const S2Ty &S2) { -+ bool Changed = false; -+ -+ for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); -+ SI != SE; ++SI) -+ if (S1.insert(*SI).second) -+ Changed = true; -+ -+ return Changed; -+} -+ -+template -+struct X{ -+ using ClassifyReloc = gold::Default_classify_reloc; -+ using EmitRelocsStrategy = gold::Default_emit_relocs_strategy; -+ using SizedRel = Sized_relobj_file; -+ using Address = typename elfcpp::Elf_types::Elf_Addr; -+ using RelInfo = Relocate_info; -+ using Offset = typename elfcpp::Elf_types::Elf_Off; -+ using Sym = elfcpp::Sym; -+ using Rela = elfcpp::Rela; -+ using Addend = typename elfcpp::Elf_types::Elf_Addr; -+ using RelType = elfcpp::SwRelType; -+ using LocalIndex = unsigned int; -+ using GSymbol = const Symbol*; -+ using LSymbol = std::pair; -+ using Shndx = unsigned int; -+ -+ class Target_sw_64; -+ class Target_selector_sw_64; -+ class Output_data_got_sw_64; -+ class Output_data_plt_sw_64; -+ class Output_data_reloc_sw_64; -+ -+ struct USymbol{ -+ union{ -+ GSymbol gsym_; -+ SizedRel* object_; -+ }; -+ LocalIndex index_; -+ -+ USymbol(GSymbol gsym) -+ : gsym_(gsym) -+ , index_(GLOBAL_INDEX) -+ {} -+ -+ USymbol(LSymbol lsym) -+ : object_(std::get<0>(lsym)) -+ , index_(std::get<1>(lsym)) -+ {} -+ -+ USymbol(GSymbol gsym, SizedRel* object, LocalIndex index){ -+ if(nullptr != gsym){ -+ gsym_ = gsym; -+ index_ = GLOBAL_INDEX; -+ }else{ -+ object_ = object; -+ index_ = index; -+ } -+ } -+ -+ bool is_local()const{ -+ return GLOBAL_INDEX != index_; -+ } -+ -+ const GSymbol& as_global()const{ -+ return gsym_; -+ } -+ -+ const LSymbol& as_local()const{ -+ static_assert(sizeof(LSymbol) == sizeof(*this)); -+ return *reinterpret_cast(this); -+ } -+ -+ bool operator<(const USymbol &rhs)const{ -+ return object_ < rhs.object_ || (object_ == rhs.object_ && index_ < rhs.index_); -+ } -+ -+ static constexpr LocalIndex GLOBAL_INDEX = -1U; -+ }; -+ -+ static bool is_static_link_time_constant(const GSymbol gsym){ -+ return gsym->final_value_is_known(); -+ } -+ -+ static bool is_static_link_time_constant(const LSymbol &){ -+ return !parameters->options().output_is_position_independent(); -+ } -+ -+ static bool is_preemptible(const GSymbol gsym){ -+ if(parameters->options().is_static())return false; -+ return gsym->is_from_dynobj() || gsym->is_undefined()|| gsym->is_preemptible(); -+ } -+ -+ static bool is_preemptible(const LSymbol &){ -+ return false; -+ } -+ -+ static bool is_tls(const GSymbol &gsym){ -+ return elfcpp::STT_TLS == gsym->type(); -+ } -+ -+ static bool is_tls(const LSymbol &lsym){ -+ return std::get<0>(lsym)->local_is_tls(std::get<1>(lsym)); -+ } -+ -+ static bool is_undef(const GSymbol &gsym){ -+ return nullptr == gsym; -+ } -+ -+ static bool is_undef(const LSymbol &lsym){ -+ return 0 == std::get<1>(lsym); -+ } -+ -+ static bool is_func(const GSymbol &gsym){ -+ return gsym->is_func(); -+ } -+ -+ static bool is_func(const LSymbol &lsym){ -+ // FIXME: This implement is totally wrong, but the current only user -+ // do not care about local symbol. -+ return false; -+ } -+ -+ class ScanRelocatableRelocs: public gold::Default_scan_relocatable_relocs{ -+ public: -+ // Return the strategy to use for a local symbol which is a section -+ // symbol, given the relocation type. -+ inline Relocatable_relocs::Reloc_strategy -+ local_section_strategy(unsigned int r_type, Relobj*) -+ { -+ gold_assert(ClassifyReloc::sh_type == elfcpp::SHT_RELA); -+ switch(r_type){ -+ case elfcpp::R_SW_64_GPDISP: -+ case elfcpp::R_SW_64_LITUSE: -+ return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA_0; -+ default: -+ break; -+ } -+ return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; -+ } -+ }; -+}; -+ -+template -+class X::Target_sw_64: public Sized_target -+{ -+ public: -+ using super = Sized_target; -+ using Reloc_section = Output_data_reloc; -+ static constexpr Offset INVALID_OFFSET = static_cast(0) - 1; -+ static constexpr auto ORDER_GOT = ORDER_LARGE_DATA; -+ // Get access to `Relocate::do_gpdisp` class. -+ friend class Output_data_plt_sw_64; -+ -+ Target_sw_64(): super(&sw64_info) -+ {} -+ -+ void -+ gc_process_relocs(Symbol_table* symtab, -+ Layout *layout, -+ SizedRel *object, -+ unsigned int data_shndx, -+ unsigned int sh_type, -+ const unsigned char* prelocs, -+ size_t reloc_count, -+ Output_section* output_section, -+ bool needs_special_offset_handling, -+ size_t local_symbol_count, -+ const unsigned char* plocal_symbols -+ )override; -+ -+ void -+ scan_relocs(Symbol_table* symtab, -+ Layout *layout, -+ SizedRel *object, -+ unsigned int data_shndx, -+ unsigned int sh_type, -+ const unsigned char* prelocs, -+ size_t reloc_count, -+ Output_section* output_section, -+ bool needs_special_offset_handling, -+ size_t local_symbol_count, -+ const unsigned char* plocal_symbols -+ )override; -+ -+ void -+ relocate_section(const RelInfo *, -+ unsigned int sh_type, -+ const unsigned char* prelocs, -+ size_t reloc_count, -+ Output_section* output_section, -+ bool needs_special_offset_handling, -+ unsigned char* view, -+ Address view_address, -+ section_size_type view_size, -+ const Reloc_symbol_changes* -+ )override; -+ -+ void -+ scan_relocatable_relocs(Symbol_table* symtab, -+ Layout *layout, -+ SizedRel *object, -+ unsigned int data_shndx, -+ unsigned int sh_type, -+ const unsigned char* prelocs, -+ size_t reloc_count, -+ Output_section* output_section, -+ bool needs_special_offset_handling, -+ size_t local_symbol_count, -+ const unsigned char* plocal_symbols, -+ Relocatable_relocs* -+ )override; -+ -+ void -+ emit_relocs_scan( -+ Symbol_table* symtab -+ , Layout* layout -+ , SizedRel *object -+ , unsigned int data_shndx -+ , unsigned int sh_type -+ , const unsigned char *prelocs -+ , size_t reloc_count -+ , Output_section *output_section -+ , bool needs_special_offset_handling -+ , size_t local_symbol_count -+ , const unsigned char *plocal_syms -+ , Relocatable_relocs *rr -+ )override; -+ -+ void -+ relocate_relocs(const RelInfo *relinfo, -+ unsigned int sh_type, -+ const unsigned char* prelocs, -+ size_t reloc_count, -+ Output_section* output_section, -+ Offset offset_in_output_section, -+ unsigned char* view, -+ Address view_address, -+ section_size_type view_size, -+ unsigned char* reloc_view, -+ section_size_type reloc_view_size -+ )override; -+ -+ unsigned int -+ got_entry_count() const override{ -+ gold_assert(nullptr != got_); -+ return got_->entries_num(); -+ } -+ -+ unsigned int -+ plt_entry_count() const override{ -+ gold_assert(nullptr != plt_); -+ return plt_->entries_num(); -+ } -+ -+ unsigned int -+ first_plt_entry_offset() const override{ -+ gold_assert(nullptr != plt_); -+ return plt_->first_entry_offset(); -+ } -+ -+ unsigned int -+ plt_entry_size() const override{ -+ gold_assert(nullptr != plt_); -+ return plt_->entry_size(); -+ } -+ -+ void -+ do_new_output_section(Output_section *os) const override{ -+ gold_assert(nullptr != os); -+ if(0 != strcmp(".sdata", os->name()))return; -+ static_assert(ORDER_GOT < ORDER_SMALL_DATA); -+ os->set_order(ORDER_SMALL_DATA); -+ } -+ -+ // Get the GOT section. -+ Output_data_got_sw_64* -+ got_section()const{ return this->got_; } -+ -+ // Get the dynamic reloc section. -+ Output_data_reloc_sw_64* -+ rela_dyn_section()const{ return rela_dyn_; } -+ -+ Reloc_section* -+ rela_plt_section()const{ return rela_plt_; }; -+ -+ Output_data_plt_sw_64* -+ plt_section()const{ return this->plt_; } -+ -+ void add_jsr_user(const SizedRel *f, unsigned int shndx, unsigned int relnum){ -+ jsrs_.insert({f, shndx, relnum}); -+ } -+ -+ bool is_jsr_user(const SizedRel *f, unsigned int shndx, unsigned int relnum){ -+ return std::end(jsrs_) != jsrs_.find({f, shndx, relnum}); -+ } -+ -+ Offset tls_offset()const{ return tls_offset_; } -+ -+ protected: -+ virtual void -+ do_select_as_default_target(); -+ -+ virtual void -+ do_finalize_sections(Layout*, const Input_objects*, Symbol_table*); -+ -+ private: -+ class Scan{ -+ public: -+ void -+ local( -+ Symbol_table * -+ , Layout * -+ , Target_sw_64* target -+ , SizedRel *object -+ , unsigned int data_shndx -+ , Output_section* output_section -+ , const Rela &reloc -+ , unsigned int r_type -+ , const Sym &sym -+ , bool is_discarded -+ ){ -+ ++next_; -+ if(is_discarded)return; -+ -+#ifdef GOLD_EH_FRAME_OPTIMIZATION_BUG -+ if(elfcpp::R_SW_64_GPRELHIGH == r_type -+ && object->is_output_section_offset_invalid(sym.get_st_shndx()) -+ && elfcpp::STT_SECTION == sym.get_st_type() -+ && 0 == reloc.get_r_addend() -+ && ".eh_frame" == object->section_name(sym.get_st_shndx()) -+ ){ -+ // Make the offset valid forcibly, so this symbol will have the -+ // correct final value. -+ object->set_section_offset(sym.get_st_shndx(), 0); -+ } -+#endif -+ -+ auto r_sym = elfcpp::elf_r_sym(reloc.get_r_info()); -+ static constexpr std::bitset<64> REL_TLS( -+ 1ULL << elfcpp::R_SW_64_GOTTPREL -+ ); -+ if(REL_TLS[r_type]){ -+ // Normally the same is done in `count_local_symbols`, just after -+ // `Target::finalize_sections`. But we need the TLS information in -+ // the `do_finalize_sections` function, apparently the normal situation -+ // is a little bit too late for us, so hack it here. -+ auto lv = const_cast *>(object->local_symbol(r_sym)); -+ if(elfcpp::STT_TLS == sym.get_st_type())lv->set_is_tls_symbol(); -+ } -+ -+ return scan( -+ target -+ , object -+ , data_shndx -+ , output_section -+ , reloc -+ , r_type -+ , std::move(std::make_pair(object, r_sym)) -+ ); -+ } -+ -+ void -+ global( -+ Symbol_table * -+ , Layout * -+ , Target_sw_64 *target -+ , SizedRel *object -+ , unsigned int data_shndx -+ , Output_section* output_section -+ , const Rela &reloc -+ , unsigned int r_type -+ , Symbol *gsym -+ ){ -+ ++next_; -+ return scan( -+ target -+ , object -+ , data_shndx -+ , output_section -+ , reloc -+ , r_type -+ , std::move(gsym) -+ ); -+ } -+ -+ inline bool -+ local_reloc_may_be_function_pointer( -+ Symbol_table * -+ , Layout * -+ , Target_sw_64 * -+ , SizedRel * -+ , unsigned int -+ , Output_section* -+ , const Rela & -+ , unsigned int r_type -+ , const Sym &); -+ -+ inline bool -+ global_reloc_may_be_function_pointer( -+ Symbol_table * -+ , Layout * -+ , Target_sw_64 * -+ , SizedRel * -+ , unsigned int -+ , Output_section* -+ , const Rela & -+ , unsigned int r_type -+ , Symbol* gsym); -+ -+ template -+ inline void -+ scan( -+ Target_sw_64 * -+ , SizedRel * -+ , unsigned int data_shndx -+ , Output_section* output_section -+ , const Rela & -+ , unsigned int r_type -+ , const Symbol_type &&sym -+ ); -+ -+ private: -+ size_t next_ = 0; -+ -+ static constexpr int32_t LITUSE_JSR = 3; -+ }; -+ -+ class Relocate{ -+ public: -+ using Bit32 = typename elfcpp::Swap<32, E::big_endian>; -+ using Bit16 = typename elfcpp::Swap<16, E::big_endian>; -+ using Bit32_v = typename Bit32::Valtype; -+ using Bit16_v = typename Bit16::Valtype; -+ using Inst = Bit32; -+ using Inst_v = typename Inst::Valtype; -+ using Rf = Relocate_functions; -+ -+ Relocate() -+ {} -+ -+ inline bool -+ relocate( -+ const RelInfo * -+ , unsigned int -+ , Target_sw_64 * -+ , Output_section * -+ , size_t relnum -+ , const unsigned char* -+ , const Sized_symbol* -+ , const Symbol_value* -+ , unsigned char* -+ , Address -+ , section_size_type); -+ -+ static void do_gpdisp( -+ unsigned char *view_hi -+ , unsigned char *view_lo -+ , uint64_t disp -+ ){ -+ auto i_hi = Inst::readval(view_hi); -+ auto i_lo = Inst::readval(view_lo); -+ // TODO: check the instructions. -+ uint64_t addend; -+ addend = ((i_hi & 0xffff) << 16) | (i_lo & 0xffff); -+ addend = (addend ^ 0x80008000) - 0x80008000; -+ disp += addend; -+ -+ if(static_cast(0x7fff8000) <= static_cast(disp) -+ || static_cast(disp) < -static_cast(0x7fff8000) -+ ){ -+ // TODO: overflow. -+ } -+ -+ i_hi = bit_select32( i_hi , high(disp) , 0xffff); -+ i_lo = bit_select32( i_lo , disp & 0xffff , 0xffff); -+ Inst::writeval(view_hi, i_hi); -+ Inst::writeval(view_lo, i_lo); -+ } -+ -+ private: -+ static inline uint32_t bit_select32(uint32_t a, uint32_t b, uint32_t mask){ -+ return Bits<32>::bit_select32(a, b, mask); -+ } -+ -+ static inline uint32_t high(uint32_t value){ -+ return (value >> 16) + (0 != (value & 0x8000)); -+ } -+ -+ static constexpr uintptr_t RA_SHIFT = 21; -+ static constexpr uintptr_t RB_SHIFT = 16; -+ static constexpr uintptr_t RC_MASK = 31; -+ static constexpr uintptr_t RA_MASK = RC_MASK << RA_SHIFT; -+ static constexpr uintptr_t RB_MASK = RC_MASK << RB_SHIFT; -+ -+ Offset literal_got_offset = INVALID_OFFSET; -+ }; -+ -+ // Track the relocs being scanned. -+ // This is going to work is base on the fact the scanning can **NOT** be paralleled. -+ const unsigned char *prelocs_; -+ // Track the total number of relocs being scanned. -+ size_t reloc_count_; -+ std::set> jsrs_; -+ -+ Output_data_got_sw_64 *got_ = nullptr; -+ Output_data_reloc_sw_64* rela_dyn_ = nullptr; -+ Reloc_section* rela_plt_ = nullptr; -+ Output_data_plt_sw_64* plt_ = nullptr; -+ Offset tls_offset_ = 0; -+ -+ static Target::Target_info sw64_info; -+ static constexpr uintptr_t TCB_SIZE = 16; -+}; -+ -+template -+class X::Output_data_got_sw_64: public Output_data_got_base{ -+ public: -+ static constexpr size_t ENTRY_SIZE = E::size / 8; -+ using Index = size_t; -+ using Valtype = Address; -+ -+ Output_data_got_sw_64() -+ : Output_data_got_base(ENTRY_SIZE) -+ { -+ } -+ -+ // Return gp value for particular input file. -+ int64_t gp_offset(const SizedRel *f = nullptr)const{ -+ int64_t offset = GP_OFFSET; -+ if(has_got_index(f)){ -+ offset += gots_[got_index(f)].start_index * ENTRY_SIZE; -+ } -+ return offset; -+ } -+ -+ void add_entry( -+ SizedRel *f -+ , const LSymbol &&lsym -+ , int64_t addend -+ , bool -+ ){ -+ auto &got = file_got(f); -+ got.locals.insert({{std::move(lsym), addend}, 0}); -+ } -+ -+ void add_entry( -+ SizedRel *f -+ , const GSymbol sym -+ , int64_t addend -+ , bool is_plt -+ ){ -+ auto &got = file_got(f); -+ auto &entries = is_plt && sym->in_dyn() ? got.plts : got.globals; -+ entries.insert({{sym, addend}, 0}); -+ } -+ -+ int64_t sym_entry_offset( -+ SizedRel *f -+ , const Symbol *sym -+ , LocalIndex index -+ , int64_t addend -+ , bool is_plt -+ ){ -+ auto const &got = file_got(reinterpret_cast(f)); -+ if(nullptr == sym){ -+ return got_offset(got.locals, {{f, index}, addend}); -+ } -+ auto &entries = is_plt && sym->in_dyn() ? got.plts : got.globals; -+ return got_offset(entries, {sym, addend}); -+ } -+ -+ template -+ void add_tls_entry( -+ SizedRel *f -+ , const ST &&sym -+ ){ -+ file_got(f).tlss.insert({{sym}, 0}); -+ } -+ -+ int64_t sym_tls_offset( -+ SizedRel *f -+ , const USymbol &sym -+ ){ -+ auto const &got = file_got(reinterpret_cast(f)); -+ return got_offset(got.tlss, sym); -+ } -+ -+ void add_tls_index(SizedRel *f){ -+ file_got(f).tlss.insert({{{f, 0}}, 0}); -+ } -+ -+ void build(Target_sw_64 *target){ -+ for(auto i = std::begin(gots_); i < std::end(gots_); ++i){ -+ if(nullptr == i->file)continue; -+ for(auto j = std::next(i); j < std::end(gots_); ++j){ -+ if(nullptr == j->file)continue; -+ merge_gots(*i, *j); -+ if(MAX_GOTS <= i->entries_num())break; -+ } -+ } -+ -+ size_t index = 0; -+ auto rela_dyn = target->rela_dyn_section(); -+ auto rela_plt = target->rela_plt_section(); -+ auto plt = target->plt_section(); -+ auto is_pic = parameters->options().output_is_position_independent(); -+ auto shared = parameters->options().shared(); -+ for(auto &got: gots_){ -+ if(nullptr == got.file)continue; -+ got.start_index = index; -+ -+ for(auto &p: got.globals){ -+ p.second = index++; -+ -+ auto sym = const_cast(p.first.first); -+ auto addend = p.first.second; -+ int64_t offset = p.second * ENTRY_SIZE; -+ -+ relocations_.push_back({p.second, sym, addend, is_tls(sym)}); -+ -+ if(is_preemptible(sym) -+ || (shared && sym->is_defined() && sym->binding() == elfcpp::STB_WEAK)){ -+ rela_dyn->add_entry(is_tls(sym) ? elfcpp::R_SW_64_TPREL64 : elfcpp::R_SW_64_GLOB_DAT, this, offset, sym, addend); -+ }else if(is_pic && !is_tls(sym)){ -+ rela_dyn->add_entry(elfcpp::R_SW_64_RELATIVE, this, offset, sym, addend); -+ } -+ } -+ -+ for(auto &p: got.plts){ -+ p.second = index++; -+ -+ auto sym = const_cast(p.first.first); -+ auto addend = p.first.second; -+ int64_t offset = p.second * ENTRY_SIZE; -+ gold_assert(0 == addend); -+ -+ rela_plt->add_global(sym, elfcpp::R_SW_64_JMP_SLOT, this, offset, addend); -+ // This is the bfd behavior. -+ sym->set_nonvis(0); -+ auto plt_offset = plt->add_entry(sym); -+ relocations_.push_back({p.second, sym, 0, plt_offset}); -+ } -+ -+ for(auto &p: got.locals){ -+ p.second = index++; -+ -+ auto &sym = p.first.first; -+ auto addend = p.first.second; -+ int64_t offset = p.second * ENTRY_SIZE; -+ -+ relocations_.push_back({p.second, sym, addend, is_tls(sym)}); -+ -+ // TODO: Check whether the symbol is an absolute value. -+ if(is_pic && !is_tls(sym)){ -+ rela_dyn->add_entry(elfcpp::R_SW_64_RELATIVE, this, offset, sym, addend); -+ } -+ } -+ -+ for(auto &p: got.tlss){ -+ p.second = index; -+ index += DYNAMIC_TLS_GOT_COUNT; -+ -+ auto &usym = p.first; -+ if(usym.is_local()){ -+ build_dyn_tls(rela_dyn, shared, p.second, usym.as_local()); -+ }else{ -+ build_dyn_tls(rela_dyn, shared, p.second, usym.as_global()); -+ } -+ } -+ } -+ set_data_size(index * ENTRY_SIZE); -+ } -+ -+ size_t entries_num()const{ -+ size_t count = 0; -+ for(auto &got: gots_){ -+ if(nullptr == got.file)continue; -+ count += got.entries_num(); -+ } -+ return count; -+ } -+ -+ void -+ do_print_to_mapfile(Mapfile*) const override{ -+ } -+ -+ protected: -+ virtual void -+ do_write(Output_file *of){ -+ const off_t off = this->offset(); -+ const off_t oview_size = this->data_size(); -+ unsigned char* const oview = of->get_output_view(off, oview_size); -+ -+ for(const auto &reloc: relocations_){ -+ reloc.write(oview); -+ } -+ of->write_output_view(off, oview_size, oview); -+ } -+ -+ // Reserve the slot at index I in the GOT. -+ virtual void -+ do_reserve_slot(unsigned int){ -+ } -+ -+ private: -+ class Got_reloc{ -+ public: -+ // Create a global symbol entry. -+ Got_reloc(Index index, const Symbol *gsym, Addend addend, Offset plt_offset=0) -+ : index_(index) -+ , local_sym_index_(GSYM) -+ , gsym_(gsym) -+ , addend_(addend) -+ , plt_offset_(plt_offset) -+ {} -+ -+ // Create a local symbol entry. -+ Got_reloc(Index index -+ , const LSymbol &lsym -+ , Addend addend -+ , bool use_tls_offset=false -+ ) -+ : index_(index) -+ , local_sym_index_(std::get<1>(lsym)) -+ , object_(std::get<0>(lsym)) -+ , addend_(addend) -+ , plt_offset_(use_tls_offset) -+ { -+ } -+ -+ // Create a constant entry. The constant is a host value--it will -+ // be swapped, if necessary, when it is written out. -+ Got_reloc(Index index, Valtype constant) -+ : index_(index) -+ , local_sym_index_(CONSTANT) -+ , constant_(constant) -+ , addend_(0) -+ , plt_offset_(0) -+ {} -+ -+ // Write the GOT entry to an output view. -+ void write(unsigned char* pov)const{ -+ Valtype val = 0; -+ auto &target = reinterpret_cast(parameters->target()); -+ -+ switch(this->local_sym_index_){ -+ case GSYM: { -+ // If the symbol is resolved locally, we need to write out the -+ // link-time value, which will be relocated dynamically by a -+ // RELATIVE relocation. -+ if(Output_data_plt_sw_64::is_plt_offset(plt_offset_)){ -+ val = target.plt_section()->address() + plt_offset_; -+ }else{ -+ switch(parameters->size_and_endianness()){ -+#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) -+ case Parameters::TARGET_32_LITTLE: -+ case Parameters::TARGET_32_BIG: -+ { -+ // This cast is ugly. We don't want to put a -+ // virtual method in Symbol, because we want Symbol -+ // to be as small as possible. -+ Sized_symbol<32>::Value_type v; -+ v = static_cast*>(gsym_)->value(); -+ val = convert_types::Value_type>(v); -+ }break; -+#endif -+#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) -+ case Parameters::TARGET_64_LITTLE: -+ case Parameters::TARGET_64_BIG: -+ { -+ Sized_symbol<64>::Value_type v; -+ v = static_cast*>(gsym_)->value(); -+ val = convert_types::Value_type>(v); -+ }break; -+#endif -+ default: -+ gold_unreachable(); -+ } -+ if(this->plt_offset_ && is_tls(gsym_)){ -+ val += target.tls_offset(); -+ } -+ } -+ }break; -+ -+ case CONSTANT: -+ val = this->constant_; -+ break; -+ -+ default: { -+ const unsigned int lsi = this->local_sym_index_; -+ bool is_tls = object_->local_is_tls(lsi); -+ if(this->plt_offset_ && !is_tls){ -+ val = parameters->target().plt_address_for_local(object_, lsi); -+ }else{ -+ uint64_t lval = object_->local_symbol_value(lsi, 0); -+ val = convert_types(lval); -+ if(this->plt_offset_ && is_tls){ -+ val += target.tls_offset(); -+ } -+ } -+ }break; -+ } // end of switch(this->local_sym_index_). -+ -+ pov += index_ * ENTRY_SIZE; -+ elfcpp::Swap::writeval(pov, val + addend_); -+ }; -+ -+ private: -+ static constexpr LocalIndex GSYM = 0x7fffffff; -+ static constexpr LocalIndex CONSTANT = 0x7ffffffe; -+ -+ Index index_; -+ // For a local symbol, the local symbol index. This is GSYM_CODE -+ // for a global symbol, or CONSTANT_CODE for a constant. -+ LocalIndex local_sym_index_; -+ union{ -+ // For a local symbol, the object. -+ const Relobj* object_; -+ // For a global symbol, the symbol. -+ const Symbol* gsym_; -+ // For a constant, the constant. -+ Valtype constant_; -+ }; -+ Addend addend_; -+ // For TLS symbols, whether to offset the symbol value. -+ Offset plt_offset_; -+ }; -+ std::vector relocations_; -+ template using Got_entry = std::pair; -+ template using Got_map = std::map; -+ -+ struct File_got{ -+ SizedRel *file = nullptr; -+ size_t start_index = 0; -+ -+ Got_map, size_t> locals; -+ Got_map, size_t> globals; -+ Got_map, size_t> plts; -+ Got_map tlss; -+ -+ size_t entries_num()const{ -+ return locals.size() -+ + globals.size() -+ + plts.size() -+ + tlss.size() * DYNAMIC_TLS_GOT_COUNT -+ ; -+ } -+ }; -+ -+ // Return `File_got`. -+ const File_got& file_got(const SizedRel *f)const{ -+ gold_assert(nullptr != f && has_got_index(f)); -+ return gots_.at(got_index(f)); -+ } -+ -+ // Return (and create if necessary) `File_got`. -+ File_got& file_got(SizedRel *f){ -+ gold_assert(nullptr != f); -+ if(!has_got_index(f)){ -+ gots_.emplace_back(); -+ gots_.back().file = f; -+ set_got_index(f, gots_.size() - 1); -+ } -+ return gots_[got_index(f)]; -+ } -+ -+ // Container of GOT created for each input file. -+ std::vector gots_; -+ -+ template -+ inline void build_dyn_tls(Output_data_reloc_sw_64 *rela_dyn, bool shared, size_t index, const ST &sym){ -+ int64_t offset = index * ENTRY_SIZE; -+ int64_t offset2 = offset + ENTRY_SIZE; -+ -+ if(shared || is_undef(sym) || is_preemptible(sym)){ -+ rela_dyn->add_entry(elfcpp::R_SW_64_DTPMOD64, this, offset, sym, 0); -+ if(is_undef(sym))return; -+ } -+ if(is_preemptible(sym)){ -+ rela_dyn->add_entry(elfcpp::R_SW_64_DTPREL64, this, offset2, sym, 0); -+ }else{ -+ if(!shared){ -+ relocations_.push_back({index, 1}); -+ } -+ relocations_.push_back({index + 1, sym, 0, false}); -+ } -+ } -+ -+ bool merge_gots(File_got &dst, File_got &src){ -+ gold_assert(nullptr != dst.file); -+ -+ // TODO: Do an optimistic merge. -+ if(MAX_GOTS < dst.entries_num() + src.entries_num())return false; -+ -+ set_union(dst.locals, src.locals); -+ set_union(dst.globals, src.globals); -+ set_union(dst.plts, src.plts); -+ set_union(dst.tlss, src.tlss); -+ set_got_index(src.file, got_index(dst.file)); -+ src.file = nullptr; -+ -+ gold_assert(dst.entries_num() <= MAX_GOTS); -+ return true; -+ } -+ -+ static constexpr int64_t GP_OFFSET = 0x8000; -+ static constexpr unsigned int GOT_INDEX_TYPE = static_cast(-1); -+ static constexpr size_t DYNAMIC_TLS_GOT_COUNT = 2; -+ static constexpr size_t MAX_GOTS = 1 << 13; -+ -+ static bool has_got_index(const SizedRel *f){ -+ return nullptr != f && f->local_has_got_offset(0, GOT_INDEX_TYPE); -+ } -+ -+ static intptr_t got_index(const SizedRel *f){ -+ gold_assert(nullptr != f); -+ return f->local_got_offset(0, GOT_INDEX_TYPE); -+ } -+ -+ static void set_got_index(SizedRel *f, size_t index){ -+ f->set_local_got_offset(0, GOT_INDEX_TYPE, index); -+ } -+ -+ template -+ static int64_t got_offset(const Got_map &entries, const T &key){ -+ const auto it = entries.find(key); -+ return (std::end(entries) == it ? -1 : it->second * ENTRY_SIZE); -+ } -+}; -+ -+template -+class X::Output_data_plt_sw_64: public Output_section_data{ -+ public: -+ Output_data_plt_sw_64() -+ : Output_section_data(0x10) -+ , got_plt_(nullptr) -+ { -+ } -+ -+ void set_got_plt(const Output_section_data* got_plt){ -+ got_plt_ = got_plt; -+ } -+ -+ Offset add_entry(Symbol* sym){ -+ entries_.push_back(sym); -+ return HEADER_SIZE + ENTRY_SIZE * (entries_.size() - 1); -+ } -+ -+ unsigned int -+ entries_num()const{ -+ return entries_.size(); -+ } -+ -+ unsigned int -+ first_entry_offset()const{ -+ return HEADER_SIZE; -+ } -+ -+ unsigned int -+ entry_size()const{ -+ return ENTRY_SIZE; -+ } -+ -+ void -+ do_print_to_mapfile(Mapfile*) const override{ -+ } -+ -+ static bool is_plt_offset(Offset offset){ -+ return HEADER_SIZE <= offset; -+ } -+ -+ protected: -+ virtual void -+ do_write(Output_file *of){ -+ const off_t off = this->offset(); -+ const off_t oview_size = this->data_size(); -+ unsigned char* const oview = of->get_output_view(off, oview_size); -+ -+ const uint8_t plt_data[] = { -+ 0x39, 0x01, 0x7c, 0x43, // subl $r27,$r28,$r25 -+ 0x00, 0x00, 0x9c, 0xff, // ldih $r28,0($r28) <--- needs relocation. -+ 0x79, 0x01, 0x39, 0x43, // s4subl $r25,$r25,$r25 -+ 0x00, 0x00, 0x9c, 0xfb, // ldi $r28,0($r28) <--- needs relocation. -+ 0x00, 0x00, 0x7c, 0x8f, // ldl $r27,0($r28) -+ 0x19, 0x01, 0x39, 0x43, // addl $r25,$r25,$r25 -+ 0x08, 0x00, 0x9c, 0x8f, // ldl $r28,8($r28) -+ 0x00, 0x00, 0xfb, 0x0f, // jmp $r31,($r27),1200020, 0x<_PROCEDURE_LINKAGE_TABLE_+0x20> -+ 0xf7, 0xff, 0x9f, 0x13, // br $r28,1200000, 0x<_PROCEDURE_LINKAGE_TABLE_> -+ }; -+ static_assert(HEADER_SIZE == sizeof(plt_data)); -+ memcpy(oview, plt_data, sizeof(plt_data)); -+ // $28 point to PLT[0], need to be relocated to the beginning of .got.plt section. -+ auto disp = got_plt_->address() - address() - HEADER_SIZE; -+ Target_sw_64::Relocate::do_gpdisp(oview + 4, oview + 12, disp); -+ -+ auto buf = reinterpret_cast(oview + HEADER_SIZE); -+ for(size_t i = 0; i < entries_.size(); ++i){ -+ buf[i] = 0x13fffffe - i; -+ } -+ -+ of->write_output_view(off, oview_size, oview); -+ } -+ -+ virtual void -+ set_final_data_size(){ -+ set_data_size(HEADER_SIZE + ENTRY_SIZE * entries_.size()); -+ } -+ -+ private: -+ const Output_section_data *got_plt_; -+ std::vector entries_; -+ -+ static constexpr size_t HEADER_SIZE = 0x24; -+ static constexpr size_t ENTRY_SIZE = 4; -+}; -+ -+template -+class X::Output_data_reloc_sw_64: public Output_data_reloc{ -+ public: -+ using super = Output_data_reloc; -+ using super::super; -+ -+ void add_entry( -+ RelType rel -+ , Output_data *od -+ , SizedRel *obj -+ , Shndx shndx -+ , Address offset -+ , const USymbol &sym -+ , Addend addend -+ ){ -+ auto is_relative = elfcpp::R_SW_64_RELATIVE == rel; -+ if(sym.is_local()){ -+ const LSymbol &lsym = sym.as_local(); -+ gold_assert(nullptr == obj || obj == std::get<0>(lsym)); -+ this->add(od, {obj, std::get<1>(lsym), rel, shndx, offset, addend, is_relative, is_relative, false, false}); -+ }else{ -+ this->add(od, {const_cast(sym.as_global()), rel, obj, shndx, offset, addend, is_relative, is_relative, false}); -+ } -+ } -+ -+ void add_entry( -+ RelType rel -+ , Output_data *od -+ , Address offset -+ , const GSymbol &sym -+ , Addend addend -+ ){ -+ auto is_relative = elfcpp::R_SW_64_RELATIVE == rel; -+ this->add(od, { -+ const_cast(sym), -+ rel, -+ od, -+ offset, -+ addend, -+ is_relative, // is_relative -+ is_relative, // is_symbolless -+ false, // use_plt_offset -+ }); -+ } -+ -+ void add_entry( -+ RelType rel -+ , Output_data *od -+ , Address offset -+ , const LSymbol &lsym -+ , Addend addend -+ ){ -+ auto is_relative = elfcpp::R_SW_64_RELATIVE == rel; -+ this->add(od, { -+ std::get<0>(lsym), -+ elfcpp::R_SW_64_DTPMOD64 == rel ? 0 : std::get<1>(lsym), -+ rel, -+ od, -+ offset, -+ addend, -+ is_relative, // is_relative -+ is_relative, // is_symbolless -+ false, // is_section_symbol -+ false, // use_plt_offset -+ }); -+ } -+}; -+ -+template -+void -+X::Target_sw_64::gc_process_relocs(Symbol_table* symtab, -+ Layout *layout, -+ SizedRel *object, -+ unsigned int data_shndx, -+ unsigned int sh_type, -+ const unsigned char* prelocs, -+ size_t reloc_count, -+ Output_section* output_section, -+ bool needs_special_offset_handling, -+ size_t local_symbol_count, -+ const unsigned char* plocal_symbols) -+{ -+ if(elfcpp::SHT_RELA != sh_type)return; -+ gold::gc_process_relocs( -+ symtab -+ , layout -+ , this -+ , object -+ , data_shndx -+ , prelocs -+ , reloc_count -+ , output_section -+ , needs_special_offset_handling -+ , local_symbol_count -+ , plocal_symbols -+ ); -+} -+ -+template -+void -+X::Target_sw_64::scan_relocs(Symbol_table* symtab, -+ Layout *layout, -+ SizedRel *object, -+ unsigned int data_shndx, -+ unsigned int sh_type, -+ const unsigned char* prelocs, -+ size_t reloc_count, -+ Output_section* output_section, -+ bool needs_special_offset_handling, -+ size_t local_symbol_count, -+ const unsigned char* plocal_symbols) -+{ -+ if(elfcpp::SHT_RELA != sh_type){ -+ gold_error(_("%s: unsupported reloc type %d section.") -+ , object->name().c_str(), sh_type); -+ return; -+ } -+ prelocs_ = prelocs; -+ reloc_count_ = reloc_count; -+ gold::scan_relocs( -+ symtab -+ , layout -+ , this -+ , object -+ , data_shndx -+ , prelocs -+ , reloc_count -+ , output_section -+ , needs_special_offset_handling -+ , local_symbol_count -+ , plocal_symbols); -+} -+ -+template -+void -+X::Target_sw_64::relocate_section( -+ const RelInfo *relinfo -+ , unsigned int sh_type -+ , const unsigned char* prelocs -+ , size_t reloc_count -+ , Output_section* output_section -+ , bool needs_special_offset_handling -+ , unsigned char* view -+ , Address view_address -+ , section_size_type view_size -+ , const Reloc_symbol_changes* reloc_symbol_changes -+){ -+ gold_assert(elfcpp::SHT_RELA == sh_type); -+ gold::relocate_section( -+ relinfo -+ , this -+ , prelocs -+ , reloc_count -+ , output_section -+ , needs_special_offset_handling -+ , view -+ , view_address -+ , view_size -+ , reloc_symbol_changes -+ ); -+} -+ -+template -+void -+X::Target_sw_64::scan_relocatable_relocs( -+ Symbol_table *symtab -+ , Layout *layout -+ , SizedRel *object -+ , unsigned int data_shndx -+ , unsigned int sh_type -+ , const unsigned char* prelocs -+ , size_t reloc_count -+ , Output_section* output_section -+ , bool needs_special_offset_handling -+ , size_t local_symbol_count -+ , const unsigned char* plocal_symbols -+ , Relocatable_relocs* rr -+){ -+ gold_assert(sh_type == elfcpp::SHT_RELA); -+ gold::scan_relocatable_relocs( -+ symtab, -+ layout, -+ object, -+ data_shndx, -+ prelocs, -+ reloc_count, -+ output_section, -+ needs_special_offset_handling, -+ local_symbol_count, -+ plocal_symbols, -+ rr); -+} -+ -+template -+void -+X::Target_sw_64::emit_relocs_scan( -+ Symbol_table *symtab -+ , Layout *layout -+ , SizedRel *object -+ , unsigned int data_shndx -+ , unsigned int sh_type -+ , const unsigned char *prelocs -+ , size_t reloc_count -+ , Output_section *output_section -+ , bool needs_special_offset_handling -+ , size_t local_symbol_count -+ , const unsigned char *plocal_syms -+ , Relocatable_relocs *rr -+){ -+ gold_assert(sh_type == elfcpp::SHT_RELA); -+ gold::scan_relocatable_relocs( -+ symtab, -+ layout, -+ object, -+ data_shndx, -+ prelocs, -+ reloc_count, -+ output_section, -+ needs_special_offset_handling, -+ local_symbol_count, -+ plocal_syms, -+ rr); -+} -+ -+template -+void -+X::Target_sw_64::relocate_relocs(const RelInfo *relinfo, -+ unsigned int sh_type, -+ const unsigned char* prelocs, -+ size_t reloc_count, -+ Output_section* output_section, -+ Offset offset_in_output_section, -+ unsigned char* view, -+ Address view_address, -+ section_size_type view_size, -+ unsigned char* reloc_view, -+ section_size_type reloc_view_size) -+{ -+ gold_assert(sh_type == elfcpp::SHT_RELA); -+ -+ gold::relocate_relocs( -+ relinfo, -+ prelocs, -+ reloc_count, -+ output_section, -+ offset_in_output_section, -+ view, -+ view_address, -+ view_size, -+ reloc_view, -+ reloc_view_size); -+} -+ -+template -+void -+X::Target_sw_64::do_select_as_default_target(){ -+ got_ = new Output_data_got_sw_64; -+ rela_dyn_ = new Output_data_reloc_sw_64(!parameters->options_valid() || parameters->options().combreloc()); -+ rela_plt_ = new Reloc_section(false); -+ plt_ = new Output_data_plt_sw_64; -+} -+ -+template -+void -+X::Target_sw_64::do_finalize_sections( -+ Layout* layout -+ , const Input_objects* -+ , Symbol_table *symtab -+){ -+ Output_section_data* got_plt = nullptr; -+ if(auto tls_segment = layout->tls_segment()){ -+ tls_offset_ = align_address(TCB_SIZE, tls_segment->maximum_alignment()); -+ } -+ -+ got_->build(this); -+ -+ if(0 < rela_dyn_->current_data_size()){ -+ layout->add_output_section_data( -+ ".rela.dyn" -+ , elfcpp::SHT_RELA -+ , elfcpp::SHF_ALLOC -+ , rela_dyn_ -+ , ORDER_DYNAMIC_RELOCS -+ , false // is_relro -+ ); -+ }else{ -+ rela_dyn_ = nullptr; -+ } -+ -+ if(0 < rela_plt_->current_data_size()){ -+ layout->add_output_section_data( -+ ".rela.plt" -+ , elfcpp::SHT_RELA -+ , elfcpp::SHF_ALLOC -+ , rela_plt_ -+ , ORDER_DYNAMIC_PLT_RELOCS -+ , false // is_relro -+ ); -+ -+ layout->add_output_section_data( -+ ".plt" -+ , elfcpp::SHT_PROGBITS -+ , (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR) -+ , plt_ -+ , ORDER_PLT -+ , false // is_relro -+ ); -+ // Make it compatible with bfd. -+ symtab->define_in_output_data( -+ "_PROCEDURE_LINKAGE_TABLE_" -+ , NULL -+ , Symbol_table::PREDEFINED -+ , plt_ -+ , 0 -+ , 0 -+ , elfcpp::STT_OBJECT -+ , elfcpp::STB_LOCAL -+ , elfcpp::STV_DEFAULT -+ , 0 -+ , false -+ , false -+ ); -+ -+ static std::string got_plt_data(E::size / 8 * 2, '\0'); -+ got_plt = new Output_data_const(got_plt_data, E::size / 8); -+ layout->add_output_section_data( -+ ".got.plt" -+ , elfcpp::SHT_PROGBITS -+ , (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE) -+ , got_plt -+ , ORDER_RELRO -+ , true // is_relro -+ ); -+ plt_->set_got_plt(got_plt); -+ }else{ -+ rela_plt_ = nullptr; -+ } -+ -+ layout->add_target_dynamic_tags( -+ false // use_rel -+ , got_plt -+ , rela_plt_ -+ , rela_dyn_ -+ , true // add_debug -+ , false // dynrel_includes_plt -+ ); -+ auto dyn = layout->dynamic_data(); -+ if(nullptr != dyn){ -+ dyn->add_constant(elfcpp::DT_SW_64_PLTRO, 1); -+ } -+ -+ layout->add_output_section_data( -+ ".got" -+ , elfcpp::SHT_PROGBITS -+ , elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE -+ , got_ -+ , ORDER_GOT -+ , false // is_relro -+ ); -+} -+ -+template -+template -+inline void -+X::Target_sw_64::Scan::scan( -+ Target_sw_64 *target -+ , SizedRel *object -+ , unsigned int data_shndx -+ , Output_section* output_section -+ , const Rela &reloc -+ , unsigned int r_type -+ , const Symbol_type &&sym -+){ -+ auto r_addend = reloc.get_r_addend(); -+ -+ switch(r_type){ -+ case elfcpp::R_SW_64_NONE: -+ case elfcpp::R_SW_64_GPREL32: -+ case elfcpp::R_SW_64_GPREL16: -+ case elfcpp::R_SW_64_GPDISP: -+ case elfcpp::R_SW_64_LITUSE: -+ case elfcpp::R_SW_64_REFLONG: -+ case elfcpp::R_SW_64_HINT: -+ case elfcpp::R_SW_64_SREL16: -+ case elfcpp::R_SW_64_SREL32: -+ case elfcpp::R_SW_64_SREL64: -+ case elfcpp::R_SW_64_GPRELHIGH: -+ case elfcpp::R_SW_64_GPRELLOW: -+ case elfcpp::R_SW_64_GLOB_DAT: -+ case elfcpp::R_SW_64_JMP_SLOT: -+ case elfcpp::R_SW_64_RELATIVE: -+ case elfcpp::R_SW_64_LITERAL_GOT: -+ case elfcpp::R_SW_64_DTPRELHI: -+ case elfcpp::R_SW_64_DTPRELLO: -+ case elfcpp::R_SW_64_TPREL64: -+ case elfcpp::R_SW_64_TPRELHI: -+ case elfcpp::R_SW_64_TPRELLO: -+ case elfcpp::R_SW_64_TPREL16: -+ case elfcpp::R_SW_64_BRADDR: -+ // TODO: Check target's .prologue and merge GOTs. -+ case elfcpp::R_SW_64_BRSGP: -+ // Nothing to do. -+ break; -+ case elfcpp::R_SW_64_REFQUAD: -+ { -+ if(!is_static_link_time_constant(sym)){ -+ auto rel = is_preemptible(sym) ? static_cast(r_type) : elfcpp::R_SW_64_RELATIVE; -+ target->rela_dyn_section()->add_entry( -+ rel -+ , output_section -+ , object -+ , data_shndx -+ , reloc.get_r_offset() -+ , sym -+ , r_addend -+ ); -+ } -+ }break; -+ case elfcpp::R_SW_64_LITERAL: { -+ bool use_plt = false; -+ if(next_ < target->reloc_count_){ -+ Rela next_reloc(target->prelocs_ -+ + next_ * Reloc_types::reloc_size); -+ auto next_info = next_reloc.get_r_info(); -+ auto next_type = elfcpp::elf_r_type(next_info); -+ if(elfcpp::R_SW_64_LITUSE == next_type){ -+ use_plt = is_func(sym) && LITUSE_JSR == next_reloc.get_r_addend(); -+ if(use_plt)target->add_jsr_user(object, data_shndx, next_ - 1); -+ } -+ } -+ target->got_section()->add_entry(object, std::move(sym), r_addend, use_plt); -+ }break; -+ case elfcpp::R_SW_64_TLSGD: { -+ target->got_section()->add_tls_entry(object, std::move(sym)); -+ }break; -+ case elfcpp::R_SW_64_TLS_LDM: { -+ if(parameters->options().shared() || !parameters->options().relax()){ -+ target->got_section()->add_tls_index(object); -+ }else{ -+ gold_error(_("TODO: relax from LD to LE is not implemented yet.")); -+ } -+ }break; -+ case elfcpp::R_SW_64_GOTTPREL: { -+ target->got_section()->add_entry(object, std::move(sym), r_addend, false); -+ }break; -+ default: -+ gold_error(_("%s: unsupported relocation '%s' at offset %#lx.") -+ , object->name().c_str() -+ , get_relocation_name(r_type) -+ , reloc.get_r_offset() -+ ); -+ } -+} -+ -+template -+inline bool -+X::Target_sw_64::Scan::local_reloc_may_be_function_pointer( -+ Symbol_table* -+ , Layout* -+ , Target_sw_64* -+ , SizedRel * -+ , unsigned int -+ , Output_section* -+ , const Rela & -+ , unsigned int r_type -+ , const Sym &) -+{ -+ // TODO -+ return true; -+} -+ -+template -+inline bool -+X::Target_sw_64::Scan::global_reloc_may_be_function_pointer( -+ Symbol_table * -+ , Layout * -+ , Target_sw_64 * -+ , SizedRel * -+ , unsigned int -+ , Output_section * -+ , const Rela & -+ , unsigned int r_type -+ , Symbol* gsym) -+{ -+ // TODO -+ return true; -+} -+ -+template -+inline bool -+X::Target_sw_64::Relocate::relocate( -+ const RelInfo *relinfo -+ , unsigned int -+ , Target_sw_64 *target -+ , Output_section * -+ , size_t relnum -+ , const unsigned char *preloc -+ , const Sized_symbol* gsym -+ , const Symbol_value* symval -+ , unsigned char* view -+ , Address address -+ , section_size_type -+){ -+ const Rela rela(preloc); -+ auto r_type = elfcpp::elf_r_type(rela.get_r_info()); -+ auto r_offset = rela.get_r_offset(); -+ auto r_addend = rela.get_r_addend(); -+ auto r_info = rela.get_r_info(); -+ auto r_sym = elfcpp::elf_r_sym(r_info); -+ auto object = relinfo->object; -+ -+ switch(r_type){ -+ case elfcpp::R_SW_64_NONE: -+ // This reloc only immediately follows a R_SW_64_LITERAL reloc, and it -+ // does not do any real relocation. -+ case elfcpp::R_SW_64_LITUSE: -+ case elfcpp::R_SW_64_GLOB_DAT: -+ case elfcpp::R_SW_64_JMP_SLOT: -+ case elfcpp::R_SW_64_RELATIVE: -+ // Nothing to do. -+ break; -+ case elfcpp::R_SW_64_REFLONG: { -+ auto val = symval->value(object, r_addend); -+ Rf::rel32(view, val); -+ }break; -+ case elfcpp::R_SW_64_REFQUAD: { -+ auto val = symval->value(object, r_addend); -+ Rf::rel64(view, val); -+ }break; -+ case elfcpp::R_SW_64_GPREL32: { -+ auto got = target->got_section(); -+ auto disp = symval->value(object, r_addend) - got->address() - got->gp_offset(object); -+ disp += Inst::readval(view); -+ Inst::writeval(view, disp); -+ }break; -+ case elfcpp::R_SW_64_GOTTPREL: -+ case elfcpp::R_SW_64_LITERAL: { -+ auto got = target->got_section(); -+ auto use_plt = target->is_jsr_user(object, relinfo->data_shndx, relnum); -+ auto offset = got->sym_entry_offset(object, gsym, r_sym, r_addend, use_plt) -+ - got->gp_offset(object); -+ auto literal_inst = Inst::readval(view); -+ -+ if(INVALID_OFFSET != literal_got_offset){ -+ auto hi_view = view - r_offset + literal_got_offset; -+ auto hi_inst = Inst::readval(hi_view); -+ // TODO: Check the protocol is correct. -+ -+ // Change previous instruction with R_SW_64_LITERAL_GOT to load the high part of GOT. -+ Inst::writeval(hi_view, bit_select32(hi_inst, high(offset), 0xffff)); -+ // Change the base register of low load to the destination register of the high load. -+ literal_inst = bit_select32( -+ literal_inst -+ , (hi_inst & RA_MASK) >> (RA_SHIFT - RB_SHIFT) -+ , RC_MASK << RB_SHIFT -+ ); -+ }else if(static_cast(offset) < INT16_MIN || INT16_MAX < static_cast(offset)){ -+ gold_error("%s: relocation '%s' at offset %#lx overflowed %#lx." -+ , relinfo->object->name().data() -+ , get_relocation_name(r_type) -+ , r_offset -+ , offset -+ ); -+ } -+ Inst::writeval(view, bit_select32(literal_inst, offset, 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_GPDISP: { -+ auto got = target->got_section(); -+ auto disp = got->address() + got->gp_offset(object) - address; -+ do_gpdisp(view, view + r_addend, disp); -+ }break; -+ case elfcpp::R_SW_64_BRADDR: -+ case elfcpp::R_SW_64_BRSGP: -+ { -+ auto inst = Inst::readval(view); -+ auto val = (symval->value(object, r_addend) - address) / 4 - 1; -+ Inst::writeval(view, bit_select32(inst, val, 0x1fffff)); -+ }break; -+ case elfcpp::R_SW_64_HINT: { -+ auto inst = Inst::readval(view); -+ auto disp = (symval->value(object, r_addend) ?: address +4) - address; -+ disp = (disp >> 2) - 1; -+ Inst::writeval(view, bit_select32(inst, disp, 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_SREL16: { -+ auto disp = symval->value(object, r_addend) - address; -+ Rf::rel16(view, disp); -+ }break; -+ case elfcpp::R_SW_64_SREL32: { -+ auto disp = symval->value(object, r_addend) - address; -+ Rf::rel32(view, disp); -+ }break; -+ case elfcpp::R_SW_64_SREL64: { -+ auto disp = symval->value(object, r_addend) - address; -+ Rf::rel64(view, disp); -+ }break; -+ case elfcpp::R_SW_64_GPRELHIGH: { -+ auto got = target->got_section(); -+ auto disp = symval->value(object, r_addend) - got->address() - got->gp_offset(object); -+ auto inst = Inst::readval(view); -+ Inst::writeval(view, bit_select32(inst, high(disp), 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_GPREL16: -+ case elfcpp::R_SW_64_GPRELLOW: { -+ auto got = target->got_section(); -+ auto disp = symval->value(object, r_addend) - got->address() - got->gp_offset(object); -+ auto inst = Inst::readval(view); -+ Inst::writeval(view, bit_select32(inst, disp, 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_TLSGD: { -+ auto got = target->got_section(); -+ auto disp = got->sym_tls_offset(object, {gsym, object, r_sym}) - got->gp_offset(object); -+ auto inst = Inst::readval(view); -+ Inst::writeval(view, bit_select32(inst, disp, 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_TLS_LDM: { -+ auto got = target->got_section(); -+ auto disp = got->sym_tls_offset(object, {nullptr, object, 0}) - got->gp_offset(object); -+ auto inst = Inst::readval(view); -+ Inst::writeval(view, bit_select32(inst, disp, 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_DTPRELHI: { -+ auto inst = Inst::readval(view); -+ auto val = symval->value(object, r_addend); -+ Inst::writeval(view, bit_select32(inst, high(val), 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_DTPRELLO: { -+ auto inst = Inst::readval(view); -+ auto val = symval->value(object, r_addend); -+ Inst::writeval(view, bit_select32(inst, val, 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_TPREL64: { -+ auto val = symval->value(object, r_addend) + target->tls_offset(); -+ Rf::rel64(view, val); -+ }break; -+ case elfcpp::R_SW_64_TPRELHI: { -+ auto inst = Inst::readval(view); -+ auto val = symval->value(object, r_addend) + target->tls_offset(); -+ Inst::writeval(view, bit_select32(inst, high(val), 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_TPRELLO: { -+ auto inst = Inst::readval(view); -+ auto val = symval->value(object, r_addend) + target->tls_offset(); -+ Inst::writeval(view, bit_select32(inst, val, 0xffff)); -+ }break; -+ case elfcpp::R_SW_64_TPREL16: { -+ auto val = symval->value(object, r_addend) + target->tls_offset(); -+ Rf::rel16(view, val); -+ }break; -+ case elfcpp::R_SW_64_LITERAL_GOT: -+ literal_got_offset = r_offset; -+ return true; -+ default: -+ gold_error_at_location( -+ relinfo -+ , relnum -+ , r_offset -+ , _("can't handle relocation '%s'.") -+ , get_relocation_name(r_type) -+ ); -+ break; -+ } -+ -+ literal_got_offset = INVALID_OFFSET; -+ return true; -+} -+ -+template -+Target::Target_info X::Target_sw_64::sw64_info = { -+ E::size, // size -+ E::big_endian, // is_big_endian -+ elfcpp::EM_SW_64, // machine_code -+ false, // has_make_symbol -+ false, // has_resolve -+ false, // has_code_fill -+ false, // is_default_stack_executable -+ false, // can_icf_inline_merge_sections -+ '\0', // wrap_char -+ "/lib/ld-linux.so.2", // dynamic_linker -+ 0x120000000, // default_text_segment_address -+ 64 * 1024, // abi_pagesize -+ 64 * 1024, // common_pagesize -+ false, // isolate_execinstr -+ 0, // rosegment_gap -+ elfcpp::SHN_UNDEF, // small_common_shndx -+ elfcpp::SHN_UNDEF, // large_common_shndx -+ 0, // small_common_section_flags -+ 0, // large_common_section_flags -+ NULL, // attributes_section -+ NULL, // attributes_vendor -+ "_start", // entry_symbol_name -+ 64, // hash_entry_size -+ elfcpp::SHT_PROGBITS, // unwind_section_type -+}; -+ -+template -+class X::Target_selector_sw_64: public Target_selector -+{ -+ public: -+ Target_selector_sw_64(); -+ -+ virtual Target* -+ do_instantiate_target() -+ { return new Target_sw_64(); } -+}; -+ -+template<> -+X::Target_selector_sw_64::Target_selector_sw_64() -+ : Target_selector(elfcpp::EM_SW_64, 64, false, "elf64-sw_64", "elf64sw_64") -+{} -+ -+X::Target_selector_sw_64 target_selector_elf64_sw_64; -+} // End anonymous namespace. -diff --git a/gprof/sw_64.c b/gprof/sw_64.c -new file mode 100644 -index 00000000..42e9de54 ---- /dev/null -+++ b/gprof/sw_64.c -@@ -0,0 +1,176 @@ -+/* -+ * Copyright (c) 1983, 1993, 1998 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+#include "gprof.h" -+#include "search_list.h" -+#include "source.h" -+#include "symtab.h" -+#include "cg_arcs.h" -+#include "corefile.h" -+#include "hist.h" -+ -+/* -+ * Opcodes of the call instructions: -+ */ -+#define OP_Jxx 0x1aU -+#define OP_BSR 0x34U -+ -+#define Jxx_FUNC_JMP 0U -+#define Jxx_FUNC_JSR 1U -+#define Jxx_FUNC_RET 2U -+#define Jxx_FUNC_JSR_COROUTINE 3U -+ -+/* *INDENT-OFF* */ -+/* Here to document only. We can't use this when cross compiling as -+ the bitfield layout might not be the same as native. -+ -+ typedef union -+ { -+ struct -+ { -+ unsigned other:26; -+ unsigned op_code:6; -+ } -+ a; -- any format -+ struct -+ { -+ int disp:21; -+ unsigned ra:5; -+ unsigned op_code:6; -+ } -+ b; -- branch format -+ struct -+ { -+ int hint:14; -+ unsigned func:2; -+ unsigned rb:5; -+ unsigned ra:5; -+ unsigned op_code:6; -+ } -+ j; -- jump format -+ } -+ sw_64_Instruction; -+*/ -+/* *INDENT-ON* */ -+ -+static Sym indirect_child; -+ -+void sw_64_find_call (Sym *, bfd_vma, bfd_vma); -+ -+/* -+ * On the Alpha we can only detect PC relative calls, which are -+ * usually generated for calls to functions within the same -+ * object file only. This is still better than nothing, however. -+ * (In particular it should be possible to find functions that -+ * potentially call integer division routines, for example.) -+ */ -+void -+sw_64_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc) -+{ -+ bfd_vma pc, dest_pc; -+ unsigned int insn; -+ Sym *child; -+ -+ if (indirect_child.name == NULL) -+ { -+ sym_init (&indirect_child); -+ indirect_child.name = _(""); -+ indirect_child.cg.prop.fract = 1.0; -+ indirect_child.cg.cyc.head = &indirect_child; -+ } -+ -+ DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"), -+ parent->name, (unsigned long) p_lowpc, -+ (unsigned long) p_highpc)); -+ for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4) -+ { -+ insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space -+ + pc - core_text_sect->vma)); -+ switch (insn & (0x3fU << 26)) -+ { -+ case OP_Jxx << 26: -+ /* -+ * There is no simple and reliable way to determine the -+ * target of a jsr (the hint bits help, but there aren't -+ * enough bits to get a satisfactory hit rate). Instead, -+ * for any indirect jump we simply add an arc from PARENT -+ * to INDIRECT_CHILD---that way the user it at least able -+ * to see that there are other calls as well. -+ */ -+ if ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14 -+ || (insn & (3 << 14)) == Jxx_FUNC_JSR_COROUTINE << 14) -+ { -+ DBG (CALLDEBUG, -+ printf (_("[find_call] 0x%lx: jsr%s \n"), -+ (unsigned long) pc, -+ ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14 -+ ? "" : "_coroutine"))); -+ arc_add (parent, &indirect_child, (unsigned long) 0); -+ } -+ break; -+ -+ case OP_BSR << 26: -+ DBG (CALLDEBUG, -+ printf (_("[find_call] 0x%lx: bsr"), (unsigned long) pc)); -+ /* -+ * Regular PC relative addressing. Check that this is the -+ * address of a function. The linker sometimes redirects -+ * the entry point by 8 bytes to skip loading the global -+ * pointer, so we allow for either address: -+ */ -+ dest_pc = pc + 4 + (((bfd_signed_vma) (insn & 0x1fffff) -+ ^ 0x100000) - 0x100000); -+ if (hist_check_address (dest_pc)) -+ { -+ child = sym_lookup (&symtab, dest_pc); -+ if (child) -+ { -+ DBG (CALLDEBUG, -+ printf (" 0x%lx\t; name=%s, addr=0x%lx", -+ (unsigned long) dest_pc, child->name, -+ (unsigned long) child->addr)); -+ if (child->addr == dest_pc || child->addr == dest_pc - 8) -+ { -+ DBG (CALLDEBUG, printf ("\n")); -+ /* a hit: */ -+ arc_add (parent, child, (unsigned long) 0); -+ continue; -+ } -+ } -+ } -+ /* -+ * Something funny going on. -+ */ -+ DBG (CALLDEBUG, printf ("\tbut it's a botch\n")); -+ break; -+ -+ default: -+ break; -+ } -+ } -+} -diff --git a/include/coff/sw_64.h b/include/coff/sw_64.h -new file mode 100644 -index 00000000..45307b7a ---- /dev/null -+++ b/include/coff/sw_64.h -@@ -0,0 +1,386 @@ -+/* ECOFF support on Sw_64 machines. -+ coff/ecoff.h must be included before this file. -+ -+ Copyright (C) 2001-2018 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 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+ MA 02110-1301, USA. */ -+ -+/********************** FILE HEADER **********************/ -+ -+struct external_filehdr -+{ -+ unsigned char f_magic[2]; /* magic number */ -+ unsigned char f_nscns[2]; /* number of sections */ -+ unsigned char f_timdat[4]; /* time & date stamp */ -+ unsigned char f_symptr[8]; /* file pointer to symtab */ -+ unsigned char f_nsyms[4]; /* number of symtab entries */ -+ unsigned char f_opthdr[2]; /* sizeof(optional hdr) */ -+ unsigned char f_flags[2]; /* flags */ -+}; -+ -+/* Magic numbers are defined in coff/ecoff.h. */ -+#define SW_64_ECOFF_BADMAG(x) \ -+ ((x).f_magic != SW_64_MAGIC && (x).f_magic != SW_64_MAGIC_BSD) -+ -+#define SW_64_ECOFF_COMPRESSEDMAG(x) \ -+ ((x).f_magic == SW_64_MAGIC_COMPRESSED) -+ -+/* The object type is encoded in the f_flags. */ -+#define F_SW_64_OBJECT_TYPE_MASK 0x3000 -+#define F_SW_64_NO_SHARED 0x1000 -+#define F_SW_64_SHARABLE 0x2000 -+#define F_SW_64_CALL_SHARED 0x3000 -+ -+#define FILHDR struct external_filehdr -+#define FILHSZ 24 -+ -+/********************** AOUT "OPTIONAL HEADER" **********************/ -+ -+typedef struct external_aouthdr -+{ -+ unsigned char magic[2]; /* type of file */ -+ unsigned char vstamp[2]; /* version stamp */ -+ unsigned char bldrev[2]; /* ?? */ -+ unsigned char padding[2]; /* pad to quadword boundary */ -+ unsigned char tsize[8]; /* text size in bytes */ -+ unsigned char dsize[8]; /* initialized data " " */ -+ unsigned char bsize[8]; /* uninitialized data " " */ -+ unsigned char entry[8]; /* entry pt. */ -+ unsigned char text_start[8]; /* base of text used for this file */ -+ unsigned char data_start[8]; /* base of data used for this file */ -+ unsigned char bss_start[8]; /* base of bss used for this file */ -+ unsigned char gprmask[4]; /* bitmask of general registers used */ -+ unsigned char fprmask[4]; /* bitmask of floating point registers used */ -+ unsigned char gp_value[8]; /* value for gp register */ -+} AOUTHDR; -+ -+/* compute size of a header */ -+ -+#define AOUTSZ 80 -+#define AOUTHDRSZ 80 -+ -+/********************** SECTION HEADER **********************/ -+ -+struct external_scnhdr -+{ -+ unsigned char s_name[8]; /* section name */ -+ unsigned char s_paddr[8]; /* physical address, aliased s_nlib */ -+ unsigned char s_vaddr[8]; /* virtual address */ -+ unsigned char s_size[8]; /* section size */ -+ unsigned char s_scnptr[8]; /* file ptr to raw data for section */ -+ unsigned char s_relptr[8]; /* file ptr to relocation */ -+ unsigned char s_lnnoptr[8]; /* file ptr to line numbers */ -+ unsigned char s_nreloc[2]; /* number of relocation entries */ -+ unsigned char s_nlnno[2]; /* number of line number entries*/ -+ unsigned char s_flags[4]; /* flags */ -+}; -+ -+#define SCNHDR struct external_scnhdr -+#define SCNHSZ 64 -+ -+/********************** RELOCATION DIRECTIVES **********************/ -+ -+struct external_reloc -+{ -+ unsigned char r_vaddr[8]; -+ unsigned char r_symndx[4]; -+ unsigned char r_bits[4]; -+}; -+ -+#define RELOC struct external_reloc -+#define RELSZ 16 -+ -+/* Constants to unpack the r_bits field. The Sw_64 seems to always be -+ little endian, so I haven't bothered to define big endian variants -+ of these. */ -+ -+#define RELOC_BITS0_TYPE_LITTLE 0xff -+#define RELOC_BITS0_TYPE_SH_LITTLE 0 -+ -+#define RELOC_BITS1_EXTERN_LITTLE 0x01 -+ -+#define RELOC_BITS1_OFFSET_LITTLE 0x7e -+#define RELOC_BITS1_OFFSET_SH_LITTLE 1 -+ -+#define RELOC_BITS1_RESERVED_LITTLE 0x80 -+#define RELOC_BITS1_RESERVED_SH_LITTLE 7 -+#define RELOC_BITS2_RESERVED_LITTLE 0xff -+#define RELOC_BITS2_RESERVED_SH_LEFT_LITTLE 1 -+#define RELOC_BITS3_RESERVED_LITTLE 0x03 -+#define RELOC_BITS3_RESERVED_SH_LEFT_LITTLE 9 -+ -+#define RELOC_BITS3_SIZE_LITTLE 0xfc -+#define RELOC_BITS3_SIZE_SH_LITTLE 2 -+ -+/* The r_type field in a reloc is one of the following values. */ -+#define SW_64_R_IGNORE 0 -+#define SW_64_R_REFLONG 1 -+#define SW_64_R_REFQUAD 2 -+#define SW_64_R_GPREL32 3 -+#define SW_64_R_LITERAL 4 -+#define SW_64_R_LITUSE 5 -+#define SW_64_R_GPDISP 6 -+#define SW_64_R_BRADDR 7 -+#define SW_64_R_HINT 8 -+#define SW_64_R_SREL16 9 -+#define SW_64_R_SREL32 10 -+#define SW_64_R_SREL64 11 -+#define SW_64_R_OP_PUSH 12 -+#define SW_64_R_OP_STORE 13 -+#define SW_64_R_OP_PSUB 14 -+#define SW_64_R_OP_PRSHIFT 15 -+#define SW_64_R_GPVALUE 16 -+#define SW_64_R_GPRELHIGH 17 -+#define SW_64_R_GPRELLOW 18 -+#define SW_64_R_IMMED 19 -+ -+/* Overloaded reloc value used by Net- and OpenBSD. */ -+#define SW_64_R_LITERALSLEAZY 17 -+ -+/* With SW_64_R_LITUSE, the r_size field is one of the following values. */ -+#define SW_64_R_LU_BASE 1 -+#define SW_64_R_LU_BYTOFF 2 -+#define SW_64_R_LU_JSR 3 -+ -+/* With SW_64_R_IMMED, the r_size field is one of the following values. */ -+#define SW_64_R_IMMED_GP_16 1 -+#define SW_64_R_IMMED_GP_HI32 2 -+#define SW_64_R_IMMED_SCN_HI32 3 -+#define SW_64_R_IMMED_BR_HI32 4 -+#define SW_64_R_IMMED_LO32 5 -+ -+/********************** SYMBOLIC INFORMATION **********************/ -+ -+/* Written by John Gilmore. */ -+ -+/* ECOFF uses COFF-like section structures, but its own symbol format. -+ This file defines the symbol format in fields whose size and alignment -+ will not vary on different host systems. */ -+ -+/* File header as a set of bytes */ -+ -+struct hdr_ext -+{ -+ unsigned char h_magic[2]; -+ unsigned char h_vstamp[2]; -+ unsigned char h_ilineMax[4]; -+ unsigned char h_idnMax[4]; -+ unsigned char h_ipdMax[4]; -+ unsigned char h_isymMax[4]; -+ unsigned char h_ioptMax[4]; -+ unsigned char h_iauxMax[4]; -+ unsigned char h_issMax[4]; -+ unsigned char h_issExtMax[4]; -+ unsigned char h_ifdMax[4]; -+ unsigned char h_crfd[4]; -+ unsigned char h_iextMax[4]; -+ unsigned char h_cbLine[8]; -+ unsigned char h_cbLineOffset[8]; -+ unsigned char h_cbDnOffset[8]; -+ unsigned char h_cbPdOffset[8]; -+ unsigned char h_cbSymOffset[8]; -+ unsigned char h_cbOptOffset[8]; -+ unsigned char h_cbAuxOffset[8]; -+ unsigned char h_cbSsOffset[8]; -+ unsigned char h_cbSsExtOffset[8]; -+ unsigned char h_cbFdOffset[8]; -+ unsigned char h_cbRfdOffset[8]; -+ unsigned char h_cbExtOffset[8]; -+}; -+ -+/* File descriptor external record */ -+ -+struct fdr_ext -+{ -+ unsigned char f_adr[8]; -+ unsigned char f_cbLineOffset[8]; -+ unsigned char f_cbLine[8]; -+ unsigned char f_cbSs[8]; -+ unsigned char f_rss[4]; -+ unsigned char f_issBase[4]; -+ unsigned char f_isymBase[4]; -+ unsigned char f_csym[4]; -+ unsigned char f_ilineBase[4]; -+ unsigned char f_cline[4]; -+ unsigned char f_ioptBase[4]; -+ unsigned char f_copt[4]; -+ unsigned char f_ipdFirst[4]; -+ unsigned char f_cpd[4]; -+ unsigned char f_iauxBase[4]; -+ unsigned char f_caux[4]; -+ unsigned char f_rfdBase[4]; -+ unsigned char f_crfd[4]; -+ unsigned char f_bits1[1]; -+ unsigned char f_bits2[3]; -+ unsigned char f_padding[4]; -+}; -+ -+#define FDR_BITS1_LANG_BIG 0xF8 -+#define FDR_BITS1_LANG_SH_BIG 3 -+#define FDR_BITS1_LANG_LITTLE 0x1F -+#define FDR_BITS1_LANG_SH_LITTLE 0 -+ -+#define FDR_BITS1_FMERGE_BIG 0x04 -+#define FDR_BITS1_FMERGE_LITTLE 0x20 -+ -+#define FDR_BITS1_FREADIN_BIG 0x02 -+#define FDR_BITS1_FREADIN_LITTLE 0x40 -+ -+#define FDR_BITS1_FBIGENDIAN_BIG 0x01 -+#define FDR_BITS1_FBIGENDIAN_LITTLE 0x80 -+ -+#define FDR_BITS2_GLEVEL_BIG 0xC0 -+#define FDR_BITS2_GLEVEL_SH_BIG 6 -+#define FDR_BITS2_GLEVEL_LITTLE 0x03 -+#define FDR_BITS2_GLEVEL_SH_LITTLE 0 -+ -+/* We ignore the `reserved' field in bits2. */ -+ -+/* Procedure descriptor external record */ -+ -+struct pdr_ext { -+ unsigned char p_adr[8]; -+ unsigned char p_cbLineOffset[8]; -+ unsigned char p_isym[4]; -+ unsigned char p_iline[4]; -+ unsigned char p_regmask[4]; -+ unsigned char p_regoffset[4]; -+ unsigned char p_iopt[4]; -+ unsigned char p_fregmask[4]; -+ unsigned char p_fregoffset[4]; -+ unsigned char p_frameoffset[4]; -+ unsigned char p_lnLow[4]; -+ unsigned char p_lnHigh[4]; -+ unsigned char p_gp_prologue[1]; -+ unsigned char p_bits1[1]; -+ unsigned char p_bits2[1]; -+ unsigned char p_localoff[1]; -+ unsigned char p_framereg[2]; -+ unsigned char p_pcreg[2]; -+}; -+ -+#define PDR_BITS1_GP_USED_BIG 0x80 -+#define PDR_BITS1_REG_FRAME_BIG 0x40 -+#define PDR_BITS1_PROF_BIG 0x20 -+#define PDR_BITS1_RESERVED_BIG 0x1f -+#define PDR_BITS1_RESERVED_SH_LEFT_BIG 8 -+#define PDR_BITS2_RESERVED_BIG 0xff -+#define PDR_BITS2_RESERVED_SH_BIG 0 -+ -+#define PDR_BITS1_GP_USED_LITTLE 0x01 -+#define PDR_BITS1_REG_FRAME_LITTLE 0x02 -+#define PDR_BITS1_PROF_LITTLE 0x04 -+#define PDR_BITS1_RESERVED_LITTLE 0xf8 -+#define PDR_BITS1_RESERVED_SH_LITTLE 3 -+#define PDR_BITS2_RESERVED_LITTLE 0xff -+#define PDR_BITS2_RESERVED_SH_LEFT_LITTLE 5 -+ -+/* Line numbers */ -+ -+struct line_ext { -+ unsigned char l_line[4]; -+}; -+ -+/* Symbol external record */ -+ -+struct sym_ext { -+ unsigned char s_value[8]; -+ unsigned char s_iss[4]; -+ unsigned char s_bits1[1]; -+ unsigned char s_bits2[1]; -+ unsigned char s_bits3[1]; -+ unsigned char s_bits4[1]; -+}; -+ -+#define SYM_BITS1_ST_BIG 0xFC -+#define SYM_BITS1_ST_SH_BIG 2 -+#define SYM_BITS1_ST_LITTLE 0x3F -+#define SYM_BITS1_ST_SH_LITTLE 0 -+ -+#define SYM_BITS1_SC_BIG 0x03 -+#define SYM_BITS1_SC_SH_LEFT_BIG 3 -+#define SYM_BITS1_SC_LITTLE 0xC0 -+#define SYM_BITS1_SC_SH_LITTLE 6 -+ -+#define SYM_BITS2_SC_BIG 0xE0 -+#define SYM_BITS2_SC_SH_BIG 5 -+#define SYM_BITS2_SC_LITTLE 0x07 -+#define SYM_BITS2_SC_SH_LEFT_LITTLE 2 -+ -+#define SYM_BITS2_RESERVED_BIG 0x10 -+#define SYM_BITS2_RESERVED_LITTLE 0x08 -+ -+#define SYM_BITS2_INDEX_BIG 0x0F -+#define SYM_BITS2_INDEX_SH_LEFT_BIG 16 -+#define SYM_BITS2_INDEX_LITTLE 0xF0 -+#define SYM_BITS2_INDEX_SH_LITTLE 4 -+ -+#define SYM_BITS3_INDEX_SH_LEFT_BIG 8 -+#define SYM_BITS3_INDEX_SH_LEFT_LITTLE 4 -+ -+#define SYM_BITS4_INDEX_SH_LEFT_BIG 0 -+#define SYM_BITS4_INDEX_SH_LEFT_LITTLE 12 -+ -+/* External symbol external record */ -+ -+struct ext_ext { -+ struct sym_ext es_asym; -+ unsigned char es_bits1[1]; -+ unsigned char es_bits2[3]; -+ unsigned char es_ifd[4]; -+}; -+ -+#define EXT_BITS1_JMPTBL_BIG 0x80 -+#define EXT_BITS1_JMPTBL_LITTLE 0x01 -+ -+#define EXT_BITS1_COBOL_MAIN_BIG 0x40 -+#define EXT_BITS1_COBOL_MAIN_LITTLE 0x02 -+ -+#define EXT_BITS1_WEAKEXT_BIG 0x20 -+#define EXT_BITS1_WEAKEXT_LITTLE 0x04 -+ -+/* Dense numbers external record */ -+ -+struct dnr_ext { -+ unsigned char d_rfd[4]; -+ unsigned char d_index[4]; -+}; -+ -+/* Relative file descriptor */ -+ -+struct rfd_ext { -+ unsigned char rfd[4]; -+}; -+ -+/* Optimizer symbol external record */ -+ -+struct opt_ext { -+ unsigned char o_bits1[1]; -+ unsigned char o_bits2[1]; -+ unsigned char o_bits3[1]; -+ unsigned char o_bits4[1]; -+ struct rndx_ext o_rndx; -+ unsigned char o_offset[4]; -+}; -+ -+#define OPT_BITS2_VALUE_SH_LEFT_BIG 16 -+#define OPT_BITS2_VALUE_SH_LEFT_LITTLE 0 -+ -+#define OPT_BITS3_VALUE_SH_LEFT_BIG 8 -+#define OPT_BITS3_VALUE_SH_LEFT_LITTLE 8 -+ -+#define OPT_BITS4_VALUE_SH_LEFT_BIG 0 -+#define OPT_BITS4_VALUE_SH_LEFT_LITTLE 16 -diff --git a/include/elf/sw_64.h b/include/elf/sw_64.h -new file mode 100644 -index 00000000..6c547f83 ---- /dev/null -+++ b/include/elf/sw_64.h -@@ -0,0 +1,136 @@ -+/* SW_64 ELF support for BFD. -+ Copyright (C) 1996-2018 Free Software Foundation, Inc. -+ -+ By Eric Youngdale, . No processor supplement available -+ for this platform. -+ -+ This file is part of BFD, the Binary File Descriptor library. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+ MA 02110-1301, USA. */ -+ -+/* This file holds definitions specific to the SW_64 ELF ABI. Note -+ that most of this is not actually implemented by BFD. */ -+ -+#ifndef _ELF_SW_64_H -+#define _ELF_SW_64_H -+ -+/* Processor specific flags for the ELF header e_flags field. */ -+ -+/* All addresses must be below 2GB. */ -+#define EF_SW_64_32BIT 0x00000001 -+ -+/* All relocations needed for relaxation with code movement are present. */ -+#define EF_SW_64_CANRELAX 0x00000002 -+ -+/* Processor specific section flags. */ -+ -+/* This section must be in the global data area. */ -+#define SHF_SW_64_GPREL 0x10000000 -+ -+/* Section contains some sort of debugging information. The exact -+ format is unspecified. It's probably ECOFF symbols. */ -+#define SHT_SW_64_DEBUG 0x70000001 -+ -+/* Section contains register usage information. */ -+#define SHT_SW_64_REGINFO 0x70000002 -+ -+ -+/* Special values for the st_other field in the symbol table. */ -+ -+#define STO_SW_64_NOPV 0x80 -+#define STO_SW_64_STD_GPLOAD 0x88 -+ -+/* Special values for Elf64_Dyn tag. */ -+#define DT_SW_64_PLTRO DT_LOPROC -+ -+#include "elf/reloc-macros.h" -+ -+ -+unsigned long bfd_elf_sw_64_mach (flagword flags); -+ -+enum -+{ -+ E_SW_64_MACH_SW6A = 4, -+ E_SW_64_MACH_SW6B = 8, -+}; -+ -+#define EF_SW_64_MACH ~(0x3) -+ -+#define E_SW_64_MACH_SW6A 4 -+#define E_SW_64_MACH_SW6B 8 -+ -+/* Sw_64 relocs. */ -+START_RELOC_NUMBERS (elf_sw_64_reloc_type) -+ RELOC_NUMBER (R_SW_64_NONE, 0) /* No reloc */ -+ RELOC_NUMBER (R_SW_64_REFLONG, 1) /* Direct 32 bit */ -+ RELOC_NUMBER (R_SW_64_REFQUAD, 2) /* Direct 64 bit */ -+ RELOC_NUMBER (R_SW_64_GPREL32, 3) /* GP relative 32 bit */ -+ RELOC_NUMBER (R_SW_64_LITERAL, 4) /* GP relative 16 bit w/optimization */ -+ RELOC_NUMBER (R_SW_64_LITUSE, 5) /* Optimization hint for LITERAL */ -+ RELOC_NUMBER (R_SW_64_GPDISP, 6) /* Add displacement to GP */ -+ RELOC_NUMBER (R_SW_64_BRADDR, 7) /* PC+4 relative 23 bit shifted */ -+ RELOC_NUMBER (R_SW_64_HINT, 8) /* PC+4 relative 16 bit shifted */ -+ RELOC_NUMBER (R_SW_64_SREL16, 9) /* PC relative 16 bit */ -+ RELOC_NUMBER (R_SW_64_SREL32, 10) /* PC relative 32 bit */ -+ RELOC_NUMBER (R_SW_64_SREL64, 11) /* PC relative 64 bit */ -+ -+ /* Skip 12 - 16; deprecated ECOFF relocs. */ -+ -+ RELOC_NUMBER (R_SW_64_GPRELHIGH, 17) /* GP relative 32 bit, high 16 bits */ -+ RELOC_NUMBER (R_SW_64_GPRELLOW, 18) /* GP relative 32 bit, low 16 bits */ -+ RELOC_NUMBER (R_SW_64_GPREL16, 19) /* GP relative 16 bit */ -+ -+ /* Skip 20 - 23; deprecated ECOFF relocs. */ -+ -+ /* These relocations are specific to shared libraries. */ -+ RELOC_NUMBER (R_SW_64_COPY, 24) /* Copy symbol at runtime */ -+ RELOC_NUMBER (R_SW_64_GLOB_DAT, 25) /* Create GOT entry */ -+ RELOC_NUMBER (R_SW_64_JMP_SLOT, 26) /* Create PLT entry */ -+ RELOC_NUMBER (R_SW_64_RELATIVE, 27) /* Adjust by program base */ -+ -+ /* Like BRADDR, but assert that the source and target object file -+ share the same GP value, and adjust the target address for -+ STO_SW_64_STD_GPLOAD. */ -+ RELOC_NUMBER (R_SW_64_BRSGP, 28) -+ -+ /* Thread-Local Storage. */ -+ RELOC_NUMBER (R_SW_64_TLSGD, 29) -+ RELOC_NUMBER (R_SW_64_TLSLDM, 30) -+ RELOC_NUMBER (R_SW_64_DTPMOD64, 31) -+ RELOC_NUMBER (R_SW_64_GOTDTPREL, 32) -+ RELOC_NUMBER (R_SW_64_DTPREL64, 33) -+ RELOC_NUMBER (R_SW_64_DTPRELHI, 34) -+ RELOC_NUMBER (R_SW_64_DTPRELLO, 35) -+ RELOC_NUMBER (R_SW_64_DTPREL16, 36) -+ RELOC_NUMBER (R_SW_64_GOTTPREL, 37) -+ RELOC_NUMBER (R_SW_64_TPREL64, 38) -+ RELOC_NUMBER (R_SW_64_TPRELHI, 39) -+ RELOC_NUMBER (R_SW_64_TPRELLO, 40) -+ RELOC_NUMBER (R_SW_64_TPREL16, 41) -+ RELOC_NUMBER (R_SW_64_BR26ADDR, 42) -+ RELOC_NUMBER (R_SW_64_LITERAL_GOT, 43) /* GP relative 16 bit */ -+ -+END_RELOC_NUMBERS (R_SW_64_max) -+ -+#define LITUSE_SW_64_ADDR 0 -+#define LITUSE_SW_64_BASE 1 -+#define LITUSE_SW_64_BYTOFF 2 -+#define LITUSE_SW_64_JSR 3 -+#define LITUSE_SW_64_TLSGD 4 -+#define LITUSE_SW_64_TLSLDM 5 -+#define LITUSE_SW_64_JSRDIRECT 6 -+ -+#endif /* _ELF_SW_64_H */ -diff --git a/include/opcode/pe.h b/include/opcode/pe.h -new file mode 100644 -index 00000000..3000e9ac ---- /dev/null -+++ b/include/opcode/pe.h -@@ -0,0 +1,605 @@ -+/* pe.h - PE COFF header information -+ -+ Copyright (C) 1999-2018 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 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software Foundation, -+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -+#ifndef _PE_H -+#define _PE_H -+ -+#include "msdos.h" -+ -+/* NT specific file attributes. */ -+#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 -+#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 -+#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 -+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 -+#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 -+#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 -+#define IMAGE_FILE_16BIT_MACHINE 0x0040 -+#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 -+#define IMAGE_FILE_32BIT_MACHINE 0x0100 -+#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 -+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 -+#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 -+#define IMAGE_FILE_SYSTEM 0x1000 -+#define IMAGE_FILE_DLL 0x2000 -+#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 -+#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 -+ -+/* DllCharacteristics flag bits. The inconsistent naming may seem -+ odd, but that is how they are defined in the PE specification. */ -+#define IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 -+#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040 -+#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080 -+#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100 -+#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 -+#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 -+#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 -+#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 -+#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 -+ -+/* Additional flags to be set for section headers to allow the NT loader to -+ read and write to the section data (to replace the addresses of data in -+ dlls for one thing); also to execute the section in .text's case. */ -+#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 -+#define IMAGE_SCN_MEM_EXECUTE 0x20000000 -+#define IMAGE_SCN_MEM_READ 0x40000000 -+#define IMAGE_SCN_MEM_WRITE 0x80000000 -+ -+/* Section characteristics added for ppc-nt. */ -+ -+#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */ -+ -+#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */ -+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */ -+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */ -+ -+#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */ -+#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */ -+#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */ -+#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */ -+ -+#define IMAGE_SCN_MEM_FARDATA 0x00008000 -+ -+#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 -+#define IMAGE_SCN_MEM_16BIT 0x00020000 -+#define IMAGE_SCN_MEM_LOCKED 0x00040000 -+#define IMAGE_SCN_MEM_PRELOAD 0x00080000 -+ -+/* Bit position in the s_flags field where the alignment values start. */ -+#define IMAGE_SCN_ALIGN_POWER_BIT_POS 20 -+#define IMAGE_SCN_ALIGN_POWER_BIT_MASK 0x00f00000 -+#define IMAGE_SCN_ALIGN_POWER_NUM(val) \ -+ (((val) >> IMAGE_SCN_ALIGN_POWER_BIT_POS) - 1) -+#define IMAGE_SCN_ALIGN_POWER_CONST(val) \ -+ (((val) + 1) << IMAGE_SCN_ALIGN_POWER_BIT_POS) -+ -+#define IMAGE_SCN_ALIGN_1BYTES IMAGE_SCN_ALIGN_POWER_CONST (0) -+#define IMAGE_SCN_ALIGN_2BYTES IMAGE_SCN_ALIGN_POWER_CONST (1) -+#define IMAGE_SCN_ALIGN_4BYTES IMAGE_SCN_ALIGN_POWER_CONST (2) -+#define IMAGE_SCN_ALIGN_8BYTES IMAGE_SCN_ALIGN_POWER_CONST (3) -+/* Default alignment if no others are specified. */ -+#define IMAGE_SCN_ALIGN_16BYTES IMAGE_SCN_ALIGN_POWER_CONST (4) -+#define IMAGE_SCN_ALIGN_32BYTES IMAGE_SCN_ALIGN_POWER_CONST (5) -+#define IMAGE_SCN_ALIGN_64BYTES IMAGE_SCN_ALIGN_POWER_CONST (6) -+#define IMAGE_SCN_ALIGN_128BYTES IMAGE_SCN_ALIGN_POWER_CONST (7) -+#define IMAGE_SCN_ALIGN_256BYTES IMAGE_SCN_ALIGN_POWER_CONST (8) -+#define IMAGE_SCN_ALIGN_512BYTES IMAGE_SCN_ALIGN_POWER_CONST (9) -+#define IMAGE_SCN_ALIGN_1024BYTES IMAGE_SCN_ALIGN_POWER_CONST (10) -+#define IMAGE_SCN_ALIGN_2048BYTES IMAGE_SCN_ALIGN_POWER_CONST (11) -+#define IMAGE_SCN_ALIGN_4096BYTES IMAGE_SCN_ALIGN_POWER_CONST (12) -+#define IMAGE_SCN_ALIGN_8192BYTES IMAGE_SCN_ALIGN_POWER_CONST (13) -+ -+/* Encode alignment power into IMAGE_SCN_ALIGN bits of s_flags. */ -+#define COFF_ENCODE_ALIGNMENT(SECTION, ALIGNMENT_POWER) \ -+ ((SECTION).s_flags |= IMAGE_SCN_ALIGN_POWER_CONST ((ALIGNMENT_POWER) <= 13 \ -+ ? (ALIGNMENT_POWER) : 13)) -+#define COFF_DECODE_ALIGNMENT(X) \ -+ IMAGE_SCN_ALIGN_POWER_NUM ((X) & IMAGE_SCN_ALIGN_POWER_BIT_MASK) -+ -+#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */ -+#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */ -+#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */ -+#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */ -+ -+/* COMDAT selection codes. */ -+ -+#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */ -+#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */ -+#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */ -+#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */ -+#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */ -+ -+/* Machine numbers. */ -+ -+#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 -+#define IMAGE_FILE_MACHINE_ALPHA 0x0184 -+#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 -+#define IMAGE_FILE_MACHINE_SW_64 0x0184 -+#define IMAGE_FILE_MACHINE_SW_6464 0x0284 -+#define IMAGE_FILE_MACHINE_AM33 0x01d3 -+#define IMAGE_FILE_MACHINE_AMD64 0x8664 -+#define IMAGE_FILE_MACHINE_ARM 0x01c0 -+#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 -+#define IMAGE_FILE_MACHINE_CEE 0xc0ee -+#define IMAGE_FILE_MACHINE_CEF 0x0cef -+#define IMAGE_FILE_MACHINE_EBC 0x0ebc -+#define IMAGE_FILE_MACHINE_I386 0x014c -+#define IMAGE_FILE_MACHINE_IA64 0x0200 -+#define IMAGE_FILE_MACHINE_M32R 0x9041 -+#define IMAGE_FILE_MACHINE_M68K 0x0268 -+#define IMAGE_FILE_MACHINE_MIPS16 0x0266 -+#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 -+#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 -+#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 -+#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 -+#define IMAGE_FILE_MACHINE_R10000 0x0168 -+#define IMAGE_FILE_MACHINE_R3000 0x0162 -+#define IMAGE_FILE_MACHINE_R4000 0x0166 -+#define IMAGE_FILE_MACHINE_SH3 0x01a2 -+#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 -+#define IMAGE_FILE_MACHINE_SH3E 0x01a4 -+#define IMAGE_FILE_MACHINE_SH4 0x01a6 -+#define IMAGE_FILE_MACHINE_SH5 0x01a8 -+#define IMAGE_FILE_MACHINE_THUMB 0x01c2 -+#define IMAGE_FILE_MACHINE_TRICORE 0x0520 -+#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 -+#define IMAGE_FILE_MACHINE_AMD64 0x8664 -+ -+#define IMAGE_SUBSYSTEM_UNKNOWN 0 -+#define IMAGE_SUBSYSTEM_NATIVE 1 -+#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 -+#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 -+#define IMAGE_SUBSYSTEM_POSIX_CUI 7 -+#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 -+#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 -+#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 -+#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 -+#define IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 -+#define IMAGE_SUBSYSTEM_XBOX 14 -+ -+/* NT allows long filenames, we want to accommodate this. -+ This may break some of the bfd functions. */ -+#undef FILNMLEN -+#define FILNMLEN 18 /* # characters in a file name. */ -+ -+struct external_PEI_IMAGE_hdr -+{ -+ char nt_signature[4]; /* Required NT signature, 0x4550. */ -+ -+ /* From standard header. */ -+ char f_magic[2]; /* Magic number. */ -+ char f_nscns[2]; /* Number of sections. */ -+ char f_timdat[4]; /* Time & date stamp. */ -+ char f_symptr[4]; /* File pointer to symtab. */ -+ char f_nsyms[4]; /* Number of symtab entries. */ -+ char f_opthdr[2]; /* Sizeof(optional hdr). */ -+ char f_flags[2]; /* Flags. */ -+}; -+ -+struct external_PEI_filehdr -+{ -+ /* DOS header fields - always at offset zero in the EXE file. */ -+ char e_magic[2]; /* Magic number, 0x5a4d. */ -+ char e_cblp[2]; /* Bytes on last page of file, 0x90. */ -+ char e_cp[2]; /* Pages in file, 0x3. */ -+ char e_crlc[2]; /* Relocations, 0x0. */ -+ char e_cparhdr[2]; /* Size of header in paragraphs, 0x4. */ -+ char e_minalloc[2]; /* Minimum extra paragraphs needed, 0x0. */ -+ char e_maxalloc[2]; /* Maximum extra paragraphs needed, 0xFFFF. */ -+ char e_ss[2]; /* Initial (relative) SS value, 0x0. */ -+ char e_sp[2]; /* Initial SP value, 0xb8. */ -+ char e_csum[2]; /* Checksum, 0x0. */ -+ char e_ip[2]; /* Initial IP value, 0x0. */ -+ char e_cs[2]; /* Initial (relative) CS value, 0x0. */ -+ char e_lfarlc[2]; /* File address of relocation table, 0x40. */ -+ char e_ovno[2]; /* Overlay number, 0x0. */ -+ char e_res[4][2]; /* Reserved words, all 0x0. */ -+ char e_oemid[2]; /* OEM identifier (for e_oeminfo), 0x0. */ -+ char e_oeminfo[2]; /* OEM information; e_oemid specific, 0x0. */ -+ char e_res2[10][2]; /* Reserved words, all 0x0. */ -+ char e_lfanew[4]; /* File address of new exe header, usually 0x80. */ -+ char dos_message[16][4]; /* Other stuff, always follow DOS header. */ -+ -+ /* Note: additional bytes may be inserted before the signature. Use -+ the e_lfanew field to find the actual location of the NT signature. */ -+ -+ char nt_signature[4]; /* Required NT signature, 0x4550. */ -+ -+ /* From standard header. */ -+ char f_magic[2]; /* Magic number. */ -+ char f_nscns[2]; /* Number of sections. */ -+ char f_timdat[4]; /* Time & date stamp. */ -+ char f_symptr[4]; /* File pointer to symtab. */ -+ char f_nsyms[4]; /* Number of symtab entries. */ -+ char f_opthdr[2]; /* Sizeof(optional hdr). */ -+ char f_flags[2]; /* Flags. */ -+}; -+ -+#ifdef COFF_IMAGE_WITH_PE -+ -+/* The filehdr is only weird in images. */ -+ -+#undef FILHDR -+#define FILHDR struct external_PEI_filehdr -+#undef FILHSZ -+#define FILHSZ 152 -+ -+#endif /* COFF_IMAGE_WITH_PE */ -+ -+/* 32-bit PE a.out header: */ -+ -+typedef struct -+{ -+ AOUTHDR standard; -+ -+ /* NT extra fields; see internal.h for descriptions. */ -+ char ImageBase[4]; -+ char SectionAlignment[4]; -+ char FileAlignment[4]; -+ char MajorOperatingSystemVersion[2]; -+ char MinorOperatingSystemVersion[2]; -+ char MajorImageVersion[2]; -+ char MinorImageVersion[2]; -+ char MajorSubsystemVersion[2]; -+ char MinorSubsystemVersion[2]; -+ char Reserved1[4]; -+ char SizeOfImage[4]; -+ char SizeOfHeaders[4]; -+ char CheckSum[4]; -+ char Subsystem[2]; -+ char DllCharacteristics[2]; -+ char SizeOfStackReserve[4]; -+ char SizeOfStackCommit[4]; -+ char SizeOfHeapReserve[4]; -+ char SizeOfHeapCommit[4]; -+ char LoaderFlags[4]; -+ char NumberOfRvaAndSizes[4]; -+ /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */ -+ char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars. */ -+} PEAOUTHDR; -+ -+#undef AOUTSZ -+#define AOUTSZ (AOUTHDRSZ + 196) -+ -+/* Like PEAOUTHDR, except that the "standard" member has no BaseOfData -+ (aka data_start) member and that some of the members are 8 instead -+ of just 4 bytes long. */ -+typedef struct -+{ -+#ifdef AOUTHDRSZ64 -+ AOUTHDR64 standard; -+#else -+ AOUTHDR standard; -+#endif -+ /* NT extra fields; see internal.h for descriptions. */ -+ char ImageBase[8]; -+ char SectionAlignment[4]; -+ char FileAlignment[4]; -+ char MajorOperatingSystemVersion[2]; -+ char MinorOperatingSystemVersion[2]; -+ char MajorImageVersion[2]; -+ char MinorImageVersion[2]; -+ char MajorSubsystemVersion[2]; -+ char MinorSubsystemVersion[2]; -+ char Reserved1[4]; -+ char SizeOfImage[4]; -+ char SizeOfHeaders[4]; -+ char CheckSum[4]; -+ char Subsystem[2]; -+ char DllCharacteristics[2]; -+ char SizeOfStackReserve[8]; -+ char SizeOfStackCommit[8]; -+ char SizeOfHeapReserve[8]; -+ char SizeOfHeapCommit[8]; -+ char LoaderFlags[4]; -+ char NumberOfRvaAndSizes[4]; -+ /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */ -+ char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars. */ -+} PEPAOUTHDR; -+ -+#ifdef AOUTHDRSZ64 -+#define PEPAOUTSZ (AOUTHDRSZ64 + 196 + 5 * 4) /* = 240 */ -+#else -+#define PEPAOUTSZ 240 -+#endif -+ -+#undef E_FILNMLEN -+#define E_FILNMLEN 18 /* # characters in a file name. */ -+ -+/* Import Tyoes fot ILF format object files.. */ -+#define IMPORT_CODE 0 -+#define IMPORT_DATA 1 -+#define IMPORT_CONST 2 -+ -+/* Import Name Tyoes for ILF format object files. */ -+#define IMPORT_ORDINAL 0 -+#define IMPORT_NAME 1 -+#define IMPORT_NAME_NOPREFIX 2 -+#define IMPORT_NAME_UNDECORATE 3 -+ -+/* Weak external characteristics. */ -+#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 -+#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 -+#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 -+ -+/* Bigobj header. */ -+struct external_ANON_OBJECT_HEADER_BIGOBJ -+{ -+ /* ANON_OBJECT_HEADER_V2 header. */ -+ char Sig1[2]; -+ char Sig2[2]; -+ char Version[2]; -+ char Machine[2]; -+ char TimeDateStamp[4]; -+ char ClassID[16]; -+ char SizeOfData[4]; -+ char Flags[4]; -+ char MetaDataSize[4]; -+ char MetaDataOffset[4]; -+ -+ /* BIGOBJ specific. */ -+ char NumberOfSections[4]; -+ char PointerToSymbolTable[4]; -+ char NumberOfSymbols[4]; -+}; -+ -+#define FILHSZ_BIGOBJ (14 * 4) -+ -+struct external_SYMBOL_EX -+{ -+ union -+ { -+ char e_name[E_SYMNMLEN]; -+ -+ struct -+ { -+ char e_zeroes[4]; -+ char e_offset[4]; -+ } e; -+ } e; -+ -+ char e_value[4]; -+ char e_scnum[4]; -+ char e_type[2]; -+ char e_sclass[1]; -+ char e_numaux[1]; -+} ATTRIBUTE_PACKED ; -+ -+#define SYMENT_BIGOBJ struct external_SYMBOL_EX -+#define SYMESZ_BIGOBJ 20 -+ -+#define FILNMLEN_BIGOBJ 20 -+ -+union external_AUX_SYMBOL_EX -+{ -+ struct -+ { -+ char WeakDefaultSymIndex[4]; -+ char WeakSearchType[4]; -+ char rgbReserved[12]; -+ } Sym; -+ -+ struct -+ { -+ char Name[FILNMLEN_BIGOBJ]; -+ } File; -+ -+ struct -+ { -+ char Length[4]; /* Section length. */ -+ char NumberOfRelocations[2];/* # relocation entries. */ -+ char NumberOfLinenumbers[2];/* # line numbers. */ -+ char Checksum[4]; /* Section COMDAT checksum. */ -+ char Number[2]; /* COMDAT associated section index. */ -+ char Selection[1]; /* COMDAT selection number. */ -+ char bReserved[1]; -+ char HighNumber[2]; /* High bits of COMDAT associated sec. */ -+ char rgbReserved[2]; -+ } Section; -+} ATTRIBUTE_PACKED; -+ -+#define AUXENT_BIGOBJ union external_AUX_SYMBOL_EX -+#define AUXESZ_BIGOBJ 20 -+ -+/* .pdata/.xdata defines and structures for x64 PE+ for exception handling. */ -+ -+/* .pdata in exception directory. */ -+ -+struct pex64_runtime_function -+{ -+ bfd_vma rva_BeginAddress; -+ bfd_vma rva_EndAddress; -+ bfd_vma rva_UnwindData; -+}; -+ -+struct external_pex64_runtime_function -+{ -+ bfd_byte rva_BeginAddress[4]; -+ bfd_byte rva_EndAddress[4]; -+ bfd_byte rva_UnwindData[4]; -+}; -+ -+/* If the lowest significant bit is set for rva_UnwindData RVA, it -+ means that the unified RVA points to another pex64_runtime_function -+ that this entry shares the unwind_info block with. */ -+#define PEX64_IS_RUNTIME_FUNCTION_CHAINED(PTR_RTF) \ -+ (((PTR_RTF)->rva_UnwindData & 1) != 0) -+#define PEX64_GET_UNWINDDATA_UNIFIED_RVA(PTR_RTF) \ -+ ((PTR_RTF)->rva_UnwindData & ~1) -+ -+/* The unwind codes. */ -+#define UWOP_PUSH_NONVOL 0 -+#define UWOP_ALLOC_LARGE 1 -+#define UWOP_ALLOC_SMALL 2 -+#define UWOP_SET_FPREG 3 -+#define UWOP_SAVE_NONVOL 4 -+#define UWOP_SAVE_NONVOL_FAR 5 -+#define UWOP_SAVE_XMM 6 /* For version 1. */ -+#define UWOP_EPILOG 6 /* For version 2. */ -+#define UWOP_SAVE_XMM_FAR 7 /* For version 1 (deprecated). */ -+#define UWOP_SPARE 7 /* For version 2. */ -+#define UWOP_SAVE_XMM128 8 -+#define UWOP_SAVE_XMM128_FAR 9 -+#define UWOP_PUSH_MACHFRAME 10 -+ -+struct pex64_unwind_code -+{ -+ bfd_vma prologue_offset; -+ /* Contains Frame offset, or frame allocation size. */ -+ bfd_vma frame_addr; -+ unsigned int uwop_code : 4; -+ /* xmm, mm, or standard register from 0 - 15. */ -+ unsigned int reg : 4; -+ /* Used for UWOP_PUSH_MACHFRAME to indicate optional errorcode stack -+ argument. */ -+ unsigned int has_errorcode : 1; -+}; -+ -+struct external_pex64_unwind_code -+{ -+ bfd_byte dta[2]; -+}; -+ -+#define PEX64_UNWCODE_CODE(VAL) ((VAL) & 0xf) -+#define PEX64_UNWCODE_INFO(VAL) (((VAL) >> 4) & 0xf) -+ -+/* The unwind info. */ -+#define UNW_FLAG_NHANDLER 0 -+#define UNW_FLAG_EHANDLER 1 -+#define UNW_FLAG_UHANDLER 2 -+#define UNW_FLAG_FHANDLER 3 -+#define UNW_FLAG_CHAININFO 4 -+ -+#define UNW_FLAG_MASK 0x1f -+ -+struct pex64_unwind_info -+{ -+ bfd_vma SizeOfBlock; -+ bfd_byte Version; /* Values from 0 up to 7 are possible. */ -+ bfd_byte Flags; /* Values from 0 up to 31 are possible. */ -+ bfd_vma SizeOfPrologue; -+ bfd_vma CountOfCodes; /* Amount of pex64_unwind_code elements. */ -+ /* 0 = CFA, 1..15 are index of integer registers. */ -+ unsigned int FrameRegister : 4; -+ bfd_vma FrameOffset; -+ bfd_vma sizeofUnwindCodes; -+ bfd_byte *rawUnwindCodes; -+ bfd_byte *rawUnwindCodesEnd; -+ bfd_vma rva_ExceptionHandler; /* UNW_EHANDLER or UNW_FLAG_UHANDLER. */ -+ bfd_vma rva_BeginAddress; /* UNW_FLAG_CHAININFO. */ -+ bfd_vma rva_EndAddress; /* UNW_FLAG_CHAININFO. */ -+ bfd_vma rva_UnwindData; /* UNW_FLAG_CHAININFO. */ -+}; -+ -+struct external_pex64_unwind_info -+{ -+ bfd_byte Version_Flags; -+ bfd_byte SizeOfPrologue; -+ bfd_byte CountOfCodes; -+ bfd_byte FrameRegisterOffset; -+ /* external_pex64_unwind_code array. */ -+ /* bfd_byte handler[4]; */ -+ /* Optional language specific data. */ -+}; -+ -+struct external_pex64_scope -+{ -+ bfd_vma Count; -+}; -+ -+struct pex64_scope -+{ -+ bfd_byte Count[4]; -+}; -+ -+struct pex64_scope_entry -+{ -+ bfd_vma rva_BeginAddress; -+ bfd_vma rva_EndAddress; -+ bfd_vma rva_HandlerAddress; -+ bfd_vma rva_JumpAddress; -+}; -+#define PEX64_SCOPE_ENTRY_SIZE 16 -+ -+struct external_pex64_scope_entry -+{ -+ bfd_byte rva_BeginAddress[4]; -+ bfd_byte rva_EndAddress[4]; -+ bfd_byte rva_HandlerAddress[4]; -+ bfd_byte rva_JumpAddress[4]; -+}; -+ -+#define PEX64_UWI_VERSION(VAL) ((VAL) & 7) -+#define PEX64_UWI_FLAGS(VAL) (((VAL) >> 3) & 0x1f) -+#define PEX64_UWI_FRAMEREG(VAL) ((VAL) & 0xf) -+#define PEX64_UWI_FRAMEOFF(VAL) (((VAL) >> 4) & 0xf) -+#define PEX64_UWI_SIZEOF_UWCODE_ARRAY(VAL) \ -+ ((((VAL) + 1) & ~1) * 2) -+ -+#define PEX64_OFFSET_TO_UNWIND_CODE 0x4 -+ -+#define PEX64_OFFSET_TO_HANDLER_RVA (COUNTOFUNWINDCODES) \ -+ (PEX64_OFFSET_TO_UNWIND_CODE + \ -+ PEX64_UWI_SIZEOF_UWCODE_ARRAY(COUNTOFUNWINDCODES)) -+ -+#define PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) \ -+ (PEX64_OFFSET_TO_HANDLER_RVA(COUNTOFUNWINDCODES) + 4) -+ -+#define PEX64_SCOPE_ENTRY(COUNTOFUNWINDCODES, IDX) \ -+ (PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) + \ -+ PEX64_SCOPE_ENTRY_SIZE * (IDX)) -+ -+/* Extra structure used in debug directory. */ -+struct external_IMAGE_DEBUG_DIRECTORY -+{ -+ char Characteristics[4]; -+ char TimeDateStamp[4]; -+ char MajorVersion[2]; -+ char MinorVersion[2]; -+ char Type[4]; -+ char SizeOfData[4]; -+ char AddressOfRawData[4]; -+ char PointerToRawData[4]; -+}; -+ -+/* Extra structures used in codeview debug record. */ -+/* This is not part of the PE specification. */ -+ -+#define CVINFO_PDB70_CVSIGNATURE 0x53445352 // "RSDS" -+#define CVINFO_PDB20_CVSIGNATURE 0x3031424e // "NB10" -+#define CVINFO_CV50_CVSIGNATURE 0x3131424e // "NB11" -+#define CVINFO_CV41_CVSIGNATURE 0x3930424e // "NB09" -+ -+typedef struct _CV_INFO_PDB70 -+{ -+ char CvSignature[4]; -+ char Signature[16]; -+ char Age[4]; -+ char PdbFileName[]; -+} CV_INFO_PDB70; -+ -+typedef struct _CV_INFO_PDB20 -+{ -+ char CvHeader[4]; -+ char Offset[4]; -+ char Signature[4]; -+ char Age[4]; -+ char PdbFileName[]; -+} CV_INFO_PDB20; -+ -+#endif /* _PE_H */ -diff --git a/include/opcode/sw_64.h b/include/opcode/sw_64.h -new file mode 100644 -index 00000000..ade22c7e ---- /dev/null -+++ b/include/opcode/sw_64.h -@@ -0,0 +1,255 @@ -+/* sw_64.h -- Header file for Sw_64 opcode table -+ Copyright (C) 1996-2018 Free Software Foundation, Inc. -+ Contributed by Richard Henderson , -+ patterned after the PPC opcode table written by Ian Lance Taylor. -+ -+ This file is part of GDB, GAS, and the GNU binutils. -+ -+ GDB, GAS, and the GNU binutils are free software; you can redistribute -+ them and/or modify them under the terms of the GNU General Public -+ License as published by the Free Software Foundation; either version 3, -+ or (at your option) any later version. -+ -+ GDB, GAS, and the GNU binutils are distributed in the hope that they -+ will be useful, but WITHOUT ANY WARRANTY; without even the implied -+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -+ the GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this file; see the file COPYING3. If not, write to the Free -+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, -+ MA 02110-1301, USA. */ -+ -+#ifndef OPCODE_SW_64_H -+#define OPCODE_SW_64_H -+ -+/* The opcode table is an array of struct sw_64_opcode. */ -+ -+struct sw_64_opcode -+{ -+ /* The opcode name. */ -+ const char *name; -+ -+ /* The opcode itself. Those bits which will be filled in with -+ operands are zeroes. */ -+ unsigned opcode; -+ -+ /* The opcode mask. This is used by the disassembler. This is a -+ mask containing ones indicating those bits which must match the -+ opcode field, and zeroes indicating those bits which need not -+ match (and are presumably filled in by operands). */ -+ unsigned mask; -+ -+ /* One bit flags for the opcode. These are primarily used to -+ indicate specific processors and environments support the -+ instructions. The defined values are listed below. */ -+ unsigned flags; -+ -+ /* An array of operand codes. Each code is an index into the -+ operand table. They appear in the order which the operands must -+ appear in assembly code, and are terminated by a zero. */ -+ -+ unsigned char operands[5]; -+}; -+ -+/* The table itself is sorted by major opcode number, and is otherwise -+ in the order in which the disassembler should consider -+ instructions. */ -+extern const struct sw_64_opcode sw_64_opcodes[]; -+extern const unsigned sw_64_num_opcodes; -+ -+/* Values defined for the flags field of a struct sw_64_opcode. */ -+ -+/* CPU Availability */ -+#define AXP_OPCODE_SW6 0x0800 /* SW6 insns. */ -+#define AXP_OPCODE_SW6A 0x1000 /* SW6A insns. */ -+#define AXP_OPCODE_SW6B 0x2000 /* SW6B insns. */ -+ -+ -+#define AXP_OPCODE_NOPAL ((AXP_OPCODE_SW6|AXP_OPCODE_SW6A|AXP_OPCODE_SW6B)) -+ -+/* A macro to extract the major opcode from an instruction. */ -+#define AXP_OP(i) (((i) >> 26) & 0x3F) -+ -+#define AXP_LITOP(i) (((i) >> 26) & 0x3D) -+ -+/* The total number of major opcodes. */ -+#define AXP_NOPS 0x40 -+ -+ -+/* The operands table is an array of struct sw_64_operand. */ -+ -+struct sw_64_operand -+{ -+ /* The number of bits in the operand. */ -+ unsigned int bits : 5; -+ -+ /* How far the operand is left shifted in the instruction. */ -+ unsigned int shift : 5; -+ -+ /* The default relocation type for this operand. */ -+ signed int default_reloc : 16; -+ -+ /* One bit syntax flags. */ -+ unsigned int flags : 16; -+ -+ /* Insertion function. This is used by the assembler. To insert an -+ operand value into an instruction, check this field. -+ -+ If it is NULL, execute -+ i |= (op & ((1 << o->bits) - 1)) << o->shift; -+ (i is the instruction which we are filling in, o is a pointer to -+ this structure, and op is the opcode value; this assumes twos -+ complement arithmetic). -+ -+ If this field is not NULL, then simply call it with the -+ instruction and the operand value. It will return the new value -+ of the instruction. If the ERRMSG argument is not NULL, then if -+ the operand value is illegal, *ERRMSG will be set to a warning -+ string (the operand will be inserted in any case). If the -+ operand value is legal, *ERRMSG will be unchanged (most operands -+ can accept any value). */ -+ unsigned (*insert) (unsigned instruction, int op, const char **errmsg); -+ -+ /* Extraction function. This is used by the disassembler. To -+ extract this operand type from an instruction, check this field. -+ -+ If it is NULL, compute -+ op = ((i) >> o->shift) & ((1 << o->bits) - 1); -+ if ((o->flags & AXP_OPERAND_SIGNED) != 0 -+ && (op & (1 << (o->bits - 1))) != 0) -+ op -= 1 << o->bits; -+ (i is the instruction, o is a pointer to this structure, and op -+ is the result; this assumes twos complement arithmetic). -+ -+ If this field is not NULL, then simply call it with the -+ instruction value. It will return the value of the operand. If -+ the INVALID argument is not NULL, *INVALID will be set to -+ non-zero if this operand type can not actually be extracted from -+ this operand (i.e., the instruction does not match). If the -+ operand is valid, *INVALID will not be changed. */ -+ int (*extract) (unsigned instruction, int *invalid); -+}; -+ -+ -+#define ISA_UNKNOWN 0 /* Gas internal use. */ -+#define ISA_SW6A 4 -+#define ISA_SW6B 8 -+ -+#define CPU_UNKNOWN 0 /* Gas internal use. */ -+#define CPU_SW6A 4 -+#define CPU_SW6B 8 -+ -+#define EF_SW6A_FLGAS 4 /* Low 2-bit is '0'. */ -+#define EF_SW6B_FLGAS 8 -+ -+ -+/* Elements in the table are retrieved by indexing with values from -+ the operands field of the sw_64_opcodes table. */ -+ -+extern const struct sw_64_operand sw_64_operands[]; -+extern const unsigned sw_64_num_operands; -+ -+/* Values defined for the flags field of a struct sw_64_operand. */ -+ -+/* Mask for selecting the type for typecheck purposes */ -+#define AXP_OPERAND_TYPECHECK_MASK \ -+ (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA | AXP_OPERAND_IR | \ -+ AXP_OPERAND_FPR | AXP_OPERAND_RELATIVE | AXP_OPERAND_SIGNED | \ -+ AXP_OPERAND_UNSIGNED) -+ -+/* This operand does not actually exist in the assembler input. This -+ is used to support extended mnemonics, for which two operands fields -+ are identical. The assembler should call the insert function with -+ any op value. The disassembler should call the extract function, -+ ignore the return value, and check the value placed in the invalid -+ argument. */ -+#define AXP_OPERAND_FAKE 01 -+ -+/* The operand should be wrapped in parentheses rather than separated -+ from the previous by a comma. This is used for the load and store -+ instructions which want their operands to look like "Ra,disp(Rb)". */ -+#define AXP_OPERAND_PARENS 02 -+ -+/* Used in combination with PARENS, this supresses the supression of -+ the comma. This is used for "jmp Ra,(Rb),hint". */ -+#define AXP_OPERAND_COMMA 04 -+ -+/* This operand names an integer register. */ -+#define AXP_OPERAND_IR 010 -+ -+/* This operand names a floating point register. */ -+#define AXP_OPERAND_FPR 020 -+ -+/* This operand is a relative branch displacement. The disassembler -+ prints these symbolically if possible. */ -+#define AXP_OPERAND_RELATIVE 040 -+ -+/* This operand takes signed values. */ -+#define AXP_OPERAND_SIGNED 0100 -+ -+/* This operand takes unsigned values. This exists primarily so that -+ a flags value of 0 can be treated as end-of-arguments. */ -+#define AXP_OPERAND_UNSIGNED 0200 -+ -+/* Supress overflow detection on this field. This is used for hints. */ -+#define AXP_OPERAND_NOOVERFLOW 0400 -+ -+/* Mask for optional argument default value. */ -+#define AXP_OPERAND_OPTIONAL_MASK 07000 -+ -+/* This operand defaults to zero. This is used for jump hints. */ -+#define AXP_OPERAND_DEFAULT_ZERO 01000 -+ -+/* This operand should default to the first (real) operand and is used -+ in conjunction with AXP_OPERAND_OPTIONAL. This allows -+ "and $0,3,$0" to be written as "and $0,3", etc. I don't like -+ it, but it's what DEC does. */ -+#define AXP_OPERAND_DEFAULT_FIRST 02000 -+ -+/* Similarly, this operand should default to the second (real) operand. -+ This allows "negl $0" instead of "negl $0,$0". */ -+#define AXP_OPERAND_DEFAULT_SECOND 04000 -+ -+/* Similarly, this operand should default to the third (real) operand. -+ * This allows "selne $0,$1,$2,$2" to be written as "selne $0,$1,$2" */ -+#define AXP_OPERAND_DEFAULT_THIRD 0xa00 -+ -+ -+/* Register common names */ -+ -+#define AXP_REG_V0 0 -+#define AXP_REG_T0 1 -+#define AXP_REG_T1 2 -+#define AXP_REG_T2 3 -+#define AXP_REG_T3 4 -+#define AXP_REG_T4 5 -+#define AXP_REG_T5 6 -+#define AXP_REG_T6 7 -+#define AXP_REG_T7 8 -+#define AXP_REG_S0 9 -+#define AXP_REG_S1 10 -+#define AXP_REG_S2 11 -+#define AXP_REG_S3 12 -+#define AXP_REG_S4 13 -+#define AXP_REG_S5 14 -+#define AXP_REG_FP 15 -+#define AXP_REG_A0 16 -+#define AXP_REG_A1 17 -+#define AXP_REG_A2 18 -+#define AXP_REG_A3 19 -+#define AXP_REG_A4 20 -+#define AXP_REG_A5 21 -+#define AXP_REG_T8 22 -+#define AXP_REG_T9 23 -+#define AXP_REG_T10 24 -+#define AXP_REG_T11 25 -+#define AXP_REG_RA 26 -+#define AXP_REG_PV 27 -+#define AXP_REG_T12 27 -+#define AXP_REG_AT 28 -+#define AXP_REG_GP 29 -+#define AXP_REG_SP 30 -+#define AXP_REG_ZERO 31 -+ -+#endif /* OPCODE_SW_64_H */ -diff --git a/ld/emulparams/elf64sw_64.sh b/ld/emulparams/elf64sw_64.sh -new file mode 100644 -index 00000000..b2aa4740 ---- /dev/null -+++ b/ld/emulparams/elf64sw_64.sh -@@ -0,0 +1,36 @@ -+ENTRY=_start -+SCRIPT_NAME=elf -+ELFSIZE=64 -+TEMPLATE_NAME=elf -+EXTRA_EM_FILE=sw_64elf -+OUTPUT_FORMAT="elf64-sw_64" -+NO_REL_RELOCS=yes -+TEXT_START_ADDR="0x120000000" -+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" -+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)" -+ -+# for flags of elf file header -+if [ "$sw_cpu_type" = "sw_64sw6a" ]; then -+ ARCH=sw_64:4 -+elif [ "$sw_cpu_type" = "sw_64sw6b" ]; then -+ ARCH=sw_64:8 -+else -+ ARCH=sw_64 -+fi -+ -+MACHINE= -+GENERATE_SHLIB_SCRIPT=yes -+GENERATE_PIE_SCRIPT=yes -+ -+# Yes, we want duplicate .plt sections. The linker chooses the -+# appropriate one magically in sw_64_after_open. -+PLT=".plt ${RELOCATING-0} : SPECIAL { *(.plt) }" -+DATA_PLT=yes -+TEXT_PLT=yes -+ -+# Note that the number is always big-endian, thus we have to -+# reverse the digit string. -+NOP=0x5f07ff435f07ff43 -+ -+OTHER_READONLY_SECTIONS=" -+ .reginfo ${RELOCATING-0} : { *(.reginfo) }" -diff --git a/ld/emulparams/elf64sw_64_fbsd.sh b/ld/emulparams/elf64sw_64_fbsd.sh -new file mode 100644 -index 00000000..deef0352 ---- /dev/null -+++ b/ld/emulparams/elf64sw_64_fbsd.sh -@@ -0,0 +1,3 @@ -+source_sh ${srcdir}/emulparams/elf64sw_64.sh -+source_sh ${srcdir}/emulparams/elf_fbsd.sh -+OUTPUT_FORMAT="elf64-sw_64-freebsd" -diff --git a/ld/emulparams/elf64sw_64_nbsd.sh b/ld/emulparams/elf64sw_64_nbsd.sh -new file mode 100644 -index 00000000..234df284 ---- /dev/null -+++ b/ld/emulparams/elf64sw_64_nbsd.sh -@@ -0,0 +1,2 @@ -+source_sh ${srcdir}/emulparams/elf64sw_64.sh -+ENTRY=__start -diff --git a/ld/emulparams/sw_64.sh b/ld/emulparams/sw_64.sh -new file mode 100644 -index 00000000..17c49bd7 ---- /dev/null -+++ b/ld/emulparams/sw_64.sh -@@ -0,0 +1,3 @@ -+SCRIPT_NAME=sw_64 -+OUTPUT_FORMAT="ecoff-littlesw_64" -+ARCH=sw_64 -diff --git a/ld/emulparams/sw_64vms.sh b/ld/emulparams/sw_64vms.sh -new file mode 100644 -index 00000000..67029ebe ---- /dev/null -+++ b/ld/emulparams/sw_64vms.sh -@@ -0,0 +1,7 @@ -+SCRIPT_NAME=sw_64vms -+ -+OUTPUT_FORMAT="vms-sw_64" -+ARCH=sw_64 -+ -+COMPILE_IN=yes -+EXTRA_EM_FILE=vms -\ No newline at end of file -diff --git a/ld/emultempl/sw_64elf.em b/ld/emultempl/sw_64elf.em -new file mode 100644 -index 00000000..a6cf6a80 ---- /dev/null -+++ b/ld/emultempl/sw_64elf.em -@@ -0,0 +1,152 @@ -+# This shell script emits a C file. -*- C -*- -+# Copyright (C) 2003-2015 Free Software Foundation, Inc. -+# -+# This file is part of the 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 3 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+# MA 02110-1301, USA. -+# -+ -+# This file is sourced from elf.em, and defines extra sw_64 -+# specific routines. -+# -+fragment <next) -+ { -+ if (os->constraint == SPECIAL && strcmp (os->name, ".plt") == 0) -+ { -+ if (num_plt < 2) -+ plt_os[num_plt] = os; -+ ++num_plt; -+ } -+ } -+ -+ if (num_plt == 2) -+ { -+ plt_os[0]->constraint = elf64_sw_64_use_secureplt ? 0 : -1; -+ plt_os[1]->constraint = elf64_sw_64_use_secureplt ? -1 : 0; -+ } -+ } -+ -+ gld${EMULATION_NAME}_after_open (); -+} -+ -+static void -+sw_64_after_parse (void) -+{ -+ link_info.relax_pass = 2; -+ if (limit_32bit -+ && !bfd_link_pic (&link_info) -+ && !bfd_link_relocatable (&link_info)) -+ lang_section_start (".interp", -+ exp_binop ('+', -+ exp_intop (SW_64_TEXT_START_32BIT), -+ exp_nameop (SIZEOF_HEADERS, NULL)), -+ NULL); -+ -+ ldelf_after_parse (); -+} -+ -+static void -+sw_64_before_allocation (void) -+{ -+ /* Call main function; we're just extending it. */ -+ gld${EMULATION_NAME}_before_allocation (); -+ -+ /* Add -relax if -O, not -r, and not explicitly disabled. */ -+ if (link_info.optimize -+ && !bfd_link_relocatable (&link_info) -+ && ! RELAXATION_DISABLED_BY_USER) -+ ENABLE_RELAXATION; -+} -+ -+static void -+sw_64_finish (void) -+{ -+ if (limit_32bit) -+ elf_elfheader (link_info.output_bfd)->e_flags |= EF_SW_64_32BIT; -+ -+ finish_default (); -+} -+EOF -+ -+# Define some shell vars to insert bits of code into the standard elf -+# parse_args and list_options functions. -+# -+PARSE_AND_LIST_PROLOGUE=' -+#define OPTION_TASO 300 -+#define OPTION_SECUREPLT (OPTION_TASO + 1) -+#define OPTION_NO_SECUREPLT (OPTION_SECUREPLT + 1) -+' -+ -+PARSE_AND_LIST_LONGOPTS=' -+ { "taso", no_argument, NULL, OPTION_TASO }, -+ { "secureplt", no_argument, NULL, OPTION_SECUREPLT }, -+ { "no-secureplt", no_argument, NULL, OPTION_NO_SECUREPLT }, -+' -+ -+PARSE_AND_LIST_OPTIONS=' -+ fprintf (file, _("\ -+ --taso Load executable in the lower 31-bit addressable\n\ -+ virtual address range.\n\ -+ --secureplt Force PLT in text segment.\n\ -+ --no-secureplt Force PLT in data segment.\n\ -+")); -+' -+ -+PARSE_AND_LIST_ARGS_CASES=' -+ case OPTION_TASO: -+ limit_32bit = 1; -+ break; -+ case OPTION_SECUREPLT: -+ elf64_sw_64_use_secureplt = true; -+ break; -+ case OPTION_NO_SECUREPLT: -+ elf64_sw_64_use_secureplt = false; -+ break; -+' -+ -+# Put these extra sw_64 routines in ld_${EMULATION_NAME}_emulation -+# -+LDEMUL_AFTER_OPEN=sw_64_after_open -+LDEMUL_AFTER_PARSE=sw_64_after_parse -+LDEMUL_BEFORE_ALLOCATION=sw_64_before_allocation -+LDEMUL_FINISH=sw_64_finish -diff --git a/ld/scripttempl/sw_64.sc b/ld/scripttempl/sw_64.sc -new file mode 100644 -index 00000000..10bbcfb5 ---- /dev/null -+++ b/ld/scripttempl/sw_64.sc -@@ -0,0 +1,87 @@ -+# Linker script for Sw_64 systems. -+# Ian Lance Taylor . -+# These variables may be overridden by the emulation file. The -+# defaults are appropriate for an Sw_64 running OSF/1. -+# -+# Copyright (C) 2014-2020 Free Software Foundation, Inc. -+# -+# Copying and distribution of this file, with or without modification, -+# are permitted in any medium without royalty provided the copyright -+# notice and this notice are preserved. -+ -+test -z "$ENTRY" && ENTRY=__start -+test -z "$TEXT_START_ADDR" && TEXT_START_ADDR="0x120000000 + SIZEOF_HEADERS" -+if test "x$LD_FLAG" = "xn" -o "x$LD_FLAG" = "xN"; then -+ DATA_ADDR=. -+else -+ test -z "$DATA_ADDR" && DATA_ADDR=0x140000000 -+fi -+cat <. -+# -+# Copyright (C) 2014-2020 Free Software Foundation, Inc. -+# -+# Copying and distribution of this file, with or without modification, -+# are permitted in any medium without royalty provided the copyright -+# notice and this notice are preserved. -+ -+PAGESIZE=0x10000 -+ -+cat <, -+ patterned after the PPC opcode handling written by Ian Lance Taylor. -+ -+ This file is part of libopcodes. -+ -+ This library is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3, or (at your option) -+ any later version. -+ -+ It is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this file; see the file COPYING. If not, write to the Free -+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA -+ 02110-1301, USA. */ -+ -+#include "sysdep.h" -+#include -+#include "disassemble.h" -+#include "opcode/sw_64.h" -+ -+/* OSF register names. */ -+ -+static const char * const osf_regnames[64] = { -+ "$r0", "$r1", "$r2", "$r3" , "$r4", "$r5", "$r6", "$r7", -+ "$r8", "$r9", "$r10", "$r11" , "$r12", "$r13", "$r14", "fp", -+ "$r16", "$r17", "$r18", "$r19" , "$r20", "$r21", "$r22", "$r23", -+ "$r24", "$r25", "ra", "$r27" , "$r28", "$r29", "sp", "$r31", -+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", -+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", -+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", -+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" -+}; -+ -+/* VMS register names. */ -+ -+static const char * const vms_regnames[64] = { -+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", -+ "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", -+ "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23", -+ "R24", "AI", "RA", "PV", "AT", "FP", "SP", "RZ", -+ "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", -+ "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", -+ "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", -+ "F24", "F25", "F26", "F27", "F28", "F29", "F30", "FZ" -+}; -+ -+/* Disassemble Sw_64 instructions. */ -+ -+int -+print_insn_sw_64 (bfd_vma memaddr, struct disassemble_info *info) -+{ -+ static const struct sw_64_opcode *opcode_index[AXP_NOPS+1]; -+ const char * const * regnames; -+ const struct sw_64_opcode *opcode, *opcode_end; -+ const unsigned char *opindex; -+ unsigned insn, op, isa_mask; -+ int need_comma; -+ -+ /* Initialize the majorop table the first time through */ -+ if (!opcode_index[0]) -+ { -+ opcode = sw_64_opcodes; -+ opcode_end = opcode + sw_64_num_opcodes; -+ -+ for (op = 0; op < AXP_NOPS; ++op) -+ { -+ opcode_index[op] = opcode; -+ if ((AXP_LITOP (opcode->opcode) != 0x10) -+ && (AXP_LITOP (opcode->opcode) != 0x11)) -+ { -+ while (opcode < opcode_end && op == AXP_OP (opcode->opcode)) -+ ++opcode; -+ } -+ else -+ { -+ while (opcode < opcode_end && op == AXP_LITOP (opcode->opcode)) -+ ++opcode; -+ } -+ } -+ opcode_index[op] = opcode; -+ } -+ -+ if (info->flavour == bfd_target_evax_flavour) -+ regnames = vms_regnames; -+ else -+ regnames = osf_regnames; -+ -+ isa_mask = AXP_OPCODE_NOPAL; -+ switch (info->mach) -+ { -+ case bfd_mach_sw_64_sw6a: -+ isa_mask |= AXP_OPCODE_SW6 | AXP_OPCODE_SW6A; -+ break; -+ case bfd_mach_sw_64_sw6b: -+ isa_mask |= AXP_OPCODE_SW6 | AXP_OPCODE_SW6B; -+ break; -+ } -+ -+ /* Read the insn into a host word */ -+ { -+ bfd_byte buffer[4]; -+ int status = (*info->read_memory_func) (memaddr, buffer, 4, info); -+ if (status != 0) -+ { -+ (*info->memory_error_func) (status, memaddr, info); -+ return -1; -+ } -+ insn = bfd_getl32 (buffer); -+ } -+ -+ /* Get the major opcode of the instruction. */ -+ -+ if((AXP_LITOP (insn)==0x10) || (AXP_LITOP (insn)==0x11)) -+ op = AXP_LITOP (insn); -+ else if((AXP_OP(insn) & 0x3C) == 0x14 ) //logx -+ op=0x14; -+ else -+ op = AXP_OP (insn); -+ -+ /* Find the first match in the opcode table. */ -+ opcode_end = opcode_index[op + 1]; -+ for (opcode = opcode_index[op]; opcode < opcode_end; ++opcode) -+ { -+ if ((insn ^ opcode->opcode) & opcode->mask) -+ continue; -+ -+ if (!(opcode->flags & isa_mask)) -+ continue; -+ -+ /* Make two passes over the operands. First see if any of them -+ have extraction functions, and, if they do, make sure the -+ instruction is valid. */ -+ { -+ int invalid = 0; -+ for (opindex = opcode->operands; *opindex != 0; opindex++) -+ { -+ const struct sw_64_operand *operand = sw_64_operands + *opindex; -+ if (operand->extract) -+ (*operand->extract) (insn, &invalid); -+ } -+ if (invalid) -+ continue; -+ } -+ -+ /* The instruction is valid. */ -+ goto found; -+ } -+ -+ /* No instruction found */ -+ (*info->fprintf_func) (info->stream, ".long %#08x", insn); -+ -+ return 4; -+ -+found: -+ if (!strncmp ("sys_call", opcode->name,8)) -+ { -+ if (insn & (0x1 << 25)) -+ (*info->fprintf_func) (info->stream, "%s", "sys_call"); -+ else -+ (*info->fprintf_func) (info->stream, "%s", "sys_call/b"); -+ } -+ else -+ (*info->fprintf_func) (info->stream, "%s", opcode->name); -+ -+/* get zz[7:6] and zz[5:0] to form truth for vlog */ -+ if (!strcmp(opcode->name,"vlog")) -+ { -+ unsigned int truth; -+ char tr[4]; -+ truth = (AXP_OP (insn) & 3) << 6; -+ truth = truth | ((insn & 0xFC00) >> 10); -+ sprintf (tr,"%x",truth); -+ (*info->fprintf_func) (info->stream, "%s", tr); -+ } -+ if (opcode->operands[0] != 0) -+ (*info->fprintf_func) (info->stream, "\t"); -+ -+ /* Now extract and print the operands. */ -+ need_comma = 0; -+ for (opindex = opcode->operands; *opindex != 0; opindex++) -+ { -+ const struct sw_64_operand *operand = sw_64_operands + *opindex; -+ int value; -+ -+ /* Operands that are marked FAKE are simply ignored. We -+ already made sure that the extract function considered -+ the instruction to be valid. */ -+ if ((operand->flags & AXP_OPERAND_FAKE) != 0) -+ continue; -+ -+ /* Extract the value from the instruction. */ -+ if (operand->extract) -+ value = (*operand->extract) (insn, (int *) NULL); -+ else -+ { -+ value = (insn >> operand->shift) & ((1 << operand->bits) - 1); -+ if (operand->flags & AXP_OPERAND_SIGNED) -+ { -+ int signbit = 1 << (operand->bits - 1); -+ value = (value ^ signbit) - signbit; -+ } -+ } -+ -+ if (need_comma && -+ ((operand->flags & (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA)) -+ != AXP_OPERAND_PARENS)) -+ { -+ (*info->fprintf_func) (info->stream, ","); -+ } -+ if (operand->flags & AXP_OPERAND_PARENS) -+ (*info->fprintf_func) (info->stream, "("); -+ -+ /* Print the operand as directed by the flags. */ -+ if (operand->flags & AXP_OPERAND_IR) -+ (*info->fprintf_func) (info->stream, "%s", regnames[value]); -+ else if (operand->flags & AXP_OPERAND_FPR) -+ (*info->fprintf_func) (info->stream, "%s", regnames[value + 32]); -+ else if (operand->flags & AXP_OPERAND_RELATIVE) -+ (*info->print_address_func) (memaddr + 4 + value, info); -+ else if (operand->flags & AXP_OPERAND_SIGNED) -+ (*info->fprintf_func) (info->stream, "%d", value); -+ else -+ (*info->fprintf_func) (info->stream, "%#x", value); -+ -+ if (operand->flags & AXP_OPERAND_PARENS) -+ (*info->fprintf_func) (info->stream, ")"); -+ need_comma = 1; -+ } -+ -+ return 4; -+} -diff --git a/opcodes/sw_64-opc.c b/opcodes/sw_64-opc.c -new file mode 100644 -index 00000000..aefea498 ---- /dev/null -+++ b/opcodes/sw_64-opc.c -@@ -0,0 +1,1055 @@ -+/* sw_64-opc.c -- Sw_64 AXP opcode list -+ Copyright (C) 1996-2018 Free Software Foundation, Inc. -+ Contributed by Richard Henderson , -+ patterned after the PPC opcode handling written by Ian Lance Taylor. -+ -+ This file is part of libopcodes. -+ -+ This library is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3, or (at your option) -+ any later version. -+ -+ It is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this file; see the file COPYING. If not, write to the -+ Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA -+ 02110-1301, USA. */ -+ -+#include "sysdep.h" -+#include -+#include "opcode/sw_64.h" -+#include "bfd.h" -+#include "opintl.h" -+ -+/* This file holds the Sw_64 AXP opcode table. The opcode table includes -+ almost all of the extended instruction mnemonics. This permits the -+ disassembler to use them, and simplifies the assembler logic, at the -+ cost of increasing the table size. The table is strictly constant -+ data, so the compiler should be able to put it in the text segment. -+ -+ This file also holds the operand table. All knowledge about inserting -+ and extracting operands from instructions is kept in this file. -+ -+ The information for the base instruction set was compiled from the -+ _Sw_64 Architecture Handbook_, Digital Order Number EC-QD2KB-TE, -+ version 2. -+ */ -+ -+/* The RB field when it is the same as the RA field in the same insn. -+ This operand is marked fake. The insertion function just copies -+ the RA field into the RB field, and the extraction function just -+ checks that the fields are the same. */ -+ -+static unsigned -+insert_rba (unsigned insn, -+ int value ATTRIBUTE_UNUSED, -+ const char **errmsg ATTRIBUTE_UNUSED) -+{ -+ return insn | (((insn >> 21) & 0x1f) << 16); -+} -+ -+static int -+extract_rba (unsigned insn, int *invalid) -+{ -+ if (invalid != (int *) NULL -+ && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f)) -+ *invalid = 1; -+ return 0; -+} -+ -+/* The same for the RC field. */ -+ -+static unsigned -+insert_rca (unsigned insn, -+ int value ATTRIBUTE_UNUSED, -+ const char **errmsg ATTRIBUTE_UNUSED) -+{ -+ return insn | ((insn >> 21) & 0x1f); -+} -+ -+static int -+extract_rca (unsigned insn, int *invalid) -+{ -+ if (invalid != (int *) NULL -+ && ((insn >> 21) & 0x1f) != (insn & 0x1f)) -+ *invalid = 1; -+ return 0; -+} -+ -+static unsigned -+insert_rdc (unsigned insn, -+ int value ATTRIBUTE_UNUSED, -+ const char **errmsg ATTRIBUTE_UNUSED) -+{ -+ return insn | ((insn >> 5) & 0x1f); -+} -+ -+static int -+extract_rdc (unsigned insn, int *invalid) -+{ -+ if (invalid != (int *) NULL -+ && ((insn >> 5) & 0x1f) != (insn & 0x1f)) -+ *invalid = 1; -+ return 0; -+} -+ -+/* Fake arguments in which the registers must be set to ZERO. */ -+ -+static unsigned -+insert_za (unsigned insn, -+ int value ATTRIBUTE_UNUSED, -+ const char **errmsg ATTRIBUTE_UNUSED) -+{ -+ return insn | (31 << 21); -+} -+ -+static int -+extract_za (unsigned insn, int *invalid) -+{ -+ if (invalid != (int *) NULL && ((insn >> 21) & 0x1f) != 31) -+ *invalid = 1; -+ return 0; -+} -+ -+static unsigned -+insert_zb (unsigned insn, -+ int value ATTRIBUTE_UNUSED, -+ const char **errmsg ATTRIBUTE_UNUSED) -+{ -+ return insn | (31 << 16); -+} -+ -+static int -+extract_zb (unsigned insn, int *invalid) -+{ -+ if (invalid != (int *) NULL && ((insn >> 16) & 0x1f) != 31) -+ *invalid = 1; -+ return 0; -+} -+ -+static unsigned -+insert_zc (unsigned insn, -+ int value ATTRIBUTE_UNUSED, -+ const char **errmsg ATTRIBUTE_UNUSED) -+{ -+ return insn | 31; -+} -+ -+static int -+extract_zc (unsigned insn, int *invalid) -+{ -+ if (invalid != (int *) NULL && (insn & 0x1f) != 31) -+ *invalid = 1; -+ return 0; -+} -+ -+ -+/* The displacement field of a Branch format insn. */ -+ -+static unsigned -+insert_bdisp (unsigned insn, int value, const char **errmsg) -+{ -+ if (errmsg != (const char **)NULL && (value & 3)) -+ *errmsg = _("branch operand unaligned"); -+ return insn | ((value / 4) & 0x1FFFFF); -+} -+ -+static int -+extract_bdisp (unsigned insn, int *invalid ATTRIBUTE_UNUSED) -+{ -+ return 4 * (((insn & 0x1FFFFF) ^ 0x100000) - 0x100000); -+} -+ -+/* The hint field of a JMP/JSR insn. */ -+ -+/* sw use 16 bits hint disp. */ -+static unsigned -+insert_jhint (unsigned insn, int value, const char **errmsg) -+{ -+ if (errmsg != (const char **)NULL && (value & 3)) -+ *errmsg = _("jump hint unaligned"); -+ return insn | ((value / 4) & 0xFFFF); -+} -+ -+static int -+extract_jhint (unsigned insn, int *invalid ATTRIBUTE_UNUSED) -+{ -+ return 4 * (((insn & 0xFFFF) ^ 0x8000) - 0x8000); -+} -+ -+/* The hint field of an SW6 HW_JMP/JSR insn. */ -+ -+static unsigned -+insert_sw6hwjhint (unsigned insn, int value, const char **errmsg) -+{ -+ if (errmsg != (const char **)NULL && (value & 3)) -+ *errmsg = _("jump hint unaligned"); -+ return insn | ((value / 4) & 0x1FFF); -+} -+ -+static int -+extract_sw6hwjhint (unsigned insn, int *invalid ATTRIBUTE_UNUSED) -+{ -+ return 4 * (((insn & 0x1FFF) ^ 0x1000) - 0x1000); -+} -+ -+/* The operands table. */ -+ -+const struct sw_64_operand sw_64_operands[] = -+{ -+ /* The fields are bits, shift, insert, extract, flags */ -+ /* The zero index is used to indicate end-of-list */ -+#define UNUSED 0 -+ { 0, 0, 0, 0, 0, 0 }, -+ -+ /* The plain integer register fields. */ -+#define RA (UNUSED + 1) -+ { 5, 21, 0, AXP_OPERAND_IR, 0, 0 }, -+#define RB (RA + 1) -+ { 5, 16, 0, AXP_OPERAND_IR, 0, 0 }, -+#define RC (RB + 1) -+ { 5, 0, 0, AXP_OPERAND_IR, 0, 0 }, -+ -+ /* The plain fp register fields. */ -+#define FA (RC + 1) -+ { 5, 21, 0, AXP_OPERAND_FPR, 0, 0 }, -+#define FB (FA + 1) -+ { 5, 16, 0, AXP_OPERAND_FPR, 0, 0 }, -+#define FC (FB + 1) -+ { 5, 0, 0, AXP_OPERAND_FPR, 0, 0 }, -+ -+ /* The integer registers when they are ZERO. */ -+#define ZA (FC + 1) -+ { 5, 21, 0, AXP_OPERAND_FAKE, insert_za, extract_za }, -+#define ZB (ZA + 1) -+ { 5, 16, 0, AXP_OPERAND_FAKE, insert_zb, extract_zb }, -+#define ZC (ZB + 1) -+ { 5, 0, 0, AXP_OPERAND_FAKE, insert_zc, extract_zc }, -+ -+ /* The RB field when it needs parentheses. */ -+#define PRB (ZC + 1) -+ { 5, 16, 0, AXP_OPERAND_IR|AXP_OPERAND_PARENS, 0, 0 }, -+ -+ /* The RB field when it needs parentheses _and_ a preceding comma. */ -+#define CPRB (PRB + 1) -+ { 5, 16, 0, -+ AXP_OPERAND_IR|AXP_OPERAND_PARENS|AXP_OPERAND_COMMA, 0, 0 }, -+ -+ /* The RB field when it must be the same as the RA field. */ -+#define RBA (CPRB + 1) -+ { 5, 16, 0, AXP_OPERAND_FAKE, insert_rba, extract_rba }, -+ -+ /* The RC field when it must be the same as the RB field. */ -+#define RCA (RBA + 1) -+ { 5, 0, 0, AXP_OPERAND_FAKE, insert_rca, extract_rca }, -+ -+#define RDC (RCA + 1) -+ { 5, 0, 0, AXP_OPERAND_FAKE, insert_rdc, extract_rdc }, -+ -+ /* The RC field when it can *default* to RA. */ -+#define DRC1 (RDC + 1) -+ { 5, 0, 0, -+ AXP_OPERAND_IR|AXP_OPERAND_DEFAULT_FIRST, 0, 0 }, -+ -+ /* The RC field when it can *default* to RB. */ -+#define DRC2 (DRC1 + 1) -+ { 5, 0, 0, -+ AXP_OPERAND_IR|AXP_OPERAND_DEFAULT_SECOND, 0, 0 }, -+ -+ /* The RD field when it can *default* to RC. */ -+#define DRC3 (DRC2 + 1) -+ { 5, 0, 0, -+ AXP_OPERAND_IR|AXP_OPERAND_DEFAULT_THIRD, 0, 0 }, -+ -+ /* The FC field when it can *default* to RA. */ -+#define DFC1 (DRC3 + 1) -+ { 5, 0, 0, -+ AXP_OPERAND_FPR|AXP_OPERAND_DEFAULT_FIRST, 0, 0 }, -+ -+ /* The FC field when it can *default* to RB. */ -+#define DFC2 (DFC1 + 1) -+ { 5, 0, 0, -+ AXP_OPERAND_FPR|AXP_OPERAND_DEFAULT_SECOND, 0, 0 }, -+ -+ /* The FD field when it can *default* to FC. */ -+#define DFC3 (DFC2 + 1) -+ { 5, 0, 0, -+ AXP_OPERAND_FPR|AXP_OPERAND_DEFAULT_THIRD, 0, 0 }, -+ -+ /* The unsigned 8-bit literal of Operate format insns. */ -+#define LIT (DFC3 + 1) -+ { 8, 13, -LIT, AXP_OPERAND_UNSIGNED, 0, 0 }, -+ -+ /* The signed 16-bit displacement of Memory format insns. From here -+ we can't tell what relocation should be used, so don't use a default. */ -+#define MDISP (LIT + 1) -+ { 16, 0, -MDISP, AXP_OPERAND_SIGNED, 0, 0 }, -+ -+ /* The signed "23-bit" aligned displacement of Branch format insns. */ -+#define BDISP (MDISP + 1) -+ { 21, 0, BFD_RELOC_23_PCREL_S2, -+ AXP_OPERAND_RELATIVE, insert_bdisp, extract_bdisp }, -+ -+ /* The 25-bit PALcode function. */ -+#define PALFN (BDISP + 1) -+ { 25, 0, -PALFN, AXP_OPERAND_UNSIGNED, 0, 0 }, -+ -+ /* sw jsr/ret insntructions has no function bits. */ -+ /* The optional signed "16-bit" aligned displacement of the JMP/JSR hint. */ -+#define JMPHINT (PALFN + 1) -+ { 16, 0, BFD_RELOC_SW_64_HINT, -+ AXP_OPERAND_RELATIVE|AXP_OPERAND_DEFAULT_ZERO|AXP_OPERAND_NOOVERFLOW, -+ insert_jhint, extract_jhint }, -+ -+ /* The optional hint to RET/JSR_COROUTINE. */ -+#define RETHINT (JMPHINT + 1) -+ { 16, 0, -RETHINT, -+ AXP_OPERAND_UNSIGNED|AXP_OPERAND_DEFAULT_ZERO, 0, 0 }, -+ -+#define SW6HWDISP (RETHINT + 1) -+ {12, 0, -SW6HWDISP, AXP_OPERAND_SIGNED, 0, 0 }, -+ -+ /* The 16-bit combined index/scoreboard mask for the sw6 -+ hw_m[ft]pr (pal19/pal1d) insns. */ -+#define SW6HWINDEX (SW6HWDISP + 1) -+ { 16, 0, -SW6HWINDEX, AXP_OPERAND_UNSIGNED, 0, 0 }, -+ -+ /* The 13-bit branch hint for the sw6 hw_jmp/jsr (pal1e) insn. */ -+#define SW6HWJMPHINT (SW6HWINDEX+ 1) -+ { 8, 0, -SW6HWJMPHINT, -+ AXP_OPERAND_RELATIVE|AXP_OPERAND_DEFAULT_ZERO|AXP_OPERAND_NOOVERFLOW, -+ insert_sw6hwjhint, extract_sw6hwjhint }, -+ -+ /* for the third operand of ternary operands integer insn. */ -+#define R3 (SW6HWJMPHINT + 1) -+ { 5, 5, 0, AXP_OPERAND_IR, 0, 0 }, -+ -+ /* The plain fp register fields */ -+#define F3 (R3 + 1) -+ { 5, 5, 0, AXP_OPERAND_FPR, 0, 0 }, -+ -+/* sw simd settle instruction lit */ -+#define FMALIT (F3 + 1) -+ { 5, 5, -FMALIT, AXP_OPERAND_UNSIGNED, 0, 0 },//V1.1 -+ -+/*for pal to check disp which must be plus sign and less than 0x8000,WCH20080901*/ -+#define LMDISP (FMALIT + 1) -+ { 15, 0, -LMDISP, AXP_OPERAND_UNSIGNED, 0, 0 }, -+ -+#define RPIINDEX (LMDISP + 1) -+ { 8, 0, -RPIINDEX, AXP_OPERAND_UNSIGNED, 0, 0 }, -+ -+#define ATMDISP (RPIINDEX + 1) -+ { 12, 0, -ATMDISP, AXP_OPERAND_SIGNED, 0, 0 }, -+}; -+ -+const unsigned sw_64_num_operands = sizeof(sw_64_operands)/sizeof(*sw_64_operands); -+ -+ -+/* Macros used to form opcodes. */ -+ -+/* The main opcode. */ -+#define OP(x) (((x) & 0x3Fu) << 26) -+#define OP_MASK 0xFC000000 -+ -+/* Branch format instructions. */ -+#define BRA_(oo) OP(oo) -+#define BRA_MASK OP_MASK -+#define BRA(oo) BRA_(oo), BRA_MASK -+ -+/* Floating point format instructions. */ -+#define FP_(oo,fff) (OP(oo) | (((fff) & 0xFF) << 5)) -+#define FP_MASK (OP_MASK | 0x1FE0) -+#define FP(oo,fff) FP_(oo,fff), FP_MASK -+ -+#define FMA_(oo,fff) (OP(oo) | (((fff) & 0x3F) << 10 )) -+#define FMA_MASK (OP_MASK | 0xFC00) -+#define FMA(oo,fff) FMA_(oo,fff), FMA_MASK -+ -+/* Memory format instructions. */ -+#define MEM_(oo) OP(oo) -+#define MEM_MASK OP_MASK -+#define MEM(oo) MEM_(oo), MEM_MASK -+ -+/* Memory/Func Code format instructions. */ -+#define MFC_(oo,ffff) (OP(oo) | ((ffff) & 0xFFFF)) -+#define MFC_MASK (OP_MASK | 0xFFFF) -+#define MFC(oo,ffff) MFC_(oo,ffff), MFC_MASK -+ -+/* Memory/Branch format instructions. */ -+#define MBR_(oo,h) (OP(oo) | (((h) & 3) << 14)) -+#define MBR_MASK (OP_MASK | 0xC000) -+#define MBR(oo,h) MBR_(oo,h), MBR_MASK -+ -+/* Operate format instructions. The OPRL variant specifies a -+ literal second argument. */ -+#define OPR_(oo,ff) (OP(oo) | (((ff) & 0xFF) << 5)) -+#define OPRL_(oo,ff) (OPR_((oo),(ff)) ) -+#define OPR_MASK (OP_MASK | 0x1FE0) -+#define OPR(oo,ff) OPR_(oo,ff), OPR_MASK -+#define OPRL(oo,ff) OPRL_(oo,ff), OPR_MASK -+ -+/* sw ternary operands Operate format instructions. */ -+#define TOPR_(oo,ff) (OP(oo) | (((ff) & 0x07) << 10)) -+#define TOPRL_(oo,ff) (TOPR_((oo),(ff))) -+#define TOPR_MASK (OP_MASK | 0x1C00) -+#define TOPR(oo,ff) TOPR_(oo,ff), TOPR_MASK -+#define TOPRL(oo,ff) TOPRL_(oo,ff), TOPR_MASK -+ -+/* sw atom instructions. */ -+#define ATMEM_(oo,h) (OP(oo) | (((h) & 0xF) << 12)) -+#define ATMEM_MASK (OP_MASK | 0xF000) -+#define ATMEM(oo,h) ATMEM_(oo,h), ATMEM_MASK -+ -+/* sw privilege instructions. */ -+#define PRIRET_(oo,h) (OP(oo) | (((h) & 0x1) << 20)) -+#define PRIRET_MASK (OP_MASK | 0x100000) -+#define PRIRET(oo,h) PRIRET_(oo,h), PRIRET_MASK -+ -+/* sw rpi_rcsr,rpi_wcsr. */ -+#define CSR_(oo,ff) (OP(oo) | (((ff) & 0xFF) << 8)) -+#define CSR_MASK (OP_MASK | 0xFF00) -+#define CSR(oo,ff) CSR_(oo,ff), CSR_MASK -+ -+/* Generic PALcode format instructions. */ -+#define PCD_(oo,ff) (OP(oo) | (ff << 25)) -+#define PCD_MASK OP_MASK -+#define PCD(oo,ff) PCD_(oo,ff), PCD_MASK -+ -+/* Specific PALcode instructions. */ -+#define SPCD_(oo,ffff) (OP(oo) | ((ffff) & 0x3FFFFFF)) -+#define SPCD_MASK 0xFFFFFFFF -+#define SPCD(oo,ffff) SPCD_(oo,ffff), SPCD_MASK -+ -+/* Hardware memory (hw_{ld,st}) instructions. */ -+#define SW6HWMEM_(oo,f) (OP(oo) | (((f) & 0xF) << 12)) -+#define SW6HWMEM_MASK (OP_MASK | 0xF000) -+#define SW6HWMEM(oo,f) SW6HWMEM_(oo,f), SW6HWMEM_MASK -+ -+#define SW6HWMBR_(oo,h) (OP(oo) | (((h) & 7) << 13)) -+#define SW6HWMBR_MASK (OP_MASK | 0xE000) -+#define SW6HWMBR(oo,h) SW6HWMBR_(oo,h), SW6HWMBR_MASK -+ -+#define LOGX_(oo,ff) (OP(oo) | (((ff) & 0x3F) << 10)) -+#define LOGX_MASK (0xF0000000) -+#define LOGX(oo,ff) LOGX_(oo,ff), LOGX_MASK -+ -+#define PSE_LOGX_(oo,ff) (OP(oo) | (((ff) & 0x3F) << 10) | (((ff) >> 0x6) << 26 ) | 0x3E0 ) -+#define PSE_LOGX(oo,ff) PSE_LOGX_(oo,ff), LOGX_MASK -+ -+/* Abbreviations for instruction subsets. */ -+#define SW6 AXP_OPCODE_SW6 -+#define SW6A AXP_OPCODE_SW6A -+#define SW6B AXP_OPCODE_SW6B -+ -+/* Common combinations of arguments. */ -+#define ARG_NONE { 0 } -+#define ARG_BRA { RA, BDISP } -+#define ARG_FBRA { FA, BDISP } -+#define ARG_FP { FA, FB, DFC1 } -+#define ARG_FPZ1 { ZA, FB, DFC1 } -+#define ARG_MEM { RA, MDISP, PRB } -+#define ARG_FMEM { FA, MDISP, PRB } -+#define ARG_OPR { RA, RB, DRC1 } -+#define ARG_OPRL { RA, LIT, DRC1 } -+#define ARG_OPRZ1 { ZA, RB, DRC1 } -+#define ARG_OPRLZ1 { ZA, LIT, RC } -+#define ARG_PCD { PALFN } -+#define ARG_SW6HWMEM { RA, SW6HWDISP, PRB } -+ -+#define ARG_FPL { FA,LIT, DFC1 } -+#define ARG_FMA { FA,FB,F3, DFC1 } -+#define ARG_PREFETCH { ZA, MDISP, PRB } -+#define ARG_FCMOV { FA,FB,F3, DFC3 } -+#define ARG_TOPR { RA, RB,R3, DRC3 } -+#define ARG_TOPRL { RA, LIT, R3,DRC3 } -+ -+/* for cmov** instruction. */ -+#define ARG_TOPC { RA, RB, R3, RDC } -+#define ARG_TOPCL { RA, LIT, R3, RDC } -+#define ARG_TOPFC { FA, FB, F3, RDC } -+#define ARG_TOPFCL { FA, LIT, F3, RDC } -+ -+/* sw settle instruction. */ -+#define ARG_FMAL { FA,FB,FMALIT, DFC1 } -+/* sw atom insitruction. */ -+#define ARG_ATMEM { RA, ATMDISP, PRB } -+ -+#define ARG_VUAMEM { FA, ATMDISP, PRB } -+#define ARG_OPRLZ3 { RA, LIT, ZC } -+ -+/* The opcode table. -+ -+ The format of the opcode table is: -+ -+ NAME OPCODE MASK { OPERANDS } -+ -+ NAME is the name of the instruction. -+ -+ OPCODE is the instruction opcode. -+ -+ MASK is the opcode mask; this is used to tell the disassembler -+ which bits in the actual opcode must match OPCODE. -+ -+ OPERANDS is the list of operands. -+ -+ The preceding macros merge the text of the OPCODE and MASK fields. -+ -+ The disassembler reads the table in order and prints the first -+ instruction which matches, so this table is sorted to put more -+ specific instructions before more general instructions. -+ -+ Otherwise, it is sorted by major opcode and minor function code. -+ -+ There are three classes of not-really-instructions in this table: -+ -+ ALIAS is another name for another instruction. Some of -+ these come from the Architecture Handbook, some -+ come from the original gas opcode tables. In all -+ cases, the functionality of the opcode is unchanged. -+ -+ PSEUDO a stylized code form endorsed by Chapter A.4 of the -+ Architecture Handbook. -+ -+ EXTRA a stylized code form found in the original gas tables. -+ */ -+ -+const struct sw_64_opcode sw_64_opcodes[] = -+{ -+ { "sys_call/b", PCD(0x00,0x00), SW6, ARG_PCD }, -+ { "sys_call", PCD(0x00,0x01), SW6, ARG_PCD }, -+ { "draina", SPCD(0x00,0x0002), SW6, ARG_NONE }, -+ { "bpt", SPCD(0x00,0x0080), SW6, ARG_NONE }, -+ { "bugchk", SPCD(0x00,0x0081), SW6, ARG_NONE }, -+ { "callsys", SPCD(0x00,0x0083), SW6, ARG_NONE }, -+ { "chmk", SPCD(0x00,0x0083), SW6, ARG_NONE }, -+ { "imb", SPCD(0x00,0x0086), SW6, ARG_NONE }, -+ { "rduniq", SPCD(0x00,0x009e), SW6, ARG_NONE }, -+ { "wruniq", SPCD(0x00,0x009f), SW6, ARG_NONE }, -+ { "gentrap", SPCD(0x00,0x00aa), SW6, ARG_NONE }, -+ { "call", MEM(0x01), SW6, { RA, CPRB, JMPHINT } }, -+ { "ret", MEM(0x02), SW6, { RA, CPRB, RETHINT } }, -+ { "ret", MEM_(0x02)| (31 << 21) | (26 << 16) | 1,0xFFFFFFFF, SW6, { 0 } }, /*pseudo*/ -+ { "jmp", MEM(0x03), SW6, { RA, CPRB, JMPHINT } }, -+ { "br", BRA(0x04), SW6, { ZA, BDISP } }, /* pseudo */ -+ { "br", BRA(0x04), SW6, ARG_BRA }, -+ { "bsr", BRA(0x05), SW6, ARG_BRA }, -+ { "memb", MFC(0x06,0x0000), SW6, ARG_NONE }, -+ { "imemb", MFC(0x06,0x0001), SW6, ARG_NONE }, -+ { "rtc", MFC(0x06,0x0020), SW6, { RA, ZB } }, -+ { "rtc", MFC(0x06,0x0020), SW6, { RA, RB } }, -+ { "rcid", MFC(0x06,0x0040), SW6, { RA , ZB} }, -+ { "halt", MFC(0x06,0x0080), SW6, { ZA, ZB } }, -+ { "rd_f", MFC(0x06,0x1000), SW6, { RA, ZB } }, -+ { "wr_f", MFC(0x06,0x1020), SW6, { RA, ZB } }, -+ { "rtid", MFC(0x06,0x1040), SW6, { RA } }, -+ { "pri_rcsr", CSR(0x06,0xFE), SW6, { RA, RPIINDEX ,ZB } }, -+ { "pri_wcsr", CSR(0x06,0xFF), SW6, { RA, RPIINDEX ,ZB } }, -+ { "pri_ret", PRIRET(0x07,0x0), SW6, { RA } }, -+ { "pri_ret/b", PRIRET(0x07,0x1), SW6, { RA } }, -+ { "lldw", ATMEM(0x08,0x0), SW6, ARG_ATMEM }, -+ { "lldl", ATMEM(0x08,0x1), SW6, ARG_ATMEM }, -+ { "ldw_inc", ATMEM(0x08,0x2), SW6, ARG_ATMEM }, -+ { "ldl_inc", ATMEM(0x08,0x3), SW6, ARG_ATMEM }, -+ { "ldw_dec", ATMEM(0x08,0x4), SW6, ARG_ATMEM }, -+ { "ldl_dec", ATMEM(0x08,0x5), SW6, ARG_ATMEM }, -+ { "ldw_set", ATMEM(0x08,0x6), SW6, ARG_ATMEM }, -+ { "ldl_set", ATMEM(0x08,0x7), SW6, ARG_ATMEM }, -+ { "lstw", ATMEM(0x08,0x8), SW6, ARG_ATMEM }, -+ { "lstl", ATMEM(0x08,0x9), SW6, ARG_ATMEM }, -+ { "ldw_nc", ATMEM(0x08,0xA), SW6, ARG_ATMEM }, -+ { "ldl_nc", ATMEM(0x08,0xB), SW6, ARG_ATMEM }, -+ { "ldd_nc", ATMEM(0x08,0xC), SW6, ARG_VUAMEM }, -+ { "stw_nc", ATMEM(0x08,0xD), SW6, ARG_ATMEM }, -+ { "stl_nc", ATMEM(0x08,0xE), SW6, ARG_ATMEM }, -+ { "std_nc", ATMEM(0x08,0xF), SW6, ARG_VUAMEM }, -+ { "fillcs", MEM(0x09), SW6, ARG_PREFETCH }, -+ { "ldwe", MEM(0x09), SW6, ARG_FMEM }, //sw6 v0.2a -+ { "e_fillcs", MEM(0x0A), SW6, ARG_PREFETCH }, -+ { "ldse", MEM(0x0A), SW6, ARG_FMEM }, -+ { "lds4e", MEM(0x0A), SW6, ARG_FMEM },/* pseudo SW6 SIMD WCH20081028*/ -+ { "fillcs_e", MEM(0x0B), SW6, ARG_PREFETCH }, -+ { "ldde", MEM(0x0B), SW6, ARG_FMEM }, -+ { "ldd4e", MEM(0x0B), SW6, ARG_FMEM },/* pseudo SW6 SIMD WCH20081028*/ -+ { "e_fillde", MEM(0x0C), SW6, ARG_PREFETCH }, -+ { "vlds", MEM(0x0C), SW6, ARG_FMEM }, -+ { "v4lds", MEM(0x0C), SW6, ARG_FMEM }, -+ { "vldd", MEM(0x0D), SW6, ARG_FMEM }, -+ { "v4ldd", MEM(0x0D), SW6, ARG_FMEM }, -+ { "vsts", MEM(0x0E), SW6, ARG_FMEM }, -+ { "v4sts", MEM(0x0E), SW6, ARG_FMEM }, -+ { "vstd", MEM(0x0F), SW6, ARG_FMEM }, -+ { "v4std", MEM(0x0F), SW6, ARG_FMEM }, -+ { "addw", OPR(0x10,0x00), SW6, ARG_OPR }, -+ { "addw", OPRL(0x12,0x00), SW6, ARG_OPRL }, -+ { "sextl", OPR(0x10,0x00), SW6, ARG_OPRZ1 }, /* pseudo */ -+ { "sextl", OPRL(0x12,0x00), SW6, ARG_OPRLZ1 }, /* pseudo */ -+ { "subw", OPR(0x10,0x01), SW6, ARG_OPR }, -+ { "subw", OPRL(0x12,0x01), SW6, ARG_OPRL }, -+ { "negw", OPR(0x10,0x01), SW6, ARG_OPRZ1 }, /* pseudo swgcc */ -+ { "negw", OPRL(0x12,0x01), SW6, ARG_OPRLZ1 }, /* pseudo swgcc */ -+ { "s4addw", OPR(0x10,0x02), SW6, ARG_OPR }, -+ { "s4addw", OPRL(0x12,0x02), SW6, ARG_OPRL }, -+ { "s4subw", OPR(0x10,0x03), SW6, ARG_OPR }, -+ { "s4subw", OPRL(0x12,0x03), SW6, ARG_OPRL }, -+ { "s8addw", OPR(0x10,0x04), SW6, ARG_OPR }, -+ { "s8addw", OPRL(0x12,0x04), SW6, ARG_OPRL }, -+ { "s8subw", OPR(0x10,0x05), SW6, ARG_OPR }, -+ { "s8subw", OPRL(0x12,0x05), SW6, ARG_OPRL }, -+ { "addl", OPR(0x10,0x08), SW6, ARG_OPR }, -+ { "addl", OPRL(0x12,0x08), SW6, ARG_OPRL }, -+ { "subl", OPR(0x10,0x09), SW6, ARG_OPR }, -+ { "subl", OPRL(0x12,0x09), SW6, ARG_OPRL }, -+ { "negl", OPR(0x10,0x09), SW6, ARG_OPRZ1 }, /* pseudo swgcc */ -+ { "negl", OPRL(0x12,0x09), SW6, ARG_OPRLZ1 }, /* pseudo swgcc */ -+ { "neglv", OPR(0x10,0x09), SW6, ARG_OPRZ1 }, /* pseudo swgcc */ -+ { "neglv", OPRL(0x12,0x09), SW6, ARG_OPRLZ1 }, /* pseudo swgcc */ -+ { "s4addl", OPR(0x10,0x0A), SW6, ARG_OPR }, -+ { "s4addl", OPRL(0x12,0x0A), SW6, ARG_OPRL }, -+ { "s4subl", OPR(0x10,0x0B), SW6, ARG_OPR }, -+ { "s4subl", OPRL(0x12,0x0B), SW6, ARG_OPRL }, -+ { "s8addl", OPR(0x10,0x0C), SW6, ARG_OPR }, -+ { "s8addl", OPRL(0x12,0x0C), SW6, ARG_OPRL }, -+ { "s8subl", OPR(0x10,0x0D), SW6, ARG_OPR }, -+ { "s8subl", OPRL(0x12,0x0D), SW6, ARG_OPRL }, -+ { "mulw", OPR(0x10,0x10), SW6, ARG_OPR }, -+ { "mulw", OPRL(0x12,0x10), SW6, ARG_OPRL }, -+ { "divw", OPR(0x10,0x11), SW6B, ARG_OPR }, -+ { "udivw", OPR(0x10,0x12), SW6B, ARG_OPR }, -+ { "remw", OPR(0x10,0x13), SW6B, ARG_OPR }, -+ { "uremw", OPR(0x10,0x14), SW6B, ARG_OPR }, -+ { "mull", OPR(0x10,0x18), SW6, ARG_OPR }, -+ { "mull", OPRL(0x12,0x18), SW6, ARG_OPRL }, -+ { "umulh", OPR(0x10,0x19), SW6, ARG_OPR }, -+ { "umulh", OPRL(0x12,0x19), SW6, ARG_OPRL }, -+ { "cmpeq", OPR(0x10,0x28), SW6, ARG_OPR }, -+ { "cmpeq", OPRL(0x12,0x28), SW6, ARG_OPRL }, -+ { "cmplt", OPR(0x10,0x29), SW6, ARG_OPR }, -+ { "cmplt", OPRL(0x12,0x29), SW6, ARG_OPRL }, -+ { "cmple", OPR(0x10,0x2A), SW6, ARG_OPR }, -+ { "cmple", OPRL(0x12,0x2A), SW6, ARG_OPRL }, -+ { "cmpult", OPR(0x10,0x2B), SW6, ARG_OPR }, -+ { "cmpult", OPRL(0x12,0x2B), SW6, ARG_OPRL }, -+ { "cmpule", OPR(0x10,0x2C), SW6, ARG_OPR }, -+ { "cmpule", OPRL(0x12,0x2C), SW6, ARG_OPRL }, -+ { "and", OPR(0x10,0x38), SW6, ARG_OPR }, -+ { "and", OPRL(0x12,0x38),SW6, ARG_OPRL }, -+ { "bic", OPR(0x10,0x39), SW6, ARG_OPR }, -+ { "bic", OPRL(0x12,0x39),SW6, ARG_OPRL }, -+ { "andnot", OPR(0x10,0x39), SW6, ARG_OPR },/* pseudo */ -+ { "andnot", OPRL(0x12,0x39),SW6, ARG_OPRL },/* pseudo */ -+ { "nop", OPR(0x10,0x3A), SW6, { ZA, ZB, ZC } }, /* now unop has a new expression */ -+ { "excb", OPR(0x10,0x3A), SW6, { ZA, ZB, ZC } }, /* pseudo */ -+ { "clr", OPR(0x10,0x3A),SW6, { ZA, ZB, RC } }, /* pseudo swgcc */ -+ { "mov", OPR(0x10,0x3A), SW6, { ZA, RB, RC } }, /* pseudo */ -+ { "mov", OPRL(0x12,0x3A),SW6, { ZA, LIT, RC } }, /* pseudo */ -+ { "implver", OPRL_(0x12,0x3A)|2<<13,0xFFFFFFE0,SW6, {ZA,RC } }, /* pseudo swgcc */ -+ { "amask", OPR_(0x10,0x3A)|31<<16,OPR_MASK, SW6, { ZA, RB, RC } }, /* pseudo */ -+ { "amask", OPRL(0x12,0x3A), SW6, { ZA, LIT, RC } }, /* pseudo */ -+ { "or", OPR(0x10,0x3A), SW6, ARG_OPR }, -+ { "or", OPRL(0x12,0x3A),SW6, ARG_OPRL }, -+ { "bis", OPR(0x10,0x3A), SW6, ARG_OPR }, -+ { "bis", OPRL(0x12,0x3A),SW6, ARG_OPRL }, -+ { "not", OPR(0x10,0x3B), SW6, ARG_OPRZ1 }, /* pseudo swgcc */ -+ { "not", OPRL(0x12,0x3B),SW6, ARG_OPRLZ1 }, /* pseudo swgcc */ -+ { "ornot", OPR(0x10,0x3B), SW6, ARG_OPR }, -+ { "ornot", OPRL(0x12,0x3B),SW6, ARG_OPRL }, -+ { "xor", OPR(0x10,0x3C), SW6, ARG_OPR }, -+ { "xor", OPRL(0x12,0x3C),SW6, ARG_OPRL }, -+ { "eqv", OPR(0x10,0x3D), SW6, ARG_OPR }, -+ { "eqv", OPRL(0x12,0x3D),SW6, ARG_OPRL }, -+ { "xornot", OPR(0x10,0x3D), SW6, ARG_OPR }, /* pseudo swgcc */ -+ { "xornot", OPRL(0x12,0x3D),SW6, ARG_OPRL },/* pseudo swgcc */ -+ { "inslb", OPR(0x10,0x40), SW6, ARG_OPR }, -+ { "inslb", OPRL(0x12,0x40),SW6, ARG_OPRL }, -+ { "ins0b", OPR(0x10,0x40), SW6, ARG_OPR }, -+ { "ins0b", OPRL(0x12,0x40),SW6, ARG_OPRL }, -+ { "inslh", OPR(0x10,0x41), SW6, ARG_OPR }, -+ { "inslh", OPRL(0x12,0x41),SW6, ARG_OPRL }, -+ { "ins1b", OPR(0x10,0x41), SW6, ARG_OPR }, -+ { "ins1b", OPRL(0x12,0x41),SW6, ARG_OPRL }, -+ { "inslw", OPR(0x10,0x42), SW6, ARG_OPR }, -+ { "inslw", OPRL(0x12,0x42),SW6, ARG_OPRL }, -+ { "ins2b", OPR(0x10,0x42), SW6, ARG_OPR }, -+ { "ins2b", OPRL(0x12,0x42),SW6, ARG_OPRL }, -+ { "insll", OPR(0x10,0x43), SW6, ARG_OPR }, -+ { "insll", OPRL(0x12,0x43),SW6, ARG_OPRL }, -+ { "ins3b", OPR(0x10,0x43), SW6, ARG_OPR }, -+ { "ins3b", OPRL(0x12,0x43),SW6, ARG_OPRL }, -+ { "inshb", OPR(0x10,0x44), SW6, ARG_OPR }, -+ { "inshb", OPRL(0x12,0x44),SW6, ARG_OPRL }, -+ { "ins4b", OPR(0x10,0x44), SW6, ARG_OPR }, -+ { "ins4b", OPRL(0x12,0x44),SW6, ARG_OPRL }, -+ { "inshh", OPR(0x10,0x45), SW6, ARG_OPR }, -+ { "inshh", OPRL(0x12,0x45),SW6, ARG_OPRL }, -+ { "ins5b", OPR(0x10,0x45), SW6, ARG_OPR }, -+ { "ins5b", OPRL(0x12,0x45),SW6, ARG_OPRL }, -+ { "inshw", OPR(0x10,0x46), SW6, ARG_OPR }, -+ { "inshw", OPRL(0x12,0x46),SW6, ARG_OPRL }, -+ { "ins6b", OPR(0x10,0x46), SW6, ARG_OPR }, -+ { "ins6b", OPRL(0x12,0x46),SW6, ARG_OPRL }, -+ { "inshl", OPR(0x10,0x47), SW6, ARG_OPR }, -+ { "inshl", OPRL(0x12,0x47),SW6, ARG_OPRL }, -+ { "ins7b", OPR(0x10,0x47), SW6, ARG_OPR }, -+ { "ins7b", OPRL(0x12,0x47),SW6, ARG_OPRL }, -+ { "sll", OPR(0x10,0x48), SW6, ARG_OPR }, -+ { "sll", OPRL(0x12,0x48),SW6, ARG_OPRL }, -+ { "srl", OPR(0x10,0x49), SW6, ARG_OPR }, -+ { "srl", OPRL(0x12,0x49),SW6, ARG_OPRL }, -+ { "sra", OPR(0x10,0x4A), SW6, ARG_OPR }, -+ { "sra", OPRL(0x12,0x4A),SW6, ARG_OPRL }, -+ { "sllw2", OPR(0x10,0x4C), SW6, ARG_OPR }, //sw6 v0.2a -+ { "sllw2", OPRL(0x12,0x4C),SW6, ARG_OPRL },//sw6 v0.2a -+ { "srlw2", OPR(0x10,0x4D), SW6, ARG_OPR }, //sw6 v0.2a -+ { "srlw2", OPRL(0x12,0x4D),SW6, ARG_OPRL },//sw6 v0.2a -+ { "sraw2", OPR(0x10,0x4E), SW6, ARG_OPR }, //sw6 v0.2a -+ { "sraw2", OPRL(0x12,0x4E),SW6, ARG_OPRL },//sw6 v0.2a -+ { "extlb", OPR(0x10,0x50), SW6, ARG_OPR }, -+ { "extlb", OPRL(0x12,0x50),SW6, ARG_OPRL }, -+ { "ext0b", OPR(0x10,0x50), SW6, ARG_OPR }, -+ { "ext0b", OPRL(0x12,0x50),SW6, ARG_OPRL }, -+ { "extlh", OPR(0x10,0x51), SW6, ARG_OPR }, -+ { "extlh", OPRL(0x12,0x51),SW6, ARG_OPRL }, -+ { "ext1b", OPR(0x10,0x51), SW6, ARG_OPR }, -+ { "ext1b", OPRL(0x12,0x51),SW6, ARG_OPRL }, -+ { "extlw", OPR(0x10,0x52), SW6, ARG_OPR }, -+ { "extlw", OPRL(0x12,0x52),SW6, ARG_OPRL }, -+ { "ext2b", OPR(0x10,0x52), SW6, ARG_OPR }, -+ { "ext2b", OPRL(0x12,0x52),SW6, ARG_OPRL }, -+ { "extll", OPR(0x10,0x53), SW6, ARG_OPR }, -+ { "extll", OPRL(0x12,0x53),SW6, ARG_OPRL }, -+ { "ext3b", OPR(0x10,0x53), SW6, ARG_OPR }, -+ { "ext3b", OPRL(0x12,0x53),SW6, ARG_OPRL }, -+ { "exthb", OPR(0x10,0x54), SW6, ARG_OPR }, -+ { "exthb", OPRL(0x12,0x54),SW6, ARG_OPRL }, -+ { "ext4b", OPR(0x10,0x54), SW6, ARG_OPR }, -+ { "ext4b", OPRL(0x12,0x54),SW6, ARG_OPRL }, -+ { "exthh", OPR(0x10,0x55), SW6, ARG_OPR }, -+ { "exthh", OPRL(0x12,0x55),SW6, ARG_OPRL }, -+ { "ext5b", OPR(0x10,0x55), SW6, ARG_OPR }, -+ { "ext5b", OPRL(0x12,0x55),SW6, ARG_OPRL }, -+ { "exthw", OPR(0x10,0x56), SW6, ARG_OPR }, -+ { "exthw", OPRL(0x12,0x56),SW6, ARG_OPRL }, -+ { "ext6b", OPR(0x10,0x56), SW6, ARG_OPR }, -+ { "ext6b", OPRL(0x12,0x56),SW6, ARG_OPRL }, -+ { "exthl", OPR(0x10,0x57), SW6, ARG_OPR }, -+ { "exthl", OPRL(0x12,0x57),SW6, ARG_OPRL }, -+ { "ext7b", OPR(0x10,0x57), SW6, ARG_OPR }, -+ { "ext7b", OPRL(0x12,0x57),SW6, ARG_OPRL }, -+ { "ctpop", OPR(0x10,0x58), SW6, ARG_OPRZ1 }, -+ { "ctlz", OPR(0x10,0x59), SW6, ARG_OPRZ1 }, -+ { "cttz", OPR(0x10,0x5A), SW6, ARG_OPRZ1 }, -+ { "masklb", OPR(0x10,0x60), SW6, ARG_OPR }, -+ { "masklb", OPRL(0x12,0x60),SW6, ARG_OPRL }, -+ { "mask0b", OPR(0x10,0x60), SW6, ARG_OPR }, -+ { "mask0b", OPRL(0x12,0x60),SW6, ARG_OPRL }, -+ { "masklh", OPR(0x10,0x61), SW6, ARG_OPR }, -+ { "masklh", OPRL(0x12,0x61),SW6, ARG_OPRL }, -+ { "mask1b", OPR(0x10,0x61), SW6, ARG_OPR }, -+ { "mask1b", OPRL(0x12,0x61),SW6, ARG_OPRL }, -+ { "masklw", OPR(0x10,0x62), SW6, ARG_OPR }, -+ { "masklw", OPRL(0x12,0x62),SW6, ARG_OPRL }, -+ { "mask2b", OPR(0x10,0x62), SW6, ARG_OPR }, -+ { "mask2b", OPRL(0x12,0x62),SW6, ARG_OPRL }, -+ { "maskll", OPR(0x10,0x63), SW6, ARG_OPR }, -+ { "maskll", OPRL(0x12,0x63),SW6, ARG_OPRL }, -+ { "mask3b", OPR(0x10,0x63), SW6, ARG_OPR }, -+ { "mask3b", OPRL(0x12,0x63),SW6, ARG_OPRL }, -+ { "maskhb", OPR(0x10,0x64), SW6, ARG_OPR }, -+ { "maskhb", OPRL(0x12,0x64),SW6, ARG_OPRL }, -+ { "mask4b", OPR(0x10,0x64), SW6, ARG_OPR }, -+ { "mask4b", OPRL(0x12,0x64),SW6, ARG_OPRL }, -+ { "maskhh", OPR(0x10,0x65), SW6, ARG_OPR }, -+ { "maskhh", OPRL(0x12,0x65),SW6, ARG_OPRL }, -+ { "mask5b", OPR(0x10,0x65), SW6, ARG_OPR }, -+ { "mask5b", OPRL(0x12,0x65),SW6, ARG_OPRL }, -+ { "maskhw", OPR(0x10,0x66), SW6, ARG_OPR }, -+ { "maskhw", OPRL(0x12,0x66),SW6, ARG_OPRL }, -+ { "mask6b", OPR(0x10,0x66), SW6, ARG_OPR }, -+ { "mask6b", OPRL(0x12,0x66),SW6, ARG_OPRL }, -+ { "maskhl", OPR(0x10,0x67), SW6, ARG_OPR }, -+ { "maskhl", OPRL(0x12,0x67),SW6, ARG_OPRL }, -+ { "mask7b", OPR(0x10,0x67), SW6, ARG_OPR }, -+ { "mask7b", OPRL(0x12,0x67),SW6, ARG_OPRL }, -+ { "zap", OPR(0x10,0x68), SW6, ARG_OPR }, -+ { "zap", OPRL(0x12,0x68),SW6, ARG_OPRL }, -+ { "zapnot", OPR(0x10,0x69), SW6, ARG_OPR }, -+ { "zapnot", OPRL(0x12,0x69),SW6, ARG_OPRL }, -+ { "sextb", OPR(0x10,0x6A), SW6, ARG_OPRZ1}, -+ { "sextb", OPRL(0x12,0x6A),SW6, ARG_OPRLZ1 }, -+ { "sexth", OPR(0x10,0x6B), SW6, ARG_OPRZ1 }, -+ { "sexth", OPRL(0x12,0x6B),SW6, ARG_OPRLZ1 }, -+ { "cmpgeb", OPR(0x10,0x6C), SW6, ARG_OPR }, -+ { "cmpgeb", OPRL(0x12,0x6C),SW6, ARG_OPRL }, -+ { "fimovs", OPR(0x10,0x70), SW6, { FA, ZB, RC } }, -+ { "fimovd", OPR(0x10,0x78), SW6, { FA, ZB, RC } }, -+ { "ftoid", OPR(0x10,0x78), SW6, { FA, ZB, RC } }, -+ { "seleq", TOPR(0x11,0x0), SW6, ARG_TOPR }, -+ { "seleq", TOPRL(0x13,0x0),SW6, ARG_TOPRL }, -+ { "selge", TOPR(0x11,0x1), SW6, ARG_TOPR }, -+ { "selge", TOPRL(0x13,0x1),SW6, ARG_TOPRL }, -+ { "selgt", TOPR(0x11,0x2), SW6, ARG_TOPR }, -+ { "selgt", TOPRL(0x13,0x2),SW6, ARG_TOPRL }, -+ { "selle", TOPR(0x11,0x3), SW6, ARG_TOPR }, -+ { "selle", TOPRL(0x13,0x3),SW6, ARG_TOPRL }, -+ { "sellt", TOPR(0x11,0x4), SW6, ARG_TOPR }, -+ { "sellt", TOPRL(0x13,0x4),SW6, ARG_TOPRL }, -+ { "selne", TOPR(0x11,0x5), SW6, ARG_TOPR }, -+ { "selne", TOPRL(0x13,0x5),SW6, ARG_TOPRL }, -+ { "sellbc", TOPR(0x11,0x6), SW6, ARG_TOPR }, -+ { "sellbc", TOPRL(0x13,0x6),SW6, ARG_TOPRL }, -+ { "sellbs", TOPR(0x11,0x7), SW6, ARG_TOPR }, -+ { "sellbs", TOPRL(0x13,0x7),SW6, ARG_TOPRL }, -+ { "vlog", LOGX(0x14,0x00), SW6, ARG_FMA }, -+ -+ { "vbicw", PSE_LOGX(0x14,0x30), SW6, { FA , FB , DFC1 } }, -+ { "vxorw", PSE_LOGX(0x14,0x3c), SW6, { FA , FB , DFC1 } }, -+ { "vandw", PSE_LOGX(0x14,0xc0), SW6, { FA , FB , DFC1 } }, -+ { "veqvw", PSE_LOGX(0x14,0xc3), SW6, { FA , FB , DFC1 } }, -+ { "vornotw", PSE_LOGX(0x14,0xf3), SW6, { FA , FB , DFC1 } }, -+ { "vbisw", PSE_LOGX(0x14,0xfc), SW6, { FA , FB , DFC1 } }, -+ -+ { "fadds", FP(0x18,0x00), SW6, ARG_FP }, -+ { "faddd", FP(0x18,0x01), SW6, ARG_FP }, -+ { "fsubs", FP(0x18,0x02), SW6, ARG_FP }, -+ { "fsubd", FP(0x18,0x03), SW6, ARG_FP }, -+ { "fmuls", FP(0x18,0x04), SW6, ARG_FP }, -+ { "fmuld", FP(0x18,0x05), SW6, ARG_FP }, -+ { "fdivs", FP(0x18,0x06), SW6, ARG_FP }, -+ { "fdivd", FP(0x18,0x07), SW6, ARG_FP }, -+ { "fsqrts", FP(0x18,0x08), SW6, ARG_FPZ1 }, -+ { "fsqrtd", FP(0x18,0x09), SW6, ARG_FPZ1 }, -+ { "fcmpeq", FP(0x18,0x10), SW6, ARG_FP }, -+ { "fcmple", FP(0x18,0x11), SW6, ARG_FP }, -+ { "fcmplt", FP(0x18,0x12), SW6, ARG_FP }, -+ { "fcmpun", FP(0x18,0x13), SW6, ARG_FP }, -+ -+ { "fcvtsd", FP(0x18,0x20), SW6, ARG_FPZ1 }, -+ { "fcvtds", FP(0x18,0x21), SW6, ARG_FPZ1 }, -+ { "fcvtdl_g", FP(0x18,0x22), SW6, ARG_FPZ1 }, -+ { "fcvtdl_p", FP(0x18,0x23), SW6, ARG_FPZ1 }, -+ { "fcvtdl_z", FP(0x18,0x24), SW6, ARG_FPZ1 }, -+ { "fcvtdl_n", FP(0x18,0x25), SW6, ARG_FPZ1 }, -+ { "fcvtdl", FP(0x18,0x27), SW6, ARG_FPZ1 }, -+ { "fcvtwl", FP(0x18,0x28), SW6, ARG_FPZ1 }, -+ { "fcvtlw", FP(0x18,0x29), SW6, ARG_FPZ1 }, -+ { "fcvtls", FP(0x18,0x2d), SW6, ARG_FPZ1 }, -+ { "fcvtld", FP(0x18,0x2f), SW6, ARG_FPZ1 }, -+ -+ { "fnop", FP(0x18,0x030), SW6, { ZA, ZB, ZC } }, -+ { "fclr", FP(0x18,0x030), SW6, { ZA, ZB, FC } }, -+ { "fabs", FP(0x18,0x030), SW6, ARG_FPZ1 }, -+ { "fcpys", FP(0x18,0x30), SW6, ARG_FP }, -+ { "fmov", FP(0x18,0x30), SW6, { FA, RBA, FC } }, -+ { "fcpyse", FP(0x18,0x31), SW6, ARG_FP }, -+ { "fneg", FP(0x18,0x32), SW6, { FA, RBA, FC } }, -+ { "fcpysn", FP(0x18,0x32), SW6, ARG_FP }, -+ -+ { "ifmovs", FP(0x18,0x40), SW6, { RA, ZB, FC } }, -+ { "ifmovd", FP(0x18,0x41), SW6, { RA, ZB, FC } }, -+ { "itofd", FP(0x18,0x41), SW6, { RA, ZB, FC } }, -+ -+ { "rfpcr", FP(0x18,0x50), SW6, { FA, RBA, RCA } }, -+ { "wfpcr", FP(0x18,0x51), SW6, { FA, RBA, RCA } }, -+ { "setfpec0", FP(0x18,0x54), SW6, ARG_NONE }, -+ { "setfpec1", FP(0x18,0x55), SW6, ARG_NONE }, -+ { "setfpec2", FP(0x18,0x56), SW6, ARG_NONE }, -+ { "setfpec3", FP(0x18,0x57), SW6, ARG_NONE }, -+ { "fmas", FMA(0x19,0x00), SW6, ARG_FMA }, -+ { "fmad", FMA(0x19,0x01), SW6, ARG_FMA }, -+ { "fmss", FMA(0x19,0x02), SW6, ARG_FMA }, -+ { "fmsd", FMA(0x19,0x03), SW6, ARG_FMA }, -+ { "fnmas", FMA(0x19,0x04), SW6, ARG_FMA }, -+ { "fnmad", FMA(0x19,0x05), SW6, ARG_FMA }, -+ { "fnmss", FMA(0x19,0x06), SW6, ARG_FMA }, -+ { "fnmsd", FMA(0x19,0x07), SW6, ARG_FMA }, -+ -+//fcmov*(SW6) to fcmov*(SW6) for fcmov* no need in sw64, and fsel*->fcmov* has difference in operands number,so it should not repalce directly. The default FD should be the same FC but not FA -+ { "fseleq", FMA(0x19,0x10), SW6, ARG_FCMOV }, -+ { "fselne", FMA(0x19,0x11), SW6, ARG_FCMOV }, -+ { "fsellt", FMA(0x19,0x12), SW6, ARG_FCMOV }, -+ { "fselle", FMA(0x19,0x13), SW6, ARG_FCMOV }, -+ { "fselgt", FMA(0x19,0x14), SW6, ARG_FCMOV }, -+ { "fselge", FMA(0x19,0x15), SW6, ARG_FCMOV }, -+ -+ { "vaddw", FP(0x1A,0x00), SW6, ARG_FP }, -+ { "vaddw", FP(0x1A,0x20), SW6, ARG_FPL }, -+ { "vsubw", FP(0x1A,0x01), SW6, ARG_FP }, -+ { "vsubw", FP(0x1A,0x21), SW6, ARG_FPL }, -+ { "vcmpgew", FP(0x1A,0x02), SW6, ARG_FP }, -+ { "vcmpgew", FP(0x1A,0x22), SW6, ARG_FPL }, -+ { "vcmpeqw", FP(0x1A,0x03), SW6, ARG_FP }, -+ { "vcmpeqw", FP(0x1A,0x23), SW6, ARG_FPL }, -+ { "vcmplew", FP(0x1A,0x04), SW6, ARG_FP }, -+ { "vcmplew", FP(0x1A,0x24), SW6, ARG_FPL }, -+ { "vcmpltw", FP(0x1A,0x05), SW6, ARG_FP }, -+ { "vcmpltw", FP(0x1A,0x25), SW6, ARG_FPL }, -+ { "vcmpulew", FP(0x1A,0x06), SW6, ARG_FP }, -+ { "vcmpulew", FP(0x1A,0x26), SW6, ARG_FPL }, -+ { "vcmpultw", FP(0x1A,0x07), SW6, ARG_FP }, -+ { "vcmpultw", FP(0x1A,0x27), SW6, ARG_FPL }, -+ -+ { "vsllw", FP(0x1A,0x08), SW6, ARG_FP }, -+ { "vsllw", FP(0x1A,0x28), SW6, ARG_FPL }, -+ { "vsrlw", FP(0x1A,0x09), SW6, ARG_FP }, -+ { "vsrlw", FP(0x1A,0x29), SW6, ARG_FPL }, -+ { "vsraw", FP(0x1A,0x0A), SW6, ARG_FP }, -+ { "vsraw", FP(0x1A,0x2A), SW6, ARG_FPL }, -+ { "vrolw", FP(0x1A,0x0B), SW6, ARG_FP }, -+ { "vrolw", FP(0x1A,0x2B), SW6, ARG_FPL }, -+ { "sllow", FP(0x1A,0x0C), SW6, ARG_FP }, -+ { "sllow", FP(0x1A,0x2C), SW6, ARG_FPL }, -+ { "srlow", FP(0x1A,0x0D), SW6, ARG_FP }, -+ { "srlow", FP(0x1A,0x2D), SW6, ARG_FPL }, -+ { "vaddl", FP(0x1A,0x0E), SW6, ARG_FP }, -+ { "vaddl", FP(0x1A,0x2E), SW6, ARG_FPL }, -+ { "vsubl", FP(0x1A,0x0F), SW6, ARG_FP }, -+ { "vsubl", FP(0x1A,0x2F), SW6, ARG_FPL }, -+ { "ctpopow", FP(0x1A,0x18), SW6, { FA, ZB, DFC1 } }, -+ { "ctlzow", FP(0x1A,0x19), SW6, { FA, ZB, DFC1 } }, -+ { "vucaddw", FP(0x1A,0x40), SW6, ARG_FP }, -+ { "vucaddw", FP(0x1A,0x60), SW6, ARG_FPL }, -+ { "vucsubw", FP(0x1A,0x41), SW6, ARG_FP }, -+ { "vucsubw", FP(0x1A,0x61), SW6, ARG_FPL }, -+ { "vucaddh", FP(0x1A,0x42), SW6, ARG_FP }, -+ { "vucaddh", FP(0x1A,0x62), SW6, ARG_FPL }, -+ { "vucsubh", FP(0x1A,0x43), SW6, ARG_FP }, -+ { "vucsubh", FP(0x1A,0x63), SW6, ARG_FPL }, -+ { "vucaddb", FP(0x1A,0x44), SW6, ARG_FP }, -+ { "vucaddb", FP(0x1A,0x64), SW6, ARG_FPL }, -+ { "vucsubb", FP(0x1A,0x45), SW6, ARG_FP }, -+ { "vucsubb", FP(0x1A,0x65), SW6, ARG_FPL }, -+ { "vadds", FP(0x1A,0x80), SW6, ARG_FP }, -+ { "v4adds", FP(0x1A,0x80), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -+ { "vaddd", FP(0x1A,0x81), SW6, ARG_FP }, -+ { "v4addd", FP(0x1A,0x81), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -+ { "vsubs", FP(0x1A,0x82), SW6, ARG_FP }, -+ { "v4subs", FP(0x1A,0x82), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -+ { "vsubd", FP(0x1A,0x83), SW6, ARG_FP }, -+ { "v4subd", FP(0x1A,0x83), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -+ { "vmuls", FP(0x1A,0x84), SW6, ARG_FP }, -+ { "v4muls", FP(0x1A,0x84), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -+ { "vmuld", FP(0x1A,0x85), SW6, ARG_FP }, -+ { "v4muld", FP(0x1A,0x85), SW6, ARG_FP },/* pseudo SW6 SIMD*/ -+ { "vdivs", FP(0x1A,0x86), SW6, ARG_FP }, -+ { "vdivd", FP(0x1A,0x87), SW6, ARG_FP }, -+ { "vsqrts", FP(0x1A,0x88), SW6, ARG_FPZ1 }, -+ { "vsqrtd", FP(0x1A,0x89), SW6, ARG_FPZ1 }, -+ { "vfcmpeq", FP(0x1A,0x8C), SW6, ARG_FP }, -+ { "vfcmple", FP(0x1A,0x8D), SW6, ARG_FP }, -+ { "vfcmplt", FP(0x1A,0x8E), SW6, ARG_FP }, -+ { "vfcmpun", FP(0x1A,0x8F), SW6, ARG_FP }, -+ { "vcpys", FP(0x1A,0x90), SW6, ARG_FP }, -+ { "vfmov", FP(0x1A,0x90), SW6, { FA, RBA, FC } }, //V1.1 -+ { "vcpyse", FP(0x1A,0x91), SW6, ARG_FP }, // SW6 1.0 -+ { "vcpysn", FP(0x1A,0x92), SW6, ARG_FP }, // SW6 1.0 -+ { "vmas", FMA(0x1B,0x00), SW6, ARG_FMA }, -+ { "vmad", FMA(0x1B,0x01), SW6, ARG_FMA }, -+ { "vmss", FMA(0x1B,0x02), SW6, ARG_FMA }, -+ { "vmsd", FMA(0x1B,0x03), SW6, ARG_FMA }, -+ { "vnmas", FMA(0x1B,0x04), SW6, ARG_FMA }, -+ { "vnmad", FMA(0x1B,0x05), SW6, ARG_FMA }, -+ { "vnmss", FMA(0x1B,0x06), SW6, ARG_FMA }, -+ { "vnmsd", FMA(0x1B,0x07), SW6, ARG_FMA }, -+ { "vfseleq", FMA(0x1B,0x10), SW6, ARG_FMA }, -+ { "vfsellt", FMA(0x1B,0x12), SW6, ARG_FMA }, -+ { "vfselle", FMA(0x1B,0x13), SW6, ARG_FMA }, -+ { "vseleqw", FMA(0x1B,0x18), SW6, ARG_FMA }, -+ { "vseleqw", FMA(0x1B,0x38), SW6, ARG_FMAL }, -+ { "vsellbcw", FMA(0x1B,0x19), SW6, ARG_FMA }, -+ { "vsellbcw", FMA(0x1B,0x39), SW6, ARG_FMAL }, -+ { "vselltw", FMA(0x1B,0x1A), SW6, ARG_FMA }, -+ { "vselltw", FMA(0x1B,0x3A), SW6, ARG_FMAL }, -+ { "vsellew", FMA(0x1B,0x1B), SW6, ARG_FMA }, -+ { "vsellew", FMA(0x1B,0x3B), SW6, ARG_FMAL }, -+ { "vinsw", FMA(0x1B,0x20), SW6, ARG_FMAL }, -+ { "vinsf", FMA(0x1B,0x21), SW6, ARG_FMAL }, -+ { "vextw", FMA(0x1B,0x22), SW6, { FA, FMALIT, DFC1 }}, -+ { "vextf", FMA(0x1B,0x23), SW6, { FA, FMALIT, DFC1 }}, -+ { "vcpyw", FMA(0x1B,0x24), SW6, { FA, DFC1 }}, -+ { "vcpyf", FMA(0x1B,0x25), SW6, { FA, DFC1 }}, -+ { "vconw", FMA(0x1B,0x26), SW6, ARG_FMA }, -+ { "vshfw", FMA(0x1B,0x27), SW6, ARG_FMA }, -+ { "vcons", FMA(0x1B,0x28), SW6, ARG_FMA }, -+ { "vcond", FMA(0x1B,0x29), SW6, ARG_FMA }, -+ { "vldw_u", ATMEM(0x1C,0x0), SW6, ARG_VUAMEM }, -+ { "vstw_u", ATMEM(0x1C,0x1), SW6, ARG_VUAMEM }, -+ { "vlds_u", ATMEM(0x1C,0x2), SW6, ARG_VUAMEM }, -+ { "vsts_u", ATMEM(0x1C,0x3), SW6, ARG_VUAMEM }, -+ { "vldd_u", ATMEM(0x1C,0x4), SW6, ARG_VUAMEM }, -+ { "vstd_u", ATMEM(0x1C,0x5), SW6, ARG_VUAMEM }, -+ { "vstw_ul", ATMEM(0x1C,0x8), SW6, ARG_VUAMEM }, -+ { "vstw_uh", ATMEM(0x1C,0x9), SW6, ARG_VUAMEM }, -+ { "vsts_ul", ATMEM(0x1C,0xA), SW6, ARG_VUAMEM }, -+ { "vsts_uh", ATMEM(0x1C,0xB), SW6, ARG_VUAMEM }, -+ { "vstd_ul", ATMEM(0x1C,0xC), SW6, ARG_VUAMEM }, -+ { "vstd_uh", ATMEM(0x1C,0xD), SW6, ARG_VUAMEM }, -+ { "vldd_nc", ATMEM(0x1C,0xE), SW6, ARG_VUAMEM }, -+ { "vstd_nc", ATMEM(0x1C,0xF), SW6, ARG_VUAMEM }, -+ { "flushd", MEM(0x20), SW6, ARG_PREFETCH }, -+ { "ldbu", MEM(0x20), SW6, ARG_MEM }, -+ { "evictdg", MEM(0x21), SW6, ARG_PREFETCH }, -+ { "ldhu", MEM(0x21), SW6, ARG_MEM }, -+ { "s_fillcs", MEM(0x22), SW6, ARG_PREFETCH }, -+ { "ldw", MEM(0x22), SW6, ARG_MEM }, -+ { "wh64", MFC(0x22,0xF800), SW6, { ZA, PRB } }, -+ { "s_fillde", MEM(0x23), SW6, ARG_PREFETCH }, -+ { "ldl", MEM(0x23), SW6, ARG_MEM }, -+ { "evictdl", MEM(0x24), SW6, ARG_PREFETCH }, -+ { "ldl_u", MEM(0x24), SW6, ARG_MEM }, -+ { "pri_ldw/p", SW6HWMEM(0x25,0x0), SW6, ARG_SW6HWMEM }, -+ { "pri_ldw_inc/p", SW6HWMEM(0x25,0x2), SW6, ARG_SW6HWMEM }, -+ { "pri_ldw_dec/p", SW6HWMEM(0x25,0x4), SW6, ARG_SW6HWMEM }, -+ { "pri_ldw_set/p", SW6HWMEM(0x25,0x6), SW6, ARG_SW6HWMEM }, -+ { "pri_ldw/v", SW6HWMEM(0x25,0x8), SW6, ARG_SW6HWMEM }, -+ { "pri_ldw/vpte", SW6HWMEM(0x25,0xA), SW6, ARG_SW6HWMEM }, -+ { "pri_ldl/p", SW6HWMEM(0x25,0x1), SW6, ARG_SW6HWMEM }, -+ { "pri_ldl_inc/p", SW6HWMEM(0x25,0x3), SW6, ARG_SW6HWMEM }, -+ { "pri_ldl_dec/p", SW6HWMEM(0x25,0x5), SW6, ARG_SW6HWMEM }, -+ { "pri_ldl_set/p", SW6HWMEM(0x25,0x7), SW6, ARG_SW6HWMEM }, -+ { "pri_ldl/v", SW6HWMEM(0x25,0x9), SW6, ARG_SW6HWMEM }, -+ { "pri_ldl/vpte", SW6HWMEM(0x25,0xB), SW6, ARG_SW6HWMEM }, -+ { "fillde", MEM(0x26), SW6, ARG_PREFETCH }, -+ { "flds", MEM(0x26), SW6, ARG_FMEM }, -+ { "fillde_e", MEM(0x27), SW6, ARG_PREFETCH }, -+ { "fldd", MEM(0x27), SW6, ARG_FMEM }, -+ -+ { "stb", MEM(0x28), SW6, ARG_MEM }, -+ { "sth", MEM(0x29), SW6, ARG_MEM }, -+ { "stw", MEM(0x2A), SW6, ARG_MEM }, -+ { "stl", MEM(0x2B), SW6, ARG_MEM }, -+ { "stl_u", MEM(0x2C), SW6, ARG_MEM }, -+ { "pri_stw/p", SW6HWMEM(0x2D,0x0), SW6, ARG_SW6HWMEM }, -+ { "pri_stw/v", SW6HWMEM(0x2D,0x8), SW6, ARG_SW6HWMEM }, -+ { "pri_stl/p", SW6HWMEM(0x2D,0x1), SW6, ARG_SW6HWMEM }, -+ { "pri_stl/v", SW6HWMEM(0x2D,0x9), SW6, ARG_SW6HWMEM }, -+ { "fsts", MEM(0x2E), SW6, ARG_FMEM }, -+ { "fstd", MEM(0x2F), SW6, ARG_FMEM }, -+ { "beq", BRA(0x30), SW6, ARG_BRA }, -+ { "bne", BRA(0x31), SW6, ARG_BRA }, -+ { "blt", BRA(0x32), SW6, ARG_BRA }, -+ { "ble", BRA(0x33), SW6, ARG_BRA }, -+ { "bgt", BRA(0x34), SW6, ARG_BRA }, -+ { "bge", BRA(0x35), SW6, ARG_BRA }, -+ { "blbc", BRA(0x36), SW6, ARG_BRA }, -+ { "blbs", BRA(0x37), SW6, ARG_BRA }, -+ -+ { "fbeq", BRA(0x38), SW6, ARG_FBRA }, -+ { "fbne", BRA(0x39), SW6, ARG_FBRA }, -+ { "fblt", BRA(0x3A), SW6, ARG_FBRA }, -+ { "fble", BRA(0x3B), SW6, ARG_FBRA }, -+ { "fbgt", BRA(0x3C), SW6, ARG_FBRA }, -+ { "fbge", BRA(0x3D), SW6, ARG_FBRA }, -+ { "ldi", MEM(0x3E), SW6, { RA, MDISP, ZB } }, -+ { "ldi", MEM(0x3E), SW6, ARG_MEM }, -+ { "ldih", MEM(0x3F), SW6, { RA, MDISP, ZB } }, -+ { "ldih", MEM(0x3F), SW6, ARG_MEM }, -+ { "unop", MEM_(0x3F) | (30 << 16), MEM_MASK, SW6 , { ZA } }, -+}; -+ -+const unsigned sw_64_num_opcodes = sizeof(sw_64_opcodes)/sizeof(*sw_64_opcodes); --- -2.33.0 - -- Gitee