From patchwork Wed May 8 09:29:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tiezhu Yang X-Patchwork-Id: 89765 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 145C038A1402 for ; Wed, 8 May 2024 09:31:44 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id 017F438AA251; Wed, 8 May 2024 09:29:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 017F438AA251 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=loongson.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 017F438AA251 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715160589; cv=none; b=b+OvVLErlCuhTWfYzjQSI0YB2As1YHBSA6aewu1UAgh6EW4WMeo8kOLWKssJ64aVj5fqwgCg56ePb4H87ZS3nqhBy3wi/Wv/o/F0vMSyGxNcDjZwHFQgCLDustOJXztpUzE4KmzYIKfLIRvaHdCpXKUvuQ2tS7bRWzJL16zAcSw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715160589; c=relaxed/simple; bh=2vghshrbXMauCAYBDMcZfsUAEMhyy/VtvWFf6wyxNz0=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=iBOeJJPw35deuD5HP8dB2+pai8704IZWy4oNPDJQQiJEzRD+k8CdS08/S4booMJxDMX0WyvIK0ILFjzmn+4bntE7vzd4R/VXitX0Da2xg23M9JSYEs3D29i4QgAlWTHLDieRVegke6LQx43B+eWLvIgSrwhSc3zfSovzj6mMb+Y= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from loongson.cn (unknown [113.200.148.30]) by gateway (Coremail) with SMTP id _____8Ax6un6RTtm100JAA--.12761S3; Wed, 08 May 2024 17:29:30 +0800 (CST) Received: from linux.localdomain (unknown [113.200.148.30]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxLlXnRTtmzHQVAA--.24860S4; Wed, 08 May 2024 17:29:24 +0800 (CST) From: Tiezhu Yang To: binutils@sourceware.org, gdb-patches@sourceware.org Cc: Jim Wilson , Jeff Johnston , Kevin Buettner Subject: [PATCH 2/2] gdb: Remove Itanium (IA-64) architecture Date: Wed, 8 May 2024 17:29:10 +0800 Message-ID: <20240508092911.24823-3-yangtiezhu@loongson.cn> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20240508092911.24823-1-yangtiezhu@loongson.cn> References: <20240508092911.24823-1-yangtiezhu@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxLlXnRTtmzHQVAA--.24860S4 X-CM-SenderInfo: p1dqw3xlh2x3gn0dqz5rrqw2lrqou0/ X-Coremail-Antispam: 1Uk129KBj9kXoW8Jr45JF1kXF4rJF18WrWDKw1xp5X_XFW3JF 4xpFWfCas8tr48tr48Za1xGa18AF15Cr93ta4Yv34DG342k3s8W3s3ZFyftrWavF1DKry8 ur4Y9Fs0q3yrWF4DAagCm3ZEXasCq-sJn29KB7ZKAUJUUUU5529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29K BjDU0xBIdaVrnRJUUUk2b4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26c xKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r126r13M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vE j48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxV AFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x02 67AKxVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6x ACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1q6rW5McIj6I8E 87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41l42xK82 IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC2 0s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r126r1DMIIYrxkI7VAKI48JMI IF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87 Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjxUco7KUUUUU X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org The Itanium architecture is obsolete, after the upstream Linux kernel commit cf8e8658100d ("arch: Remove Itanium (IA-64) architecture"), the IA-64 port has been removed from the Linux kernel, so also remove the IA-64 specific code from gdb. Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cf8e8658100d Signed-off-by: Tiezhu Yang --- gdb/MAINTAINERS | 5 - gdb/Makefile.in | 10 - gdb/NEWS | 2 + gdb/README | 5 - gdb/config.in | 3 - gdb/config/djgpp/fnchange.lst | 19 - gdb/configure | 238 +- gdb/configure.ac | 39 - gdb/configure.host | 3 - gdb/configure.nat | 4 - gdb/configure.tgt | 16 - gdb/disasm-selftests.c | 5 - gdb/doc/gdb.texinfo | 7 +- gdb/dwarf2/frame.c | 2 +- gdb/gdbtypes.c | 4 - gdb/gdbtypes.h | 1 - gdb/ia64-libunwind-tdep.c | 582 --- gdb/ia64-libunwind-tdep.h | 79 - gdb/ia64-linux-nat.c | 931 ---- gdb/ia64-linux-tdep.c | 267 -- gdb/ia64-tdep.c | 4024 ----------------- gdb/ia64-tdep.h | 268 -- gdb/ia64-vms-tdep.c | 162 - gdb/inf-ptrace.c | 3 - gdb/nat/linux-ptrace.c | 5 - gdb/regcache.c | 3 +- gdb/regformats/reg-ia64.dat | 475 -- gdb/stubs/ia64vms-stub.c | 2601 ----------- gdb/symtab.c | 5 +- gdb/target.h | 2 - gdb/testsuite/configure | 4 +- gdb/testsuite/configure.ac | 4 +- .../gdb.arch/ia64-breakpoint-shadow.S | 44 - .../gdb.arch/ia64-breakpoint-shadow.exp | 73 - gdb/testsuite/gdb.asm/asm-source.exp | 4 - gdb/testsuite/gdb.asm/ia64.inc | 51 - gdb/testsuite/gdb.base/callfuncs.exp | 7 +- gdb/testsuite/gdb.base/float.exp | 2 - gdb/testsuite/gdb.base/step-test.exp | 10 +- gdb/testsuite/gdb.dwarf2/pr10770.c | 1 - .../gdb.threads/clone-attach-detach.c | 5 - gdb/testsuite/gdb.threads/clone-thread_db.c | 5 - gdb/testsuite/gdb.threads/ia64-sigill.c | 371 -- gdb/testsuite/gdb.threads/ia64-sigill.exp | 77 - gdb/testsuite/lib/gdb.exp | 2 - gdb/top.c | 10 - gdbserver/configure.srv | 4 - gdbserver/linux-ia64-low.cc | 395 -- 48 files changed, 23 insertions(+), 10816 deletions(-) delete mode 100644 gdb/ia64-libunwind-tdep.c delete mode 100644 gdb/ia64-libunwind-tdep.h delete mode 100644 gdb/ia64-linux-nat.c delete mode 100644 gdb/ia64-linux-tdep.c delete mode 100644 gdb/ia64-tdep.c delete mode 100644 gdb/ia64-tdep.h delete mode 100644 gdb/ia64-vms-tdep.c delete mode 100644 gdb/regformats/reg-ia64.dat delete mode 100644 gdb/stubs/ia64vms-stub.c delete mode 100644 gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.S delete mode 100644 gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.exp delete mode 100644 gdb/testsuite/gdb.asm/ia64.inc delete mode 100644 gdb/testsuite/gdb.threads/ia64-sigill.c delete mode 100644 gdb/testsuite/gdb.threads/ia64-sigill.exp delete mode 100644 gdbserver/linux-ia64-low.cc diff --git a/gdb/MAINTAINERS b/gdb/MAINTAINERS index 457dd4041c5..14979ff6e32 100644 --- a/gdb/MAINTAINERS +++ b/gdb/MAINTAINERS @@ -348,9 +348,6 @@ the native maintainer when resolving ABI issues. i386 --target=i386-elf Felix Willgerodt felix.willgerodt@intel.com - ia64 --target=ia64-linux-gnu - (--target=ia64-elf broken) - lm32 --target=lm32-elf loongarch --target=loongarch32-elf @@ -517,12 +514,10 @@ to do so! ARM Richard Earnshaw rearnsha@arm.com Blackfin Mike Frysinger vapier@gentoo.org CRIS Hans-Peter Nilsson hp@axis.com -IA64 Jeff Johnston jjohnstn@redhat.com PowerPC Kevin Buettner kevinb@redhat.com S390 Ulrich Weigand uweigand@de.ibm.com djgpp DJ Delorie dj@delorie.com [Please use this address to contact DJ about DJGPP] -ia64 Kevin Buettner kevinb@redhat.com AIX Kevin Buettner kevinb@redhat.com GNU/Linux PPC native Kevin Buettner kevinb@redhat.com Pascal support Pierre Muller muller@sourceware.org diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 234d0051f49..dde74a32ea3 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -751,9 +751,6 @@ ALL_64_TARGET_OBS = \ arch/amd64.o \ arch/riscv.o \ bpf-tdep.o \ - ia64-linux-tdep.o \ - ia64-tdep.o \ - ia64-vms-tdep.o \ loongarch-linux-tdep.o \ loongarch-tdep.o \ mips-fbsd-tdep.o \ @@ -1401,8 +1398,6 @@ HFILES_NO_SRCDIR = \ i386-linux-tdep.h \ i386-tdep.h \ i387-tdep.h \ - ia64-libunwind-tdep.h \ - ia64-tdep.h \ inf-child.h \ inf-loop.h \ inf-ptrace.h \ @@ -1756,11 +1751,6 @@ ALLDEPFILES = \ i386-tdep.c \ i386-windows-tdep.c \ i387-tdep.c \ - ia64-libunwind-tdep.c \ - ia64-linux-nat.c \ - ia64-linux-tdep.c \ - ia64-tdep.c \ - ia64-vms-tdep.c \ inf-ptrace.c \ linux-fork.c \ linux-record.c \ diff --git a/gdb/NEWS b/gdb/NEWS index 050f6f96e62..3ead1172171 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -16,6 +16,8 @@ the background, resulting in faster startup. This can be controlled using "maint set dwarf synchronous". +* Remove Itanium (IA-64) architecture. + * Changed commands disassemble diff --git a/gdb/README b/gdb/README index 763089bb02d..9b833b908e1 100644 --- a/gdb/README +++ b/gdb/README @@ -441,11 +441,6 @@ more obscure GDB `configure' options are not listed here. with version 0.178. You can get the latest version from 'https://sourceware.org/elfutils/'. -`--with-libunwind-ia64' - Use the libunwind library for unwinding function call stack on ia64 - target platforms. - See http://www.nongnu.org/libunwind/index.html for details. - `--with-system-readline' Use the readline library installed on the host, rather than the library supplied as part of GDB. Readline 7 or newer is required; diff --git a/gdb/config.in b/gdb/config.in index 0c144c8918b..f7703bfdbcd 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -280,9 +280,6 @@ /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM -/* Define to 1 if you have the header file. */ -#undef HAVE_LIBUNWIND_IA64_H - /* Define if you have the xxhash library. */ #undef HAVE_LIBXXHASH diff --git a/gdb/config/djgpp/fnchange.lst b/gdb/config/djgpp/fnchange.lst index 3e77bece2fc..562a0c096ae 100644 --- a/gdb/config/djgpp/fnchange.lst +++ b/gdb/config/djgpp/fnchange.lst @@ -17,16 +17,9 @@ @V@/bfd/coff-tic80.c @V@/bfd/cofftic80.c @V@/bfd/cpu-cr16.c @V@/bfd/cpucr16.c @V@/bfd/cpu-cr16c.c @V@/bfd/cpucr16c.c -@V@/bfd/cpu-ia64-opc.c @V@/bfd/cpuia64-opc.c @V@/bfd/cpu-microblaze.c @V@/bfd/cpumb.c @V@/bfd/cpu-m68hc11.c @V@/bfd/cm68hc11.c @V@/bfd/cpu-m68hc12.c @V@/bfd/cm68hc12.c -@V@/bfd/efi-app-ia32.c @V@/bfd/efiia32app.c -@V@/bfd/efi-app-ia64.c @V@/bfd/efiia64app.c -@V@/bfd/efi-bsdrv-ia32.c @V@/bfd/efiia32bsdrv.c -@V@/bfd/efi-bsdrv-ia64.c @V@/bfd/efiia64bsdrv.c -@V@/bfd/efi-rtdrv-ia32.c @V@/bfd/efiia32rtdrv.c -@V@/bfd/efi-rtdrv-ia64.c @V@/bfd/efiia64rtdrv.c @V@/bfd/elf32-arc.c @V@/bfd/elf32arc.c @V@/bfd/elf32-crx.c @V@/bfd/elf32crx.c @V@/bfd/elf32-cris.c @V@/bfd/elf32cris.c @@ -297,10 +290,6 @@ @V@/gdb/i386-obsd-tdep.c @V@/gdb/i3obsd-tdep.c @V@/gdb/i386-sol2-nat.c @V@/gdb/i3sol2-nat.c @V@/gdb/i386-sol2-tdep.c @V@/gdb/i3sol2-tdep.c -@V@/gdb/ia64-aix-nat.c @V@/gdb/ia64ax-nat.c -@V@/gdb/ia64-aix-tdep.c @V@/gdb/ia64ax-tdep.c -@V@/gdb/ia64-linux-nat.c @V@/gdb/ia64lx-nat.c -@V@/gdb/ia64-linux-tdep.c @V@/gdb/ia64lx-tdep.c @V@/gdb/jv-exp.tab.c @V@/gdb/jv-exp_tab.c @V@/gdb/m2-exp.tab.c @V@/gdb/m2-exp_tab.c @V@/gdb/m32r-linux-nat.c @V@/gdb/m32rlnxnat.c @@ -551,14 +540,6 @@ @V@/opcodes/ChangeLog-2006 @V@/opcodes/ChangeLog.006 @V@/opcodes/ChangeLog-2007 @V@/opcodes/ChangeLog.007 @V@/opcodes/ChangeLog-2008 @V@/opcodes/ChangeLog.008 -@V@/opcodes/ia64-opc-a.c @V@/opcodes/ia64opca.c -@V@/opcodes/ia64-opc-b.c @V@/opcodes/ia64opcb.c -@V@/opcodes/ia64-opc-d.c @V@/opcodes/ia64opcd.c -@V@/opcodes/ia64-opc-f.c @V@/opcodes/ia64opcf.c -@V@/opcodes/ia64-opc-i.c @V@/opcodes/ia64opci.c -@V@/opcodes/ia64-opc-m.c @V@/opcodes/ia64opcm.c -@V@/opcodes/ia64-opc-x.c @V@/opcodes/ia64opcx.c -@V@/opcodes/ia64-opc.c @V@/opcodes/ia64-opc.c @V@/opcodes/iq2000-desc.c @V@/opcodes/iq2000desc.c @V@/opcodes/iq2000-dis.c @V@/opcodes/iq2000dis.c @V@/opcodes/microblaze-opc.h @V@/opcodes/mb-opc.h diff --git a/gdb/configure b/gdb/configure index 98cd488a737..2c78497e4c6 100755 --- a/gdb/configure +++ b/gdb/configure @@ -938,7 +938,6 @@ with_amd_dbgapi enable_tui enable_gdbtk with_debuginfod -with_libunwind_ia64 with_curses enable_profiling enable_codesign @@ -1706,7 +1705,6 @@ Optional Packages: --with-amd-dbgapi support for the amd-dbgapi target (yes / no / auto) --with-debuginfod Enable debuginfo lookups with debuginfod (auto/yes/no) - --with-libunwind-ia64 use libunwind frame unwinding for ia64 targets --with-curses use the curses library instead of the termcap library --with-pkgversion=PKG Use PKG in the version string in place of "GDB" @@ -6341,10 +6339,6 @@ haiku*) hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl @@ -6945,11 +6939,6 @@ aix*) cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; -hpux*) - if test "$host_cpu" = ia64; then - symcode='[ABCDEGRST]' - fi - ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; @@ -6980,7 +6969,7 @@ case `$NM -V 2>&1` in esac # Transform an extracted symbol line into a proper C declaration. -# Some systems (esp. on ia64) link data and code symbols differently, +# Some systems link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" @@ -7180,25 +7169,6 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext @@ -8534,10 +8504,6 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - fi lt_prog_compiler_pic='-fPIC' ;; @@ -8634,12 +8600,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } case $host_os in aix*) lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - else - lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' - fi + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' ;; mingw* | cygwin* | pw32* | os2* | cegcc*) @@ -8653,7 +8614,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in - hppa*64*|ia64*) + hppa*64*) # +Z the default ;; *) @@ -9178,7 +9139,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 @@ -9190,7 +9150,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie *** You will then need to restart the configuration process. _LT_EOF - fi ;; amigaos*) @@ -9286,10 +9245,6 @@ _LT_EOF # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 @@ -9443,13 +9398,6 @@ _LT_EOF ;; aix[4-9]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global @@ -9476,7 +9424,6 @@ _LT_EOF exp_sym_flag='-bexport' no_entry_flag='-bnoentry' - fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library @@ -9519,17 +9466,11 @@ _LT_EOF fi else # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi - fi fi export_dynamic_flag_spec='${wl}-bexpall' @@ -9575,11 +9516,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else # Determine the default libpath from the value encoded in an # empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9627,7 +9563,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi fi ;; @@ -9776,9 +9711,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; - ia64*) - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; @@ -9788,9 +9720,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; - ia64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; *) # Older versions of the 11.00 compiler do not understand -b yet @@ -9840,7 +9769,7 @@ fi hardcode_libdir_separator=: case $host_cpu in - hppa*64*|ia64*) + hppa*64*) hardcode_direct=no hardcode_shlibpath_var=no ;; @@ -10477,11 +10406,6 @@ aix[4-9]*) need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to @@ -10513,7 +10437,6 @@ aix[4-9]*) soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH - fi ;; amigaos*) @@ -10690,21 +10613,6 @@ hpux9* | hpux10* | hpux11*) need_lib_prefix=no need_version=no case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes @@ -11795,7 +11703,7 @@ $as_echo_n "checking whether to build shared libraries... " >&6; } ;; aix[4-9]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + if test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; @@ -12251,13 +12159,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie ld_shlibs_CXX=no ;; aix[4-9]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal @@ -12277,7 +12178,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie exp_sym_flag='-bexport' no_entry_flag='-bnoentry' - fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library @@ -12319,17 +12219,11 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie fi else # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi - fi fi export_dynamic_flag_spec_CXX='${wl}-bexpall' @@ -12377,11 +12271,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_CXX="-z nodefs" - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else # Determine the default libpath from the value encoded in an # empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -12430,7 +12319,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # This is similar to how AIX traditionally builds its shared # libraries. archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi fi ;; @@ -12598,7 +12486,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_separator_CXX=: case $host_cpu in - hppa*64*|ia64*) + hppa*64*) ;; *) export_dynamic_flag_spec_CXX='${wl}-E' @@ -12606,7 +12494,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi esac fi case $host_cpu in - hppa*64*|ia64*) + hppa*64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; @@ -12629,9 +12517,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hppa*64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; - ia64*) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; @@ -12653,9 +12538,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; - ia64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; *) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; @@ -12751,9 +12633,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; *) # Version 8.0 or newer tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; @@ -13399,10 +13278,6 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - fi lt_prog_compiler_pic_CXX='-fPIC' ;; @@ -13479,12 +13354,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } case $host_os in aix[4-9]*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - else - lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' - fi + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' ;; chorus*) case $cc_basename in @@ -13515,15 +13385,13 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then - lt_prog_compiler_pic_CXX='+Z' - fi + lt_prog_compiler_pic_CXX='+Z' ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' case $host_cpu in - hppa*64*|ia64*) + hppa*64*) # +Z the default ;; *) @@ -14154,11 +14022,6 @@ aix[4-9]*) need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to @@ -14190,7 +14053,6 @@ aix[4-9]*) soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH - fi ;; amigaos*) @@ -14365,21 +14227,6 @@ hpux9* | hpux10* | hpux11*) need_lib_prefix=no need_version=no case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes @@ -25411,71 +25258,6 @@ else $as_echo "$as_me: WARNING: debuginfod support disabled; some features may be unavailable." >&2;} fi - -# Libunwind support for ia64. - -# Check whether --with-libunwind-ia64 was given. -if test "${with_libunwind_ia64+set}" = set; then : - withval=$with_libunwind_ia64; -else - with_libunwind_ia64=auto -fi - - -# Backward compatibility option. -if test "${with_libunwind+set}" = set; then - if test x"$with_libunwind_ia64" != xauto; then - as_fn_error $? "option --with-libunwind is deprecated, use --with-libunwind-ia64" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: option --with-libunwind is deprecated, use --with-libunwind-ia64" >&5 -$as_echo "$as_me: WARNING: option --with-libunwind is deprecated, use --with-libunwind-ia64" >&2;} - with_libunwind_ia64="$with_libunwind" -fi - -case "$with_libunwind_ia64" in - yes | no) - ;; - auto) - for ac_header in libunwind-ia64.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "libunwind-ia64.h" "ac_cv_header_libunwind_ia64_h" "$ac_includes_default" -if test "x$ac_cv_header_libunwind_ia64_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBUNWIND_IA64_H 1 -_ACEOF - -fi - -done - - with_libunwind_ia64=$ac_cv_header_libunwind_ia64_h - ;; - *) - as_fn_error $? "bad value $with_libunwind_ia64 for GDB --with-libunwind-ia64 option" "$LINENO" 5 - ;; -esac - -if test x"$with_libunwind_ia64" = xyes; then - for ac_header in libunwind-ia64.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "libunwind-ia64.h" "ac_cv_header_libunwind_ia64_h" "$ac_includes_default" -if test "x$ac_cv_header_libunwind_ia64_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBUNWIND_IA64_H 1 -_ACEOF - -fi - -done - - if test x"$ac_cv_header_libunwind_ia64_h" != xyes; then - as_fn_error $? "GDB option --with-libunwind-ia64 requires libunwind-ia64.h" "$LINENO" 5 - fi - CONFIG_OBS="$CONFIG_OBS ia64-libunwind-tdep.o" - CONFIG_DEPS="$CONFIG_DEPS ia64-libunwind-tdep.o" - CONFIG_SRCS="$CONFIG_SRCS ia64-libunwind-tdep.c" -fi - opt_curses=no # Check whether --with-curses was given. diff --git a/gdb/configure.ac b/gdb/configure.ac index 62ff09cea20..4243a7f43ad 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -354,45 +354,6 @@ esac # Handle optional debuginfod support AC_DEBUGINFOD -# Libunwind support for ia64. -AC_ARG_WITH(libunwind-ia64, -AS_HELP_STRING([--with-libunwind-ia64], - [use libunwind frame unwinding for ia64 targets]),, - [with_libunwind_ia64=auto]) - -# Backward compatibility option. -if test "${with_libunwind+set}" = set; then - if test x"$with_libunwind_ia64" != xauto; then - AC_MSG_ERROR( - [option --with-libunwind is deprecated, use --with-libunwind-ia64]) - fi - AC_MSG_WARN([option --with-libunwind is deprecated, use --with-libunwind-ia64]) - with_libunwind_ia64="$with_libunwind" -fi - -case "$with_libunwind_ia64" in - yes | no) - ;; - auto) - AC_CHECK_HEADERS(libunwind-ia64.h) - with_libunwind_ia64=$ac_cv_header_libunwind_ia64_h - ;; - *) - AC_MSG_ERROR( - [bad value $with_libunwind_ia64 for GDB --with-libunwind-ia64 option]) - ;; -esac - -if test x"$with_libunwind_ia64" = xyes; then - AC_CHECK_HEADERS(libunwind-ia64.h) - if test x"$ac_cv_header_libunwind_ia64_h" != xyes; then - AC_MSG_ERROR([GDB option --with-libunwind-ia64 requires libunwind-ia64.h]) - fi - CONFIG_OBS="$CONFIG_OBS ia64-libunwind-tdep.o" - CONFIG_DEPS="$CONFIG_DEPS ia64-libunwind-tdep.o" - CONFIG_SRCS="$CONFIG_SRCS ia64-libunwind-tdep.c" -fi - opt_curses=no AC_ARG_WITH(curses, AS_HELP_STRING([--with-curses], [use the curses library instead of the termcap library]), opt_curses=$withval) diff --git a/gdb/configure.host b/gdb/configure.host index da71675b201..d64939df3c1 100644 --- a/gdb/configure.host +++ b/gdb/configure.host @@ -42,7 +42,6 @@ case $host in vax-*-netbsdaout* | \ vax-*-ultrix* | \ hppa*-*-hpux* | \ - ia64-*-hpux* | \ null) echo "*** Configuration $host is obsolete." >&2 echo "*** Support has been REMOVED." >&2 @@ -116,8 +115,6 @@ i[34567]86-*-solaris2* | x86_64-*-solaris2*) gdb_host=sol2 ;; i[34567]86-*-cygwin*) gdb_host=cygwin ;; -ia64-*-linux*) gdb_host=linux ;; - loongarch*-linux*) gdb_host=linux ;; m68*-*-linux*) gdb_host=linux ;; diff --git a/gdb/configure.nat b/gdb/configure.nat index 8b98511cef7..a3cb0eed2b3 100644 --- a/gdb/configure.nat +++ b/gdb/configure.nat @@ -258,10 +258,6 @@ case ${gdb_host} in i386-linux-nat.o x86-linux-nat.o nat/linux-btrace.o \ nat/x86-linux.o nat/x86-linux-dregs.o" ;; - ia64) - # Host: Intel IA-64 running GNU/Linux - NATDEPFILES="${NATDEPFILES} ia64-linux-nat.o" - ;; loongarch) # Host: LoongArch, running GNU/Linux. NATDEPFILES="${NATDEPFILES} loongarch-linux-nat.o linux-nat-trad.o" diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 47a674201f9..0382e369c67 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -36,7 +36,6 @@ case $targ in score-*-* | \ sh*-*-pe | \ hppa*-*-hpux* | \ - ia64-*-hpux* | \ *-*-vxworks* | \ mt-*-* | \ null) @@ -94,11 +93,6 @@ ia16*-*-*) cpu_obs="${i386_tobjs}" ;; -ia64*-*-*) - # Target: Intel IA-64 - cpu_obs="ia64-tdep.o" - ;; - loongarch*-*-*) # Target: LoongArch baremetal cpu_obs="loongarch-tdep.o arch/loongarch.o" @@ -343,16 +337,6 @@ i[34567]86-*-go32* | i[34567]86-*-msdosdjgpp*) gdb_target_obs="i386-go32-tdep.o" ;; -ia64-*-linux*) - # Target: Intel IA-64 running GNU/Linux - gdb_target_obs="ia64-linux-tdep.o linux-tdep.o \ - solib-svr4.o symfile-mem.o" - ;; -ia64-*-*vms*) - # Target: Intel IA-64 running OpenVMS - gdb_target_obs="ia64-vms-tdep.o" - ;; - iq2000-*-*) gdb_target_obs="iq2000-tdep.o" ;; diff --git a/gdb/disasm-selftests.c b/gdb/disasm-selftests.c index 14b7fb30bad..766b25a51ed 100644 --- a/gdb/disasm-selftests.c +++ b/gdb/disasm-selftests.c @@ -54,11 +54,6 @@ get_test_insn (struct gdbarch *gdbarch, size_t *len) insn = arm_insn; *len = sizeof (arm_insn); break; - case bfd_arch_ia64: - /* We get: - internal-error: gdbarch_sw_breakpoint_from_kind: - Assertion `gdbarch->sw_breakpoint_from_kind != NULL' failed. */ - return insn; case bfd_arch_mep: /* Disassembles as '*unknown*' insn, then len self-check fails. */ return insn; diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 61f91ef4ad6..5e86302bb0d 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -41183,11 +41183,6 @@ files. Enabled by default if @file{libdebuginfod} is installed and found at configure time. For more information regarding @code{debuginfod} see @ref{Debuginfod}. -@item --with-libunwind-ia64 -Use the libunwind library for unwinding function call stack on ia64 -target platforms. See @url{http://www.nongnu.org/libunwind/index.html} for -details. - @item --with-system-readline Use the readline library installed on the host, rather than the library supplied as part of @value{GDBN}. Readline 7 or newer is @@ -45450,7 +45445,7 @@ by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). @anchor{qXfer unwind info block} Return the unwind information block for @var{pc}. This packet is used -on OpenVMS/ia64 to ask the kernel unwind information. +on OpenVMS to ask the kernel unwind information. This packet is not probed by default. diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index 9ebf3ac4ac4..54044500355 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -2152,7 +2152,7 @@ dwarf2_build_frame_info (struct objfile *objfile) if (got) unit->dbase = got->vma; - /* GCC emits the DW_EH_PE_textrel encoding type on sh and ia64 + /* GCC emits the DW_EH_PE_textrel encoding type on sh so far. */ txt = bfd_get_section_by_name (unit->abfd, ".text"); if (txt) diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 5b3c5ac8a02..e051f764497 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -110,10 +110,6 @@ const struct floatformat *floatformats_arm_ext[BFD_ENDIAN_UNKNOWN] = { &floatformat_arm_ext_big, &floatformat_arm_ext_littlebyte_bigword }; -const struct floatformat *floatformats_ia64_spill[BFD_ENDIAN_UNKNOWN] = { - &floatformat_ia64_spill_big, - &floatformat_ia64_spill_little -}; const struct floatformat *floatformats_vax_f[BFD_ENDIAN_UNKNOWN] = { &floatformat_vax_f, &floatformat_vax_f diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index f80bd7e071a..f1370a3026e 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -2198,7 +2198,6 @@ extern const struct floatformat *floatformats_ieee_double_littlebyte_bigword[BFD extern const struct floatformat *floatformats_i387_ext[BFD_ENDIAN_UNKNOWN]; extern const struct floatformat *floatformats_m68881_ext[BFD_ENDIAN_UNKNOWN]; extern const struct floatformat *floatformats_arm_ext[BFD_ENDIAN_UNKNOWN]; -extern const struct floatformat *floatformats_ia64_spill[BFD_ENDIAN_UNKNOWN]; extern const struct floatformat *floatformats_vax_f[BFD_ENDIAN_UNKNOWN]; extern const struct floatformat *floatformats_vax_d[BFD_ENDIAN_UNKNOWN]; extern const struct floatformat *floatformats_ibm_long_double[BFD_ENDIAN_UNKNOWN]; diff --git a/gdb/ia64-libunwind-tdep.c b/gdb/ia64-libunwind-tdep.c deleted file mode 100644 index 72e4fae418d..00000000000 --- a/gdb/ia64-libunwind-tdep.c +++ /dev/null @@ -1,582 +0,0 @@ -/* Frame unwinder for ia64 frames using the libunwind library. - - Copyright (C) 2003-2024 Free Software Foundation, Inc. - - Written by Jeff Johnston, contributed by Red Hat Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 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, see . */ - - -#include "inferior.h" -#include "frame.h" -#include "frame-base.h" -#include "frame-unwind.h" -#include "gdbcore.h" -#include "gdbtypes.h" -#include "symtab.h" -#include "objfiles.h" -#include "regcache.h" - -#include - -#include "ia64-libunwind-tdep.h" - -#include "gdbsupport/preprocessor.h" - -/* IA-64 is the only target that currently uses ia64-libunwind-tdep. - Note how UNW_TARGET, UNW_OBJ, etc. are compile time constants below. - Those come from libunwind's headers, and are target dependent. - Also, some of libunwind's typedefs are target dependent, as e.g., - unw_word_t. If some other target wants to use this, we will need - to do some abstracting in order to make it possible to select which - libunwind we're talking to at runtime (and have one per arch). */ - -/* The following two macros are normally defined in . - But systems such as ia64-hpux do not provide such header, so - we just define them here if not already defined. */ -#ifndef __LITTLE_ENDIAN -#define __LITTLE_ENDIAN 1234 -#endif -#ifndef __BIG_ENDIAN -#define __BIG_ENDIAN 4321 -#endif - -static int libunwind_initialized; -static const registry::key libunwind_descr_handle; - -/* Required function pointers from libunwind. */ -typedef int (unw_get_reg_p_ftype) (unw_cursor_t *, unw_regnum_t, unw_word_t *); -static unw_get_reg_p_ftype *unw_get_reg_p; -typedef int (unw_get_fpreg_p_ftype) (unw_cursor_t *, unw_regnum_t, - unw_fpreg_t *); -static unw_get_fpreg_p_ftype *unw_get_fpreg_p; -typedef int (unw_get_saveloc_p_ftype) (unw_cursor_t *, unw_regnum_t, - unw_save_loc_t *); -static unw_get_saveloc_p_ftype *unw_get_saveloc_p; -typedef int (unw_is_signal_frame_p_ftype) (unw_cursor_t *); -static unw_is_signal_frame_p_ftype *unw_is_signal_frame_p; -typedef int (unw_step_p_ftype) (unw_cursor_t *); -static unw_step_p_ftype *unw_step_p; -typedef int (unw_init_remote_p_ftype) (unw_cursor_t *, unw_addr_space_t, - void *); -static unw_init_remote_p_ftype *unw_init_remote_p; -typedef unw_addr_space_t (unw_create_addr_space_p_ftype) (unw_accessors_t *, - int); -static unw_create_addr_space_p_ftype *unw_create_addr_space_p; -typedef void (unw_destroy_addr_space_p_ftype) (unw_addr_space_t); -static unw_destroy_addr_space_p_ftype *unw_destroy_addr_space_p; -typedef int (unw_search_unwind_table_p_ftype) (unw_addr_space_t, unw_word_t, - unw_dyn_info_t *, - unw_proc_info_t *, int, void *); -static unw_search_unwind_table_p_ftype *unw_search_unwind_table_p; -typedef unw_word_t (unw_find_dyn_list_p_ftype) (unw_addr_space_t, - unw_dyn_info_t *, void *); -static unw_find_dyn_list_p_ftype *unw_find_dyn_list_p; - - -struct libunwind_frame_cache -{ - CORE_ADDR base; - CORE_ADDR func_addr; - unw_cursor_t cursor; - unw_addr_space_t as; -}; - -/* We need to qualify the function names with a platform-specific prefix - to match the names used by the libunwind library. The UNW_OBJ macro is - provided by the libunwind.h header file. */ - -#ifndef LIBUNWIND_SO -/* Use the stable ABI major version number. `libunwind-ia64.so' is a link time - only library, not a runtime one. */ -#define LIBUNWIND_SO "libunwind-" STRINGIFY(UNW_TARGET) ".so.8" - -/* Provide also compatibility with older .so. The two APIs are compatible, .8 - is only extended a bit, GDB does not use the extended API at all. */ -#define LIBUNWIND_SO_7 "libunwind-" STRINGIFY(UNW_TARGET) ".so.7" -#endif - -static const char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg)); -static const char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg)); -static const char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_save_loc)); -static const char *is_signal_frame_name = STRINGIFY(UNW_OBJ(is_signal_frame)); -static const char *step_name = STRINGIFY(UNW_OBJ(step)); -static const char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote)); -static const char *create_addr_space_name - = STRINGIFY(UNW_OBJ(create_addr_space)); -static const char *destroy_addr_space_name - = STRINGIFY(UNW_OBJ(destroy_addr_space)); -static const char *search_unwind_table_name - = STRINGIFY(UNW_OBJ(search_unwind_table)); -static const char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list)); - -static struct libunwind_descr * -libunwind_descr (struct gdbarch *gdbarch) -{ - struct libunwind_descr *result = libunwind_descr_handle.get (gdbarch); - if (result == nullptr) - result = libunwind_descr_handle.emplace (gdbarch); - return result; -} - -void -libunwind_frame_set_descr (struct gdbarch *gdbarch, - struct libunwind_descr *descr) -{ - struct libunwind_descr *arch_descr; - - gdb_assert (gdbarch != NULL); - - arch_descr = libunwind_descr (gdbarch); - gdb_assert (arch_descr != NULL); - - /* Copy new descriptor info into arch descriptor. */ - arch_descr->gdb2uw = descr->gdb2uw; - arch_descr->uw2gdb = descr->uw2gdb; - arch_descr->is_fpreg = descr->is_fpreg; - arch_descr->accessors = descr->accessors; - arch_descr->special_accessors = descr->special_accessors; -} - -static struct libunwind_frame_cache * -libunwind_frame_cache (const frame_info_ptr &this_frame, void **this_cache) -{ - unw_accessors_t *acc; - unw_addr_space_t as; - unw_word_t fp; - unw_regnum_t uw_sp_regnum; - struct libunwind_frame_cache *cache; - struct libunwind_descr *descr; - struct gdbarch *gdbarch = get_frame_arch (this_frame); - int ret; - - if (*this_cache) - return (struct libunwind_frame_cache *) *this_cache; - - /* Allocate a new cache. */ - cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache); - - cache->func_addr = get_frame_func (this_frame); - if (cache->func_addr == 0) - /* This can happen when the frame corresponds to a function for which - there is no debugging information nor any entry in the symbol table. - This is probably a static function for which an entry in the symbol - table was not created when the objfile got linked (observed in - libpthread.so on ia64-hpux). - - The best we can do, in that case, is use the frame PC as the function - address. We don't need to give up since we still have the unwind - record to help us perform the unwinding. There is also another - compelling to continue, because abandoning now means stopping - the backtrace, which can never be helpful for the user. */ - cache->func_addr = get_frame_pc (this_frame); - - /* Get a libunwind cursor to the previous frame. - - We do this by initializing a cursor. Libunwind treats a new cursor - as the top of stack and will get the current register set via the - libunwind register accessor. Now, we provide the platform-specific - accessors and we set up the register accessor to use the frame - register unwinding interfaces so that we properly get the registers - for the current frame rather than the top. We then use the unw_step - function to move the libunwind cursor back one frame. We can later - use this cursor to find previous registers via the unw_get_reg - interface which will invoke libunwind's special logic. */ - descr = libunwind_descr (gdbarch); - acc = (unw_accessors_t *) descr->accessors; - as = unw_create_addr_space_p (acc, - gdbarch_byte_order (gdbarch) - == BFD_ENDIAN_BIG - ? __BIG_ENDIAN - : __LITTLE_ENDIAN); - - unw_init_remote_p (&cache->cursor, as, this_frame); - if (unw_step_p (&cache->cursor) < 0) - { - unw_destroy_addr_space_p (as); - return NULL; - } - - /* To get base address, get sp from previous frame. */ - uw_sp_regnum = descr->gdb2uw (gdbarch_sp_regnum (gdbarch)); - ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp); - if (ret < 0) - { - unw_destroy_addr_space_p (as); - error (_("Can't get libunwind sp register.")); - } - - cache->base = (CORE_ADDR)fp; - cache->as = as; - - *this_cache = cache; - return cache; -} - -void -libunwind_frame_dealloc_cache (frame_info_ptr self, void *this_cache) -{ - struct libunwind_frame_cache *cache - = (struct libunwind_frame_cache *) this_cache; - - if (cache->as) - unw_destroy_addr_space_p (cache->as); -} - -unw_word_t -libunwind_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg) -{ - return unw_find_dyn_list_p (as, di, arg); -} - -/* Verify if there is sufficient libunwind information for the frame to use - libunwind frame unwinding. */ -int -libunwind_frame_sniffer (const struct frame_unwind *self, - const frame_info_ptr &this_frame, void **this_cache) -{ - unw_cursor_t cursor; - unw_accessors_t *acc; - unw_addr_space_t as; - struct libunwind_descr *descr; - struct gdbarch *gdbarch = get_frame_arch (this_frame); - int ret; - - /* To test for libunwind unwind support, initialize a cursor to - the current frame and try to back up. We use this same method - when setting up the frame cache (see libunwind_frame_cache()). - If libunwind returns success for this operation, it means that - it has found sufficient libunwind unwinding information to do so. */ - - descr = libunwind_descr (gdbarch); - acc = (unw_accessors_t *) descr->accessors; - as = unw_create_addr_space_p (acc, - gdbarch_byte_order (gdbarch) - == BFD_ENDIAN_BIG - ? __BIG_ENDIAN - : __LITTLE_ENDIAN); - - ret = unw_init_remote_p (&cursor, as, this_frame); - - if (ret < 0) - { - unw_destroy_addr_space_p (as); - return 0; - } - - - /* Check to see if we have libunwind info by checking if we are in a - signal frame. If it doesn't return an error, we have libunwind info - and can use libunwind. */ - ret = unw_is_signal_frame_p (&cursor); - unw_destroy_addr_space_p (as); - - if (ret < 0) - return 0; - - return 1; -} - -void -libunwind_frame_this_id (const frame_info_ptr &this_frame, void **this_cache, - struct frame_id *this_id) -{ - struct libunwind_frame_cache *cache = - libunwind_frame_cache (this_frame, this_cache); - - if (cache != NULL) - (*this_id) = frame_id_build (cache->base, cache->func_addr); -} - -struct value * -libunwind_frame_prev_register (const frame_info_ptr &this_frame, - void **this_cache, int regnum) -{ - struct libunwind_frame_cache *cache = - libunwind_frame_cache (this_frame, this_cache); - - unw_save_loc_t sl; - int ret; - unw_word_t intval; - unw_fpreg_t fpval; - unw_regnum_t uw_regnum; - struct libunwind_descr *descr; - struct value *val = NULL; - - if (cache == NULL) - return frame_unwind_got_constant (this_frame, regnum, 0); - - /* Convert from gdb register number to libunwind register number. */ - descr = libunwind_descr (get_frame_arch (this_frame)); - uw_regnum = descr->gdb2uw (regnum); - - gdb_assert (regnum >= 0); - - if (!target_has_registers ()) - error (_("No registers.")); - - if (uw_regnum < 0) - return frame_unwind_got_constant (this_frame, regnum, 0); - - if (unw_get_saveloc_p (&cache->cursor, uw_regnum, &sl) < 0) - return frame_unwind_got_constant (this_frame, regnum, 0); - - switch (sl.type) - { - case UNW_SLT_MEMORY: - val = frame_unwind_got_memory (this_frame, regnum, sl.u.addr); - break; - - case UNW_SLT_REG: - val = frame_unwind_got_register (this_frame, regnum, - descr->uw2gdb (sl.u.regnum)); - break; - case UNW_SLT_NONE: - { - /* The register is not stored at a specific memory address nor - inside another register. So use libunwind to fetch the register - value for us, and create a constant value with the result. */ - if (descr->is_fpreg (uw_regnum)) - { - ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval); - if (ret < 0) - return frame_unwind_got_constant (this_frame, regnum, 0); - val = frame_unwind_got_bytes (this_frame, regnum, - (gdb_byte *) &fpval); - } - else - { - ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval); - if (ret < 0) - return frame_unwind_got_constant (this_frame, regnum, 0); - val = frame_unwind_got_constant (this_frame, regnum, intval); - } - break; - } - } - - return val; -} - -/* The following is a glue routine to call the libunwind unwind table - search function to get unwind information for a specified ip address. */ -int -libunwind_search_unwind_table (void *as, long ip, void *di, - void *pi, int need_unwind_info, void *args) -{ - return unw_search_unwind_table_p (*(unw_addr_space_t *) as, (unw_word_t) ip, - (unw_dyn_info_t *) di, - (unw_proc_info_t *) pi, need_unwind_info, - args); -} - -/* Verify if we are in a sigtramp frame and we can use libunwind to unwind. */ -int -libunwind_sigtramp_frame_sniffer (const struct frame_unwind *self, - const frame_info_ptr &this_frame, - void **this_cache) -{ - unw_cursor_t cursor; - unw_accessors_t *acc; - unw_addr_space_t as; - struct libunwind_descr *descr; - struct gdbarch *gdbarch = get_frame_arch (this_frame); - int ret; - - /* To test for libunwind unwind support, initialize a cursor to the - current frame and try to back up. We use this same method when - setting up the frame cache (see libunwind_frame_cache()). If - libunwind returns success for this operation, it means that it - has found sufficient libunwind unwinding information to do - so. */ - - descr = libunwind_descr (gdbarch); - acc = (unw_accessors_t *) descr->accessors; - as = unw_create_addr_space_p (acc, - gdbarch_byte_order (gdbarch) - == BFD_ENDIAN_BIG - ? __BIG_ENDIAN - : __LITTLE_ENDIAN); - - ret = unw_init_remote_p (&cursor, as, this_frame); - - if (ret < 0) - { - unw_destroy_addr_space_p (as); - return 0; - } - - /* Check to see if we are in a signal frame. */ - ret = unw_is_signal_frame_p (&cursor); - unw_destroy_addr_space_p (as); - if (ret > 0) - return 1; - - return 0; -} - -/* The following routine is for accessing special registers of the top frame. - A special set of accessors must be given that work without frame info. - This is used by ia64 to access the rse registers r32-r127. While they - are usually located at BOF, this is not always true and only the libunwind - info can decipher where they actually are. */ -int -libunwind_get_reg_special (struct gdbarch *gdbarch, readable_regcache *regcache, - int regnum, void *buf) -{ - unw_cursor_t cursor; - unw_accessors_t *acc; - unw_addr_space_t as; - struct libunwind_descr *descr; - int ret; - unw_regnum_t uw_regnum; - unw_word_t intval; - unw_fpreg_t fpval; - void *ptr; - - - descr = libunwind_descr (gdbarch); - acc = (unw_accessors_t *) descr->special_accessors; - as = unw_create_addr_space_p (acc, - gdbarch_byte_order (gdbarch) - == BFD_ENDIAN_BIG - ? __BIG_ENDIAN - : __LITTLE_ENDIAN); - - ret = unw_init_remote_p (&cursor, as, regcache); - if (ret < 0) - { - unw_destroy_addr_space_p (as); - return -1; - } - - uw_regnum = descr->gdb2uw (regnum); - - if (descr->is_fpreg (uw_regnum)) - { - ret = unw_get_fpreg_p (&cursor, uw_regnum, &fpval); - ptr = &fpval; - } - else - { - ret = unw_get_reg_p (&cursor, uw_regnum, &intval); - ptr = &intval; - } - - unw_destroy_addr_space_p (as); - - if (ret < 0) - return -1; - - if (buf) - memcpy (buf, ptr, register_size (gdbarch, regnum)); - - return 0; -} - -static int -libunwind_load (void) -{ - void *handle; - char *so_error = NULL; - - handle = dlopen (LIBUNWIND_SO, RTLD_NOW); - if (handle == NULL) - { - so_error = xstrdup (dlerror ()); -#ifdef LIBUNWIND_SO_7 - handle = dlopen (LIBUNWIND_SO_7, RTLD_NOW); -#endif /* LIBUNWIND_SO_7 */ - } - if (handle == NULL) - { - gdb_printf (gdb_stderr, _("[GDB failed to load %s: %s]\n"), - LIBUNWIND_SO, so_error); -#ifdef LIBUNWIND_SO_7 - gdb_printf (gdb_stderr, _("[GDB failed to load %s: %s]\n"), - LIBUNWIND_SO_7, dlerror ()); -#endif /* LIBUNWIND_SO_7 */ - } - xfree (so_error); - if (handle == NULL) - return 0; - - /* Initialize pointers to the dynamic library functions we will use. */ - - unw_get_reg_p = (unw_get_reg_p_ftype *) dlsym (handle, get_reg_name); - if (unw_get_reg_p == NULL) - return 0; - - unw_get_fpreg_p = (unw_get_fpreg_p_ftype *) dlsym (handle, get_fpreg_name); - if (unw_get_fpreg_p == NULL) - return 0; - - unw_get_saveloc_p - = (unw_get_saveloc_p_ftype *) dlsym (handle, get_saveloc_name); - if (unw_get_saveloc_p == NULL) - return 0; - - unw_is_signal_frame_p - = (unw_is_signal_frame_p_ftype *) dlsym (handle, is_signal_frame_name); - if (unw_is_signal_frame_p == NULL) - return 0; - - unw_step_p = (unw_step_p_ftype *) dlsym (handle, step_name); - if (unw_step_p == NULL) - return 0; - - unw_init_remote_p - = (unw_init_remote_p_ftype *) dlsym (handle, init_remote_name); - if (unw_init_remote_p == NULL) - return 0; - - unw_create_addr_space_p - = (unw_create_addr_space_p_ftype *) dlsym (handle, create_addr_space_name); - if (unw_create_addr_space_p == NULL) - return 0; - - unw_destroy_addr_space_p - = (unw_destroy_addr_space_p_ftype *) dlsym (handle, - destroy_addr_space_name); - if (unw_destroy_addr_space_p == NULL) - return 0; - - unw_search_unwind_table_p - = (unw_search_unwind_table_p_ftype *) dlsym (handle, - search_unwind_table_name); - if (unw_search_unwind_table_p == NULL) - return 0; - - unw_find_dyn_list_p - = (unw_find_dyn_list_p_ftype *) dlsym (handle, find_dyn_list_name); - if (unw_find_dyn_list_p == NULL) - return 0; - - return 1; -} - -int -libunwind_is_initialized (void) -{ - return libunwind_initialized; -} - -void _initialize_libunwind_frame (); -void -_initialize_libunwind_frame () -{ - libunwind_initialized = libunwind_load (); -} diff --git a/gdb/ia64-libunwind-tdep.h b/gdb/ia64-libunwind-tdep.h deleted file mode 100644 index 4f064bfc333..00000000000 --- a/gdb/ia64-libunwind-tdep.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Frame unwinder for ia64 frames with libunwind frame information. - - Copyright (C) 2003-2024 Free Software Foundation, Inc. - - Contributed by Jeff Johnston. - - This file is part of GDB. - - This program is free software; you can 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, see . */ - -#ifndef IA64_LIBUNWIND_TDEP_H -#define IA64_LIBUNWIND_TDEP_H 1 - -class frame_info_ptr; -struct frame_id; -struct regcache; -struct gdbarch; -struct frame_unwind; - -/* IA-64 is the only target that currently uses libunwind. If some - other target wants to use it, we will need to do some abstracting - in order to make it possible to have more than one - ia64-libunwind-tdep instance. Including "libunwind.h" is wrong as - that ends up including the libunwind-$(arch).h for the host gdb is - running on. */ -#include "libunwind-ia64.h" - -#include "gdbarch.h" - -struct libunwind_descr -{ - int (*gdb2uw) (int) = nullptr; - int (*uw2gdb) (int) = nullptr; - int (*is_fpreg) (int) = nullptr; - void *accessors = nullptr; - void *special_accessors = nullptr; -}; - -int libunwind_frame_sniffer (const struct frame_unwind *self, - const frame_info_ptr &this_frame, - void **this_cache); - -int libunwind_sigtramp_frame_sniffer (const struct frame_unwind *self, - const frame_info_ptr &this_frame, - void **this_cache); - -void libunwind_frame_set_descr (struct gdbarch *arch, - struct libunwind_descr *descr); - -void libunwind_frame_this_id (const frame_info_ptr &this_frame, void **this_cache, - struct frame_id *this_id); -struct value *libunwind_frame_prev_register (const frame_info_ptr &this_frame, - void **this_cache, int regnum); -void libunwind_frame_dealloc_cache (frame_info_ptr self, void *cache); - -int libunwind_is_initialized (void); - -int libunwind_search_unwind_table (void *as, long ip, void *di, - void *pi, int need_unwind_info, void *args); - -unw_word_t libunwind_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *, - void *); - -int libunwind_get_reg_special (struct gdbarch *gdbarch, - readable_regcache *regcache, - int regnum, void *buf); - -#endif /* IA64_LIBUNWIND_TDEP_H */ diff --git a/gdb/ia64-linux-nat.c b/gdb/ia64-linux-nat.c deleted file mode 100644 index 7a8e742daea..00000000000 --- a/gdb/ia64-linux-nat.c +++ /dev/null @@ -1,931 +0,0 @@ -/* Functions specific to running gdb native on IA-64 running - GNU/Linux. - - Copyright (C) 1999-2024 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 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, see . */ - -#include "inferior.h" -#include "target.h" -#include "gdbarch.h" -#include "gdbcore.h" -#include "regcache.h" -#include "ia64-tdep.h" -#include "linux-nat.h" - -#include -#include "nat/gdb_ptrace.h" -#include "gdbsupport/gdb_wait.h" -#ifdef HAVE_SYS_REG_H -#include -#endif -#include -#include - -#include -#include - -/* Prototypes for supply_gregset etc. */ -#include "gregset.h" - -#include "inf-ptrace.h" - -class ia64_linux_nat_target final : public linux_nat_target -{ -public: - /* Add our register access methods. */ - void fetch_registers (struct regcache *, int) override; - void store_registers (struct regcache *, int) override; - - enum target_xfer_status xfer_partial (enum target_object object, - const char *annex, - gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, - ULONGEST *xfered_len) override; - - /* Override watchpoint routines. */ - - /* The IA-64 architecture can step over a watch point (without - triggering it again) if the "dd" (data debug fault disable) bit - in the processor status word is set. - - This PSR bit is set in - ia64_linux_nat_target::stopped_by_watchpoint when the code there - has determined that a hardware watchpoint has indeed been hit. - The CPU will then be able to execute one instruction without - triggering a watchpoint. */ - bool have_steppable_watchpoint () override { return true; } - - int can_use_hw_breakpoint (enum bptype, int, int) override; - bool stopped_by_watchpoint () override; - bool stopped_data_address (CORE_ADDR *) override; - int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type, - struct expression *) override; - int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type, - struct expression *) override; - /* Override linux_nat_target low methods. */ - void low_new_thread (struct lwp_info *lp) override; - bool low_status_is_event (int status) override; - - void enable_watchpoints_in_psr (ptid_t ptid); -}; - -static ia64_linux_nat_target the_ia64_linux_nat_target; - -/* These must match the order of the register names. - - Some sort of lookup table is needed because the offsets associated - with the registers are all over the board. */ - -static int u_offsets[] = - { - /* general registers */ - -1, /* gr0 not available; i.e, it's always zero. */ - PT_R1, - PT_R2, - PT_R3, - PT_R4, - PT_R5, - PT_R6, - PT_R7, - PT_R8, - PT_R9, - PT_R10, - PT_R11, - PT_R12, - PT_R13, - PT_R14, - PT_R15, - PT_R16, - PT_R17, - PT_R18, - PT_R19, - PT_R20, - PT_R21, - PT_R22, - PT_R23, - PT_R24, - PT_R25, - PT_R26, - PT_R27, - PT_R28, - PT_R29, - PT_R30, - PT_R31, - /* gr32 through gr127 not directly available via the ptrace interface. */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* Floating point registers */ - -1, -1, /* f0 and f1 not available (f0 is +0.0 and f1 is +1.0). */ - PT_F2, - PT_F3, - PT_F4, - PT_F5, - PT_F6, - PT_F7, - PT_F8, - PT_F9, - PT_F10, - PT_F11, - PT_F12, - PT_F13, - PT_F14, - PT_F15, - PT_F16, - PT_F17, - PT_F18, - PT_F19, - PT_F20, - PT_F21, - PT_F22, - PT_F23, - PT_F24, - PT_F25, - PT_F26, - PT_F27, - PT_F28, - PT_F29, - PT_F30, - PT_F31, - PT_F32, - PT_F33, - PT_F34, - PT_F35, - PT_F36, - PT_F37, - PT_F38, - PT_F39, - PT_F40, - PT_F41, - PT_F42, - PT_F43, - PT_F44, - PT_F45, - PT_F46, - PT_F47, - PT_F48, - PT_F49, - PT_F50, - PT_F51, - PT_F52, - PT_F53, - PT_F54, - PT_F55, - PT_F56, - PT_F57, - PT_F58, - PT_F59, - PT_F60, - PT_F61, - PT_F62, - PT_F63, - PT_F64, - PT_F65, - PT_F66, - PT_F67, - PT_F68, - PT_F69, - PT_F70, - PT_F71, - PT_F72, - PT_F73, - PT_F74, - PT_F75, - PT_F76, - PT_F77, - PT_F78, - PT_F79, - PT_F80, - PT_F81, - PT_F82, - PT_F83, - PT_F84, - PT_F85, - PT_F86, - PT_F87, - PT_F88, - PT_F89, - PT_F90, - PT_F91, - PT_F92, - PT_F93, - PT_F94, - PT_F95, - PT_F96, - PT_F97, - PT_F98, - PT_F99, - PT_F100, - PT_F101, - PT_F102, - PT_F103, - PT_F104, - PT_F105, - PT_F106, - PT_F107, - PT_F108, - PT_F109, - PT_F110, - PT_F111, - PT_F112, - PT_F113, - PT_F114, - PT_F115, - PT_F116, - PT_F117, - PT_F118, - PT_F119, - PT_F120, - PT_F121, - PT_F122, - PT_F123, - PT_F124, - PT_F125, - PT_F126, - PT_F127, - /* Predicate registers - we don't fetch these individually. */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - /* branch registers */ - PT_B0, - PT_B1, - PT_B2, - PT_B3, - PT_B4, - PT_B5, - PT_B6, - PT_B7, - /* Virtual frame pointer and virtual return address pointer. */ - -1, -1, - /* other registers */ - PT_PR, - PT_CR_IIP, /* ip */ - PT_CR_IPSR, /* psr */ - PT_CFM, /* cfm */ - /* kernel registers not visible via ptrace interface (?) */ - -1, -1, -1, -1, -1, -1, -1, -1, - /* hole */ - -1, -1, -1, -1, -1, -1, -1, -1, - PT_AR_RSC, - PT_AR_BSP, - PT_AR_BSPSTORE, - PT_AR_RNAT, - -1, - -1, /* Not available: FCR, IA32 floating control register. */ - -1, -1, - -1, /* Not available: EFLAG */ - -1, /* Not available: CSD */ - -1, /* Not available: SSD */ - -1, /* Not available: CFLG */ - -1, /* Not available: FSR */ - -1, /* Not available: FIR */ - -1, /* Not available: FDR */ - -1, - PT_AR_CCV, - -1, -1, -1, - PT_AR_UNAT, - -1, -1, -1, - PT_AR_FPSR, - -1, -1, -1, - -1, /* Not available: ITC */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, - PT_AR_PFS, - PT_AR_LC, - PT_AR_EC, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, - /* nat bits - not fetched directly; instead we obtain these bits from - either rnat or unat or from memory. */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - }; - -static CORE_ADDR -ia64_register_addr (struct gdbarch *gdbarch, int regno) -{ - CORE_ADDR addr; - - if (regno < 0 || regno >= gdbarch_num_regs (gdbarch)) - error (_("Invalid register number %d."), regno); - - if (u_offsets[regno] == -1) - addr = 0; - else - addr = (CORE_ADDR) u_offsets[regno]; - - return addr; -} - -static int -ia64_cannot_fetch_register (struct gdbarch *gdbarch, int regno) -{ - return regno < 0 - || regno >= gdbarch_num_regs (gdbarch) - || u_offsets[regno] == -1; -} - -static int -ia64_cannot_store_register (struct gdbarch *gdbarch, int regno) -{ - /* Rationale behind not permitting stores to bspstore... - - The IA-64 architecture provides bspstore and bsp which refer - memory locations in the RSE's backing store. bspstore is the - next location which will be written when the RSE needs to write - to memory. bsp is the address at which r32 in the current frame - would be found if it were written to the backing store. - - The IA-64 architecture provides read-only access to bsp and - read/write access to bspstore (but only when the RSE is in - the enforced lazy mode). It should be noted that stores - to bspstore also affect the value of bsp. Changing bspstore - does not affect the number of dirty entries between bspstore - and bsp, so changing bspstore by N words will also cause bsp - to be changed by (roughly) N as well. (It could be N-1 or N+1 - depending upon where the NaT collection bits fall.) - - OTOH, the Linux kernel provides read/write access to bsp (and - currently read/write access to bspstore as well). But it - is definitely the case that if you change one, the other - will change at the same time. It is more useful to gdb to - be able to change bsp. So in order to prevent strange and - undesirable things from happening when a dummy stack frame - is popped (after calling an inferior function), we allow - bspstore to be read, but not written. (Note that popping - a (generic) dummy stack frame causes all registers that - were previously read from the inferior process to be written - back.) */ - - return regno < 0 - || regno >= gdbarch_num_regs (gdbarch) - || u_offsets[regno] == -1 - || regno == IA64_BSPSTORE_REGNUM; -} - -void -supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) -{ - int regi; - const greg_t *regp = (const greg_t *) gregsetp; - - for (regi = IA64_GR0_REGNUM; regi <= IA64_GR31_REGNUM; regi++) - { - regcache->raw_supply (regi, regp + (regi - IA64_GR0_REGNUM)); - } - - /* FIXME: NAT collection bits are at index 32; gotta deal with these - somehow... */ - - regcache->raw_supply (IA64_PR_REGNUM, regp + 33); - - for (regi = IA64_BR0_REGNUM; regi <= IA64_BR7_REGNUM; regi++) - { - regcache->raw_supply (regi, regp + 34 + (regi - IA64_BR0_REGNUM)); - } - - regcache->raw_supply (IA64_IP_REGNUM, regp + 42); - regcache->raw_supply (IA64_CFM_REGNUM, regp + 43); - regcache->raw_supply (IA64_PSR_REGNUM, regp + 44); - regcache->raw_supply (IA64_RSC_REGNUM, regp + 45); - regcache->raw_supply (IA64_BSP_REGNUM, regp + 46); - regcache->raw_supply (IA64_BSPSTORE_REGNUM, regp + 47); - regcache->raw_supply (IA64_RNAT_REGNUM, regp + 48); - regcache->raw_supply (IA64_CCV_REGNUM, regp + 49); - regcache->raw_supply (IA64_UNAT_REGNUM, regp + 50); - regcache->raw_supply (IA64_FPSR_REGNUM, regp + 51); - regcache->raw_supply (IA64_PFS_REGNUM, regp + 52); - regcache->raw_supply (IA64_LC_REGNUM, regp + 53); - regcache->raw_supply (IA64_EC_REGNUM, regp + 54); -} - -void -fill_gregset (const struct regcache *regcache, gregset_t *gregsetp, int regno) -{ - int regi; - greg_t *regp = (greg_t *) gregsetp; - -#define COPY_REG(_idx_,_regi_) \ - if ((regno == -1) || regno == _regi_) \ - regcache->raw_collect (_regi_, regp + _idx_) - - for (regi = IA64_GR0_REGNUM; regi <= IA64_GR31_REGNUM; regi++) - { - COPY_REG (regi - IA64_GR0_REGNUM, regi); - } - - /* FIXME: NAT collection bits at index 32? */ - - COPY_REG (33, IA64_PR_REGNUM); - - for (regi = IA64_BR0_REGNUM; regi <= IA64_BR7_REGNUM; regi++) - { - COPY_REG (34 + (regi - IA64_BR0_REGNUM), regi); - } - - COPY_REG (42, IA64_IP_REGNUM); - COPY_REG (43, IA64_CFM_REGNUM); - COPY_REG (44, IA64_PSR_REGNUM); - COPY_REG (45, IA64_RSC_REGNUM); - COPY_REG (46, IA64_BSP_REGNUM); - COPY_REG (47, IA64_BSPSTORE_REGNUM); - COPY_REG (48, IA64_RNAT_REGNUM); - COPY_REG (49, IA64_CCV_REGNUM); - COPY_REG (50, IA64_UNAT_REGNUM); - COPY_REG (51, IA64_FPSR_REGNUM); - COPY_REG (52, IA64_PFS_REGNUM); - COPY_REG (53, IA64_LC_REGNUM); - COPY_REG (54, IA64_EC_REGNUM); -} - -/* Given a pointer to a floating point register set in /proc format - (fpregset_t *), unpack the register contents and supply them as gdb's - idea of the current floating point register values. */ - -void -supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) -{ - int regi; - const char *from; - const gdb_byte f_zero[16] = { 0 }; - const gdb_byte f_one[16] = - { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 }; - - /* Kernel generated cores have fr1==0 instead of 1.0. Older GDBs - did the same. So ignore whatever might be recorded in fpregset_t - for fr0/fr1 and always supply their expected values. */ - - /* fr0 is always read as zero. */ - regcache->raw_supply (IA64_FR0_REGNUM, f_zero); - /* fr1 is always read as one (1.0). */ - regcache->raw_supply (IA64_FR1_REGNUM, f_one); - - for (regi = IA64_FR2_REGNUM; regi <= IA64_FR127_REGNUM; regi++) - { - from = (const char *) &((*fpregsetp)[regi - IA64_FR0_REGNUM]); - regcache->raw_supply (regi, from); - } -} - -/* Given a pointer to a floating point register set in /proc format - (fpregset_t *), update the register specified by REGNO from gdb's idea - of the current floating point register set. If REGNO is -1, update - them all. */ - -void -fill_fpregset (const struct regcache *regcache, - fpregset_t *fpregsetp, int regno) -{ - int regi; - - for (regi = IA64_FR0_REGNUM; regi <= IA64_FR127_REGNUM; regi++) - { - if ((regno == -1) || (regno == regi)) - regcache->raw_collect (regi, &((*fpregsetp)[regi - IA64_FR0_REGNUM])); - } -} - -#define IA64_PSR_DB (1UL << 24) -#define IA64_PSR_DD (1UL << 39) - -void -ia64_linux_nat_target::enable_watchpoints_in_psr (ptid_t ptid) -{ - struct regcache *regcache = get_thread_regcache (this, ptid); - ULONGEST psr; - - regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr); - if (!(psr & IA64_PSR_DB)) - { - psr |= IA64_PSR_DB; /* Set the db bit - this enables hardware - watchpoints and breakpoints. */ - regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr); - } -} - -static long debug_registers[8]; - -static void -store_debug_register (ptid_t ptid, int idx, long val) -{ - int tid; - - tid = ptid.lwp (); - if (tid == 0) - tid = ptid.pid (); - - (void) ptrace (PT_WRITE_U, tid, (PTRACE_TYPE_ARG3) (PT_DBR + 8 * idx), val); -} - -static void -store_debug_register_pair (ptid_t ptid, int idx, long *dbr_addr, - long *dbr_mask) -{ - if (dbr_addr) - store_debug_register (ptid, 2 * idx, *dbr_addr); - if (dbr_mask) - store_debug_register (ptid, 2 * idx + 1, *dbr_mask); -} - -static int -is_power_of_2 (int val) -{ - int i, onecount; - - onecount = 0; - for (i = 0; i < 8 * sizeof (val); i++) - if (val & (1 << i)) - onecount++; - - return onecount <= 1; -} - -int -ia64_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len, - enum target_hw_bp_type type, - struct expression *cond) -{ - int idx; - long dbr_addr, dbr_mask; - int max_watchpoints = 4; - - if (len <= 0 || !is_power_of_2 (len)) - return -1; - - for (idx = 0; idx < max_watchpoints; idx++) - { - dbr_mask = debug_registers[idx * 2 + 1]; - if ((dbr_mask & (0x3UL << 62)) == 0) - { - /* Exit loop if both r and w bits clear. */ - break; - } - } - - if (idx == max_watchpoints) - return -1; - - dbr_addr = (long) addr; - dbr_mask = (~(len - 1) & 0x00ffffffffffffffL); /* construct mask to match */ - dbr_mask |= 0x0800000000000000L; /* Only match privilege level 3 */ - switch (type) - { - case hw_write: - dbr_mask |= (1L << 62); /* Set w bit */ - break; - case hw_read: - dbr_mask |= (1L << 63); /* Set r bit */ - break; - case hw_access: - dbr_mask |= (3L << 62); /* Set both r and w bits */ - break; - default: - return -1; - } - - debug_registers[2 * idx] = dbr_addr; - debug_registers[2 * idx + 1] = dbr_mask; - - for (const lwp_info *lp : all_lwps ()) - { - store_debug_register_pair (lp->ptid, idx, &dbr_addr, &dbr_mask); - enable_watchpoints_in_psr (lp->ptid); - } - - return 0; -} - -int -ia64_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len, - enum target_hw_bp_type type, - struct expression *cond) -{ - int idx; - long dbr_addr, dbr_mask; - int max_watchpoints = 4; - - if (len <= 0 || !is_power_of_2 (len)) - return -1; - - for (idx = 0; idx < max_watchpoints; idx++) - { - dbr_addr = debug_registers[2 * idx]; - dbr_mask = debug_registers[2 * idx + 1]; - if ((dbr_mask & (0x3UL << 62)) && addr == (CORE_ADDR) dbr_addr) - { - debug_registers[2 * idx] = 0; - debug_registers[2 * idx + 1] = 0; - dbr_addr = 0; - dbr_mask = 0; - - for (const lwp_info *lp : all_lwps ()) - store_debug_register_pair (lp->ptid, idx, &dbr_addr, &dbr_mask); - - return 0; - } - } - return -1; -} - -void -ia64_linux_nat_target::low_new_thread (struct lwp_info *lp) -{ - int i, any; - - any = 0; - for (i = 0; i < 8; i++) - { - if (debug_registers[i] != 0) - any = 1; - store_debug_register (lp->ptid, i, debug_registers[i]); - } - - if (any) - enable_watchpoints_in_psr (lp->ptid); -} - -bool -ia64_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p) -{ - CORE_ADDR psr; - siginfo_t siginfo; - regcache *regcache = get_thread_regcache (inferior_thread ()); - - if (!linux_nat_get_siginfo (inferior_ptid, &siginfo)) - return false; - - if (siginfo.si_signo != SIGTRAP - || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */) - return false; - - regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr); - psr |= IA64_PSR_DD; /* Set the dd bit - this will disable the watchpoint - for the next instruction. */ - regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr); - - *addr_p = (CORE_ADDR) siginfo.si_addr; - return true; -} - -bool -ia64_linux_nat_target::stopped_by_watchpoint () -{ - CORE_ADDR addr; - return stopped_data_address (&addr); -} - -int -ia64_linux_nat_target::can_use_hw_breakpoint (enum bptype type, - int cnt, int othertype) -{ - return 1; -} - - -/* Fetch register REGNUM from the inferior. */ - -static void -ia64_linux_fetch_register (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - CORE_ADDR addr; - size_t size; - PTRACE_TYPE_RET *buf; - pid_t pid; - int i; - - /* r0 cannot be fetched but is always zero. */ - if (regnum == IA64_GR0_REGNUM) - { - const gdb_byte zero[8] = { 0 }; - - gdb_assert (sizeof (zero) == register_size (gdbarch, regnum)); - regcache->raw_supply (regnum, zero); - return; - } - - /* fr0 cannot be fetched but is always zero. */ - if (regnum == IA64_FR0_REGNUM) - { - const gdb_byte f_zero[16] = { 0 }; - - gdb_assert (sizeof (f_zero) == register_size (gdbarch, regnum)); - regcache->raw_supply (regnum, f_zero); - return; - } - - /* fr1 cannot be fetched but is always one (1.0). */ - if (regnum == IA64_FR1_REGNUM) - { - const gdb_byte f_one[16] = - { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 }; - - gdb_assert (sizeof (f_one) == register_size (gdbarch, regnum)); - regcache->raw_supply (regnum, f_one); - return; - } - - if (ia64_cannot_fetch_register (gdbarch, regnum)) - { - regcache->raw_supply (regnum, NULL); - return; - } - - pid = get_ptrace_pid (regcache->ptid ()); - - /* This isn't really an address, but ptrace thinks of it as one. */ - addr = ia64_register_addr (gdbarch, regnum); - size = register_size (gdbarch, regnum); - - gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0); - buf = (PTRACE_TYPE_RET *) alloca (size); - - /* Read the register contents from the inferior a chunk at a time. */ - for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++) - { - errno = 0; - buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)addr, 0); - if (errno != 0) - error (_("Couldn't read register %s (#%d): %s."), - gdbarch_register_name (gdbarch, regnum), - regnum, safe_strerror (errno)); - - addr += sizeof (PTRACE_TYPE_RET); - } - regcache->raw_supply (regnum, buf); -} - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers. */ - -void -ia64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum) -{ - if (regnum == -1) - for (regnum = 0; - regnum < gdbarch_num_regs (regcache->arch ()); - regnum++) - ia64_linux_fetch_register (regcache, regnum); - else - ia64_linux_fetch_register (regcache, regnum); -} - -/* Store register REGNUM into the inferior. */ - -static void -ia64_linux_store_register (const struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - CORE_ADDR addr; - size_t size; - PTRACE_TYPE_RET *buf; - pid_t pid; - int i; - - if (ia64_cannot_store_register (gdbarch, regnum)) - return; - - pid = get_ptrace_pid (regcache->ptid ()); - - /* This isn't really an address, but ptrace thinks of it as one. */ - addr = ia64_register_addr (gdbarch, regnum); - size = register_size (gdbarch, regnum); - - gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0); - buf = (PTRACE_TYPE_RET *) alloca (size); - - /* Write the register contents into the inferior a chunk at a time. */ - regcache->raw_collect (regnum, buf); - for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++) - { - errno = 0; - ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)addr, buf[i]); - if (errno != 0) - error (_("Couldn't write register %s (#%d): %s."), - gdbarch_register_name (gdbarch, regnum), - regnum, safe_strerror (errno)); - - addr += sizeof (PTRACE_TYPE_RET); - } -} - -/* Store register REGNUM back into the inferior. If REGNUM is -1, do - this for all registers. */ - -void -ia64_linux_nat_target::store_registers (struct regcache *regcache, int regnum) -{ - if (regnum == -1) - for (regnum = 0; - regnum < gdbarch_num_regs (regcache->arch ()); - regnum++) - ia64_linux_store_register (regcache, regnum); - else - ia64_linux_store_register (regcache, regnum); -} - -/* Implement the xfer_partial target_ops method. */ - -enum target_xfer_status -ia64_linux_nat_target::xfer_partial (enum target_object object, - const char *annex, - gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, - ULONGEST *xfered_len) -{ - if (object == TARGET_OBJECT_UNWIND_TABLE && readbuf != NULL) - { - static long gate_table_size; - gdb_byte *tmp_buf; - long res; - - /* Probe for the table size once. */ - if (gate_table_size == 0) - gate_table_size = syscall (__NR_getunwind, NULL, 0); - if (gate_table_size < 0) - return TARGET_XFER_E_IO; - - if (offset >= gate_table_size) - return TARGET_XFER_EOF; - - tmp_buf = (gdb_byte *) alloca (gate_table_size); - res = syscall (__NR_getunwind, tmp_buf, gate_table_size); - if (res < 0) - return TARGET_XFER_E_IO; - gdb_assert (res == gate_table_size); - - if (offset + len > gate_table_size) - len = gate_table_size - offset; - - memcpy (readbuf, tmp_buf + offset, len); - *xfered_len = len; - return TARGET_XFER_OK; - } - - return linux_nat_target::xfer_partial (object, annex, readbuf, writebuf, - offset, len, xfered_len); -} - -/* For break.b instruction ia64 CPU forgets the immediate value and generates - SIGILL with ILL_ILLOPC instead of more common SIGTRAP with TRAP_BRKPT. - ia64 does not use gdbarch_decr_pc_after_break so we do not have to make any - difference for the signals here. */ - -bool -ia64_linux_nat_target::low_status_is_event (int status) -{ - return WIFSTOPPED (status) && (WSTOPSIG (status) == SIGTRAP - || WSTOPSIG (status) == SIGILL); -} - -void _initialize_ia64_linux_nat (); -void -_initialize_ia64_linux_nat () -{ - /* Register the target. */ - linux_target = &the_ia64_linux_nat_target; - add_inf_child_target (&the_ia64_linux_nat_target); -} diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c deleted file mode 100644 index 12083e94ca3..00000000000 --- a/gdb/ia64-linux-tdep.c +++ /dev/null @@ -1,267 +0,0 @@ -/* Target-dependent code for the IA-64 for GDB, the GNU debugger. - - Copyright (C) 2000-2024 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 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, see . */ - -#include "extract-store-integer.h" -#include "ia64-tdep.h" -#include "arch-utils.h" -#include "gdbcore.h" -#include "regcache.h" -#include "osabi.h" -#include "solib-svr4.h" -#include "symtab.h" -#include "linux-tdep.h" -#include "regset.h" - -#include - -/* The sigtramp code is in a non-readable (executable-only) region - of memory called the ``gate page''. The addresses in question - were determined by examining the system headers. They are - overly generous to allow for different pages sizes. */ - -#define GATE_AREA_START 0xa000000000000100LL -#define GATE_AREA_END 0xa000000000020000LL - -/* Offset to sigcontext structure from frame of handler. */ -#define IA64_LINUX_SIGCONTEXT_OFFSET 192 - -static int -ia64_linux_pc_in_sigtramp (CORE_ADDR pc) -{ - return (pc >= (CORE_ADDR) GATE_AREA_START && pc < (CORE_ADDR) GATE_AREA_END); -} - -/* IA-64 GNU/Linux specific function which, given a frame address and - a register number, returns the address at which that register may be - found. 0 is returned for registers which aren't stored in the - sigcontext structure. */ - -static CORE_ADDR -ia64_linux_sigcontext_register_address (struct gdbarch *gdbarch, - CORE_ADDR sp, int regno) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[8]; - CORE_ADDR sigcontext_addr = 0; - - /* The address of the sigcontext area is found at offset 16 in the - sigframe. */ - read_memory (sp + 16, buf, 8); - sigcontext_addr = extract_unsigned_integer (buf, 8, byte_order); - - if (IA64_GR0_REGNUM <= regno && regno <= IA64_GR31_REGNUM) - return sigcontext_addr + 200 + 8 * (regno - IA64_GR0_REGNUM); - else if (IA64_BR0_REGNUM <= regno && regno <= IA64_BR7_REGNUM) - return sigcontext_addr + 136 + 8 * (regno - IA64_BR0_REGNUM); - else if (IA64_FR0_REGNUM <= regno && regno <= IA64_FR127_REGNUM) - return sigcontext_addr + 464 + 16 * (regno - IA64_FR0_REGNUM); - else - switch (regno) - { - case IA64_IP_REGNUM : - return sigcontext_addr + 40; - case IA64_CFM_REGNUM : - return sigcontext_addr + 48; - case IA64_PSR_REGNUM : - return sigcontext_addr + 56; /* user mask only */ - /* sc_ar_rsc is provided, from which we could compute bspstore, but - I don't think it's worth it. Anyway, if we want it, it's at offset - 64. */ - case IA64_BSP_REGNUM : - return sigcontext_addr + 72; - case IA64_RNAT_REGNUM : - return sigcontext_addr + 80; - case IA64_CCV_REGNUM : - return sigcontext_addr + 88; - case IA64_UNAT_REGNUM : - return sigcontext_addr + 96; - case IA64_FPSR_REGNUM : - return sigcontext_addr + 104; - case IA64_PFS_REGNUM : - return sigcontext_addr + 112; - case IA64_LC_REGNUM : - return sigcontext_addr + 120; - case IA64_PR_REGNUM : - return sigcontext_addr + 128; - default : - return 0; - } -} - -static void -ia64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) -{ - ia64_write_pc (regcache, pc); - - /* We must be careful with modifying the instruction-pointer: if we - just interrupt a system call, the kernel would ordinarily try to - restart it when we resume the inferior, which typically results - in SIGSEGV or SIGILL. We prevent this by clearing r10, which - will tell the kernel that r8 does NOT contain a valid error code - and hence it will skip system-call restart. - - The clearing of r10 is safe as long as ia64_write_pc() is only - called as part of setting up an inferior call. */ - regcache_cooked_write_unsigned (regcache, IA64_GR10_REGNUM, 0); -} - -/* Implementation of `gdbarch_stap_is_single_operand', as defined in - gdbarch.h. */ - -static int -ia64_linux_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) -{ - return ((isdigit (*s) && s[1] == '[' && s[2] == 'r') /* Displacement. */ - || *s == 'r' /* Register value. */ - || isdigit (*s)); /* Literal number. */ -} - -/* Core file support. */ - -static const struct regcache_map_entry ia64_linux_gregmap[] = - { - { 32, IA64_GR0_REGNUM, 8 }, /* r0 ... r31 */ - { 1, REGCACHE_MAP_SKIP, 8 }, /* FIXME: NAT collection bits? */ - { 1, IA64_PR_REGNUM, 8 }, - { 8, IA64_BR0_REGNUM, 8 }, /* b0 ... b7 */ - { 1, IA64_IP_REGNUM, 8 }, - { 1, IA64_CFM_REGNUM, 8 }, - { 1, IA64_PSR_REGNUM, 8 }, - { 1, IA64_RSC_REGNUM, 8 }, - { 1, IA64_BSP_REGNUM, 8 }, - { 1, IA64_BSPSTORE_REGNUM, 8 }, - { 1, IA64_RNAT_REGNUM, 8 }, - { 1, IA64_CCV_REGNUM, 8 }, - { 1, IA64_UNAT_REGNUM, 8 }, - { 1, IA64_FPSR_REGNUM, 8 }, - { 1, IA64_PFS_REGNUM, 8 }, - { 1, IA64_LC_REGNUM, 8 }, - { 1, IA64_EC_REGNUM, 8 }, - { 0 } - }; - -/* Size of 'gregset_t', as defined by the Linux kernel. Note that - this is more than actually mapped in the regmap above. */ - -#define IA64_LINUX_GREGS_SIZE (128 * 8) - -static const struct regcache_map_entry ia64_linux_fpregmap[] = - { - { 128, IA64_FR0_REGNUM, 16 }, /* f0 ... f127 */ - { 0 } - }; - -#define IA64_LINUX_FPREGS_SIZE (128 * 16) - -static void -ia64_linux_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *regs, size_t len) -{ - const gdb_byte f_zero[16] = { 0 }; - const gdb_byte f_one[16] = - { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 }; - - regcache_supply_regset (regset, regcache, regnum, regs, len); - - /* Kernel generated cores have fr1==0 instead of 1.0. Older GDBs - did the same. So ignore whatever might be recorded in fpregset_t - for fr0/fr1 and always supply their expected values. */ - if (regnum == -1 || regnum == IA64_FR0_REGNUM) - regcache->raw_supply (IA64_FR0_REGNUM, f_zero); - if (regnum == -1 || regnum == IA64_FR1_REGNUM) - regcache->raw_supply (IA64_FR1_REGNUM, f_one); -} - -static const struct regset ia64_linux_gregset = - { - ia64_linux_gregmap, - regcache_supply_regset, regcache_collect_regset - }; - -static const struct regset ia64_linux_fpregset = - { - ia64_linux_fpregmap, - ia64_linux_supply_fpregset, regcache_collect_regset - }; - -static void -ia64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", IA64_LINUX_GREGS_SIZE, IA64_LINUX_GREGS_SIZE, &ia64_linux_gregset, - NULL, cb_data); - cb (".reg2", IA64_LINUX_FPREGS_SIZE, IA64_LINUX_FPREGS_SIZE, - &ia64_linux_fpregset, NULL, cb_data); -} - -static void -ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - ia64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - static const char *const stap_register_prefixes[] = { "r", NULL }; - static const char *const stap_register_indirection_prefixes[] = { "[", - NULL }; - static const char *const stap_register_indirection_suffixes[] = { "]", - NULL }; - - linux_init_abi (info, gdbarch, 0); - - /* Set the method of obtaining the sigcontext addresses at which - registers are saved. */ - tdep->sigcontext_register_address = ia64_linux_sigcontext_register_address; - - /* Set the pc_in_sigtramp method. */ - tdep->pc_in_sigtramp = ia64_linux_pc_in_sigtramp; - - set_gdbarch_write_pc (gdbarch, ia64_linux_write_pc); - - set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); - - set_solib_svr4_fetch_link_map_offsets - (gdbarch, linux_lp64_fetch_link_map_offsets); - - /* Enable TLS support. */ - set_gdbarch_fetch_tls_load_module_address (gdbarch, - svr4_fetch_objfile_link_map); - - /* Core file support. */ - set_gdbarch_iterate_over_regset_sections - (gdbarch, ia64_linux_iterate_over_regset_sections); - - /* SystemTap related. */ - set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes); - set_gdbarch_stap_register_indirection_prefixes (gdbarch, - stap_register_indirection_prefixes); - set_gdbarch_stap_register_indirection_suffixes (gdbarch, - stap_register_indirection_suffixes); - set_gdbarch_stap_gdb_register_prefix (gdbarch, "r"); - set_gdbarch_stap_is_single_operand (gdbarch, - ia64_linux_stap_is_single_operand); -} - -void _initialize_ia64_linux_tdep (); -void -_initialize_ia64_linux_tdep () -{ - gdbarch_register_osabi (bfd_arch_ia64, 0, GDB_OSABI_LINUX, - ia64_linux_init_abi); -} diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c deleted file mode 100644 index 6376cf8d069..00000000000 --- a/gdb/ia64-tdep.c +++ /dev/null @@ -1,4024 +0,0 @@ -/* Target-dependent code for the IA-64 for GDB, the GNU debugger. - - Copyright (C) 1999-2024 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 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, see . */ - -#include "extract-store-integer.h" -#include "inferior.h" -#include "gdbcore.h" -#include "arch-utils.h" -#include "floatformat.h" -#include "gdbtypes.h" -#include "regcache.h" -#include "reggroups.h" -#include "frame.h" -#include "frame-base.h" -#include "frame-unwind.h" -#include "target-float.h" -#include "value.h" -#include "objfiles.h" -#include "elf/common.h" -#include "elf-bfd.h" -#include "dis-asm.h" -#include "infcall.h" -#include "osabi.h" -#include "ia64-tdep.h" -#include "cp-abi.h" - -#ifdef HAVE_LIBUNWIND_IA64_H -#include "elf/ia64.h" -#include "ia64-libunwind-tdep.h" - -/* Note: KERNEL_START is supposed to be an address which is not going - to ever contain any valid unwind info. For ia64 linux, the choice - of 0xc000000000000000 is fairly safe since that's uncached space. - - We use KERNEL_START as follows: after obtaining the kernel's - unwind table via getunwind(), we project its unwind data into - address-range KERNEL_START-(KERNEL_START+ktab_size) and then - when ia64_access_mem() sees a memory access to this - address-range, we redirect it to ktab instead. - - None of this hackery is needed with a modern kernel/libcs - which uses the kernel virtual DSO to provide access to the - kernel's unwind info. In that case, ktab_size remains 0 and - hence the value of KERNEL_START doesn't matter. */ - -#define KERNEL_START 0xc000000000000000ULL - -static size_t ktab_size = 0; -struct ia64_table_entry - { - uint64_t start_offset; - uint64_t end_offset; - uint64_t info_offset; - }; - -static struct ia64_table_entry *ktab = NULL; -static std::optional ktab_buf; - -#endif - -/* An enumeration of the different IA-64 instruction types. */ - -enum ia64_instruction_type -{ - A, /* Integer ALU ; I-unit or M-unit */ - I, /* Non-ALU integer; I-unit */ - M, /* Memory ; M-unit */ - F, /* Floating-point ; F-unit */ - B, /* Branch ; B-unit */ - L, /* Extended (L+X) ; I-unit */ - X, /* Extended (L+X) ; I-unit */ - undefined /* undefined or reserved */ -}; - -/* We represent IA-64 PC addresses as the value of the instruction - pointer or'd with some bit combination in the low nibble which - represents the slot number in the bundle addressed by the - instruction pointer. The problem is that the Linux kernel - multiplies its slot numbers (for exceptions) by one while the - disassembler multiplies its slot numbers by 6. In addition, I've - heard it said that the simulator uses 1 as the multiplier. - - I've fixed the disassembler so that the bytes_per_line field will - be the slot multiplier. If bytes_per_line comes in as zero, it - is set to six (which is how it was set up initially). -- objdump - displays pretty disassembly dumps with this value. For our purposes, - we'll set bytes_per_line to SLOT_MULTIPLIER. This is okay since we - never want to also display the raw bytes the way objdump does. */ - -#define SLOT_MULTIPLIER 1 - -/* Length in bytes of an instruction bundle. */ - -#define BUNDLE_LEN 16 - -/* See the saved memory layout comment for ia64_memory_insert_breakpoint. */ - -#if BREAKPOINT_MAX < BUNDLE_LEN - 2 -# error "BREAKPOINT_MAX < BUNDLE_LEN - 2" -#endif - -static gdbarch_init_ftype ia64_gdbarch_init; - -static gdbarch_register_name_ftype ia64_register_name; -static gdbarch_register_type_ftype ia64_register_type; -static gdbarch_breakpoint_from_pc_ftype ia64_breakpoint_from_pc; -static gdbarch_skip_prologue_ftype ia64_skip_prologue; -static struct type *is_float_or_hfa_type (struct type *t); -static CORE_ADDR ia64_find_global_pointer (struct gdbarch *gdbarch, - CORE_ADDR faddr); - -#define NUM_IA64_RAW_REGS 462 - -/* Big enough to hold a FP register in bytes. */ -#define IA64_FP_REGISTER_SIZE 16 - -static int sp_regnum = IA64_GR12_REGNUM; - -/* NOTE: we treat the register stack registers r32-r127 as - pseudo-registers because they may not be accessible via the ptrace - register get/set interfaces. */ - -enum pseudo_regs { FIRST_PSEUDO_REGNUM = NUM_IA64_RAW_REGS, - VBOF_REGNUM = IA64_NAT127_REGNUM + 1, V32_REGNUM, - V127_REGNUM = V32_REGNUM + 95, - VP0_REGNUM, VP16_REGNUM = VP0_REGNUM + 16, - VP63_REGNUM = VP0_REGNUM + 63, LAST_PSEUDO_REGNUM }; - -/* Array of register names; There should be ia64_num_regs strings in - the initializer. */ - -static const char * const ia64_register_names[] = -{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - - "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", - "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39", - "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", - "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55", - "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63", - "f64", "f65", "f66", "f67", "f68", "f69", "f70", "f71", - "f72", "f73", "f74", "f75", "f76", "f77", "f78", "f79", - "f80", "f81", "f82", "f83", "f84", "f85", "f86", "f87", - "f88", "f89", "f90", "f91", "f92", "f93", "f94", "f95", - "f96", "f97", "f98", "f99", "f100", "f101", "f102", "f103", - "f104", "f105", "f106", "f107", "f108", "f109", "f110", "f111", - "f112", "f113", "f114", "f115", "f116", "f117", "f118", "f119", - "f120", "f121", "f122", "f123", "f124", "f125", "f126", "f127", - - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - - "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", - - "vfp", "vrap", - - "pr", "ip", "psr", "cfm", - - "kr0", "kr1", "kr2", "kr3", "kr4", "kr5", "kr6", "kr7", - "", "", "", "", "", "", "", "", - "rsc", "bsp", "bspstore", "rnat", - "", "fcr", "", "", - "eflag", "csd", "ssd", "cflg", "fsr", "fir", "fdr", "", - "ccv", "", "", "", "unat", "", "", "", - "fpsr", "", "", "", "itc", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", - "pfs", "lc", "ec", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", - "nat0", "nat1", "nat2", "nat3", "nat4", "nat5", "nat6", "nat7", - "nat8", "nat9", "nat10", "nat11", "nat12", "nat13", "nat14", "nat15", - "nat16", "nat17", "nat18", "nat19", "nat20", "nat21", "nat22", "nat23", - "nat24", "nat25", "nat26", "nat27", "nat28", "nat29", "nat30", "nat31", - "nat32", "nat33", "nat34", "nat35", "nat36", "nat37", "nat38", "nat39", - "nat40", "nat41", "nat42", "nat43", "nat44", "nat45", "nat46", "nat47", - "nat48", "nat49", "nat50", "nat51", "nat52", "nat53", "nat54", "nat55", - "nat56", "nat57", "nat58", "nat59", "nat60", "nat61", "nat62", "nat63", - "nat64", "nat65", "nat66", "nat67", "nat68", "nat69", "nat70", "nat71", - "nat72", "nat73", "nat74", "nat75", "nat76", "nat77", "nat78", "nat79", - "nat80", "nat81", "nat82", "nat83", "nat84", "nat85", "nat86", "nat87", - "nat88", "nat89", "nat90", "nat91", "nat92", "nat93", "nat94", "nat95", - "nat96", "nat97", "nat98", "nat99", "nat100","nat101","nat102","nat103", - "nat104","nat105","nat106","nat107","nat108","nat109","nat110","nat111", - "nat112","nat113","nat114","nat115","nat116","nat117","nat118","nat119", - "nat120","nat121","nat122","nat123","nat124","nat125","nat126","nat127", - - "bof", - - "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", - "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", - "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", - "r56", "r57", "r58", "r59", "r60", "r61", "r62", "r63", - "r64", "r65", "r66", "r67", "r68", "r69", "r70", "r71", - "r72", "r73", "r74", "r75", "r76", "r77", "r78", "r79", - "r80", "r81", "r82", "r83", "r84", "r85", "r86", "r87", - "r88", "r89", "r90", "r91", "r92", "r93", "r94", "r95", - "r96", "r97", "r98", "r99", "r100", "r101", "r102", "r103", - "r104", "r105", "r106", "r107", "r108", "r109", "r110", "r111", - "r112", "r113", "r114", "r115", "r116", "r117", "r118", "r119", - "r120", "r121", "r122", "r123", "r124", "r125", "r126", "r127", - - "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", - "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", - "p16", "p17", "p18", "p19", "p20", "p21", "p22", "p23", - "p24", "p25", "p26", "p27", "p28", "p29", "p30", "p31", - "p32", "p33", "p34", "p35", "p36", "p37", "p38", "p39", - "p40", "p41", "p42", "p43", "p44", "p45", "p46", "p47", - "p48", "p49", "p50", "p51", "p52", "p53", "p54", "p55", - "p56", "p57", "p58", "p59", "p60", "p61", "p62", "p63", -}; - -struct ia64_frame_cache -{ - CORE_ADDR base; /* frame pointer base for frame */ - CORE_ADDR pc; /* function start pc for frame */ - CORE_ADDR saved_sp; /* stack pointer for frame */ - CORE_ADDR bsp; /* points at r32 for the current frame */ - CORE_ADDR cfm; /* cfm value for current frame */ - CORE_ADDR prev_cfm; /* cfm value for previous frame */ - int frameless; - int sof; /* Size of frame (decoded from cfm value). */ - int sol; /* Size of locals (decoded from cfm value). */ - int sor; /* Number of rotating registers (decoded from - cfm value). */ - CORE_ADDR after_prologue; - /* Address of first instruction after the last - prologue instruction; Note that there may - be instructions from the function's body - intermingled with the prologue. */ - int mem_stack_frame_size; - /* Size of the memory stack frame (may be zero), - or -1 if it has not been determined yet. */ - int fp_reg; /* Register number (if any) used a frame pointer - for this frame. 0 if no register is being used - as the frame pointer. */ - - /* Saved registers. */ - CORE_ADDR saved_regs[NUM_IA64_RAW_REGS]; - -}; - -static int -floatformat_valid (const struct floatformat *fmt, const void *from) -{ - return 1; -} - -static const struct floatformat floatformat_ia64_ext_little = -{ - floatformat_little, 82, 0, 1, 17, 65535, 0x1ffff, 18, 64, - floatformat_intbit_yes, "floatformat_ia64_ext_little", floatformat_valid, NULL -}; - -static const struct floatformat floatformat_ia64_ext_big = -{ - floatformat_big, 82, 46, 47, 17, 65535, 0x1ffff, 64, 64, - floatformat_intbit_yes, "floatformat_ia64_ext_big", floatformat_valid -}; - -static const struct floatformat *floatformats_ia64_ext[2] = -{ - &floatformat_ia64_ext_big, - &floatformat_ia64_ext_little -}; - -static struct type * -ia64_ext_type (struct gdbarch *gdbarch) -{ - ia64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - if (!tdep->ia64_ext_type) - { - type_allocator alloc (gdbarch); - tdep->ia64_ext_type - = init_float_type (alloc, 128, "builtin_type_ia64_ext", - floatformats_ia64_ext); - } - - return tdep->ia64_ext_type; -} - -static int -ia64_register_reggroup_p (struct gdbarch *gdbarch, int regnum, - const struct reggroup *group) -{ - int vector_p; - int float_p; - int raw_p; - if (group == all_reggroup) - return 1; - vector_p = register_type (gdbarch, regnum)->is_vector (); - float_p = register_type (gdbarch, regnum)->code () == TYPE_CODE_FLT; - raw_p = regnum < NUM_IA64_RAW_REGS; - if (group == float_reggroup) - return float_p; - if (group == vector_reggroup) - return vector_p; - if (group == general_reggroup) - return (!vector_p && !float_p); - if (group == save_reggroup || group == restore_reggroup) - return raw_p; - return 0; -} - -static const char * -ia64_register_name (struct gdbarch *gdbarch, int reg) -{ - return ia64_register_names[reg]; -} - -struct type * -ia64_register_type (struct gdbarch *arch, int reg) -{ - if (reg >= IA64_FR0_REGNUM && reg <= IA64_FR127_REGNUM) - return ia64_ext_type (arch); - else - return builtin_type (arch)->builtin_long; -} - -static int -ia64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) -{ - if (reg >= IA64_GR32_REGNUM && reg <= IA64_GR127_REGNUM) - return V32_REGNUM + (reg - IA64_GR32_REGNUM); - return reg; -} - - -/* Extract ``len'' bits from an instruction bundle starting at - bit ``from''. */ - -static long long -extract_bit_field (const gdb_byte *bundle, int from, int len) -{ - long long result = 0LL; - int to = from + len; - int from_byte = from / 8; - int to_byte = to / 8; - unsigned char *b = (unsigned char *) bundle; - unsigned char c; - int lshift; - int i; - - c = b[from_byte]; - if (from_byte == to_byte) - c = ((unsigned char) (c << (8 - to % 8))) >> (8 - to % 8); - result = c >> (from % 8); - lshift = 8 - (from % 8); - - for (i = from_byte+1; i < to_byte; i++) - { - result |= ((long long) b[i]) << lshift; - lshift += 8; - } - - if (from_byte < to_byte && (to % 8 != 0)) - { - c = b[to_byte]; - c = ((unsigned char) (c << (8 - to % 8))) >> (8 - to % 8); - result |= ((long long) c) << lshift; - } - - return result; -} - -/* Replace the specified bits in an instruction bundle. */ - -static void -replace_bit_field (gdb_byte *bundle, long long val, int from, int len) -{ - int to = from + len; - int from_byte = from / 8; - int to_byte = to / 8; - unsigned char *b = (unsigned char *) bundle; - unsigned char c; - - if (from_byte == to_byte) - { - unsigned char left, right; - c = b[from_byte]; - left = (c >> (to % 8)) << (to % 8); - right = ((unsigned char) (c << (8 - from % 8))) >> (8 - from % 8); - c = (unsigned char) (val & 0xff); - c = (unsigned char) (c << (from % 8 + 8 - to % 8)) >> (8 - to % 8); - c |= right | left; - b[from_byte] = c; - } - else - { - int i; - c = b[from_byte]; - c = ((unsigned char) (c << (8 - from % 8))) >> (8 - from % 8); - c = c | (val << (from % 8)); - b[from_byte] = c; - val >>= 8 - from % 8; - - for (i = from_byte+1; i < to_byte; i++) - { - c = val & 0xff; - val >>= 8; - b[i] = c; - } - - if (to % 8 != 0) - { - unsigned char cv = (unsigned char) val; - c = b[to_byte]; - c = c >> (to % 8) << (to % 8); - c |= ((unsigned char) (cv << (8 - to % 8))) >> (8 - to % 8); - b[to_byte] = c; - } - } -} - -/* Return the contents of slot N (for N = 0, 1, or 2) in - and instruction bundle. */ - -static long long -slotN_contents (gdb_byte *bundle, int slotnum) -{ - return extract_bit_field (bundle, 5+41*slotnum, 41); -} - -/* Store an instruction in an instruction bundle. */ - -static void -replace_slotN_contents (gdb_byte *bundle, long long instr, int slotnum) -{ - replace_bit_field (bundle, instr, 5+41*slotnum, 41); -} - -static const enum ia64_instruction_type template_encoding_table[32][3] = -{ - { M, I, I }, /* 00 */ - { M, I, I }, /* 01 */ - { M, I, I }, /* 02 */ - { M, I, I }, /* 03 */ - { M, L, X }, /* 04 */ - { M, L, X }, /* 05 */ - { undefined, undefined, undefined }, /* 06 */ - { undefined, undefined, undefined }, /* 07 */ - { M, M, I }, /* 08 */ - { M, M, I }, /* 09 */ - { M, M, I }, /* 0A */ - { M, M, I }, /* 0B */ - { M, F, I }, /* 0C */ - { M, F, I }, /* 0D */ - { M, M, F }, /* 0E */ - { M, M, F }, /* 0F */ - { M, I, B }, /* 10 */ - { M, I, B }, /* 11 */ - { M, B, B }, /* 12 */ - { M, B, B }, /* 13 */ - { undefined, undefined, undefined }, /* 14 */ - { undefined, undefined, undefined }, /* 15 */ - { B, B, B }, /* 16 */ - { B, B, B }, /* 17 */ - { M, M, B }, /* 18 */ - { M, M, B }, /* 19 */ - { undefined, undefined, undefined }, /* 1A */ - { undefined, undefined, undefined }, /* 1B */ - { M, F, B }, /* 1C */ - { M, F, B }, /* 1D */ - { undefined, undefined, undefined }, /* 1E */ - { undefined, undefined, undefined }, /* 1F */ -}; - -/* Fetch and (partially) decode an instruction at ADDR and return the - address of the next instruction to fetch. */ - -static CORE_ADDR -fetch_instruction (CORE_ADDR addr, ia64_instruction_type *it, long long *instr) -{ - gdb_byte bundle[BUNDLE_LEN]; - int slotnum = (int) (addr & 0x0f) / SLOT_MULTIPLIER; - long long templ; - int val; - - /* Warn about slot numbers greater than 2. We used to generate - an error here on the assumption that the user entered an invalid - address. But, sometimes GDB itself requests an invalid address. - This can (easily) happen when execution stops in a function for - which there are no symbols. The prologue scanner will attempt to - find the beginning of the function - if the nearest symbol - happens to not be aligned on a bundle boundary (16 bytes), the - resulting starting address will cause GDB to think that the slot - number is too large. - - So we warn about it and set the slot number to zero. It is - not necessarily a fatal condition, particularly if debugging - at the assembly language level. */ - if (slotnum > 2) - { - warning (_("Can't fetch instructions for slot numbers greater than 2.\n" - "Using slot 0 instead")); - slotnum = 0; - } - - addr &= ~0x0f; - - val = target_read_memory (addr, bundle, BUNDLE_LEN); - - if (val != 0) - return 0; - - *instr = slotN_contents (bundle, slotnum); - templ = extract_bit_field (bundle, 0, 5); - *it = template_encoding_table[(int)templ][slotnum]; - - if (slotnum == 2 || (slotnum == 1 && *it == L)) - addr += 16; - else - addr += (slotnum + 1) * SLOT_MULTIPLIER; - - return addr; -} - -/* There are 5 different break instructions (break.i, break.b, - break.m, break.f, and break.x), but they all have the same - encoding. (The five bit template in the low five bits of the - instruction bundle distinguishes one from another.) - - The runtime architecture manual specifies that break instructions - used for debugging purposes must have the upper two bits of the 21 - bit immediate set to a 0 and a 1 respectively. A breakpoint - instruction encodes the most significant bit of its 21 bit - immediate at bit 36 of the 41 bit instruction. The penultimate msb - is at bit 25 which leads to the pattern below. - - Originally, I had this set up to do, e.g, a "break.i 0x80000" But - it turns out that 0x80000 was used as the syscall break in the early - simulators. So I changed the pattern slightly to do "break.i 0x080001" - instead. But that didn't work either (I later found out that this - pattern was used by the simulator that I was using.) So I ended up - using the pattern seen below. - - SHADOW_CONTENTS has byte-based addressing (PLACED_ADDRESS and SHADOW_LEN) - while we need bit-based addressing as the instructions length is 41 bits and - we must not modify/corrupt the adjacent slots in the same bundle. - Fortunately we may store larger memory incl. the adjacent bits with the - original memory content (not the possibly already stored breakpoints there). - We need to be careful in ia64_memory_remove_breakpoint to always restore - only the specific bits of this instruction ignoring any adjacent stored - bits. - - We use the original addressing with the low nibble in the range <0..2> which - gets incorrectly interpreted by generic non-ia64 breakpoint_restore_shadows - as the direct byte offset of SHADOW_CONTENTS. We store whole BUNDLE_LEN - bytes just without these two possibly skipped bytes to not to exceed to the - next bundle. - - If we would like to store the whole bundle to SHADOW_CONTENTS we would have - to store already the base address (`address & ~0x0f') into PLACED_ADDRESS. - In such case there is no other place where to store - SLOTNUM (`adress & 0x0f', value in the range <0..2>). We need to know - SLOTNUM in ia64_memory_remove_breakpoint. - - There is one special case where we need to be extra careful: - L-X instructions, which are instructions that occupy 2 slots - (The L part is always in slot 1, and the X part is always in - slot 2). We must refuse to insert breakpoints for an address - that points at slot 2 of a bundle where an L-X instruction is - present, since there is logically no instruction at that address. - However, to make things more interesting, the opcode of L-X - instructions is located in slot 2. This means that, to insert - a breakpoint at an address that points to slot 1, we actually - need to write the breakpoint in slot 2! Slot 1 is actually - the extended operand, so writing the breakpoint there would not - have the desired effect. Another side-effect of this issue - is that we need to make sure that the shadow contents buffer - does save byte 15 of our instruction bundle (this is the tail - end of slot 2, which wouldn't be saved if we were to insert - the breakpoint in slot 1). - - ia64 16-byte bundle layout: - | 5 bits | slot 0 with 41 bits | slot 1 with 41 bits | slot 2 with 41 bits | - - The current addressing used by the code below: - original PC placed_address placed_size required covered - == bp_tgt->shadow_len reqd \subset covered - 0xABCDE0 0xABCDE0 0x10 <0x0...0x5> <0x0..0xF> - 0xABCDE1 0xABCDE1 0xF <0x5...0xA> <0x1..0xF> - 0xABCDE2 0xABCDE2 0xE <0xA...0xF> <0x2..0xF> - - L-X instructions are treated a little specially, as explained above: - 0xABCDE1 0xABCDE1 0xF <0xA...0xF> <0x1..0xF> - - `objdump -d' and some other tools show a bit unjustified offsets: - original PC byte where starts the instruction objdump offset - 0xABCDE0 0xABCDE0 0xABCDE0 - 0xABCDE1 0xABCDE5 0xABCDE6 - 0xABCDE2 0xABCDEA 0xABCDEC - */ - -#define IA64_BREAKPOINT 0x00003333300LL - -static int -ia64_memory_insert_breakpoint (struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) -{ - CORE_ADDR addr = bp_tgt->placed_address = bp_tgt->reqstd_address; - gdb_byte bundle[BUNDLE_LEN]; - int slotnum = (int) (addr & 0x0f) / SLOT_MULTIPLIER, shadow_slotnum; - long long instr_breakpoint; - int val; - int templ; - - if (slotnum > 2) - error (_("Can't insert breakpoint for slot numbers greater than 2.")); - - addr &= ~0x0f; - - /* Enable the automatic memory restoration from breakpoints while - we read our instruction bundle for the purpose of SHADOW_CONTENTS. - Otherwise, we could possibly store into the shadow parts of the adjacent - placed breakpoints. It is due to our SHADOW_CONTENTS overlapping the real - breakpoint instruction bits region. */ - scoped_restore restore_memory_0 - = make_scoped_restore_show_memory_breakpoints (0); - val = target_read_memory (addr, bundle, BUNDLE_LEN); - if (val != 0) - return val; - - /* SHADOW_SLOTNUM saves the original slot number as expected by the caller - for addressing the SHADOW_CONTENTS placement. */ - shadow_slotnum = slotnum; - - /* Always cover the last byte of the bundle in case we are inserting - a breakpoint on an L-X instruction. */ - bp_tgt->shadow_len = BUNDLE_LEN - shadow_slotnum; - - templ = extract_bit_field (bundle, 0, 5); - if (template_encoding_table[templ][slotnum] == X) - { - /* X unit types can only be used in slot 2, and are actually - part of a 2-slot L-X instruction. We cannot break at this - address, as this is the second half of an instruction that - lives in slot 1 of that bundle. */ - gdb_assert (slotnum == 2); - error (_("Can't insert breakpoint for non-existing slot X")); - } - if (template_encoding_table[templ][slotnum] == L) - { - /* L unit types can only be used in slot 1. But the associated - opcode for that instruction is in slot 2, so bump the slot number - accordingly. */ - gdb_assert (slotnum == 1); - slotnum = 2; - } - - /* Store the whole bundle, except for the initial skipped bytes by the slot - number interpreted as bytes offset in PLACED_ADDRESS. */ - memcpy (bp_tgt->shadow_contents, bundle + shadow_slotnum, - bp_tgt->shadow_len); - - /* Re-read the same bundle as above except that, this time, read it in order - to compute the new bundle inside which we will be inserting the - breakpoint. Therefore, disable the automatic memory restoration from - breakpoints while we read our instruction bundle. Otherwise, the general - restoration mechanism kicks in and we would possibly remove parts of the - adjacent placed breakpoints. It is due to our SHADOW_CONTENTS overlapping - the real breakpoint instruction bits region. */ - scoped_restore restore_memory_1 - = make_scoped_restore_show_memory_breakpoints (1); - val = target_read_memory (addr, bundle, BUNDLE_LEN); - if (val != 0) - return val; - - /* Breakpoints already present in the code will get detected and not get - reinserted by bp_loc_is_permanent. Multiple breakpoints at the same - location cannot induce the internal error as they are optimized into - a single instance by update_global_location_list. */ - instr_breakpoint = slotN_contents (bundle, slotnum); - if (instr_breakpoint == IA64_BREAKPOINT) - internal_error (_("Address %s already contains a breakpoint."), - paddress (gdbarch, bp_tgt->placed_address)); - replace_slotN_contents (bundle, IA64_BREAKPOINT, slotnum); - - val = target_write_memory (addr + shadow_slotnum, bundle + shadow_slotnum, - bp_tgt->shadow_len); - - return val; -} - -static int -ia64_memory_remove_breakpoint (struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) -{ - CORE_ADDR addr = bp_tgt->placed_address; - gdb_byte bundle_mem[BUNDLE_LEN], bundle_saved[BUNDLE_LEN]; - int slotnum = (addr & 0x0f) / SLOT_MULTIPLIER, shadow_slotnum; - long long instr_breakpoint, instr_saved; - int val; - int templ; - - addr &= ~0x0f; - - /* Disable the automatic memory restoration from breakpoints while - we read our instruction bundle. Otherwise, the general restoration - mechanism kicks in and we would possibly remove parts of the adjacent - placed breakpoints. It is due to our SHADOW_CONTENTS overlapping the real - breakpoint instruction bits region. */ - scoped_restore restore_memory_1 - = make_scoped_restore_show_memory_breakpoints (1); - val = target_read_memory (addr, bundle_mem, BUNDLE_LEN); - if (val != 0) - return val; - - /* SHADOW_SLOTNUM saves the original slot number as expected by the caller - for addressing the SHADOW_CONTENTS placement. */ - shadow_slotnum = slotnum; - - templ = extract_bit_field (bundle_mem, 0, 5); - if (template_encoding_table[templ][slotnum] == X) - { - /* X unit types can only be used in slot 2, and are actually - part of a 2-slot L-X instruction. We refuse to insert - breakpoints at this address, so there should be no reason - for us attempting to remove one there, except if the program's - code somehow got modified in memory. */ - gdb_assert (slotnum == 2); - warning (_("Cannot remove breakpoint at address %s from non-existing " - "X-type slot, memory has changed underneath"), - paddress (gdbarch, bp_tgt->placed_address)); - return -1; - } - if (template_encoding_table[templ][slotnum] == L) - { - /* L unit types can only be used in slot 1. But the breakpoint - was actually saved using slot 2, so update the slot number - accordingly. */ - gdb_assert (slotnum == 1); - slotnum = 2; - } - - gdb_assert (bp_tgt->shadow_len == BUNDLE_LEN - shadow_slotnum); - - instr_breakpoint = slotN_contents (bundle_mem, slotnum); - if (instr_breakpoint != IA64_BREAKPOINT) - { - warning (_("Cannot remove breakpoint at address %s, " - "no break instruction at such address."), - paddress (gdbarch, bp_tgt->placed_address)); - return -1; - } - - /* Extract the original saved instruction from SLOTNUM normalizing its - bit-shift for INSTR_SAVED. */ - memcpy (bundle_saved, bundle_mem, BUNDLE_LEN); - memcpy (bundle_saved + shadow_slotnum, bp_tgt->shadow_contents, - bp_tgt->shadow_len); - instr_saved = slotN_contents (bundle_saved, slotnum); - - /* In BUNDLE_MEM, be careful to modify only the bits belonging to SLOTNUM - and not any of the other ones that are stored in SHADOW_CONTENTS. */ - replace_slotN_contents (bundle_mem, instr_saved, slotnum); - val = target_write_raw_memory (addr, bundle_mem, BUNDLE_LEN); - - return val; -} - -/* Implement the breakpoint_kind_from_pc gdbarch method. */ - -static int -ia64_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) -{ - /* A place holder of gdbarch method breakpoint_kind_from_pc. */ - return 0; -} - -/* As gdbarch_breakpoint_from_pc ranges have byte granularity and ia64 - instruction slots ranges are bit-granular (41 bits) we have to provide an - extended range as described for ia64_memory_insert_breakpoint. We also take - care of preserving the `break' instruction 21-bit (or 62-bit) parameter to - make a match for permanent breakpoints. */ - -static const gdb_byte * -ia64_breakpoint_from_pc (struct gdbarch *gdbarch, - CORE_ADDR *pcptr, int *lenptr) -{ - CORE_ADDR addr = *pcptr; - static gdb_byte bundle[BUNDLE_LEN]; - int slotnum = (int) (*pcptr & 0x0f) / SLOT_MULTIPLIER, shadow_slotnum; - long long instr_fetched; - int val; - int templ; - - if (slotnum > 2) - error (_("Can't insert breakpoint for slot numbers greater than 2.")); - - addr &= ~0x0f; - - /* Enable the automatic memory restoration from breakpoints while - we read our instruction bundle to match bp_loc_is_permanent. */ - { - scoped_restore restore_memory_0 - = make_scoped_restore_show_memory_breakpoints (0); - val = target_read_memory (addr, bundle, BUNDLE_LEN); - } - - /* The memory might be unreachable. This can happen, for instance, - when the user inserts a breakpoint at an invalid address. */ - if (val != 0) - return NULL; - - /* SHADOW_SLOTNUM saves the original slot number as expected by the caller - for addressing the SHADOW_CONTENTS placement. */ - shadow_slotnum = slotnum; - - /* Cover always the last byte of the bundle for the L-X slot case. */ - *lenptr = BUNDLE_LEN - shadow_slotnum; - - /* Check for L type instruction in slot 1, if present then bump up the slot - number to the slot 2. */ - templ = extract_bit_field (bundle, 0, 5); - if (template_encoding_table[templ][slotnum] == X) - { - gdb_assert (slotnum == 2); - error (_("Can't insert breakpoint for non-existing slot X")); - } - if (template_encoding_table[templ][slotnum] == L) - { - gdb_assert (slotnum == 1); - slotnum = 2; - } - - /* A break instruction has its all its opcode bits cleared except for - the parameter value. For L+X slot pair we are at the X slot (slot 2) so - we should not touch the L slot - the upper 41 bits of the parameter. */ - instr_fetched = slotN_contents (bundle, slotnum); - instr_fetched &= 0x1003ffffc0LL; - replace_slotN_contents (bundle, instr_fetched, slotnum); - - return bundle + shadow_slotnum; -} - -static CORE_ADDR -ia64_read_pc (readable_regcache *regcache) -{ - ULONGEST psr_value, pc_value; - int slot_num; - - regcache->cooked_read (IA64_PSR_REGNUM, &psr_value); - regcache->cooked_read (IA64_IP_REGNUM, &pc_value); - slot_num = (psr_value >> 41) & 3; - - return pc_value | (slot_num * SLOT_MULTIPLIER); -} - -void -ia64_write_pc (struct regcache *regcache, CORE_ADDR new_pc) -{ - int slot_num = (int) (new_pc & 0xf) / SLOT_MULTIPLIER; - ULONGEST psr_value; - - regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr_value); - psr_value &= ~(3LL << 41); - psr_value |= (ULONGEST)(slot_num & 0x3) << 41; - - new_pc &= ~0xfLL; - - regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr_value); - regcache_cooked_write_unsigned (regcache, IA64_IP_REGNUM, new_pc); -} - -#define IS_NaT_COLLECTION_ADDR(addr) ((((addr) >> 3) & 0x3f) == 0x3f) - -/* Returns the address of the slot that's NSLOTS slots away from - the address ADDR. NSLOTS may be positive or negative. */ -static CORE_ADDR -rse_address_add(CORE_ADDR addr, int nslots) -{ - CORE_ADDR new_addr; - int mandatory_nat_slots = nslots / 63; - int direction = nslots < 0 ? -1 : 1; - - new_addr = addr + 8 * (nslots + mandatory_nat_slots); - - if ((new_addr >> 9) != ((addr + 8 * 64 * mandatory_nat_slots) >> 9)) - new_addr += 8 * direction; - - if (IS_NaT_COLLECTION_ADDR(new_addr)) - new_addr += 8 * direction; - - return new_addr; -} - -static enum register_status -ia64_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache, - int regnum, gdb_byte *buf) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - enum register_status status; - - if (regnum >= V32_REGNUM && regnum <= V127_REGNUM) - { -#ifdef HAVE_LIBUNWIND_IA64_H - /* First try and use the libunwind special reg accessor, - otherwise fallback to standard logic. */ - if (!libunwind_is_initialized () - || libunwind_get_reg_special (gdbarch, regcache, regnum, buf) != 0) -#endif - { - /* The fallback position is to assume that r32-r127 are - found sequentially in memory starting at $bof. This - isn't always true, but without libunwind, this is the - best we can do. */ - ULONGEST cfm; - ULONGEST bsp; - CORE_ADDR reg; - - status = regcache->cooked_read (IA64_BSP_REGNUM, &bsp); - if (status != REG_VALID) - return status; - - status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm); - if (status != REG_VALID) - return status; - - /* The bsp points at the end of the register frame so we - subtract the size of frame from it to get start of - register frame. */ - bsp = rse_address_add (bsp, -(cfm & 0x7f)); - - if ((cfm & 0x7f) > regnum - V32_REGNUM) - { - ULONGEST reg_addr = rse_address_add (bsp, (regnum - V32_REGNUM)); - reg = read_memory_integer ((CORE_ADDR)reg_addr, 8, byte_order); - store_unsigned_integer (buf, register_size (gdbarch, regnum), - byte_order, reg); - } - else - store_unsigned_integer (buf, register_size (gdbarch, regnum), - byte_order, 0); - } - } - else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM) - { - ULONGEST unatN_val; - ULONGEST unat; - - status = regcache->cooked_read (IA64_UNAT_REGNUM, &unat); - if (status != REG_VALID) - return status; - unatN_val = (unat & (1LL << (regnum - IA64_NAT0_REGNUM))) != 0; - store_unsigned_integer (buf, register_size (gdbarch, regnum), - byte_order, unatN_val); - } - else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) - { - ULONGEST natN_val = 0; - ULONGEST bsp; - ULONGEST cfm; - CORE_ADDR gr_addr = 0; - - status = regcache->cooked_read (IA64_BSP_REGNUM, &bsp); - if (status != REG_VALID) - return status; - - status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm); - if (status != REG_VALID) - return status; - - /* The bsp points at the end of the register frame so we - subtract the size of frame from it to get start of register frame. */ - bsp = rse_address_add (bsp, -(cfm & 0x7f)); - - if ((cfm & 0x7f) > regnum - V32_REGNUM) - gr_addr = rse_address_add (bsp, (regnum - V32_REGNUM)); - - if (gr_addr != 0) - { - /* Compute address of nat collection bits. */ - CORE_ADDR nat_addr = gr_addr | 0x1f8; - ULONGEST nat_collection; - int nat_bit; - /* If our nat collection address is bigger than bsp, we have to get - the nat collection from rnat. Otherwise, we fetch the nat - collection from the computed address. */ - if (nat_addr >= bsp) - regcache->cooked_read (IA64_RNAT_REGNUM, &nat_collection); - else - nat_collection = read_memory_integer (nat_addr, 8, byte_order); - nat_bit = (gr_addr >> 3) & 0x3f; - natN_val = (nat_collection >> nat_bit) & 1; - } - - store_unsigned_integer (buf, register_size (gdbarch, regnum), - byte_order, natN_val); - } - else if (regnum == VBOF_REGNUM) - { - /* A virtual register frame start is provided for user convenience. - It can be calculated as the bsp - sof (sizeof frame). */ - ULONGEST bsp, vbsp; - ULONGEST cfm; - - status = regcache->cooked_read (IA64_BSP_REGNUM, &bsp); - if (status != REG_VALID) - return status; - status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm); - if (status != REG_VALID) - return status; - - /* The bsp points at the end of the register frame so we - subtract the size of frame from it to get beginning of frame. */ - vbsp = rse_address_add (bsp, -(cfm & 0x7f)); - store_unsigned_integer (buf, register_size (gdbarch, regnum), - byte_order, vbsp); - } - else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) - { - ULONGEST pr; - ULONGEST cfm; - ULONGEST prN_val; - - status = regcache->cooked_read (IA64_PR_REGNUM, &pr); - if (status != REG_VALID) - return status; - status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm); - if (status != REG_VALID) - return status; - - if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM) - { - /* Fetch predicate register rename base from current frame - marker for this frame. */ - int rrb_pr = (cfm >> 32) & 0x3f; - - /* Adjust the register number to account for register rotation. */ - regnum = VP16_REGNUM - + ((regnum - VP16_REGNUM) + rrb_pr) % 48; - } - prN_val = (pr & (1LL << (regnum - VP0_REGNUM))) != 0; - store_unsigned_integer (buf, register_size (gdbarch, regnum), - byte_order, prN_val); - } - else - memset (buf, 0, register_size (gdbarch, regnum)); - - return REG_VALID; -} - -static void -ia64_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, const gdb_byte *buf) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - - if (regnum >= V32_REGNUM && regnum <= V127_REGNUM) - { - ULONGEST bsp; - ULONGEST cfm; - regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp); - regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); - - bsp = rse_address_add (bsp, -(cfm & 0x7f)); - - if ((cfm & 0x7f) > regnum - V32_REGNUM) - { - ULONGEST reg_addr = rse_address_add (bsp, (regnum - V32_REGNUM)); - write_memory (reg_addr, buf, 8); - } - } - else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM) - { - ULONGEST unatN_val, unat, unatN_mask; - regcache_cooked_read_unsigned (regcache, IA64_UNAT_REGNUM, &unat); - unatN_val = extract_unsigned_integer (buf, register_size (gdbarch, - regnum), - byte_order); - unatN_mask = (1LL << (regnum - IA64_NAT0_REGNUM)); - if (unatN_val == 0) - unat &= ~unatN_mask; - else if (unatN_val == 1) - unat |= unatN_mask; - regcache_cooked_write_unsigned (regcache, IA64_UNAT_REGNUM, unat); - } - else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) - { - ULONGEST natN_val; - ULONGEST bsp; - ULONGEST cfm; - CORE_ADDR gr_addr = 0; - regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp); - regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); - - /* The bsp points at the end of the register frame so we - subtract the size of frame from it to get start of register frame. */ - bsp = rse_address_add (bsp, -(cfm & 0x7f)); - - if ((cfm & 0x7f) > regnum - V32_REGNUM) - gr_addr = rse_address_add (bsp, (regnum - V32_REGNUM)); - - natN_val = extract_unsigned_integer (buf, register_size (gdbarch, - regnum), - byte_order); - - if (gr_addr != 0 && (natN_val == 0 || natN_val == 1)) - { - /* Compute address of nat collection bits. */ - CORE_ADDR nat_addr = gr_addr | 0x1f8; - CORE_ADDR nat_collection; - int natN_bit = (gr_addr >> 3) & 0x3f; - ULONGEST natN_mask = (1LL << natN_bit); - /* If our nat collection address is bigger than bsp, we have to get - the nat collection from rnat. Otherwise, we fetch the nat - collection from the computed address. */ - if (nat_addr >= bsp) - { - regcache_cooked_read_unsigned (regcache, - IA64_RNAT_REGNUM, - &nat_collection); - if (natN_val) - nat_collection |= natN_mask; - else - nat_collection &= ~natN_mask; - regcache_cooked_write_unsigned (regcache, IA64_RNAT_REGNUM, - nat_collection); - } - else - { - gdb_byte nat_buf[8]; - nat_collection = read_memory_integer (nat_addr, 8, byte_order); - if (natN_val) - nat_collection |= natN_mask; - else - nat_collection &= ~natN_mask; - store_unsigned_integer (nat_buf, register_size (gdbarch, regnum), - byte_order, nat_collection); - write_memory (nat_addr, nat_buf, 8); - } - } - } - else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) - { - ULONGEST pr; - ULONGEST cfm; - ULONGEST prN_val; - ULONGEST prN_mask; - - regcache_cooked_read_unsigned (regcache, IA64_PR_REGNUM, &pr); - regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); - - if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM) - { - /* Fetch predicate register rename base from current frame - marker for this frame. */ - int rrb_pr = (cfm >> 32) & 0x3f; - - /* Adjust the register number to account for register rotation. */ - regnum = VP16_REGNUM - + ((regnum - VP16_REGNUM) + rrb_pr) % 48; - } - prN_val = extract_unsigned_integer (buf, register_size (gdbarch, regnum), - byte_order); - prN_mask = (1LL << (regnum - VP0_REGNUM)); - if (prN_val == 0) - pr &= ~prN_mask; - else if (prN_val == 1) - pr |= prN_mask; - regcache_cooked_write_unsigned (regcache, IA64_PR_REGNUM, pr); - } -} - -/* The ia64 needs to convert between various ieee floating-point formats - and the special ia64 floating point register format. */ - -static int -ia64_convert_register_p (struct gdbarch *gdbarch, int regno, struct type *type) -{ - return (regno >= IA64_FR0_REGNUM && regno <= IA64_FR127_REGNUM - && type->code () == TYPE_CODE_FLT - && type != ia64_ext_type (gdbarch)); -} - -static int -ia64_register_to_value (const frame_info_ptr &frame, int regnum, - struct type *valtype, gdb_byte *out, - int *optimizedp, int *unavailablep) -{ - struct gdbarch *gdbarch = get_frame_arch (frame); - gdb_byte in[IA64_FP_REGISTER_SIZE]; - - /* Convert to TYPE. */ - auto in_view = gdb::make_array_view (in, register_size (gdbarch, regnum)); - frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame); - if (!get_frame_register_bytes (next_frame, regnum, 0, in_view, optimizedp, - unavailablep)) - return 0; - - target_float_convert (in, ia64_ext_type (gdbarch), out, valtype); - *optimizedp = *unavailablep = 0; - return 1; -} - -static void -ia64_value_to_register (const frame_info_ptr &frame, int regnum, - struct type *valtype, const gdb_byte *in) -{ - struct gdbarch *gdbarch = get_frame_arch (frame); - gdb_byte out[IA64_FP_REGISTER_SIZE]; - type *to_type = ia64_ext_type (gdbarch); - target_float_convert (in, valtype, out, to_type); - auto out_view = gdb::make_array_view (out, to_type->length ()); - put_frame_register (get_next_frame_sentinel_okay (frame), regnum, out_view); -} - - -/* Limit the number of skipped non-prologue instructions since examining - of the prologue is expensive. */ -static int max_skip_non_prologue_insns = 40; - -/* Given PC representing the starting address of a function, and - LIM_PC which is the (sloppy) limit to which to scan when looking - for a prologue, attempt to further refine this limit by using - the line data in the symbol table. If successful, a better guess - on where the prologue ends is returned, otherwise the previous - value of lim_pc is returned. TRUST_LIMIT is a pointer to a flag - which will be set to indicate whether the returned limit may be - used with no further scanning in the event that the function is - frameless. */ - -/* FIXME: cagney/2004-02-14: This function and logic have largely been - superseded by skip_prologue_using_sal. */ - -static CORE_ADDR -refine_prologue_limit (CORE_ADDR pc, CORE_ADDR lim_pc, int *trust_limit) -{ - struct symtab_and_line prologue_sal; - CORE_ADDR start_pc = pc; - CORE_ADDR end_pc; - - /* The prologue can not possibly go past the function end itself, - so we can already adjust LIM_PC accordingly. */ - if (find_pc_partial_function (pc, NULL, NULL, &end_pc) && end_pc < lim_pc) - lim_pc = end_pc; - - /* Start off not trusting the limit. */ - *trust_limit = 0; - - prologue_sal = find_pc_line (pc, 0); - if (prologue_sal.line != 0) - { - int i; - CORE_ADDR addr = prologue_sal.end; - - /* Handle the case in which compiler's optimizer/scheduler - has moved instructions into the prologue. We scan ahead - in the function looking for address ranges whose corresponding - line number is less than or equal to the first one that we - found for the function. (It can be less than when the - scheduler puts a body instruction before the first prologue - instruction.) */ - for (i = 2 * max_skip_non_prologue_insns; - i > 0 && (lim_pc == 0 || addr < lim_pc); - i--) - { - struct symtab_and_line sal; - - sal = find_pc_line (addr, 0); - if (sal.line == 0) - break; - if (sal.line <= prologue_sal.line - && sal.symtab == prologue_sal.symtab) - { - prologue_sal = sal; - } - addr = sal.end; - } - - if (lim_pc == 0 || prologue_sal.end < lim_pc) - { - lim_pc = prologue_sal.end; - if (start_pc == get_pc_function_start (lim_pc)) - *trust_limit = 1; - } - } - return lim_pc; -} - -#define isScratch(_regnum_) ((_regnum_) == 2 || (_regnum_) == 3 \ - || (8 <= (_regnum_) && (_regnum_) <= 11) \ - || (14 <= (_regnum_) && (_regnum_) <= 31)) -#define imm9(_instr_) \ - ( ((((_instr_) & 0x01000000000LL) ? -1 : 0) << 8) \ - | (((_instr_) & 0x00008000000LL) >> 20) \ - | (((_instr_) & 0x00000001fc0LL) >> 6)) - -/* Allocate and initialize a frame cache. */ - -static struct ia64_frame_cache * -ia64_alloc_frame_cache (void) -{ - struct ia64_frame_cache *cache; - int i; - - cache = FRAME_OBSTACK_ZALLOC (struct ia64_frame_cache); - - /* Base address. */ - cache->base = 0; - cache->pc = 0; - cache->cfm = 0; - cache->prev_cfm = 0; - cache->sof = 0; - cache->sol = 0; - cache->sor = 0; - cache->bsp = 0; - cache->fp_reg = 0; - cache->frameless = 1; - - for (i = 0; i < NUM_IA64_RAW_REGS; i++) - cache->saved_regs[i] = 0; - - return cache; -} - -static CORE_ADDR -examine_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, - const frame_info_ptr &this_frame, - struct ia64_frame_cache *cache) -{ - CORE_ADDR next_pc; - CORE_ADDR last_prologue_pc = pc; - ia64_instruction_type it; - long long instr; - int cfm_reg = 0; - int ret_reg = 0; - int fp_reg = 0; - int unat_save_reg = 0; - int pr_save_reg = 0; - int mem_stack_frame_size = 0; - int spill_reg = 0; - CORE_ADDR spill_addr = 0; - char instores[8]; - char infpstores[8]; - char reg_contents[256]; - int trust_limit; - int frameless = 1; - int i; - CORE_ADDR addr; - gdb_byte buf[8]; - CORE_ADDR bof, sor, sol, sof, cfm, rrb_gr; - - memset (instores, 0, sizeof instores); - memset (infpstores, 0, sizeof infpstores); - memset (reg_contents, 0, sizeof reg_contents); - - if (cache->after_prologue != 0 - && cache->after_prologue <= lim_pc) - return cache->after_prologue; - - lim_pc = refine_prologue_limit (pc, lim_pc, &trust_limit); - next_pc = fetch_instruction (pc, &it, &instr); - - /* We want to check if we have a recognizable function start before we - look ahead for a prologue. */ - if (pc < lim_pc && next_pc - && it == M && ((instr & 0x1ee0000003fLL) == 0x02c00000000LL)) - { - /* alloc - start of a regular function. */ - int sol_bits = (int) ((instr & 0x00007f00000LL) >> 20); - int sof_bits = (int) ((instr & 0x000000fe000LL) >> 13); - int rN = (int) ((instr & 0x00000001fc0LL) >> 6); - - /* Verify that the current cfm matches what we think is the - function start. If we have somehow jumped within a function, - we do not want to interpret the prologue and calculate the - addresses of various registers such as the return address. - We will instead treat the frame as frameless. */ - if (!this_frame || - (sof_bits == (cache->cfm & 0x7f) && - sol_bits == ((cache->cfm >> 7) & 0x7f))) - frameless = 0; - - cfm_reg = rN; - last_prologue_pc = next_pc; - pc = next_pc; - } - else - { - /* Look for a leaf routine. */ - if (pc < lim_pc && next_pc - && (it == I || it == M) - && ((instr & 0x1ee00000000LL) == 0x10800000000LL)) - { - /* adds rN = imm14, rM (or mov rN, rM when imm14 is 0) */ - int imm = (int) ((((instr & 0x01000000000LL) ? -1 : 0) << 13) - | ((instr & 0x001f8000000LL) >> 20) - | ((instr & 0x000000fe000LL) >> 13)); - int rM = (int) ((instr & 0x00007f00000LL) >> 20); - int rN = (int) ((instr & 0x00000001fc0LL) >> 6); - int qp = (int) (instr & 0x0000000003fLL); - if (qp == 0 && rN == 2 && imm == 0 && rM == 12 && fp_reg == 0) - { - /* mov r2, r12 - beginning of leaf routine. */ - fp_reg = rN; - last_prologue_pc = next_pc; - } - } - - /* If we don't recognize a regular function or leaf routine, we are - done. */ - if (!fp_reg) - { - pc = lim_pc; - if (trust_limit) - last_prologue_pc = lim_pc; - } - } - - /* Loop, looking for prologue instructions, keeping track of - where preserved registers were spilled. */ - while (pc < lim_pc) - { - next_pc = fetch_instruction (pc, &it, &instr); - if (next_pc == 0) - break; - - if (it == B && ((instr & 0x1e1f800003fLL) != 0x04000000000LL)) - { - /* Exit loop upon hitting a non-nop branch instruction. */ - if (trust_limit) - lim_pc = pc; - break; - } - else if (((instr & 0x3fLL) != 0LL) && - (frameless || ret_reg != 0)) - { - /* Exit loop upon hitting a predicated instruction if - we already have the return register or if we are frameless. */ - if (trust_limit) - lim_pc = pc; - break; - } - else if (it == I && ((instr & 0x1eff8000000LL) == 0x00188000000LL)) - { - /* Move from BR */ - int b2 = (int) ((instr & 0x0000000e000LL) >> 13); - int rN = (int) ((instr & 0x00000001fc0LL) >> 6); - int qp = (int) (instr & 0x0000000003f); - - if (qp == 0 && b2 == 0 && rN >= 32 && ret_reg == 0) - { - ret_reg = rN; - last_prologue_pc = next_pc; - } - } - else if ((it == I || it == M) - && ((instr & 0x1ee00000000LL) == 0x10800000000LL)) - { - /* adds rN = imm14, rM (or mov rN, rM when imm14 is 0) */ - int imm = (int) ((((instr & 0x01000000000LL) ? -1 : 0) << 13) - | ((instr & 0x001f8000000LL) >> 20) - | ((instr & 0x000000fe000LL) >> 13)); - int rM = (int) ((instr & 0x00007f00000LL) >> 20); - int rN = (int) ((instr & 0x00000001fc0LL) >> 6); - int qp = (int) (instr & 0x0000000003fLL); - - if (qp == 0 && rN >= 32 && imm == 0 && rM == 12 && fp_reg == 0) - { - /* mov rN, r12 */ - fp_reg = rN; - last_prologue_pc = next_pc; - } - else if (qp == 0 && rN == 12 && rM == 12) - { - /* adds r12, -mem_stack_frame_size, r12 */ - mem_stack_frame_size -= imm; - last_prologue_pc = next_pc; - } - else if (qp == 0 && rN == 2 - && ((rM == fp_reg && fp_reg != 0) || rM == 12)) - { - CORE_ADDR saved_sp = 0; - /* adds r2, spilloffset, rFramePointer - or - adds r2, spilloffset, r12 - - Get ready for stf.spill or st8.spill instructions. - The address to start spilling at is loaded into r2. - FIXME: Why r2? That's what gcc currently uses; it - could well be different for other compilers. */ - - /* Hmm... whether or not this will work will depend on - where the pc is. If it's still early in the prologue - this'll be wrong. FIXME */ - if (this_frame) - saved_sp = get_frame_register_unsigned (this_frame, - sp_regnum); - spill_addr = saved_sp - + (rM == 12 ? 0 : mem_stack_frame_size) - + imm; - spill_reg = rN; - last_prologue_pc = next_pc; - } - else if (qp == 0 && rM >= 32 && rM < 40 && !instores[rM-32] && - rN < 256 && imm == 0) - { - /* mov rN, rM where rM is an input register. */ - reg_contents[rN] = rM; - last_prologue_pc = next_pc; - } - else if (frameless && qp == 0 && rN == fp_reg && imm == 0 && - rM == 2) - { - /* mov r12, r2 */ - last_prologue_pc = next_pc; - break; - } - } - else if (it == M - && ( ((instr & 0x1efc0000000LL) == 0x0eec0000000LL) - || ((instr & 0x1ffc8000000LL) == 0x0cec0000000LL) )) - { - /* stf.spill [rN] = fM, imm9 - or - stf.spill [rN] = fM */ - - int imm = imm9(instr); - int rN = (int) ((instr & 0x00007f00000LL) >> 20); - int fM = (int) ((instr & 0x000000fe000LL) >> 13); - int qp = (int) (instr & 0x0000000003fLL); - if (qp == 0 && rN == spill_reg && spill_addr != 0 - && ((2 <= fM && fM <= 5) || (16 <= fM && fM <= 31))) - { - cache->saved_regs[IA64_FR0_REGNUM + fM] = spill_addr; - - if ((instr & 0x1efc0000000LL) == 0x0eec0000000LL) - spill_addr += imm; - else - spill_addr = 0; /* last one; must be done. */ - last_prologue_pc = next_pc; - } - } - else if ((it == M && ((instr & 0x1eff8000000LL) == 0x02110000000LL)) - || (it == I && ((instr & 0x1eff8000000LL) == 0x00050000000LL)) ) - { - /* mov.m rN = arM - or - mov.i rN = arM */ - - int arM = (int) ((instr & 0x00007f00000LL) >> 20); - int rN = (int) ((instr & 0x00000001fc0LL) >> 6); - int qp = (int) (instr & 0x0000000003fLL); - if (qp == 0 && isScratch (rN) && arM == 36 /* ar.unat */) - { - /* We have something like "mov.m r3 = ar.unat". Remember the - r3 (or whatever) and watch for a store of this register... */ - unat_save_reg = rN; - last_prologue_pc = next_pc; - } - } - else if (it == I && ((instr & 0x1eff8000000LL) == 0x00198000000LL)) - { - /* mov rN = pr */ - int rN = (int) ((instr & 0x00000001fc0LL) >> 6); - int qp = (int) (instr & 0x0000000003fLL); - if (qp == 0 && isScratch (rN)) - { - pr_save_reg = rN; - last_prologue_pc = next_pc; - } - } - else if (it == M - && ( ((instr & 0x1ffc8000000LL) == 0x08cc0000000LL) - || ((instr & 0x1efc0000000LL) == 0x0acc0000000LL))) - { - /* st8 [rN] = rM - or - st8 [rN] = rM, imm9 */ - int rN = (int) ((instr & 0x00007f00000LL) >> 20); - int rM = (int) ((instr & 0x000000fe000LL) >> 13); - int qp = (int) (instr & 0x0000000003fLL); - int indirect = rM < 256 ? reg_contents[rM] : 0; - if (qp == 0 && rN == spill_reg && spill_addr != 0 - && (rM == unat_save_reg || rM == pr_save_reg)) - { - /* We've found a spill of either the UNAT register or the PR - register. (Well, not exactly; what we've actually found is - a spill of the register that UNAT or PR was moved to). - Record that fact and move on... */ - if (rM == unat_save_reg) - { - /* Track UNAT register. */ - cache->saved_regs[IA64_UNAT_REGNUM] = spill_addr; - unat_save_reg = 0; - } - else - { - /* Track PR register. */ - cache->saved_regs[IA64_PR_REGNUM] = spill_addr; - pr_save_reg = 0; - } - if ((instr & 0x1efc0000000LL) == 0x0acc0000000LL) - /* st8 [rN] = rM, imm9 */ - spill_addr += imm9(instr); - else - spill_addr = 0; /* Must be done spilling. */ - last_prologue_pc = next_pc; - } - else if (qp == 0 && 32 <= rM && rM < 40 && !instores[rM-32]) - { - /* Allow up to one store of each input register. */ - instores[rM-32] = 1; - last_prologue_pc = next_pc; - } - else if (qp == 0 && 32 <= indirect && indirect < 40 && - !instores[indirect-32]) - { - /* Allow an indirect store of an input register. */ - instores[indirect-32] = 1; - last_prologue_pc = next_pc; - } - } - else if (it == M && ((instr & 0x1ff08000000LL) == 0x08c00000000LL)) - { - /* One of - st1 [rN] = rM - st2 [rN] = rM - st4 [rN] = rM - st8 [rN] = rM - Note that the st8 case is handled in the clause above. - - Advance over stores of input registers. One store per input - register is permitted. */ - int rM = (int) ((instr & 0x000000fe000LL) >> 13); - int qp = (int) (instr & 0x0000000003fLL); - int indirect = rM < 256 ? reg_contents[rM] : 0; - if (qp == 0 && 32 <= rM && rM < 40 && !instores[rM-32]) - { - instores[rM-32] = 1; - last_prologue_pc = next_pc; - } - else if (qp == 0 && 32 <= indirect && indirect < 40 && - !instores[indirect-32]) - { - /* Allow an indirect store of an input register. */ - instores[indirect-32] = 1; - last_prologue_pc = next_pc; - } - } - else if (it == M && ((instr & 0x1ff88000000LL) == 0x0cc80000000LL)) - { - /* Either - stfs [rN] = fM - or - stfd [rN] = fM - - Advance over stores of floating point input registers. Again - one store per register is permitted. */ - int fM = (int) ((instr & 0x000000fe000LL) >> 13); - int qp = (int) (instr & 0x0000000003fLL); - if (qp == 0 && 8 <= fM && fM < 16 && !infpstores[fM - 8]) - { - infpstores[fM-8] = 1; - last_prologue_pc = next_pc; - } - } - else if (it == M - && ( ((instr & 0x1ffc8000000LL) == 0x08ec0000000LL) - || ((instr & 0x1efc0000000LL) == 0x0aec0000000LL))) - { - /* st8.spill [rN] = rM - or - st8.spill [rN] = rM, imm9 */ - int rN = (int) ((instr & 0x00007f00000LL) >> 20); - int rM = (int) ((instr & 0x000000fe000LL) >> 13); - int qp = (int) (instr & 0x0000000003fLL); - if (qp == 0 && rN == spill_reg && 4 <= rM && rM <= 7) - { - /* We've found a spill of one of the preserved general purpose - regs. Record the spill address and advance the spill - register if appropriate. */ - cache->saved_regs[IA64_GR0_REGNUM + rM] = spill_addr; - if ((instr & 0x1efc0000000LL) == 0x0aec0000000LL) - /* st8.spill [rN] = rM, imm9 */ - spill_addr += imm9(instr); - else - spill_addr = 0; /* Done spilling. */ - last_prologue_pc = next_pc; - } - } - - pc = next_pc; - } - - /* If not frameless and we aren't called by skip_prologue, then we need - to calculate registers for the previous frame which will be needed - later. */ - - if (!frameless && this_frame) - { - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - - /* Extract the size of the rotating portion of the stack - frame and the register rename base from the current - frame marker. */ - cfm = cache->cfm; - sor = cache->sor; - sof = cache->sof; - sol = cache->sol; - rrb_gr = (cfm >> 18) & 0x7f; - - /* Find the bof (beginning of frame). */ - bof = rse_address_add (cache->bsp, -sof); - - for (i = 0, addr = bof; - i < sof; - i++, addr += 8) - { - if (IS_NaT_COLLECTION_ADDR (addr)) - { - addr += 8; - } - if (i+32 == cfm_reg) - cache->saved_regs[IA64_CFM_REGNUM] = addr; - if (i+32 == ret_reg) - cache->saved_regs[IA64_VRAP_REGNUM] = addr; - if (i+32 == fp_reg) - cache->saved_regs[IA64_VFP_REGNUM] = addr; - } - - /* For the previous argument registers we require the previous bof. - If we can't find the previous cfm, then we can do nothing. */ - cfm = 0; - if (cache->saved_regs[IA64_CFM_REGNUM] != 0) - { - cfm = read_memory_integer (cache->saved_regs[IA64_CFM_REGNUM], - 8, byte_order); - } - else if (cfm_reg != 0) - { - get_frame_register (this_frame, cfm_reg, buf); - cfm = extract_unsigned_integer (buf, 8, byte_order); - } - cache->prev_cfm = cfm; - - if (cfm != 0) - { - sor = ((cfm >> 14) & 0xf) * 8; - sof = (cfm & 0x7f); - sol = (cfm >> 7) & 0x7f; - rrb_gr = (cfm >> 18) & 0x7f; - - /* The previous bof only requires subtraction of the sol (size of - locals) due to the overlap between output and input of - subsequent frames. */ - bof = rse_address_add (bof, -sol); - - for (i = 0, addr = bof; - i < sof; - i++, addr += 8) - { - if (IS_NaT_COLLECTION_ADDR (addr)) - { - addr += 8; - } - if (i < sor) - cache->saved_regs[IA64_GR32_REGNUM - + ((i + (sor - rrb_gr)) % sor)] - = addr; - else - cache->saved_regs[IA64_GR32_REGNUM + i] = addr; - } - - } - } - - /* Try and trust the lim_pc value whenever possible. */ - if (trust_limit && lim_pc >= last_prologue_pc) - last_prologue_pc = lim_pc; - - cache->frameless = frameless; - cache->after_prologue = last_prologue_pc; - cache->mem_stack_frame_size = mem_stack_frame_size; - cache->fp_reg = fp_reg; - - return last_prologue_pc; -} - -CORE_ADDR -ia64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) -{ - struct ia64_frame_cache cache; - cache.base = 0; - cache.after_prologue = 0; - cache.cfm = 0; - cache.bsp = 0; - - /* Call examine_prologue with - as third argument since we don't - have a next frame pointer to send. */ - return examine_prologue (pc, pc+1024, 0, &cache); -} - - -/* Normal frames. */ - -static struct ia64_frame_cache * -ia64_frame_cache (const frame_info_ptr &this_frame, void **this_cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct ia64_frame_cache *cache; - gdb_byte buf[8]; - CORE_ADDR cfm; - - if (*this_cache) - return (struct ia64_frame_cache *) *this_cache; - - cache = ia64_alloc_frame_cache (); - *this_cache = cache; - - get_frame_register (this_frame, sp_regnum, buf); - cache->saved_sp = extract_unsigned_integer (buf, 8, byte_order); - - /* We always want the bsp to point to the end of frame. - This way, we can always get the beginning of frame (bof) - by subtracting frame size. */ - get_frame_register (this_frame, IA64_BSP_REGNUM, buf); - cache->bsp = extract_unsigned_integer (buf, 8, byte_order); - - get_frame_register (this_frame, IA64_PSR_REGNUM, buf); - - get_frame_register (this_frame, IA64_CFM_REGNUM, buf); - cfm = extract_unsigned_integer (buf, 8, byte_order); - - cache->sof = (cfm & 0x7f); - cache->sol = (cfm >> 7) & 0x7f; - cache->sor = ((cfm >> 14) & 0xf) * 8; - - cache->cfm = cfm; - - cache->pc = get_frame_func (this_frame); - - if (cache->pc != 0) - examine_prologue (cache->pc, get_frame_pc (this_frame), this_frame, cache); - - cache->base = cache->saved_sp + cache->mem_stack_frame_size; - - return cache; -} - -static void -ia64_frame_this_id (const frame_info_ptr &this_frame, void **this_cache, - struct frame_id *this_id) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - struct ia64_frame_cache *cache = - ia64_frame_cache (this_frame, this_cache); - - /* If outermost frame, mark with null frame id. */ - if (cache->base != 0) - (*this_id) = frame_id_build_special (cache->base, cache->pc, cache->bsp); - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, - "regular frame id: code %s, stack %s, " - "special %s, this_frame %s\n", - paddress (gdbarch, this_id->code_addr), - paddress (gdbarch, this_id->stack_addr), - paddress (gdbarch, cache->bsp), - host_address_to_string (this_frame.get ())); -} - -static struct value * -ia64_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache, - int regnum) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct ia64_frame_cache *cache = ia64_frame_cache (this_frame, this_cache); - gdb_byte buf[8]; - - gdb_assert (regnum >= 0); - - if (!target_has_registers ()) - error (_("No registers.")); - - if (regnum == gdbarch_sp_regnum (gdbarch)) - return frame_unwind_got_constant (this_frame, regnum, cache->base); - - else if (regnum == IA64_BSP_REGNUM) - { - struct value *val; - CORE_ADDR prev_cfm, bsp, prev_bsp; - - /* We want to calculate the previous bsp as the end of the previous - register stack frame. This corresponds to what the hardware bsp - register will be if we pop the frame back which is why we might - have been called. We know the beginning of the current frame is - cache->bsp - cache->sof. This value in the previous frame points - to the start of the output registers. We can calculate the end of - that frame by adding the size of output: - (sof (size of frame) - sol (size of locals)). */ - val = ia64_frame_prev_register (this_frame, this_cache, IA64_CFM_REGNUM); - prev_cfm = extract_unsigned_integer (val->contents_all ().data (), - 8, byte_order); - bsp = rse_address_add (cache->bsp, -(cache->sof)); - prev_bsp = - rse_address_add (bsp, (prev_cfm & 0x7f) - ((prev_cfm >> 7) & 0x7f)); - - return frame_unwind_got_constant (this_frame, regnum, prev_bsp); - } - - else if (regnum == IA64_CFM_REGNUM) - { - CORE_ADDR addr = cache->saved_regs[IA64_CFM_REGNUM]; - - if (addr != 0) - return frame_unwind_got_memory (this_frame, regnum, addr); - - if (cache->prev_cfm) - return frame_unwind_got_constant (this_frame, regnum, cache->prev_cfm); - - if (cache->frameless) - return frame_unwind_got_register (this_frame, IA64_PFS_REGNUM, - IA64_PFS_REGNUM); - return frame_unwind_got_register (this_frame, regnum, 0); - } - - else if (regnum == IA64_VFP_REGNUM) - { - /* If the function in question uses an automatic register (r32-r127) - for the frame pointer, it'll be found by ia64_find_saved_register() - above. If the function lacks one of these frame pointers, we can - still provide a value since we know the size of the frame. */ - return frame_unwind_got_constant (this_frame, regnum, cache->base); - } - - else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) - { - struct value *pr_val; - ULONGEST prN; - - pr_val = ia64_frame_prev_register (this_frame, this_cache, - IA64_PR_REGNUM); - if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM) - { - /* Fetch predicate register rename base from current frame - marker for this frame. */ - int rrb_pr = (cache->cfm >> 32) & 0x3f; - - /* Adjust the register number to account for register rotation. */ - regnum = VP16_REGNUM + ((regnum - VP16_REGNUM) + rrb_pr) % 48; - } - prN = extract_bit_field (pr_val->contents_all ().data (), - regnum - VP0_REGNUM, 1); - return frame_unwind_got_constant (this_frame, regnum, prN); - } - - else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM) - { - struct value *unat_val; - ULONGEST unatN; - unat_val = ia64_frame_prev_register (this_frame, this_cache, - IA64_UNAT_REGNUM); - unatN = extract_bit_field (unat_val->contents_all ().data (), - regnum - IA64_NAT0_REGNUM, 1); - return frame_unwind_got_constant (this_frame, regnum, unatN); - } - - else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) - { - int natval = 0; - /* Find address of general register corresponding to nat bit we're - interested in. */ - CORE_ADDR gr_addr; - - gr_addr = cache->saved_regs[regnum - IA64_NAT0_REGNUM + IA64_GR0_REGNUM]; - - if (gr_addr != 0) - { - /* Compute address of nat collection bits. */ - CORE_ADDR nat_addr = gr_addr | 0x1f8; - CORE_ADDR bsp; - CORE_ADDR nat_collection; - int nat_bit; - - /* If our nat collection address is bigger than bsp, we have to get - the nat collection from rnat. Otherwise, we fetch the nat - collection from the computed address. */ - get_frame_register (this_frame, IA64_BSP_REGNUM, buf); - bsp = extract_unsigned_integer (buf, 8, byte_order); - if (nat_addr >= bsp) - { - get_frame_register (this_frame, IA64_RNAT_REGNUM, buf); - nat_collection = extract_unsigned_integer (buf, 8, byte_order); - } - else - nat_collection = read_memory_integer (nat_addr, 8, byte_order); - nat_bit = (gr_addr >> 3) & 0x3f; - natval = (nat_collection >> nat_bit) & 1; - } - - return frame_unwind_got_constant (this_frame, regnum, natval); - } - - else if (regnum == IA64_IP_REGNUM) - { - CORE_ADDR pc = 0; - CORE_ADDR addr = cache->saved_regs[IA64_VRAP_REGNUM]; - - if (addr != 0) - { - read_memory (addr, buf, register_size (gdbarch, IA64_IP_REGNUM)); - pc = extract_unsigned_integer (buf, 8, byte_order); - } - else if (cache->frameless) - { - get_frame_register (this_frame, IA64_BR0_REGNUM, buf); - pc = extract_unsigned_integer (buf, 8, byte_order); - } - pc &= ~0xf; - return frame_unwind_got_constant (this_frame, regnum, pc); - } - - else if (regnum == IA64_PSR_REGNUM) - { - /* We don't know how to get the complete previous PSR, but we need it - for the slot information when we unwind the pc (pc is formed of IP - register plus slot information from PSR). To get the previous - slot information, we mask it off the return address. */ - ULONGEST slot_num = 0; - CORE_ADDR pc = 0; - CORE_ADDR psr = 0; - CORE_ADDR addr = cache->saved_regs[IA64_VRAP_REGNUM]; - - get_frame_register (this_frame, IA64_PSR_REGNUM, buf); - psr = extract_unsigned_integer (buf, 8, byte_order); - - if (addr != 0) - { - read_memory (addr, buf, register_size (gdbarch, IA64_IP_REGNUM)); - pc = extract_unsigned_integer (buf, 8, byte_order); - } - else if (cache->frameless) - { - get_frame_register (this_frame, IA64_BR0_REGNUM, buf); - pc = extract_unsigned_integer (buf, 8, byte_order); - } - psr &= ~(3LL << 41); - slot_num = pc & 0x3LL; - psr |= (CORE_ADDR)slot_num << 41; - return frame_unwind_got_constant (this_frame, regnum, psr); - } - - else if (regnum == IA64_BR0_REGNUM) - { - CORE_ADDR addr = cache->saved_regs[IA64_BR0_REGNUM]; - - if (addr != 0) - return frame_unwind_got_memory (this_frame, regnum, addr); - - return frame_unwind_got_constant (this_frame, regnum, 0); - } - - else if ((regnum >= IA64_GR32_REGNUM && regnum <= IA64_GR127_REGNUM) - || (regnum >= V32_REGNUM && regnum <= V127_REGNUM)) - { - CORE_ADDR addr = 0; - - if (regnum >= V32_REGNUM) - regnum = IA64_GR32_REGNUM + (regnum - V32_REGNUM); - addr = cache->saved_regs[regnum]; - if (addr != 0) - return frame_unwind_got_memory (this_frame, regnum, addr); - - if (cache->frameless) - { - struct value *reg_val; - CORE_ADDR prev_cfm, prev_bsp, prev_bof; - - /* FIXME: brobecker/2008-05-01: Doesn't this seem redundant - with the same code above? */ - if (regnum >= V32_REGNUM) - regnum = IA64_GR32_REGNUM + (regnum - V32_REGNUM); - reg_val = ia64_frame_prev_register (this_frame, this_cache, - IA64_CFM_REGNUM); - prev_cfm = extract_unsigned_integer - (reg_val->contents_all ().data (), 8, byte_order); - reg_val = ia64_frame_prev_register (this_frame, this_cache, - IA64_BSP_REGNUM); - prev_bsp = extract_unsigned_integer - (reg_val->contents_all ().data (), 8, byte_order); - prev_bof = rse_address_add (prev_bsp, -(prev_cfm & 0x7f)); - - addr = rse_address_add (prev_bof, (regnum - IA64_GR32_REGNUM)); - return frame_unwind_got_memory (this_frame, regnum, addr); - } - - return frame_unwind_got_constant (this_frame, regnum, 0); - } - - else /* All other registers. */ - { - CORE_ADDR addr = 0; - - if (IA64_FR32_REGNUM <= regnum && regnum <= IA64_FR127_REGNUM) - { - /* Fetch floating point register rename base from current - frame marker for this frame. */ - int rrb_fr = (cache->cfm >> 25) & 0x7f; - - /* Adjust the floating point register number to account for - register rotation. */ - regnum = IA64_FR32_REGNUM - + ((regnum - IA64_FR32_REGNUM) + rrb_fr) % 96; - } - - /* If we have stored a memory address, access the register. */ - addr = cache->saved_regs[regnum]; - if (addr != 0) - return frame_unwind_got_memory (this_frame, regnum, addr); - /* Otherwise, punt and get the current value of the register. */ - else - return frame_unwind_got_register (this_frame, regnum, regnum); - } -} - -static const struct frame_unwind ia64_frame_unwind = -{ - "ia64 prologue", - NORMAL_FRAME, - default_frame_unwind_stop_reason, - &ia64_frame_this_id, - &ia64_frame_prev_register, - NULL, - default_frame_sniffer -}; - -/* Signal trampolines. */ - -static void -ia64_sigtramp_frame_init_saved_regs (const frame_info_ptr &this_frame, - struct ia64_frame_cache *cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - ia64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - if (tdep->sigcontext_register_address) - { - int regno; - - cache->saved_regs[IA64_VRAP_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_IP_REGNUM); - cache->saved_regs[IA64_CFM_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_CFM_REGNUM); - cache->saved_regs[IA64_PSR_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_PSR_REGNUM); - cache->saved_regs[IA64_BSP_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_BSP_REGNUM); - cache->saved_regs[IA64_RNAT_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_RNAT_REGNUM); - cache->saved_regs[IA64_CCV_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_CCV_REGNUM); - cache->saved_regs[IA64_UNAT_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_UNAT_REGNUM); - cache->saved_regs[IA64_FPSR_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_FPSR_REGNUM); - cache->saved_regs[IA64_PFS_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_PFS_REGNUM); - cache->saved_regs[IA64_LC_REGNUM] - = tdep->sigcontext_register_address (gdbarch, cache->base, - IA64_LC_REGNUM); - - for (regno = IA64_GR1_REGNUM; regno <= IA64_GR31_REGNUM; regno++) - cache->saved_regs[regno] = - tdep->sigcontext_register_address (gdbarch, cache->base, regno); - for (regno = IA64_BR0_REGNUM; regno <= IA64_BR7_REGNUM; regno++) - cache->saved_regs[regno] = - tdep->sigcontext_register_address (gdbarch, cache->base, regno); - for (regno = IA64_FR2_REGNUM; regno <= IA64_FR31_REGNUM; regno++) - cache->saved_regs[regno] = - tdep->sigcontext_register_address (gdbarch, cache->base, regno); - } -} - -static struct ia64_frame_cache * -ia64_sigtramp_frame_cache (const frame_info_ptr &this_frame, void **this_cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct ia64_frame_cache *cache; - gdb_byte buf[8]; - - if (*this_cache) - return (struct ia64_frame_cache *) *this_cache; - - cache = ia64_alloc_frame_cache (); - - get_frame_register (this_frame, sp_regnum, buf); - /* Note that frame size is hard-coded below. We cannot calculate it - via prologue examination. */ - cache->base = extract_unsigned_integer (buf, 8, byte_order) + 16; - - get_frame_register (this_frame, IA64_BSP_REGNUM, buf); - cache->bsp = extract_unsigned_integer (buf, 8, byte_order); - - get_frame_register (this_frame, IA64_CFM_REGNUM, buf); - cache->cfm = extract_unsigned_integer (buf, 8, byte_order); - cache->sof = cache->cfm & 0x7f; - - ia64_sigtramp_frame_init_saved_regs (this_frame, cache); - - *this_cache = cache; - return cache; -} - -static void -ia64_sigtramp_frame_this_id (const frame_info_ptr &this_frame, - void **this_cache, struct frame_id *this_id) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - struct ia64_frame_cache *cache = - ia64_sigtramp_frame_cache (this_frame, this_cache); - - (*this_id) = frame_id_build_special (cache->base, - get_frame_pc (this_frame), - cache->bsp); - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, - "sigtramp frame id: code %s, stack %s, " - "special %s, this_frame %s\n", - paddress (gdbarch, this_id->code_addr), - paddress (gdbarch, this_id->stack_addr), - paddress (gdbarch, cache->bsp), - host_address_to_string (this_frame.get ())); -} - -static struct value * -ia64_sigtramp_frame_prev_register (const frame_info_ptr &this_frame, - void **this_cache, int regnum) -{ - struct ia64_frame_cache *cache = - ia64_sigtramp_frame_cache (this_frame, this_cache); - - gdb_assert (regnum >= 0); - - if (!target_has_registers ()) - error (_("No registers.")); - - if (regnum == IA64_IP_REGNUM) - { - CORE_ADDR pc = 0; - CORE_ADDR addr = cache->saved_regs[IA64_VRAP_REGNUM]; - - if (addr != 0) - { - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - pc = read_memory_unsigned_integer (addr, 8, byte_order); - } - pc &= ~0xf; - return frame_unwind_got_constant (this_frame, regnum, pc); - } - - else if ((regnum >= IA64_GR32_REGNUM && regnum <= IA64_GR127_REGNUM) - || (regnum >= V32_REGNUM && regnum <= V127_REGNUM)) - { - CORE_ADDR addr = 0; - - if (regnum >= V32_REGNUM) - regnum = IA64_GR32_REGNUM + (regnum - V32_REGNUM); - addr = cache->saved_regs[regnum]; - if (addr != 0) - return frame_unwind_got_memory (this_frame, regnum, addr); - - return frame_unwind_got_constant (this_frame, regnum, 0); - } - - else /* All other registers not listed above. */ - { - CORE_ADDR addr = cache->saved_regs[regnum]; - - if (addr != 0) - return frame_unwind_got_memory (this_frame, regnum, addr); - - return frame_unwind_got_constant (this_frame, regnum, 0); - } -} - -static int -ia64_sigtramp_frame_sniffer (const struct frame_unwind *self, - const frame_info_ptr &this_frame, - void **this_cache) -{ - gdbarch *arch = get_frame_arch (this_frame); - ia64_gdbarch_tdep *tdep = gdbarch_tdep (arch); - if (tdep->pc_in_sigtramp) - { - CORE_ADDR pc = get_frame_pc (this_frame); - - if (tdep->pc_in_sigtramp (pc)) - return 1; - } - - return 0; -} - -static const struct frame_unwind ia64_sigtramp_frame_unwind = -{ - "ia64 sigtramp", - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - ia64_sigtramp_frame_this_id, - ia64_sigtramp_frame_prev_register, - NULL, - ia64_sigtramp_frame_sniffer -}; - - - -static CORE_ADDR -ia64_frame_base_address (const frame_info_ptr &this_frame, void **this_cache) -{ - struct ia64_frame_cache *cache = ia64_frame_cache (this_frame, this_cache); - - return cache->base; -} - -static const struct frame_base ia64_frame_base = -{ - &ia64_frame_unwind, - ia64_frame_base_address, - ia64_frame_base_address, - ia64_frame_base_address -}; - -#ifdef HAVE_LIBUNWIND_IA64_H - -struct ia64_unwind_table_entry - { - unw_word_t start_offset; - unw_word_t end_offset; - unw_word_t info_offset; - }; - -static __inline__ uint64_t -ia64_rse_slot_num (uint64_t addr) -{ - return (addr >> 3) & 0x3f; -} - -/* Skip over a designated number of registers in the backing - store, remembering every 64th position is for NAT. */ -static __inline__ uint64_t -ia64_rse_skip_regs (uint64_t addr, long num_regs) -{ - long delta = ia64_rse_slot_num(addr) + num_regs; - - if (num_regs < 0) - delta -= 0x3e; - return addr + ((num_regs + delta/0x3f) << 3); -} - -/* Gdb ia64-libunwind-tdep callback function to convert from an ia64 gdb - register number to a libunwind register number. */ -static int -ia64_gdb2uw_regnum (int regnum) -{ - if (regnum == sp_regnum) - return UNW_IA64_SP; - else if (regnum == IA64_BSP_REGNUM) - return UNW_IA64_BSP; - else if ((unsigned) (regnum - IA64_GR0_REGNUM) < 128) - return UNW_IA64_GR + (regnum - IA64_GR0_REGNUM); - else if ((unsigned) (regnum - V32_REGNUM) < 95) - return UNW_IA64_GR + 32 + (regnum - V32_REGNUM); - else if ((unsigned) (regnum - IA64_FR0_REGNUM) < 128) - return UNW_IA64_FR + (regnum - IA64_FR0_REGNUM); - else if ((unsigned) (regnum - IA64_PR0_REGNUM) < 64) - return -1; - else if ((unsigned) (regnum - IA64_BR0_REGNUM) < 8) - return UNW_IA64_BR + (regnum - IA64_BR0_REGNUM); - else if (regnum == IA64_PR_REGNUM) - return UNW_IA64_PR; - else if (regnum == IA64_IP_REGNUM) - return UNW_REG_IP; - else if (regnum == IA64_CFM_REGNUM) - return UNW_IA64_CFM; - else if ((unsigned) (regnum - IA64_AR0_REGNUM) < 128) - return UNW_IA64_AR + (regnum - IA64_AR0_REGNUM); - else if ((unsigned) (regnum - IA64_NAT0_REGNUM) < 128) - return UNW_IA64_NAT + (regnum - IA64_NAT0_REGNUM); - else - return -1; -} - -/* Gdb ia64-libunwind-tdep callback function to convert from a libunwind - register number to a ia64 gdb register number. */ -static int -ia64_uw2gdb_regnum (int uw_regnum) -{ - if (uw_regnum == UNW_IA64_SP) - return sp_regnum; - else if (uw_regnum == UNW_IA64_BSP) - return IA64_BSP_REGNUM; - else if ((unsigned) (uw_regnum - UNW_IA64_GR) < 32) - return IA64_GR0_REGNUM + (uw_regnum - UNW_IA64_GR); - else if ((unsigned) (uw_regnum - UNW_IA64_GR) < 128) - return V32_REGNUM + (uw_regnum - (IA64_GR0_REGNUM + 32)); - else if ((unsigned) (uw_regnum - UNW_IA64_FR) < 128) - return IA64_FR0_REGNUM + (uw_regnum - UNW_IA64_FR); - else if ((unsigned) (uw_regnum - UNW_IA64_BR) < 8) - return IA64_BR0_REGNUM + (uw_regnum - UNW_IA64_BR); - else if (uw_regnum == UNW_IA64_PR) - return IA64_PR_REGNUM; - else if (uw_regnum == UNW_REG_IP) - return IA64_IP_REGNUM; - else if (uw_regnum == UNW_IA64_CFM) - return IA64_CFM_REGNUM; - else if ((unsigned) (uw_regnum - UNW_IA64_AR) < 128) - return IA64_AR0_REGNUM + (uw_regnum - UNW_IA64_AR); - else if ((unsigned) (uw_regnum - UNW_IA64_NAT) < 128) - return IA64_NAT0_REGNUM + (uw_regnum - UNW_IA64_NAT); - else - return -1; -} - -/* Gdb ia64-libunwind-tdep callback function to reveal if register is - a float register or not. */ -static int -ia64_is_fpreg (int uw_regnum) -{ - return unw_is_fpreg (uw_regnum); -} - -/* Libunwind callback accessor function for general registers. */ -static int -ia64_access_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *val, - int write, void *arg) -{ - int regnum = ia64_uw2gdb_regnum (uw_regnum); - unw_word_t bsp, sof, cfm, psr, ip; - struct frame_info *this_frame = (frame_info *) arg; - struct gdbarch *gdbarch = get_frame_arch (this_frame); - ia64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* We never call any libunwind routines that need to write registers. */ - gdb_assert (!write); - - switch (uw_regnum) - { - case UNW_REG_IP: - /* Libunwind expects to see the pc value which means the slot number - from the psr must be merged with the ip word address. */ - ip = get_frame_register_unsigned (this_frame, IA64_IP_REGNUM); - psr = get_frame_register_unsigned (this_frame, IA64_PSR_REGNUM); - *val = ip | ((psr >> 41) & 0x3); - break; - - case UNW_IA64_AR_BSP: - /* Libunwind expects to see the beginning of the current - register frame so we must account for the fact that - ptrace() will return a value for bsp that points *after* - the current register frame. */ - bsp = get_frame_register_unsigned (this_frame, IA64_BSP_REGNUM); - cfm = get_frame_register_unsigned (this_frame, IA64_CFM_REGNUM); - sof = tdep->size_of_register_frame (this_frame, cfm); - *val = ia64_rse_skip_regs (bsp, -sof); - break; - - case UNW_IA64_AR_BSPSTORE: - /* Libunwind wants bspstore to be after the current register frame. - This is what ptrace() and gdb treats as the regular bsp value. */ - *val = get_frame_register_unsigned (this_frame, IA64_BSP_REGNUM); - break; - - default: - /* For all other registers, just unwind the value directly. */ - *val = get_frame_register_unsigned (this_frame, regnum); - break; - } - - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, - " access_reg: from cache: %4s=%s\n", - (((unsigned) regnum <= IA64_NAT127_REGNUM) - ? ia64_register_names[regnum] : "r??"), - paddress (gdbarch, *val)); - return 0; -} - -/* Libunwind callback accessor function for floating-point registers. */ -static int -ia64_access_fpreg (unw_addr_space_t as, unw_regnum_t uw_regnum, - unw_fpreg_t *val, int write, void *arg) -{ - int regnum = ia64_uw2gdb_regnum (uw_regnum); - frame_info_ptr this_frame = (const frame_info_ptr &) arg; - - /* We never call any libunwind routines that need to write registers. */ - gdb_assert (!write); - - get_frame_register (this_frame, regnum, (gdb_byte *) val); - - return 0; -} - -/* Libunwind callback accessor function for top-level rse registers. */ -static int -ia64_access_rse_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, - unw_word_t *val, int write, void *arg) -{ - int regnum = ia64_uw2gdb_regnum (uw_regnum); - unw_word_t bsp, sof, cfm, psr, ip; - struct regcache *regcache = (struct regcache *) arg; - struct gdbarch *gdbarch = regcache->arch (); - - /* We never call any libunwind routines that need to write registers. */ - gdb_assert (!write); - - switch (uw_regnum) - { - case UNW_REG_IP: - /* Libunwind expects to see the pc value which means the slot number - from the psr must be merged with the ip word address. */ - regcache_cooked_read_unsigned (regcache, IA64_IP_REGNUM, &ip); - regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr); - *val = ip | ((psr >> 41) & 0x3); - break; - - case UNW_IA64_AR_BSP: - /* Libunwind expects to see the beginning of the current - register frame so we must account for the fact that - ptrace() will return a value for bsp that points *after* - the current register frame. */ - regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp); - regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); - sof = (cfm & 0x7f); - *val = ia64_rse_skip_regs (bsp, -sof); - break; - - case UNW_IA64_AR_BSPSTORE: - /* Libunwind wants bspstore to be after the current register frame. - This is what ptrace() and gdb treats as the regular bsp value. */ - regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, val); - break; - - default: - /* For all other registers, just unwind the value directly. */ - regcache_cooked_read_unsigned (regcache, regnum, val); - break; - } - - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, - " access_rse_reg: from cache: %4s=%s\n", - (((unsigned) regnum <= IA64_NAT127_REGNUM) - ? ia64_register_names[regnum] : "r??"), - paddress (gdbarch, *val)); - - return 0; -} - -/* Libunwind callback accessor function for top-level fp registers. */ -static int -ia64_access_rse_fpreg (unw_addr_space_t as, unw_regnum_t uw_regnum, - unw_fpreg_t *val, int write, void *arg) -{ - int regnum = ia64_uw2gdb_regnum (uw_regnum); - struct regcache *regcache = (struct regcache *) arg; - - /* We never call any libunwind routines that need to write registers. */ - gdb_assert (!write); - - regcache->cooked_read (regnum, (gdb_byte *) val); - - return 0; -} - -/* Libunwind callback accessor function for accessing memory. */ -static int -ia64_access_mem (unw_addr_space_t as, - unw_word_t addr, unw_word_t *val, - int write, void *arg) -{ - if (addr - KERNEL_START < ktab_size) - { - unw_word_t *laddr = (unw_word_t*) ((char *) ktab - + (addr - KERNEL_START)); - - if (write) - *laddr = *val; - else - *val = *laddr; - return 0; - } - - /* XXX do we need to normalize byte-order here? */ - if (write) - return target_write_memory (addr, (gdb_byte *) val, sizeof (unw_word_t)); - else - return target_read_memory (addr, (gdb_byte *) val, sizeof (unw_word_t)); -} - -/* Call low-level function to access the kernel unwind table. */ -static std::optional -getunwind_table () -{ - /* FIXME drow/2005-09-10: This code used to call - ia64_linux_xfer_unwind_table directly to fetch the unwind table - for the currently running ia64-linux kernel. That data should - come from the core file and be accessed via the auxv vector; if - we want to preserve fall back to the running kernel's table, then - we should find a way to override the corefile layer's - xfer_partial method. */ - - return target_read_alloc (current_inferior ()->top_target (), - TARGET_OBJECT_UNWIND_TABLE, NULL); -} - -/* Get the kernel unwind table. */ -static int -get_kernel_table (unw_word_t ip, unw_dyn_info_t *di) -{ - static struct ia64_table_entry *etab; - - if (!ktab) - { - ktab_buf = getunwind_table (); - if (!ktab_buf) - return -UNW_ENOINFO; - - ktab = (struct ia64_table_entry *) ktab_buf->data (); - ktab_size = ktab_buf->size (); - - for (etab = ktab; etab->start_offset; ++etab) - etab->info_offset += KERNEL_START; - } - - if (ip < ktab[0].start_offset || ip >= etab[-1].end_offset) - return -UNW_ENOINFO; - - di->format = UNW_INFO_FORMAT_TABLE; - di->gp = 0; - di->start_ip = ktab[0].start_offset; - di->end_ip = etab[-1].end_offset; - di->u.ti.name_ptr = (unw_word_t) ""; - di->u.ti.segbase = 0; - di->u.ti.table_len = ((char *) etab - (char *) ktab) / sizeof (unw_word_t); - di->u.ti.table_data = (unw_word_t *) ktab; - - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, "get_kernel_table: found table `%s': " - "segbase=%s, length=%s, gp=%s\n", - (char *) di->u.ti.name_ptr, - hex_string (di->u.ti.segbase), - pulongest (di->u.ti.table_len), - hex_string (di->gp)); - return 0; -} - -/* Find the unwind table entry for a specified address. */ -static int -ia64_find_unwind_table (struct objfile *objfile, unw_word_t ip, - unw_dyn_info_t *dip, void **buf) -{ - Elf_Internal_Phdr *phdr, *p_text = NULL, *p_unwind = NULL; - Elf_Internal_Ehdr *ehdr; - unw_word_t segbase = 0; - CORE_ADDR load_base; - bfd *bfd; - int i; - - bfd = objfile->obfd; - - ehdr = elf_tdata (bfd)->elf_header; - phdr = elf_tdata (bfd)->phdr; - - load_base = objfile->text_section_offset (); - - for (i = 0; i < ehdr->e_phnum; ++i) - { - switch (phdr[i].p_type) - { - case PT_LOAD: - if ((unw_word_t) (ip - load_base - phdr[i].p_vaddr) - < phdr[i].p_memsz) - p_text = phdr + i; - break; - - case PT_IA_64_UNWIND: - p_unwind = phdr + i; - break; - - default: - break; - } - } - - if (!p_text || !p_unwind) - return -UNW_ENOINFO; - - /* Verify that the segment that contains the IP also contains - the static unwind table. If not, we may be in the Linux kernel's - DSO gate page in which case the unwind table is another segment. - Otherwise, we are dealing with runtime-generated code, for which we - have no info here. */ - segbase = p_text->p_vaddr + load_base; - - if ((p_unwind->p_vaddr - p_text->p_vaddr) >= p_text->p_memsz) - { - int ok = 0; - for (i = 0; i < ehdr->e_phnum; ++i) - { - if (phdr[i].p_type == PT_LOAD - && (p_unwind->p_vaddr - phdr[i].p_vaddr) < phdr[i].p_memsz) - { - ok = 1; - /* Get the segbase from the section containing the - libunwind table. */ - segbase = phdr[i].p_vaddr + load_base; - } - } - if (!ok) - return -UNW_ENOINFO; - } - - dip->start_ip = p_text->p_vaddr + load_base; - dip->end_ip = dip->start_ip + p_text->p_memsz; - dip->gp = ia64_find_global_pointer (objfile->arch (), ip); - dip->format = UNW_INFO_FORMAT_REMOTE_TABLE; - dip->u.rti.name_ptr = (unw_word_t) bfd_get_filename (bfd); - dip->u.rti.segbase = segbase; - dip->u.rti.table_len = p_unwind->p_memsz / sizeof (unw_word_t); - dip->u.rti.table_data = p_unwind->p_vaddr + load_base; - - return 0; -} - -/* Libunwind callback accessor function to acquire procedure unwind-info. */ -static int -ia64_find_proc_info_x (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - struct obj_section *sec = find_pc_section (ip); - unw_dyn_info_t di; - int ret; - void *buf = NULL; - - if (!sec) - { - /* XXX This only works if the host and the target architecture are - both ia64 and if the have (more or less) the same kernel - version. */ - if (get_kernel_table (ip, &di) < 0) - return -UNW_ENOINFO; - - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, "ia64_find_proc_info_x: %s -> " - "(name=`%s',segbase=%s,start=%s,end=%s,gp=%s," - "length=%s,data=%s)\n", - hex_string (ip), (char *)di.u.ti.name_ptr, - hex_string (di.u.ti.segbase), - hex_string (di.start_ip), hex_string (di.end_ip), - hex_string (di.gp), - pulongest (di.u.ti.table_len), - hex_string ((CORE_ADDR)di.u.ti.table_data)); - } - else - { - ret = ia64_find_unwind_table (sec->objfile, ip, &di, &buf); - if (ret < 0) - return ret; - - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, "ia64_find_proc_info_x: %s -> " - "(name=`%s',segbase=%s,start=%s,end=%s,gp=%s," - "length=%s,data=%s)\n", - hex_string (ip), (char *)di.u.rti.name_ptr, - hex_string (di.u.rti.segbase), - hex_string (di.start_ip), hex_string (di.end_ip), - hex_string (di.gp), - pulongest (di.u.rti.table_len), - hex_string (di.u.rti.table_data)); - } - - ret = libunwind_search_unwind_table (&as, ip, &di, pi, need_unwind_info, - arg); - - /* We no longer need the dyn info storage so free it. */ - xfree (buf); - - return ret; -} - -/* Libunwind callback accessor function for cleanup. */ -static void -ia64_put_unwind_info (unw_addr_space_t as, - unw_proc_info_t *pip, void *arg) -{ - /* Nothing required for now. */ -} - -/* Libunwind callback accessor function to get head of the dynamic - unwind-info registration list. */ -static int -ia64_get_dyn_info_list (unw_addr_space_t as, - unw_word_t *dilap, void *arg) -{ - struct obj_section *text_sec; - unw_word_t ip, addr; - unw_dyn_info_t di; - int ret; - - if (!libunwind_is_initialized ()) - return -UNW_ENOINFO; - - for (objfile *objfile : current_program_space->objfiles ()) - { - void *buf = NULL; - - text_sec = objfile->sections + SECT_OFF_TEXT (objfile); - ip = text_sec->addr (); - ret = ia64_find_unwind_table (objfile, ip, &di, &buf); - if (ret >= 0) - { - addr = libunwind_find_dyn_list (as, &di, arg); - /* We no longer need the dyn info storage so free it. */ - xfree (buf); - - if (addr) - { - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, - "dynamic unwind table in objfile %s " - "at %s (gp=%s)\n", - bfd_get_filename (objfile->obfd), - hex_string (addr), hex_string (di.gp)); - *dilap = addr; - return 0; - } - } - } - return -UNW_ENOINFO; -} - - -/* Frame interface functions for libunwind. */ - -static void -ia64_libunwind_frame_this_id (const frame_info_ptr &this_frame, void **this_cache, - struct frame_id *this_id) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct frame_id id = outer_frame_id; - gdb_byte buf[8]; - CORE_ADDR bsp; - - libunwind_frame_this_id (this_frame, this_cache, &id); - if (id == outer_frame_id) - { - (*this_id) = outer_frame_id; - return; - } - - /* We must add the bsp as the special address for frame comparison - purposes. */ - get_frame_register (this_frame, IA64_BSP_REGNUM, buf); - bsp = extract_unsigned_integer (buf, 8, byte_order); - - (*this_id) = frame_id_build_special (id.stack_addr, id.code_addr, bsp); - - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, - "libunwind frame id: code %s, stack %s, " - "special %s, this_frame %s\n", - paddress (gdbarch, id.code_addr), - paddress (gdbarch, id.stack_addr), - paddress (gdbarch, bsp), - host_address_to_string (this_frame)); -} - -static struct value * -ia64_libunwind_frame_prev_register (const frame_info_ptr &this_frame, - void **this_cache, int regnum) -{ - int reg = regnum; - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct value *val; - - if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) - reg = IA64_PR_REGNUM; - else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) - reg = IA64_UNAT_REGNUM; - - /* Let libunwind do most of the work. */ - val = libunwind_frame_prev_register (this_frame, this_cache, reg); - - if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) - { - ULONGEST prN_val; - - if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM) - { - int rrb_pr = 0; - ULONGEST cfm; - - /* Fetch predicate register rename base from current frame - marker for this frame. */ - cfm = get_frame_register_unsigned (this_frame, IA64_CFM_REGNUM); - rrb_pr = (cfm >> 32) & 0x3f; - - /* Adjust the register number to account for register rotation. */ - regnum = VP16_REGNUM + ((regnum - VP16_REGNUM) + rrb_pr) % 48; - } - prN_val = extract_bit_field (val->contents_all ().data (), - regnum - VP0_REGNUM, 1); - return frame_unwind_got_constant (this_frame, regnum, prN_val); - } - - else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) - { - ULONGEST unatN_val; - - unatN_val = extract_bit_field (val->contents_all ().data (), - regnum - IA64_NAT0_REGNUM, 1); - return frame_unwind_got_constant (this_frame, regnum, unatN_val); - } - - else if (regnum == IA64_BSP_REGNUM) - { - struct value *cfm_val; - CORE_ADDR prev_bsp, prev_cfm; - - /* We want to calculate the previous bsp as the end of the previous - register stack frame. This corresponds to what the hardware bsp - register will be if we pop the frame back which is why we might - have been called. We know that libunwind will pass us back the - beginning of the current frame so we should just add sof to it. */ - prev_bsp = extract_unsigned_integer (val->contents_all ().data (), - 8, byte_order); - cfm_val = libunwind_frame_prev_register (this_frame, this_cache, - IA64_CFM_REGNUM); - prev_cfm = extract_unsigned_integer (cfm_val->contents_all ().data (), - 8, byte_order); - prev_bsp = rse_address_add (prev_bsp, (prev_cfm & 0x7f)); - - return frame_unwind_got_constant (this_frame, regnum, prev_bsp); - } - else - return val; -} - -static int -ia64_libunwind_frame_sniffer (const struct frame_unwind *self, - const frame_info_ptr &this_frame, - void **this_cache) -{ - if (libunwind_is_initialized () - && libunwind_frame_sniffer (self, this_frame, this_cache)) - return 1; - - return 0; -} - -static const struct frame_unwind ia64_libunwind_frame_unwind = -{ - "ia64 libunwind", - NORMAL_FRAME, - default_frame_unwind_stop_reason, - ia64_libunwind_frame_this_id, - ia64_libunwind_frame_prev_register, - NULL, - ia64_libunwind_frame_sniffer, - libunwind_frame_dealloc_cache -}; - -static void -ia64_libunwind_sigtramp_frame_this_id (const frame_info_ptr &this_frame, - void **this_cache, - struct frame_id *this_id) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[8]; - CORE_ADDR bsp; - struct frame_id id = outer_frame_id; - - libunwind_frame_this_id (this_frame, this_cache, &id); - if (id == outer_frame_id) - { - (*this_id) = outer_frame_id; - return; - } - - /* We must add the bsp as the special address for frame comparison - purposes. */ - get_frame_register (this_frame, IA64_BSP_REGNUM, buf); - bsp = extract_unsigned_integer (buf, 8, byte_order); - - /* For a sigtramp frame, we don't make the check for previous ip being 0. */ - (*this_id) = frame_id_build_special (id.stack_addr, id.code_addr, bsp); - - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, - "libunwind sigtramp frame id: code %s, " - "stack %s, special %s, this_frame %s\n", - paddress (gdbarch, id.code_addr), - paddress (gdbarch, id.stack_addr), - paddress (gdbarch, bsp), - host_address_to_string (this_frame)); -} - -static struct value * -ia64_libunwind_sigtramp_frame_prev_register (const frame_info_ptr &this_frame, - void **this_cache, int regnum) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct value *prev_ip_val; - CORE_ADDR prev_ip; - - /* If the previous frame pc value is 0, then we want to use the SIGCONTEXT - method of getting previous registers. */ - prev_ip_val = libunwind_frame_prev_register (this_frame, this_cache, - IA64_IP_REGNUM); - prev_ip = extract_unsigned_integer (prev_ip_val->contents_all ().data (), - 8, byte_order); - - if (prev_ip == 0) - { - void *tmp_cache = NULL; - return ia64_sigtramp_frame_prev_register (this_frame, &tmp_cache, - regnum); - } - else - return ia64_libunwind_frame_prev_register (this_frame, this_cache, regnum); -} - -static int -ia64_libunwind_sigtramp_frame_sniffer (const struct frame_unwind *self, - const frame_info_ptr &this_frame, - void **this_cache) -{ - if (libunwind_is_initialized ()) - { - if (libunwind_sigtramp_frame_sniffer (self, this_frame, this_cache)) - return 1; - return 0; - } - else - return ia64_sigtramp_frame_sniffer (self, this_frame, this_cache); -} - -static const struct frame_unwind ia64_libunwind_sigtramp_frame_unwind = -{ - "ia64 libunwind sigtramp", - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - ia64_libunwind_sigtramp_frame_this_id, - ia64_libunwind_sigtramp_frame_prev_register, - NULL, - ia64_libunwind_sigtramp_frame_sniffer -}; - -/* Set of libunwind callback acccessor functions. */ -unw_accessors_t ia64_unw_accessors = -{ - ia64_find_proc_info_x, - ia64_put_unwind_info, - ia64_get_dyn_info_list, - ia64_access_mem, - ia64_access_reg, - ia64_access_fpreg, - /* resume */ - /* get_proc_name */ -}; - -/* Set of special libunwind callback acccessor functions specific for accessing - the rse registers. At the top of the stack, we want libunwind to figure out - how to read r32 - r127. Though usually they are found sequentially in - memory starting from $bof, this is not always true. */ -unw_accessors_t ia64_unw_rse_accessors = -{ - ia64_find_proc_info_x, - ia64_put_unwind_info, - ia64_get_dyn_info_list, - ia64_access_mem, - ia64_access_rse_reg, - ia64_access_rse_fpreg, - /* resume */ - /* get_proc_name */ -}; - -/* Set of ia64-libunwind-tdep gdb callbacks and data for generic - ia64-libunwind-tdep code to use. */ -struct libunwind_descr ia64_libunwind_descr = -{ - ia64_gdb2uw_regnum, - ia64_uw2gdb_regnum, - ia64_is_fpreg, - &ia64_unw_accessors, - &ia64_unw_rse_accessors, -}; - -#endif /* HAVE_LIBUNWIND_IA64_H */ - -static int -ia64_use_struct_convention (struct type *type) -{ - struct type *float_elt_type; - - /* Don't use the struct convention for anything but structure, - union, or array types. */ - if (!(type->code () == TYPE_CODE_STRUCT - || type->code () == TYPE_CODE_UNION - || type->code () == TYPE_CODE_ARRAY)) - return 0; - - /* HFAs are structures (or arrays) consisting entirely of floating - point values of the same length. Up to 8 of these are returned - in registers. Don't use the struct convention when this is the - case. */ - float_elt_type = is_float_or_hfa_type (type); - if (float_elt_type != NULL - && type->length () / float_elt_type->length () <= 8) - return 0; - - /* Other structs of length 32 or less are returned in r8-r11. - Don't use the struct convention for those either. */ - return type->length () > 32; -} - -/* Return non-zero if TYPE is a structure or union type. */ - -static int -ia64_struct_type_p (const struct type *type) -{ - return (type->code () == TYPE_CODE_STRUCT - || type->code () == TYPE_CODE_UNION); -} - -static void -ia64_extract_return_value (struct type *type, struct regcache *regcache, - gdb_byte *valbuf) -{ - struct gdbarch *gdbarch = regcache->arch (); - struct type *float_elt_type; - - float_elt_type = is_float_or_hfa_type (type); - if (float_elt_type != NULL) - { - gdb_byte from[IA64_FP_REGISTER_SIZE]; - int offset = 0; - int regnum = IA64_FR8_REGNUM; - int n = type->length () / float_elt_type->length (); - - while (n-- > 0) - { - regcache->cooked_read (regnum, from); - target_float_convert (from, ia64_ext_type (gdbarch), - valbuf + offset, float_elt_type); - offset += float_elt_type->length (); - regnum++; - } - } - else if (!ia64_struct_type_p (type) && type->length () < 8) - { - /* This is an integral value, and its size is less than 8 bytes. - These values are LSB-aligned, so extract the relevant bytes, - and copy them into VALBUF. */ - /* brobecker/2005-12-30: Actually, all integral values are LSB aligned, - so I suppose we should also add handling here for integral values - whose size is greater than 8. But I wasn't able to create such - a type, neither in C nor in Ada, so not worrying about these yet. */ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - ULONGEST val; - - regcache_cooked_read_unsigned (regcache, IA64_GR8_REGNUM, &val); - store_unsigned_integer (valbuf, type->length (), byte_order, val); - } - else - { - ULONGEST val; - int offset = 0; - int regnum = IA64_GR8_REGNUM; - int reglen = register_type (gdbarch, IA64_GR8_REGNUM)->length (); - int n = type->length () / reglen; - int m = type->length () % reglen; - - while (n-- > 0) - { - ULONGEST regval; - regcache_cooked_read_unsigned (regcache, regnum, ®val); - memcpy ((char *)valbuf + offset, ®val, reglen); - offset += reglen; - regnum++; - } - - if (m) - { - regcache_cooked_read_unsigned (regcache, regnum, &val); - memcpy ((char *)valbuf + offset, &val, m); - } - } -} - -static void -ia64_store_return_value (struct type *type, struct regcache *regcache, - const gdb_byte *valbuf) -{ - struct gdbarch *gdbarch = regcache->arch (); - struct type *float_elt_type; - - float_elt_type = is_float_or_hfa_type (type); - if (float_elt_type != NULL) - { - gdb_byte to[IA64_FP_REGISTER_SIZE]; - int offset = 0; - int regnum = IA64_FR8_REGNUM; - int n = type->length () / float_elt_type->length (); - - while (n-- > 0) - { - target_float_convert (valbuf + offset, float_elt_type, - to, ia64_ext_type (gdbarch)); - regcache->cooked_write (regnum, to); - offset += float_elt_type->length (); - regnum++; - } - } - else - { - int offset = 0; - int regnum = IA64_GR8_REGNUM; - int reglen = register_type (gdbarch, IA64_GR8_REGNUM)->length (); - int n = type->length () / reglen; - int m = type->length () % reglen; - - while (n-- > 0) - { - ULONGEST val; - memcpy (&val, (char *)valbuf + offset, reglen); - regcache_cooked_write_unsigned (regcache, regnum, val); - offset += reglen; - regnum++; - } - - if (m) - { - ULONGEST val; - memcpy (&val, (char *)valbuf + offset, m); - regcache_cooked_write_unsigned (regcache, regnum, val); - } - } -} - -static enum return_value_convention -ia64_return_value (struct gdbarch *gdbarch, struct value *function, - struct type *valtype, struct regcache *regcache, - gdb_byte *readbuf, const gdb_byte *writebuf) -{ - int struct_return = ia64_use_struct_convention (valtype); - - if (writebuf != NULL) - { - gdb_assert (!struct_return); - ia64_store_return_value (valtype, regcache, writebuf); - } - - if (readbuf != NULL) - { - gdb_assert (!struct_return); - ia64_extract_return_value (valtype, regcache, readbuf); - } - - if (struct_return) - return RETURN_VALUE_STRUCT_CONVENTION; - else - return RETURN_VALUE_REGISTER_CONVENTION; -} - -static int -is_float_or_hfa_type_recurse (struct type *t, struct type **etp) -{ - switch (t->code ()) - { - case TYPE_CODE_FLT: - if (*etp) - return (*etp)->length () == t->length (); - else - { - *etp = t; - return 1; - } - break; - case TYPE_CODE_ARRAY: - return - is_float_or_hfa_type_recurse (check_typedef (t->target_type ()), - etp); - break; - case TYPE_CODE_STRUCT: - { - int i; - - for (i = 0; i < t->num_fields (); i++) - if (!is_float_or_hfa_type_recurse - (check_typedef (t->field (i).type ()), etp)) - return 0; - return 1; - } - break; - default: - break; - } - - return 0; -} - -/* Determine if the given type is one of the floating point types or - and HFA (which is a struct, array, or combination thereof whose - bottom-most elements are all of the same floating point type). */ - -static struct type * -is_float_or_hfa_type (struct type *t) -{ - struct type *et = 0; - - return is_float_or_hfa_type_recurse (t, &et) ? et : 0; -} - - -/* Return 1 if the alignment of T is such that the next even slot - should be used. Return 0, if the next available slot should - be used. (See section 8.5.1 of the IA-64 Software Conventions - and Runtime manual). */ - -static int -slot_alignment_is_next_even (struct type *t) -{ - switch (t->code ()) - { - case TYPE_CODE_INT: - case TYPE_CODE_FLT: - if (t->length () > 8) - return 1; - else - return 0; - case TYPE_CODE_ARRAY: - return - slot_alignment_is_next_even (check_typedef (t->target_type ())); - case TYPE_CODE_STRUCT: - { - int i; - - for (i = 0; i < t->num_fields (); i++) - if (slot_alignment_is_next_even - (check_typedef (t->field (i).type ()))) - return 1; - return 0; - } - default: - return 0; - } -} - -/* Attempt to find (and return) the global pointer for the given - function. - - This is a rather nasty bit of code searchs for the .dynamic section - in the objfile corresponding to the pc of the function we're trying - to call. Once it finds the addresses at which the .dynamic section - lives in the child process, it scans the Elf64_Dyn entries for a - DT_PLTGOT tag. If it finds one of these, the corresponding - d_un.d_ptr value is the global pointer. */ - -static CORE_ADDR -ia64_find_global_pointer_from_dynamic_section (struct gdbarch *gdbarch, - CORE_ADDR faddr) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct obj_section *faddr_sect; - - faddr_sect = find_pc_section (faddr); - if (faddr_sect != NULL) - { - for (obj_section *osect : faddr_sect->objfile->sections ()) - { - if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0) - { - CORE_ADDR addr = osect->addr (); - CORE_ADDR endaddr = osect->endaddr (); - - while (addr < endaddr) - { - int status; - LONGEST tag; - gdb_byte buf[8]; - - status = target_read_memory (addr, buf, sizeof (buf)); - if (status != 0) - break; - tag = extract_signed_integer (buf, byte_order); - - if (tag == DT_PLTGOT) - { - CORE_ADDR global_pointer; - - status = target_read_memory (addr + 8, buf, - sizeof (buf)); - if (status != 0) - break; - global_pointer - = extract_unsigned_integer (buf, sizeof (buf), - byte_order); - - /* The payoff... */ - return global_pointer; - } - - if (tag == DT_NULL) - break; - - addr += 16; - } - - break; - } - } - } - return 0; -} - -/* Attempt to find (and return) the global pointer for the given - function. We first try the find_global_pointer_from_solib routine - from the gdbarch tdep vector, if provided. And if that does not - work, then we try ia64_find_global_pointer_from_dynamic_section. */ - -static CORE_ADDR -ia64_find_global_pointer (struct gdbarch *gdbarch, CORE_ADDR faddr) -{ - ia64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - CORE_ADDR addr = 0; - - if (tdep->find_global_pointer_from_solib) - addr = tdep->find_global_pointer_from_solib (gdbarch, faddr); - if (addr == 0) - addr = ia64_find_global_pointer_from_dynamic_section (gdbarch, faddr); - return addr; -} - -/* Given a function's address, attempt to find (and return) the - corresponding (canonical) function descriptor. Return 0 if - not found. */ -static CORE_ADDR -find_extant_func_descr (struct gdbarch *gdbarch, CORE_ADDR faddr) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct obj_section *faddr_sect; - - /* Return early if faddr is already a function descriptor. */ - faddr_sect = find_pc_section (faddr); - if (faddr_sect && strcmp (faddr_sect->the_bfd_section->name, ".opd") == 0) - return faddr; - - if (faddr_sect != NULL) - { - for (obj_section *osect : faddr_sect->objfile->sections ()) - { - if (strcmp (osect->the_bfd_section->name, ".opd") == 0) - { - CORE_ADDR addr = osect->addr (); - CORE_ADDR endaddr = osect->endaddr (); - - while (addr < endaddr) - { - int status; - LONGEST faddr2; - gdb_byte buf[8]; - - status = target_read_memory (addr, buf, sizeof (buf)); - if (status != 0) - break; - faddr2 = extract_signed_integer (buf, byte_order); - - if (faddr == faddr2) - return addr; - - addr += 16; - } - - break; - } - } - } - return 0; -} - -/* Attempt to find a function descriptor corresponding to the - given address. If none is found, construct one on the - stack using the address at fdaptr. */ - -static CORE_ADDR -find_func_descr (struct regcache *regcache, CORE_ADDR faddr, CORE_ADDR *fdaptr) -{ - struct gdbarch *gdbarch = regcache->arch (); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR fdesc; - - fdesc = find_extant_func_descr (gdbarch, faddr); - - if (fdesc == 0) - { - ULONGEST global_pointer; - gdb_byte buf[16]; - - fdesc = *fdaptr; - *fdaptr += 16; - - global_pointer = ia64_find_global_pointer (gdbarch, faddr); - - if (global_pointer == 0) - regcache_cooked_read_unsigned (regcache, - IA64_GR1_REGNUM, &global_pointer); - - store_unsigned_integer (buf, 8, byte_order, faddr); - store_unsigned_integer (buf + 8, 8, byte_order, global_pointer); - - write_memory (fdesc, buf, 16); - } - - return fdesc; -} - -/* Use the following routine when printing out function pointers - so the user can see the function address rather than just the - function descriptor. */ -static CORE_ADDR -ia64_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr, - struct target_ops *targ) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct obj_section *s; - gdb_byte buf[8]; - - s = find_pc_section (addr); - - /* check if ADDR points to a function descriptor. */ - if (s && strcmp (s->the_bfd_section->name, ".opd") == 0) - return read_memory_unsigned_integer (addr, 8, byte_order); - - /* Normally, functions live inside a section that is executable. - So, if ADDR points to a non-executable section, then treat it - as a function descriptor and return the target address iff - the target address itself points to a section that is executable. - Check first the memory of the whole length of 8 bytes is readable. */ - if (s && (s->the_bfd_section->flags & SEC_CODE) == 0 - && target_read_memory (addr, buf, 8) == 0) - { - CORE_ADDR pc = extract_unsigned_integer (buf, 8, byte_order); - struct obj_section *pc_section = find_pc_section (pc); - - if (pc_section && (pc_section->the_bfd_section->flags & SEC_CODE)) - return pc; - } - - /* There are also descriptors embedded in vtables. */ - if (s) - { - struct bound_minimal_symbol minsym; - - minsym = lookup_minimal_symbol_by_pc (addr); - - if (minsym.minsym - && is_vtable_name (minsym.minsym->linkage_name ())) - return read_memory_unsigned_integer (addr, 8, byte_order); - } - - return addr; -} - -static CORE_ADDR -ia64_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) -{ - return sp & ~0xfLL; -} - -/* The default "allocate_new_rse_frame" ia64_infcall_ops routine for ia64. */ - -static void -ia64_allocate_new_rse_frame (struct regcache *regcache, ULONGEST bsp, int sof) -{ - ULONGEST cfm, pfs, new_bsp; - - regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); - - new_bsp = rse_address_add (bsp, sof); - regcache_cooked_write_unsigned (regcache, IA64_BSP_REGNUM, new_bsp); - - regcache_cooked_read_unsigned (regcache, IA64_PFS_REGNUM, &pfs); - pfs &= 0xc000000000000000LL; - pfs |= (cfm & 0xffffffffffffLL); - regcache_cooked_write_unsigned (regcache, IA64_PFS_REGNUM, pfs); - - cfm &= 0xc000000000000000LL; - cfm |= sof; - regcache_cooked_write_unsigned (regcache, IA64_CFM_REGNUM, cfm); -} - -/* The default "store_argument_in_slot" ia64_infcall_ops routine for - ia64. */ - -static void -ia64_store_argument_in_slot (struct regcache *regcache, CORE_ADDR bsp, - int slotnum, gdb_byte *buf) -{ - write_memory (rse_address_add (bsp, slotnum), buf, 8); -} - -/* The default "set_function_addr" ia64_infcall_ops routine for ia64. */ - -static void -ia64_set_function_addr (struct regcache *regcache, CORE_ADDR func_addr) -{ - /* Nothing needed. */ -} - -static CORE_ADDR -ia64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, - struct regcache *regcache, CORE_ADDR bp_addr, - int nargs, struct value **args, CORE_ADDR sp, - function_call_return_method return_method, - CORE_ADDR struct_addr) -{ - ia64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - int argno; - struct value *arg; - struct type *type; - int len, argoffset; - int nslots, rseslots, memslots, slotnum, nfuncargs; - int floatreg; - ULONGEST bsp; - CORE_ADDR funcdescaddr, global_pointer; - CORE_ADDR func_addr = find_function_addr (function, NULL); - - nslots = 0; - nfuncargs = 0; - /* Count the number of slots needed for the arguments. */ - for (argno = 0; argno < nargs; argno++) - { - arg = args[argno]; - type = check_typedef (arg->type ()); - len = type->length (); - - if ((nslots & 1) && slot_alignment_is_next_even (type)) - nslots++; - - if (type->code () == TYPE_CODE_FUNC) - nfuncargs++; - - nslots += (len + 7) / 8; - } - - /* Divvy up the slots between the RSE and the memory stack. */ - rseslots = (nslots > 8) ? 8 : nslots; - memslots = nslots - rseslots; - - /* Allocate a new RSE frame. */ - regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp); - tdep->infcall_ops.allocate_new_rse_frame (regcache, bsp, rseslots); - - /* We will attempt to find function descriptors in the .opd segment, - but if we can't we'll construct them ourselves. That being the - case, we'll need to reserve space on the stack for them. */ - funcdescaddr = sp - nfuncargs * 16; - funcdescaddr &= ~0xfLL; - - /* Adjust the stack pointer to it's new value. The calling conventions - require us to have 16 bytes of scratch, plus whatever space is - necessary for the memory slots and our function descriptors. */ - sp = sp - 16 - (memslots + nfuncargs) * 8; - sp &= ~0xfLL; /* Maintain 16 byte alignment. */ - - /* Place the arguments where they belong. The arguments will be - either placed in the RSE backing store or on the memory stack. - In addition, floating point arguments or HFAs are placed in - floating point registers. */ - slotnum = 0; - floatreg = IA64_FR8_REGNUM; - for (argno = 0; argno < nargs; argno++) - { - struct type *float_elt_type; - - arg = args[argno]; - type = check_typedef (arg->type ()); - len = type->length (); - - /* Special handling for function parameters. */ - if (len == 8 - && type->code () == TYPE_CODE_PTR - && type->target_type ()->code () == TYPE_CODE_FUNC) - { - gdb_byte val_buf[8]; - ULONGEST faddr = extract_unsigned_integer - (arg->contents ().data (), 8, byte_order); - store_unsigned_integer (val_buf, 8, byte_order, - find_func_descr (regcache, faddr, - &funcdescaddr)); - if (slotnum < rseslots) - tdep->infcall_ops.store_argument_in_slot (regcache, bsp, - slotnum, val_buf); - else - write_memory (sp + 16 + 8 * (slotnum - rseslots), val_buf, 8); - slotnum++; - continue; - } - - /* Normal slots. */ - - /* Skip odd slot if necessary... */ - if ((slotnum & 1) && slot_alignment_is_next_even (type)) - slotnum++; - - argoffset = 0; - while (len > 0) - { - gdb_byte val_buf[8]; - - memset (val_buf, 0, 8); - if (!ia64_struct_type_p (type) && len < 8) - { - /* Integral types are LSB-aligned, so we have to be careful - to insert the argument on the correct side of the buffer. - This is why we use store_unsigned_integer. */ - store_unsigned_integer - (val_buf, 8, byte_order, - extract_unsigned_integer (arg->contents ().data (), len, - byte_order)); - } - else - { - /* This is either an 8bit integral type, or an aggregate. - For 8bit integral type, there is no problem, we just - copy the value over. - - For aggregates, the only potentially tricky portion - is to write the last one if it is less than 8 bytes. - In this case, the data is Byte0-aligned. Happy news, - this means that we don't need to differentiate the - handling of 8byte blocks and less-than-8bytes blocks. */ - memcpy (val_buf, arg->contents ().data () + argoffset, - (len > 8) ? 8 : len); - } - - if (slotnum < rseslots) - tdep->infcall_ops.store_argument_in_slot (regcache, bsp, - slotnum, val_buf); - else - write_memory (sp + 16 + 8 * (slotnum - rseslots), val_buf, 8); - - argoffset += 8; - len -= 8; - slotnum++; - } - - /* Handle floating point types (including HFAs). */ - float_elt_type = is_float_or_hfa_type (type); - if (float_elt_type != NULL) - { - argoffset = 0; - len = type->length (); - while (len > 0 && floatreg < IA64_FR16_REGNUM) - { - gdb_byte to[IA64_FP_REGISTER_SIZE]; - target_float_convert (arg->contents ().data () + argoffset, - float_elt_type, to, - ia64_ext_type (gdbarch)); - regcache->cooked_write (floatreg, to); - floatreg++; - argoffset += float_elt_type->length (); - len -= float_elt_type->length (); - } - } - } - - /* Store the struct return value in r8 if necessary. */ - if (return_method == return_method_struct) - regcache_cooked_write_unsigned (regcache, IA64_GR8_REGNUM, - (ULONGEST) struct_addr); - - global_pointer = ia64_find_global_pointer (gdbarch, func_addr); - - if (global_pointer != 0) - regcache_cooked_write_unsigned (regcache, IA64_GR1_REGNUM, global_pointer); - - /* The following is not necessary on HP-UX, because we're using - a dummy code sequence pushed on the stack to make the call, and - this sequence doesn't need b0 to be set in order for our dummy - breakpoint to be hit. Nonetheless, this doesn't interfere, and - it's needed for other OSes, so we do this unconditionaly. */ - regcache_cooked_write_unsigned (regcache, IA64_BR0_REGNUM, bp_addr); - - regcache_cooked_write_unsigned (regcache, sp_regnum, sp); - - tdep->infcall_ops.set_function_addr (regcache, func_addr); - - return sp; -} - -static const struct ia64_infcall_ops ia64_infcall_ops = -{ - ia64_allocate_new_rse_frame, - ia64_store_argument_in_slot, - ia64_set_function_addr -}; - -static struct frame_id -ia64_dummy_id (struct gdbarch *gdbarch, const frame_info_ptr &this_frame) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[8]; - CORE_ADDR sp, bsp; - - get_frame_register (this_frame, sp_regnum, buf); - sp = extract_unsigned_integer (buf, 8, byte_order); - - get_frame_register (this_frame, IA64_BSP_REGNUM, buf); - bsp = extract_unsigned_integer (buf, 8, byte_order); - - if (gdbarch_debug >= 1) - gdb_printf (gdb_stdlog, - "dummy frame id: code %s, stack %s, special %s\n", - paddress (gdbarch, get_frame_pc (this_frame)), - paddress (gdbarch, sp), paddress (gdbarch, bsp)); - - return frame_id_build_special (sp, get_frame_pc (this_frame), bsp); -} - -static CORE_ADDR -ia64_unwind_pc (struct gdbarch *gdbarch, const frame_info_ptr &next_frame) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[8]; - CORE_ADDR ip, psr, pc; - - frame_unwind_register (next_frame, IA64_IP_REGNUM, buf); - ip = extract_unsigned_integer (buf, 8, byte_order); - frame_unwind_register (next_frame, IA64_PSR_REGNUM, buf); - psr = extract_unsigned_integer (buf, 8, byte_order); - - pc = (ip & ~0xf) | ((psr >> 41) & 3); - return pc; -} - -static int -ia64_print_insn (bfd_vma memaddr, struct disassemble_info *info) -{ - info->bytes_per_line = SLOT_MULTIPLIER; - return default_print_insn (memaddr, info); -} - -/* The default "size_of_register_frame" gdbarch_tdep routine for ia64. */ - -static int -ia64_size_of_register_frame (const frame_info_ptr &this_frame, ULONGEST cfm) -{ - return (cfm & 0x7f); -} - -static struct gdbarch * -ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) -{ - /* If there is already a candidate, use it. */ - arches = gdbarch_list_lookup_by_info (arches, &info); - if (arches != NULL) - return arches->gdbarch; - - gdbarch *gdbarch - = gdbarch_alloc (&info, gdbarch_tdep_up (new ia64_gdbarch_tdep)); - ia64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - tdep->size_of_register_frame = ia64_size_of_register_frame; - - /* According to the ia64 specs, instructions that store long double - floats in memory use a long-double format different than that - used in the floating registers. The memory format matches the - x86 extended float format which is 80 bits. An OS may choose to - use this format (e.g. GNU/Linux) or choose to use a different - format for storing long doubles (e.g. HPUX). In the latter case, - the setting of the format may be moved/overridden in an - OS-specific tdep file. */ - set_gdbarch_long_double_format (gdbarch, floatformats_i387_ext); - - set_gdbarch_short_bit (gdbarch, 16); - set_gdbarch_int_bit (gdbarch, 32); - set_gdbarch_long_bit (gdbarch, 64); - set_gdbarch_long_long_bit (gdbarch, 64); - set_gdbarch_float_bit (gdbarch, 32); - set_gdbarch_double_bit (gdbarch, 64); - set_gdbarch_long_double_bit (gdbarch, 128); - set_gdbarch_ptr_bit (gdbarch, 64); - - set_gdbarch_num_regs (gdbarch, NUM_IA64_RAW_REGS); - set_gdbarch_num_pseudo_regs (gdbarch, - LAST_PSEUDO_REGNUM - FIRST_PSEUDO_REGNUM); - set_gdbarch_sp_regnum (gdbarch, sp_regnum); - set_gdbarch_fp0_regnum (gdbarch, IA64_FR0_REGNUM); - - set_gdbarch_register_name (gdbarch, ia64_register_name); - set_gdbarch_register_type (gdbarch, ia64_register_type); - - set_gdbarch_pseudo_register_read (gdbarch, ia64_pseudo_register_read); - set_gdbarch_deprecated_pseudo_register_write (gdbarch, - ia64_pseudo_register_write); - set_gdbarch_dwarf2_reg_to_regnum (gdbarch, ia64_dwarf_reg_to_regnum); - set_gdbarch_register_reggroup_p (gdbarch, ia64_register_reggroup_p); - set_gdbarch_convert_register_p (gdbarch, ia64_convert_register_p); - set_gdbarch_register_to_value (gdbarch, ia64_register_to_value); - set_gdbarch_value_to_register (gdbarch, ia64_value_to_register); - - set_gdbarch_skip_prologue (gdbarch, ia64_skip_prologue); - - set_gdbarch_return_value (gdbarch, ia64_return_value); - - set_gdbarch_memory_insert_breakpoint (gdbarch, - ia64_memory_insert_breakpoint); - set_gdbarch_memory_remove_breakpoint (gdbarch, - ia64_memory_remove_breakpoint); - set_gdbarch_breakpoint_from_pc (gdbarch, ia64_breakpoint_from_pc); - set_gdbarch_breakpoint_kind_from_pc (gdbarch, ia64_breakpoint_kind_from_pc); - set_gdbarch_read_pc (gdbarch, ia64_read_pc); - set_gdbarch_write_pc (gdbarch, ia64_write_pc); - - /* Settings for calling functions in the inferior. */ - set_gdbarch_push_dummy_call (gdbarch, ia64_push_dummy_call); - tdep->infcall_ops = ia64_infcall_ops; - set_gdbarch_frame_align (gdbarch, ia64_frame_align); - set_gdbarch_dummy_id (gdbarch, ia64_dummy_id); - - set_gdbarch_unwind_pc (gdbarch, ia64_unwind_pc); -#ifdef HAVE_LIBUNWIND_IA64_H - frame_unwind_append_unwinder (gdbarch, - &ia64_libunwind_sigtramp_frame_unwind); - frame_unwind_append_unwinder (gdbarch, &ia64_libunwind_frame_unwind); - frame_unwind_append_unwinder (gdbarch, &ia64_sigtramp_frame_unwind); - libunwind_frame_set_descr (gdbarch, &ia64_libunwind_descr); -#else - frame_unwind_append_unwinder (gdbarch, &ia64_sigtramp_frame_unwind); -#endif - frame_unwind_append_unwinder (gdbarch, &ia64_frame_unwind); - frame_base_set_default (gdbarch, &ia64_frame_base); - - /* Settings that should be unnecessary. */ - set_gdbarch_inner_than (gdbarch, core_addr_lessthan); - - set_gdbarch_print_insn (gdbarch, ia64_print_insn); - set_gdbarch_convert_from_func_ptr_addr (gdbarch, - ia64_convert_from_func_ptr_addr); - - /* The virtual table contains 16-byte descriptors, not pointers to - descriptors. */ - set_gdbarch_vtable_function_descriptors (gdbarch, 1); - - /* Hook in ABI-specific overrides, if they have been registered. */ - gdbarch_init_osabi (info, gdbarch); - - return gdbarch; -} - -void _initialize_ia64_tdep (); -void -_initialize_ia64_tdep () -{ - gdbarch_register (bfd_arch_ia64, ia64_gdbarch_init, NULL); -} diff --git a/gdb/ia64-tdep.h b/gdb/ia64-tdep.h deleted file mode 100644 index 64be38b4d76..00000000000 --- a/gdb/ia64-tdep.h +++ /dev/null @@ -1,268 +0,0 @@ -/* Target-dependent code for the ia64. - - Copyright (C) 2004-2024 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 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, see . */ - -#ifndef IA64_TDEP_H -#define IA64_TDEP_H - -#include "gdbarch.h" - -#ifdef HAVE_LIBUNWIND_IA64_H -#include "libunwind-ia64.h" -#include "ia64-libunwind-tdep.h" -#endif - -/* Register numbers of various important registers. */ - -/* General registers; there are 128 of these 64 bit wide registers. - The first 32 are static and the last 96 are stacked. */ -#define IA64_GR0_REGNUM 0 -#define IA64_GR1_REGNUM (IA64_GR0_REGNUM + 1) -#define IA64_GR2_REGNUM (IA64_GR0_REGNUM + 2) -#define IA64_GR3_REGNUM (IA64_GR0_REGNUM + 3) -#define IA64_GR4_REGNUM (IA64_GR0_REGNUM + 4) -#define IA64_GR5_REGNUM (IA64_GR0_REGNUM + 5) -#define IA64_GR6_REGNUM (IA64_GR0_REGNUM + 6) -#define IA64_GR7_REGNUM (IA64_GR0_REGNUM + 7) -#define IA64_GR8_REGNUM (IA64_GR0_REGNUM + 8) -#define IA64_GR9_REGNUM (IA64_GR0_REGNUM + 9) -#define IA64_GR10_REGNUM (IA64_GR0_REGNUM + 10) -#define IA64_GR11_REGNUM (IA64_GR0_REGNUM + 11) -#define IA64_GR12_REGNUM (IA64_GR0_REGNUM + 12) -#define IA64_GR31_REGNUM (IA64_GR0_REGNUM + 31) -#define IA64_GR32_REGNUM (IA64_GR0_REGNUM + 32) -#define IA64_GR127_REGNUM (IA64_GR0_REGNUM + 127) - -/* Floating point registers; 128 82-bit wide registers. */ -#define IA64_FR0_REGNUM 128 -#define IA64_FR1_REGNUM (IA64_FR0_REGNUM + 1) -#define IA64_FR2_REGNUM (IA64_FR0_REGNUM + 2) -#define IA64_FR8_REGNUM (IA64_FR0_REGNUM + 8) -#define IA64_FR9_REGNUM (IA64_FR0_REGNUM + 9) -#define IA64_FR10_REGNUM (IA64_FR0_REGNUM + 10) -#define IA64_FR11_REGNUM (IA64_FR0_REGNUM + 11) -#define IA64_FR12_REGNUM (IA64_FR0_REGNUM + 12) -#define IA64_FR13_REGNUM (IA64_FR0_REGNUM + 13) -#define IA64_FR14_REGNUM (IA64_FR0_REGNUM + 14) -#define IA64_FR15_REGNUM (IA64_FR0_REGNUM + 15) -#define IA64_FR16_REGNUM (IA64_FR0_REGNUM + 16) -#define IA64_FR31_REGNUM (IA64_FR0_REGNUM + 31) -#define IA64_FR32_REGNUM (IA64_FR0_REGNUM + 32) -#define IA64_FR127_REGNUM (IA64_FR0_REGNUM + 127) - -/* Predicate registers; There are 64 of these one bit registers. It'd - be more convenient (implementation-wise) to use a single 64 bit - word with all of these register in them. Note that there's also a - IA64_PR_REGNUM below which contains all the bits and is used for - communicating the actual values to the target. */ -#define IA64_PR0_REGNUM 256 -#define IA64_PR1_REGNUM (IA64_PR0_REGNUM + 1) -#define IA64_PR2_REGNUM (IA64_PR0_REGNUM + 2) -#define IA64_PR3_REGNUM (IA64_PR0_REGNUM + 3) -#define IA64_PR4_REGNUM (IA64_PR0_REGNUM + 4) -#define IA64_PR5_REGNUM (IA64_PR0_REGNUM + 5) -#define IA64_PR6_REGNUM (IA64_PR0_REGNUM + 6) -#define IA64_PR7_REGNUM (IA64_PR0_REGNUM + 7) -#define IA64_PR8_REGNUM (IA64_PR0_REGNUM + 8) -#define IA64_PR9_REGNUM (IA64_PR0_REGNUM + 9) -#define IA64_PR10_REGNUM (IA64_PR0_REGNUM + 10) -#define IA64_PR11_REGNUM (IA64_PR0_REGNUM + 11) -#define IA64_PR12_REGNUM (IA64_PR0_REGNUM + 12) -#define IA64_PR13_REGNUM (IA64_PR0_REGNUM + 13) -#define IA64_PR14_REGNUM (IA64_PR0_REGNUM + 14) -#define IA64_PR15_REGNUM (IA64_PR0_REGNUM + 15) -#define IA64_PR16_REGNUM (IA64_PR0_REGNUM + 16) -#define IA64_PR17_REGNUM (IA64_PR0_REGNUM + 17) -#define IA64_PR18_REGNUM (IA64_PR0_REGNUM + 18) -#define IA64_PR19_REGNUM (IA64_PR0_REGNUM + 19) -#define IA64_PR20_REGNUM (IA64_PR0_REGNUM + 20) -#define IA64_PR21_REGNUM (IA64_PR0_REGNUM + 21) -#define IA64_PR22_REGNUM (IA64_PR0_REGNUM + 22) -#define IA64_PR23_REGNUM (IA64_PR0_REGNUM + 23) -#define IA64_PR24_REGNUM (IA64_PR0_REGNUM + 24) -#define IA64_PR25_REGNUM (IA64_PR0_REGNUM + 25) -#define IA64_PR26_REGNUM (IA64_PR0_REGNUM + 26) -#define IA64_PR27_REGNUM (IA64_PR0_REGNUM + 27) -#define IA64_PR28_REGNUM (IA64_PR0_REGNUM + 28) -#define IA64_PR29_REGNUM (IA64_PR0_REGNUM + 29) -#define IA64_PR30_REGNUM (IA64_PR0_REGNUM + 30) -#define IA64_PR31_REGNUM (IA64_PR0_REGNUM + 31) -#define IA64_PR32_REGNUM (IA64_PR0_REGNUM + 32) -#define IA64_PR33_REGNUM (IA64_PR0_REGNUM + 33) -#define IA64_PR34_REGNUM (IA64_PR0_REGNUM + 34) -#define IA64_PR35_REGNUM (IA64_PR0_REGNUM + 35) -#define IA64_PR36_REGNUM (IA64_PR0_REGNUM + 36) -#define IA64_PR37_REGNUM (IA64_PR0_REGNUM + 37) -#define IA64_PR38_REGNUM (IA64_PR0_REGNUM + 38) -#define IA64_PR39_REGNUM (IA64_PR0_REGNUM + 39) -#define IA64_PR40_REGNUM (IA64_PR0_REGNUM + 40) -#define IA64_PR41_REGNUM (IA64_PR0_REGNUM + 41) -#define IA64_PR42_REGNUM (IA64_PR0_REGNUM + 42) -#define IA64_PR43_REGNUM (IA64_PR0_REGNUM + 43) -#define IA64_PR44_REGNUM (IA64_PR0_REGNUM + 44) -#define IA64_PR45_REGNUM (IA64_PR0_REGNUM + 45) -#define IA64_PR46_REGNUM (IA64_PR0_REGNUM + 46) -#define IA64_PR47_REGNUM (IA64_PR0_REGNUM + 47) -#define IA64_PR48_REGNUM (IA64_PR0_REGNUM + 48) -#define IA64_PR49_REGNUM (IA64_PR0_REGNUM + 49) -#define IA64_PR50_REGNUM (IA64_PR0_REGNUM + 50) -#define IA64_PR51_REGNUM (IA64_PR0_REGNUM + 51) -#define IA64_PR52_REGNUM (IA64_PR0_REGNUM + 52) -#define IA64_PR53_REGNUM (IA64_PR0_REGNUM + 53) -#define IA64_PR54_REGNUM (IA64_PR0_REGNUM + 54) -#define IA64_PR55_REGNUM (IA64_PR0_REGNUM + 55) -#define IA64_PR56_REGNUM (IA64_PR0_REGNUM + 56) -#define IA64_PR57_REGNUM (IA64_PR0_REGNUM + 57) -#define IA64_PR58_REGNUM (IA64_PR0_REGNUM + 58) -#define IA64_PR59_REGNUM (IA64_PR0_REGNUM + 59) -#define IA64_PR60_REGNUM (IA64_PR0_REGNUM + 60) -#define IA64_PR61_REGNUM (IA64_PR0_REGNUM + 61) -#define IA64_PR62_REGNUM (IA64_PR0_REGNUM + 62) -#define IA64_PR63_REGNUM (IA64_PR0_REGNUM + 63) - -/* Branch registers: 8 64-bit registers for holding branch targets. */ -#define IA64_BR0_REGNUM 320 -#define IA64_BR1_REGNUM (IA64_BR0_REGNUM + 1) -#define IA64_BR2_REGNUM (IA64_BR0_REGNUM + 2) -#define IA64_BR3_REGNUM (IA64_BR0_REGNUM + 3) -#define IA64_BR4_REGNUM (IA64_BR0_REGNUM + 4) -#define IA64_BR5_REGNUM (IA64_BR0_REGNUM + 5) -#define IA64_BR6_REGNUM (IA64_BR0_REGNUM + 6) -#define IA64_BR7_REGNUM (IA64_BR0_REGNUM + 7) - -/* Virtual frame pointer; this matches IA64_FRAME_POINTER_REGNUM in - gcc/config/ia64/ia64.h. */ -#define IA64_VFP_REGNUM 328 - -/* Virtual return address pointer; this matches - IA64_RETURN_ADDRESS_POINTER_REGNUM in gcc/config/ia64/ia64.h. */ -#define IA64_VRAP_REGNUM 329 - -/* Predicate registers: There are 64 of these 1-bit registers. We - define a single register which is used to communicate these values - to/from the target. We will somehow contrive to make it appear - that IA64_PR0_REGNUM thru IA64_PR63_REGNUM hold the actual values. */ -#define IA64_PR_REGNUM 330 - -/* Instruction pointer: 64 bits wide. */ -#define IA64_IP_REGNUM 331 - -/* Process Status Register. */ -#define IA64_PSR_REGNUM 332 - -/* Current Frame Marker (raw form may be the cr.ifs). */ -#define IA64_CFM_REGNUM 333 - -/* Application registers; 128 64-bit wide registers possible, but some - of them are reserved. */ -#define IA64_AR0_REGNUM 334 -#define IA64_KR0_REGNUM (IA64_AR0_REGNUM + 0) -#define IA64_KR7_REGNUM (IA64_KR0_REGNUM + 7) - -#define IA64_RSC_REGNUM (IA64_AR0_REGNUM + 16) -#define IA64_BSP_REGNUM (IA64_AR0_REGNUM + 17) -#define IA64_BSPSTORE_REGNUM (IA64_AR0_REGNUM + 18) -#define IA64_RNAT_REGNUM (IA64_AR0_REGNUM + 19) -#define IA64_FCR_REGNUM (IA64_AR0_REGNUM + 21) -#define IA64_EFLAG_REGNUM (IA64_AR0_REGNUM + 24) -#define IA64_CSD_REGNUM (IA64_AR0_REGNUM + 25) -#define IA64_SSD_REGNUM (IA64_AR0_REGNUM + 26) -#define IA64_CFLG_REGNUM (IA64_AR0_REGNUM + 27) -#define IA64_FSR_REGNUM (IA64_AR0_REGNUM + 28) -#define IA64_FIR_REGNUM (IA64_AR0_REGNUM + 29) -#define IA64_FDR_REGNUM (IA64_AR0_REGNUM + 30) -#define IA64_CCV_REGNUM (IA64_AR0_REGNUM + 32) -#define IA64_UNAT_REGNUM (IA64_AR0_REGNUM + 36) -#define IA64_FPSR_REGNUM (IA64_AR0_REGNUM + 40) -#define IA64_ITC_REGNUM (IA64_AR0_REGNUM + 44) -#define IA64_PFS_REGNUM (IA64_AR0_REGNUM + 64) -#define IA64_LC_REGNUM (IA64_AR0_REGNUM + 65) -#define IA64_EC_REGNUM (IA64_AR0_REGNUM + 66) - -/* NAT (Not A Thing) Bits for the general registers; there are 128 of - these. */ -#define IA64_NAT0_REGNUM 462 -#define IA64_NAT31_REGNUM (IA64_NAT0_REGNUM + 31) -#define IA64_NAT32_REGNUM (IA64_NAT0_REGNUM + 32) -#define IA64_NAT127_REGNUM (IA64_NAT0_REGNUM + 127) - -class frame_info_ptr; -struct regcache; - -/* A struct containing pointers to all the target-dependent operations - performed to setup an inferior function call. */ - -struct ia64_infcall_ops -{ - /* Allocate a new register stack frame starting after the output - region of the current frame. The new frame will contain SOF - registers, all in the output region. This is one way of protecting - the stacked registers of the current frame. - - Should do nothing if this operation is not permitted by the OS. */ - void (*allocate_new_rse_frame) (struct regcache *regcache, ULONGEST bsp, - int sof); - - /* Store the argument stored in BUF into the appropriate location - given the BSP and the SLOTNUM. */ - void (*store_argument_in_slot) (struct regcache *regcache, CORE_ADDR bsp, - int slotnum, gdb_byte *buf); - - /* For targets where we cannot call the function directly, store - the address of the function we want to call at the location - expected by the calling sequence. */ - void (*set_function_addr) (struct regcache *regcache, CORE_ADDR func_addr); -}; - -struct ia64_gdbarch_tdep : gdbarch_tdep_base -{ - CORE_ADDR (*sigcontext_register_address) (struct gdbarch *, CORE_ADDR, int) - = nullptr; - int (*pc_in_sigtramp) (CORE_ADDR) = nullptr; - - /* Return the total size of THIS_FRAME's register frame. - CFM is THIS_FRAME's cfm register value. - - Normally, the size of the register frame is always obtained by - extracting the lowest 7 bits ("cfm & 0x7f"). */ - int (*size_of_register_frame) (const frame_info_ptr &this_frame, ULONGEST cfm) - = nullptr; - - /* Determine the function address FADDR belongs to a shared library. - If it does, then return the associated global pointer. If no shared - library was found to contain that function, then return zero. - - This pointer may be NULL. */ - CORE_ADDR (*find_global_pointer_from_solib) (struct gdbarch *gdbarch, - CORE_ADDR faddr) = nullptr; - - /* ISA-specific data types. */ - struct type *ia64_ext_type = nullptr; - - struct ia64_infcall_ops infcall_ops {}; -}; - -extern void ia64_write_pc (struct regcache *, CORE_ADDR); - -#ifdef HAVE_LIBUNWIND_IA64_H -extern unw_accessors_t ia64_unw_accessors; -extern unw_accessors_t ia64_unw_rse_accessors; -extern struct libunwind_descr ia64_libunwind_descr; -#endif - -#endif /* ia64-tdep.h */ diff --git a/gdb/ia64-vms-tdep.c b/gdb/ia64-vms-tdep.c deleted file mode 100644 index 20308c70720..00000000000 --- a/gdb/ia64-vms-tdep.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Target-dependent code for OpenVMS IA-64. - - Copyright (C) 2012-2024 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 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, see . */ - -#include "frame-unwind.h" -#include "ia64-tdep.h" -#include "osabi.h" -#include "gdbtypes.h" -#include "gdbcore.h" -#include "gdbarch.h" - -#ifdef HAVE_LIBUNWIND_IA64_H - -/* Libunwind callback accessor function to acquire procedure unwind-info. */ - -static int -ia64_vms_find_proc_info_x (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ()); - gdb_byte buf[32]; - const char *annex = core_addr_to_string (ip); - LONGEST res; - CORE_ADDR table_addr; - unsigned int info_len; - - res = target_read (current_inferior ()->top_target (), - TARGET_OBJECT_OPENVMS_UIB, - annex + 2, buf, 0, sizeof (buf)); - - if (res != sizeof (buf)) - return -UNW_ENOINFO; - - pi->format = UNW_INFO_FORMAT_REMOTE_TABLE; - pi->start_ip = extract_unsigned_integer (buf + 0, 8, byte_order); - pi->end_ip = extract_unsigned_integer (buf + 8, 8, byte_order); - pi->gp = extract_unsigned_integer (buf + 24, 8, byte_order); - table_addr = extract_unsigned_integer (buf + 16, 8, byte_order); - - if (table_addr == 0) - { - /* No unwind data. */ - pi->unwind_info = NULL; - pi->unwind_info_size = 0; - return 0; - } - - res = target_read_memory (table_addr, buf, 8); - if (res != 0) - return -UNW_ENOINFO; - - /* Check version. */ - if (extract_unsigned_integer (buf + 6, 2, byte_order) != 1) - return -UNW_EBADVERSION; - info_len = extract_unsigned_integer (buf + 0, 4, byte_order); - pi->unwind_info_size = 8 * info_len; - - /* Read info. */ - pi->unwind_info = xmalloc (pi->unwind_info_size); - - res = target_read_memory (table_addr + 8, - (gdb_byte *) pi->unwind_info, pi->unwind_info_size); - if (res != 0) - { - xfree (pi->unwind_info); - pi->unwind_info = NULL; - return -UNW_ENOINFO; - } - - /* FIXME: Handle OSSD (OS Specific Data). This extension to ia64 unwind - information by OpenVMS is currently not handled by libunwind, but - looks to be used only in very specific context, and is not generated by - GCC. */ - - pi->lsda = table_addr + 8 + pi->unwind_info_size; - if (extract_unsigned_integer (buf + 4, 2, byte_order) & 3) - { - pi->lsda += 8; - /* There might be an handler, but this is not used for unwinding. */ - pi->handler = 0; - } - - return 0; -} - -/* Libunwind callback accessor function for cleanup. */ - -static void -ia64_vms_put_unwind_info (unw_addr_space_t as, - unw_proc_info_t *pip, void *arg) -{ - /* Nothing required for now. */ -} - -/* Libunwind callback accessor function to get head of the dynamic - unwind-info registration list. */ - -static int -ia64_vms_get_dyn_info_list (unw_addr_space_t as, - unw_word_t *dilap, void *arg) -{ - return -UNW_ENOINFO; -} - -/* Set of libunwind callback acccessor functions. */ -static unw_accessors_t ia64_vms_unw_accessors; -static unw_accessors_t ia64_vms_unw_rse_accessors; - -/* Set of ia64-libunwind-tdep gdb callbacks and data for generic - ia64-libunwind-tdep code to use. */ -static struct libunwind_descr ia64_vms_libunwind_descr; - -#endif /* HAVE_LIBUNWIND_IA64_H */ - -static void -ia64_openvms_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - set_gdbarch_long_double_format (gdbarch, floatformats_ieee_quad); - -#ifdef HAVE_LIBUNWIND_IA64_H - /* Override the default descriptor. */ - ia64_vms_unw_accessors = ia64_unw_accessors; - ia64_vms_unw_accessors.find_proc_info = ia64_vms_find_proc_info_x; - ia64_vms_unw_accessors.put_unwind_info = ia64_vms_put_unwind_info; - ia64_vms_unw_accessors.get_dyn_info_list_addr = ia64_vms_get_dyn_info_list; - - ia64_vms_unw_rse_accessors = ia64_unw_rse_accessors; - ia64_vms_unw_rse_accessors.find_proc_info = ia64_vms_find_proc_info_x; - ia64_vms_unw_rse_accessors.put_unwind_info = ia64_vms_put_unwind_info; - ia64_vms_unw_rse_accessors.get_dyn_info_list_addr = ia64_vms_get_dyn_info_list; - - ia64_vms_libunwind_descr = ia64_libunwind_descr; - ia64_vms_libunwind_descr.accessors = &ia64_vms_unw_accessors; - ia64_vms_libunwind_descr.special_accessors = &ia64_vms_unw_rse_accessors; - - libunwind_frame_set_descr (gdbarch, &ia64_vms_libunwind_descr); -#endif -} - -void _initialize_ia64_vms_tdep (); -void -_initialize_ia64_vms_tdep () -{ - gdbarch_register_osabi (bfd_arch_ia64, 0, GDB_OSABI_OPENVMS, - ia64_openvms_init_abi); -} diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c index ce303eb87ea..f75186fb945 100644 --- a/gdb/inf-ptrace.c +++ b/gdb/inf-ptrace.c @@ -466,9 +466,6 @@ inf_ptrace_target::xfer_partial (enum target_object object, offset, len); return *xfered_len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF; - case TARGET_OBJECT_UNWIND_TABLE: - return TARGET_XFER_E_IO; - case TARGET_OBJECT_AUXV: #if defined (PT_IO) && defined (PIOD_READ_AUXV) /* OpenBSD 4.5 has a new PIOD_READ_AUXV operation for the PT_IO diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c index 9ea0e22913f..491df497e69 100644 --- a/gdb/nat/linux-ptrace.c +++ b/gdb/nat/linux-ptrace.c @@ -278,13 +278,8 @@ linux_fork_to_function (gdb_byte *child_stack, int (*function) (void *)) child_stack = (gdb_byte *) xmalloc (STACK_SIZE * 4); /* Use CLONE_VM instead of fork, to support uClinux (no MMU). */ -#ifdef __ia64__ - child_pid = __clone2 (function, child_stack, STACK_SIZE, - CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2); -#else /* !__ia64__ */ child_pid = clone (function, child_stack + STACK_SIZE, CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2); -#endif /* !__ia64__ */ #else /* !defined(__UCLIBC) && defined(HAS_NOMMU) */ child_pid = fork (); diff --git a/gdb/regcache.c b/gdb/regcache.c index f04354d822f..69f194593b5 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -2132,8 +2132,7 @@ cooked_write_test (struct gdbarch *gdbarch) || type->code () == TYPE_CODE_UNION || type->code () == TYPE_CODE_STRUCT) { - if (bfd_arch == bfd_arch_ia64 - || (regnum >= gdbarch_num_regs (gdbarch) + if ((regnum >= gdbarch_num_regs (gdbarch) && (bfd_arch == bfd_arch_xtensa || bfd_arch == bfd_arch_bfin || bfd_arch == bfd_arch_m32c diff --git a/gdb/regformats/reg-ia64.dat b/gdb/regformats/reg-ia64.dat deleted file mode 100644 index 21d56645d67..00000000000 --- a/gdb/regformats/reg-ia64.dat +++ /dev/null @@ -1,475 +0,0 @@ -name:ia64 -expedite:ip,psr,r12,bsp,cfm -64:r0 -64:r1 -64:r2 -64:r3 -64:r4 -64:r5 -64:r6 -64:r7 -64:r8 -64:r9 -64:r10 -64:r11 -64:r12 -64:r13 -64:r14 -64:r15 -64:r16 -64:r17 -64:r18 -64:r19 -64:r20 -64:r21 -64:r22 -64:r23 -64:r24 -64:r25 -64:r26 -64:r27 -64:r28 -64:r29 -64:r30 -64:r31 -64:r32 -64:r33 -64:r34 -64:r35 -64:r36 -64:r37 -64:r38 -64:r39 -64:r40 -64:r41 -64:r42 -64:r43 -64:r44 -64:r45 -64:r46 -64:r47 -64:r48 -64:r49 -64:r50 -64:r51 -64:r52 -64:r53 -64:r54 -64:r55 -64:r56 -64:r57 -64:r58 -64:r59 -64:r60 -64:r61 -64:r62 -64:r63 -64:r64 -64:r65 -64:r66 -64:r67 -64:r68 -64:r69 -64:r70 -64:r71 -64:r72 -64:r73 -64:r74 -64:r75 -64:r76 -64:r77 -64:r78 -64:r79 -64:r80 -64:r81 -64:r82 -64:r83 -64:r84 -64:r85 -64:r86 -64:r87 -64:r88 -64:r89 -64:r90 -64:r91 -64:r92 -64:r93 -64:r94 -64:r95 -64:r96 -64:r97 -64:r98 -64:r99 -64:r100 -64:r101 -64:r102 -64:r103 -64:r104 -64:r105 -64:r106 -64:r107 -64:r108 -64:r109 -64:r110 -64:r111 -64:r112 -64:r113 -64:r114 -64:r115 -64:r116 -64:r117 -64:r118 -64:r119 -64:r120 -64:r121 -64:r122 -64:r123 -64:r124 -64:r125 -64:r126 -64:r127 - -128:f0 -128:f1 -128:f2 -128:f3 -128:f4 -128:f5 -128:f6 -128:f7 -128:f8 -128:f9 -128:f10 -128:f11 -128:f12 -128:f13 -128:f14 -128:f15 -128:f16 -128:f17 -128:f18 -128:f19 -128:f20 -128:f21 -128:f22 -128:f23 -128:f24 -128:f25 -128:f26 -128:f27 -128:f28 -128:f29 -128:f30 -128:f31 -128:f32 -128:f33 -128:f34 -128:f35 -128:f36 -128:f37 -128:f38 -128:f39 -128:f40 -128:f41 -128:f42 -128:f43 -128:f44 -128:f45 -128:f46 -128:f47 -128:f48 -128:f49 -128:f50 -128:f51 -128:f52 -128:f53 -128:f54 -128:f55 -128:f56 -128:f57 -128:f58 -128:f59 -128:f60 -128:f61 -128:f62 -128:f63 -128:f64 -128:f65 -128:f66 -128:f67 -128:f68 -128:f69 -128:f70 -128:f71 -128:f72 -128:f73 -128:f74 -128:f75 -128:f76 -128:f77 -128:f78 -128:f79 -128:f80 -128:f81 -128:f82 -128:f83 -128:f84 -128:f85 -128:f86 -128:f87 -128:f88 -128:f89 -128:f90 -128:f91 -128:f92 -128:f93 -128:f94 -128:f95 -128:f96 -128:f97 -128:f98 -128:f99 -128:f100 -128:f101 -128:f102 -128:f103 -128:f104 -128:f105 -128:f106 -128:f107 -128:f108 -128:f109 -128:f110 -128:f111 -128:f112 -128:f113 -128:f114 -128:f115 -128:f116 -128:f117 -128:f118 -128:f119 -128:f120 -128:f121 -128:f122 -128:f123 -128:f124 -128:f125 -128:f126 -128:f127 - -64:p0 -64:p1 -64:p2 -64:p3 -64:p4 -64:p5 -64:p6 -64:p7 -64:p8 -64:p9 -64:p10 -64:p11 -64:p12 -64:p13 -64:p14 -64:p15 -64:p16 -64:p17 -64:p18 -64:p19 -64:p20 -64:p21 -64:p22 -64:p23 -64:p24 -64:p25 -64:p26 -64:p27 -64:p28 -64:p29 -64:p30 -64:p31 -64:p32 -64:p33 -64:p34 -64:p35 -64:p36 -64:p37 -64:p38 -64:p39 -64:p40 -64:p41 -64:p42 -64:p43 -64:p44 -64:p45 -64:p46 -64:p47 -64:p48 -64:p49 -64:p50 -64:p51 -64:p52 -64:p53 -64:p54 -64:p55 -64:p56 -64:p57 -64:p58 -64:p59 -64:p60 -64:p61 -64:p62 -64:p63 - -64:b0 -64:b1 -64:b2 -64:b3 -64:b4 -64:b5 -64:b6 -64:b7 - -64:vfp -64:vrap - -64:pr -64:ip -64:psr -64:cfm - -64:kr0 -64:kr1 -64:kr2 -64:kr3 -64:kr4 -64:kr5 -64:kr6 -64:kr7 - -64: -64: -64: -64: -64: -64: -64: -64: - -64:rsc -64:bsp -64:bspstore -64:rnat - -64: -64:fcr -64: -64: - -64:eflag -64:csd -64:ssd -64:cflg -64:fsr -64:fir -64:fdr -64: -64:ccv -64: -64: -64: -64:unat -64: -64: -64: -64:fpsr -64: -64: -64: -64:itc - -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64:pfs -64:lc -64:ec -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: -64: diff --git a/gdb/stubs/ia64vms-stub.c b/gdb/stubs/ia64vms-stub.c deleted file mode 100644 index e7578d80938..00000000000 --- a/gdb/stubs/ia64vms-stub.c +++ /dev/null @@ -1,2601 +0,0 @@ -/* GDB stub for Itanium OpenVMS - Copyright (C) 2012-2024 Free Software Foundation, Inc. - - Contributed by Tristan Gingold, 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, see . */ - -/* On VMS, the debugger (in our case the stub) is loaded in the process and - executed (via SYS$IMGSTA) before the main entry point of the executable. - In UNIX parlance, this is like using LD_PRELOAD and debug via installing - SIGTRAP, SIGSEGV... handlers. - - This is currently a partial implementation. In particular, modifying - registers is currently not implemented, as well as inferior procedure - calls. - - This is written in very low-level C, in order not to use the C runtime, - because it may have weird consequences on the program being debugged. -*/ - -#if __INITIAL_POINTER_SIZE != 64 -#error "Must be compiled with 64 bit pointers" -#endif - -#define __NEW_STARLET 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define VMS_PAGE_SIZE 0x2000 -#define VMS_PAGE_MASK (VMS_PAGE_SIZE - 1) - -/* Declared in lib$ots. */ -extern void ots$fill (void *addr, size_t len, unsigned char b); -extern void ots$move (void *dst, size_t len, const void *src); -extern int ots$strcmp_eql (const void *str1, size_t str1len, - const void *str2, size_t str2len); - -/* Stub port number. */ -static unsigned int serv_port = 1234; - -/* DBGEXT structure. Not declared in any header. */ -struct dbgext_control_block -{ - unsigned short dbgext$w_function_code; -#define DBGEXT$K_NEXT_TASK 3 -#define DBGEXT$K_STOP_ALL_OTHER_TASKS 31 -#define DBGEXT$K_GET_REGS 33 - unsigned short dbgext$w_facility_id; -#define CMA$_FACILITY 64 - unsigned int dbgext$l_status; - unsigned int dbgext$l_flags; - unsigned int dbgext$l_print_routine; - unsigned int dbgext$l_evnt_code; - unsigned int dbgext$l_evnt_name; - unsigned int dbgext$l_evnt_entry; - unsigned int dbgext$l_task_value; - unsigned int dbgext$l_task_number; - unsigned int dbgext$l_ada_flags; - unsigned int dbgext$l_stop_value; -#define dbgext$l_priority dbgext$l_stop_value; -#define dbgext$l_symb_addr dbgext$l_stop_value; -#define dbgext$l_time_slice dbgext$l_stop_value; - unsigned int dbgext$l_active_registers; -}; - -#pragma pointer_size save -#pragma pointer_size 32 - -/* Pthread handler. */ -static int (*dbgext_func) (struct dbgext_control_block *blk); - -#pragma pointer_size restore - -/* Set to 1 if thread-aware. */ -static int has_threads; - -/* Current thread. */ -static pthread_t selected_thread; -static pthreadDebugId_t selected_id; - -/* Internal debugging flags. */ -struct debug_flag -{ - /* Name of the flag (as a string descriptor). */ - const struct dsc$descriptor_s name; - /* Value. */ - int val; -}; - -/* Macro to define a debugging flag. */ -#define DEBUG_FLAG_ENTRY(str) \ - { { sizeof (str) - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, str }, 0} - -static struct debug_flag debug_flags[] = -{ - /* Disp packets exchanged with gdb. */ - DEBUG_FLAG_ENTRY("packets"), -#define trace_pkt (debug_flags[0].val) - /* Display entry point informations. */ - DEBUG_FLAG_ENTRY("entry"), -#define trace_entry (debug_flags[1].val) - /* Be verbose about exceptions. */ - DEBUG_FLAG_ENTRY("excp"), -#define trace_excp (debug_flags[2].val) - /* Be verbose about unwinding. */ - DEBUG_FLAG_ENTRY("unwind"), -#define trace_unwind (debug_flags[3].val) - /* Display image at startup. */ - DEBUG_FLAG_ENTRY("images"), -#define trace_images (debug_flags[4].val) - /* Display pthread_debug info. */ - DEBUG_FLAG_ENTRY("pthreaddbg") -#define trace_pthreaddbg (debug_flags[5].val) -}; - -#define NBR_DEBUG_FLAGS (sizeof (debug_flags) / sizeof (debug_flags[0])) - -/* Connect inet device I/O channel. */ -static unsigned short conn_channel; - -/* Widely used hex digit to ascii. */ -static const char hex[] = "0123456789abcdef"; - -/* Socket characteristics. Apparently, there are no declaration for it in - standard headers. */ -struct sockchar -{ - unsigned short prot; - unsigned char type; - unsigned char af; -}; - -/* Chain of images loaded. */ -extern IMCB* ctl$gl_imglstptr; - -/* IA64 integer register representation. */ -union ia64_ireg -{ - unsigned __int64 v; - unsigned char b[8]; -}; - -/* IA64 register numbers, as defined by ia64-tdep.h. */ -#define IA64_GR0_REGNUM 0 -#define IA64_GR32_REGNUM (IA64_GR0_REGNUM + 32) - -/* Floating point registers; 128 82-bit wide registers. */ -#define IA64_FR0_REGNUM 128 - -/* Predicate registers; There are 64 of these one bit registers. It'd - be more convenient (implementation-wise) to use a single 64 bit - word with all of these register in them. Note that there's also a - IA64_PR_REGNUM below which contains all the bits and is used for - communicating the actual values to the target. */ -#define IA64_PR0_REGNUM 256 - -/* Branch registers: 8 64-bit registers for holding branch targets. */ -#define IA64_BR0_REGNUM 320 - -/* Virtual frame pointer; this matches IA64_FRAME_POINTER_REGNUM in - gcc/config/ia64/ia64.h. */ -#define IA64_VFP_REGNUM 328 - -/* Virtual return address pointer; this matches - IA64_RETURN_ADDRESS_POINTER_REGNUM in gcc/config/ia64/ia64.h. */ -#define IA64_VRAP_REGNUM 329 - -/* Predicate registers: There are 64 of these 1-bit registers. We - define a single register which is used to communicate these values - to/from the target. We will somehow contrive to make it appear - that IA64_PR0_REGNUM thru IA64_PR63_REGNUM hold the actual values. */ -#define IA64_PR_REGNUM 330 - -/* Instruction pointer: 64 bits wide. */ -#define IA64_IP_REGNUM 331 - -/* Process Status Register. */ -#define IA64_PSR_REGNUM 332 - -/* Current Frame Marker (raw form may be the cr.ifs). */ -#define IA64_CFM_REGNUM 333 - -/* Application registers; 128 64-bit wide registers possible, but some - of them are reserved. */ -#define IA64_AR0_REGNUM 334 -#define IA64_KR0_REGNUM (IA64_AR0_REGNUM + 0) -#define IA64_KR7_REGNUM (IA64_KR0_REGNUM + 7) - -#define IA64_RSC_REGNUM (IA64_AR0_REGNUM + 16) -#define IA64_BSP_REGNUM (IA64_AR0_REGNUM + 17) -#define IA64_BSPSTORE_REGNUM (IA64_AR0_REGNUM + 18) -#define IA64_RNAT_REGNUM (IA64_AR0_REGNUM + 19) -#define IA64_FCR_REGNUM (IA64_AR0_REGNUM + 21) -#define IA64_EFLAG_REGNUM (IA64_AR0_REGNUM + 24) -#define IA64_CSD_REGNUM (IA64_AR0_REGNUM + 25) -#define IA64_SSD_REGNUM (IA64_AR0_REGNUM + 26) -#define IA64_CFLG_REGNUM (IA64_AR0_REGNUM + 27) -#define IA64_FSR_REGNUM (IA64_AR0_REGNUM + 28) -#define IA64_FIR_REGNUM (IA64_AR0_REGNUM + 29) -#define IA64_FDR_REGNUM (IA64_AR0_REGNUM + 30) -#define IA64_CCV_REGNUM (IA64_AR0_REGNUM + 32) -#define IA64_UNAT_REGNUM (IA64_AR0_REGNUM + 36) -#define IA64_FPSR_REGNUM (IA64_AR0_REGNUM + 40) -#define IA64_ITC_REGNUM (IA64_AR0_REGNUM + 44) -#define IA64_PFS_REGNUM (IA64_AR0_REGNUM + 64) -#define IA64_LC_REGNUM (IA64_AR0_REGNUM + 65) -#define IA64_EC_REGNUM (IA64_AR0_REGNUM + 66) - -/* NAT (Not A Thing) Bits for the general registers; there are 128 of - these. */ -#define IA64_NAT0_REGNUM 462 - -/* Process registers when a condition is caught. */ -struct ia64_all_regs -{ - union ia64_ireg gr[32]; - union ia64_ireg br[8]; - union ia64_ireg ip; - union ia64_ireg psr; - union ia64_ireg bsp; - union ia64_ireg cfm; - union ia64_ireg pfs; - union ia64_ireg pr; -}; - -static struct ia64_all_regs excp_regs; -static struct ia64_all_regs sel_regs; -static pthread_t sel_regs_pthread; - -/* IO channel for the terminal. */ -static unsigned short term_chan; - -/* Output buffer and length. */ -static char term_buf[128]; -static int term_buf_len; - -/* Buffer for communication with gdb. */ -static unsigned char gdb_buf[sizeof (struct ia64_all_regs) * 2 + 64]; -static unsigned int gdb_blen; - -/* Previous primary handler. */ -static void *prevhnd; - -/* Entry point address and bundle. */ -static unsigned __int64 entry_pc; -static unsigned char entry_saved[16]; - -/* Write on the terminal. */ - -static void -term_raw_write (const char *str, unsigned int len) -{ - unsigned short status; - struct _iosb iosb; - - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - term_chan, /* I/O channel. */ - IO$_WRITEVBLK, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - (char *)str, /* P1 - buffer address. */ - len, /* P2 - buffer length. */ - 0, 0, 0, 0); - - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); -} - -/* Flush ther term buffer. */ - -static void -term_flush (void) -{ - if (term_buf_len != 0) - { - term_raw_write (term_buf, term_buf_len); - term_buf_len = 0; - } -} - -/* Write a single character, without translation. */ - -static void -term_raw_putchar (char c) -{ - if (term_buf_len == sizeof (term_buf)) - term_flush (); - term_buf[term_buf_len++] = c; -} - -/* Write character C. Translate '\n' to '\n\r'. */ - -static void -term_putc (char c) -{ - if (c < 32) - switch (c) - { - case '\r': - case '\n': - break; - default: - c = '.'; - break; - } - term_raw_putchar (c); - if (c == '\n') - { - term_raw_putchar ('\r'); - term_flush (); - } -} - -/* Write a C string. */ - -static void -term_puts (const char *str) -{ - while (*str) - term_putc (*str++); -} - -/* Write LEN bytes from STR. */ - -static void -term_write (const char *str, unsigned int len) -{ - for (; len > 0; len--) - term_putc (*str++); -} - -/* Write using FAO formatting. */ - -static void -term_fao (const char *str, unsigned int str_len, ...) -{ - int cnt; - va_list vargs; - int i; - __int64 *args; - int status; - struct dsc$descriptor_s dstr = - { str_len, DSC$K_DTYPE_T, DSC$K_CLASS_S, (__char_ptr32)str }; - char buf[128]; - $DESCRIPTOR (buf_desc, buf); - - va_start (vargs, str_len); - va_count (cnt); - args = (__int64 *) __ALLOCA (cnt * sizeof (__int64)); - cnt -= 2; - for (i = 0; i < cnt; i++) - args[i] = va_arg (vargs, __int64); - - status = sys$faol_64 (&dstr, &buf_desc.dsc$w_length, &buf_desc, args); - if (status & 1) - { - /* FAO !/ already insert a line feed. */ - for (i = 0; i < buf_desc.dsc$w_length; i++) - { - term_raw_putchar (buf[i]); - if (buf[i] == '\n') - term_flush (); - } - } - - va_end (vargs); -} - -#define TERM_FAO(STR, ...) term_fao (STR, sizeof (STR) - 1, __VA_ARGS__) - -/* New line. */ - -static void -term_putnl (void) -{ - term_putc ('\n'); -} - -/* Initialize terminal. */ - -static void -term_init (void) -{ - unsigned int status,i; - unsigned short len; - char resstring[LNM$C_NAMLENGTH]; - static const $DESCRIPTOR (tabdesc, "LNM$FILE_DEV"); - static const $DESCRIPTOR (logdesc, "SYS$OUTPUT"); - $DESCRIPTOR (term_desc, resstring); - ILE3 item_lst[2]; - - item_lst[0].ile3$w_length = LNM$C_NAMLENGTH; - item_lst[0].ile3$w_code = LNM$_STRING; - item_lst[0].ile3$ps_bufaddr = resstring; - item_lst[0].ile3$ps_retlen_addr = &len; - item_lst[1].ile3$w_length = 0; - item_lst[1].ile3$w_code = 0; - - /* Translate the logical name. */ - status = SYS$TRNLNM (0, /* Attr of the logical name. */ - (void *) &tabdesc, /* Logical name table. */ - (void *) &logdesc, /* Logical name. */ - 0, /* Access mode. */ - item_lst); /* Item list. */ - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); - - term_desc.dsc$w_length = len; - - /* Examine 4-byte header. Skip escape sequence. */ - if (resstring[0] == 0x1B) - { - term_desc.dsc$w_length -= 4; - term_desc.dsc$a_pointer += 4; - } - - /* Assign a channel. */ - status = sys$assign (&term_desc, /* Device name. */ - &term_chan, /* I/O channel. */ - 0, /* Access mode. */ - 0); - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); -} - -/* Convert from native endianness to network endianness (and vice-versa). */ - -static unsigned int -wordswap (unsigned int v) -{ - return ((v & 0xff) << 8) | ((v >> 8) & 0xff); -} - -/* Initialize the socket connection, and wait for a client. */ - -static void -sock_init (void) -{ - struct _iosb iosb; - unsigned int status; - - /* Listen channel and characteristics. */ - unsigned short listen_channel; - struct sockchar listen_sockchar; - - /* Client address. */ - unsigned short cli_addrlen; - struct sockaddr_in cli_addr; - ILE3 cli_itemlst; - - /* Our address. */ - struct sockaddr_in serv_addr; - ILE2 serv_itemlst; - - /* Reuseaddr option value (on). */ - int optval = 1; - ILE2 sockopt_itemlst; - ILE2 reuseaddr_itemlst; - - /* TCP/IP network pseudodevice. */ - static const $DESCRIPTOR (inet_device, "TCPIP$DEVICE:"); - - /* Initialize socket characteristics. */ - listen_sockchar.prot = TCPIP$C_TCP; - listen_sockchar.type = TCPIP$C_STREAM; - listen_sockchar.af = TCPIP$C_AF_INET; - - /* Assign I/O channels to network device. */ - status = sys$assign ((void *) &inet_device, &listen_channel, 0, 0); - if (status & STS$M_SUCCESS) - status = sys$assign ((void *) &inet_device, &conn_channel, 0, 0); - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to assign I/O channel(s)\n"); - LIB$SIGNAL (status); - } - - /* Create a listen socket. */ - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - listen_channel, /* I/O channel. */ - IO$_SETMODE, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - &listen_sockchar, /* P1 - socket characteristics. */ - 0, 0, 0, 0, 0); - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to create socket\n"); - LIB$SIGNAL (status); - } - - /* Set reuse address option. */ - /* Initialize reuseaddr's item-list element. */ - reuseaddr_itemlst.ile2$w_length = sizeof (optval); - reuseaddr_itemlst.ile2$w_code = TCPIP$C_REUSEADDR; - reuseaddr_itemlst.ile2$ps_bufaddr = &optval; - - /* Initialize setsockopt's item-list descriptor. */ - sockopt_itemlst.ile2$w_length = sizeof (reuseaddr_itemlst); - sockopt_itemlst.ile2$w_code = TCPIP$C_SOCKOPT; - sockopt_itemlst.ile2$ps_bufaddr = &reuseaddr_itemlst; - - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - listen_channel, /* I/O channel. */ - IO$_SETMODE, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - 0, /* P1. */ - 0, /* P2. */ - 0, /* P3. */ - 0, /* P4. */ - (__int64) &sockopt_itemlst, /* P5 - socket options. */ - 0); - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to set socket option\n"); - LIB$SIGNAL (status); - } - - /* Bind server's ip address and port number to listen socket. */ - /* Initialize server's socket address structure. */ - ots$fill (&serv_addr, sizeof (serv_addr), 0); - serv_addr.sin_family = TCPIP$C_AF_INET; - serv_addr.sin_port = wordswap (serv_port); - serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY; - - /* Initialize server's item-list descriptor. */ - serv_itemlst.ile2$w_length = sizeof (serv_addr); - serv_itemlst.ile2$w_code = TCPIP$C_SOCK_NAME; - serv_itemlst.ile2$ps_bufaddr = &serv_addr; - - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - listen_channel, /* I/O channel. */ - IO$_SETMODE, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - 0, /* P1. */ - 0, /* P2. */ - (__int64) &serv_itemlst, /* P3 - local socket name. */ - 0, 0, 0); - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to bind socket\n"); - LIB$SIGNAL (status); - } - - /* Set socket as a listen socket. */ - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - listen_channel, /* I/O channel. */ - IO$_SETMODE, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - 0, /* P1. */ - 0, /* P2. */ - 0, /* P3. */ - 1, /* P4 - connection backlog. */ - 0, 0); - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to set socket passive\n"); - LIB$SIGNAL (status); - } - - /* Accept connection from a client. */ - TERM_FAO ("Waiting for a client connection on port: !ZW!/", - wordswap (serv_addr.sin_port)); - - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - listen_channel, /* I/O channel. */ - IO$_ACCESS|IO$M_ACCEPT, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - 0, /* P1. */ - 0, /* P2. */ - 0, /* P3. */ - (__int64) &conn_channel, /* P4 - I/O channel for conn. */ - 0, 0); - - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to accept client connection\n"); - LIB$SIGNAL (status); - } - - /* Log client connection request. */ - cli_itemlst.ile3$w_length = sizeof (cli_addr); - cli_itemlst.ile3$w_code = TCPIP$C_SOCK_NAME; - cli_itemlst.ile3$ps_bufaddr = &cli_addr; - cli_itemlst.ile3$ps_retlen_addr = &cli_addrlen; - ots$fill (&cli_addr, sizeof(cli_addr), 0); - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - conn_channel, /* I/O channel. */ - IO$_SENSEMODE, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - 0, /* P1. */ - 0, /* P2. */ - 0, /* P3. */ - (__int64) &cli_itemlst, /* P4 - peer socket name. */ - 0, 0); - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to get client name\n"); - LIB$SIGNAL (status); - } - - TERM_FAO ("Accepted connection from host: !UB.!UB,!UB.!UB, port: !UW!/", - (cli_addr.sin_addr.s_addr >> 0) & 0xff, - (cli_addr.sin_addr.s_addr >> 8) & 0xff, - (cli_addr.sin_addr.s_addr >> 16) & 0xff, - (cli_addr.sin_addr.s_addr >> 24) & 0xff, - wordswap (cli_addr.sin_port)); -} - -/* Close the socket. */ - -static void -sock_close (void) -{ - struct _iosb iosb; - unsigned int status; - - /* Close socket. */ - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - conn_channel, /* I/O channel. */ - IO$_DEACCESS, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - 0, 0, 0, 0, 0, 0); - - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to close socket\n"); - LIB$SIGNAL (status); - } - - /* Deassign I/O channel to network device. */ - status = sys$dassgn (conn_channel); - - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to deassign I/O channel\n"); - LIB$SIGNAL (status); - } -} - -/* Mark a page as R/W. Return old rights. */ - -static unsigned int -page_set_rw (unsigned __int64 startva, unsigned __int64 len, - unsigned int *oldprot) -{ - unsigned int status; - unsigned __int64 retva; - unsigned __int64 retlen; - - status = SYS$SETPRT_64 ((void *)startva, len, PSL$C_USER, PRT$C_UW, - (void *)&retva, &retlen, oldprot); - return status; -} - -/* Restore page rights. */ - -static void -page_restore_rw (unsigned __int64 startva, unsigned __int64 len, - unsigned int prot) -{ - unsigned int status; - unsigned __int64 retva; - unsigned __int64 retlen; - unsigned int oldprot; - - status = SYS$SETPRT_64 ((void *)startva, len, PSL$C_USER, prot, - (void *)&retva, &retlen, &oldprot); - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); -} - -/* Get the TEB (thread environment block). */ - -static pthread_t -get_teb (void) -{ - return (pthread_t)__getReg (_IA64_REG_TP); -} - -/* Enable thread scheduling if VAL is true. */ - -static unsigned int -set_thread_scheduling (int val) -{ - struct dbgext_control_block blk; - unsigned int status; - - if (!dbgext_func) - return 0; - - blk.dbgext$w_function_code = DBGEXT$K_STOP_ALL_OTHER_TASKS; - blk.dbgext$w_facility_id = CMA$_FACILITY; - blk.dbgext$l_stop_value = val; - - status = dbgext_func (&blk); - if (!(status & STS$M_SUCCESS)) - { - TERM_FAO ("set_thread_scheduling error, val=!SL, status=!XL!/", - val, blk.dbgext$l_status); - lib$signal (status); - } - - return blk.dbgext$l_stop_value; -} - -/* Get next thread (after THR). Start with 0. */ - -static unsigned int -thread_next (unsigned int thr) -{ - struct dbgext_control_block blk; - unsigned int status; - - if (!dbgext_func) - return 0; - - blk.dbgext$w_function_code = DBGEXT$K_NEXT_TASK; - blk.dbgext$w_facility_id = CMA$_FACILITY; - blk.dbgext$l_ada_flags = 0; - blk.dbgext$l_task_value = thr; - - status = dbgext_func (&blk); - if (!(status & STS$M_SUCCESS)) - lib$signal (status); - - return blk.dbgext$l_task_value; -} - -/* Pthread Debug callbacks. */ - -static int -read_callback (pthreadDebugClient_t context, - pthreadDebugTargetAddr_t addr, - pthreadDebugAddr_t buf, - size_t size) -{ - if (trace_pthreaddbg) - TERM_FAO ("read_callback (!XH, !XH, !SL)!/", addr, buf, size); - ots$move (buf, size, addr); - return 0; -} - -static int -write_callback (pthreadDebugClient_t context, - pthreadDebugTargetAddr_t addr, - pthreadDebugLongConstAddr_t buf, - size_t size) -{ - if (trace_pthreaddbg) - TERM_FAO ("write_callback (!XH, !XH, !SL)!/", addr, buf, size); - ots$move (addr, size, buf); - return 0; -} - -static int -suspend_callback (pthreadDebugClient_t context) -{ - /* Always suspended. */ - return 0; -} - -static int -resume_callback (pthreadDebugClient_t context) -{ - /* So no need to resume. */ - return 0; -} - -static int -kthdinfo_callback (pthreadDebugClient_t context, - pthreadDebugKId_t kid, - pthreadDebugKThreadInfo_p thread_info) -{ - if (trace_pthreaddbg) - term_puts ("kthinfo_callback"); - return ENOSYS; -} - -static int -hold_callback (pthreadDebugClient_t context, - pthreadDebugKId_t kid) -{ - if (trace_pthreaddbg) - term_puts ("hold_callback"); - return ENOSYS; -} - -static int -unhold_callback (pthreadDebugClient_t context, - pthreadDebugKId_t kid) -{ - if (trace_pthreaddbg) - term_puts ("unhold_callback"); - return ENOSYS; -} - -static int -getfreg_callback (pthreadDebugClient_t context, - pthreadDebugFregs_t *reg, - pthreadDebugKId_t kid) -{ - if (trace_pthreaddbg) - term_puts ("getfreg_callback"); - return ENOSYS; -} - -static int -setfreg_callback (pthreadDebugClient_t context, - const pthreadDebugFregs_t *reg, - pthreadDebugKId_t kid) -{ - if (trace_pthreaddbg) - term_puts ("setfreg_callback"); - return ENOSYS; -} - -static int -getreg_callback (pthreadDebugClient_t context, - pthreadDebugRegs_t *reg, - pthreadDebugKId_t kid) -{ - if (trace_pthreaddbg) - term_puts ("getreg_callback"); - return ENOSYS; -} - -static int -setreg_callback (pthreadDebugClient_t context, - const pthreadDebugRegs_t *reg, - pthreadDebugKId_t kid) -{ - if (trace_pthreaddbg) - term_puts ("setreg_callback"); - return ENOSYS; -} - -static int -output_callback (pthreadDebugClient_t context, - pthreadDebugConstString_t line) -{ - term_puts (line); - term_putnl (); - return 0; -} - -static int -error_callback (pthreadDebugClient_t context, - pthreadDebugConstString_t line) -{ - term_puts (line); - term_putnl (); - return 0; -} - -static pthreadDebugAddr_t -malloc_callback (pthreadDebugClient_t caller_context, size_t size) -{ - unsigned int status; - unsigned int res; - int len; - - len = size + 16; - status = lib$get_vm (&len, &res, 0); - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); - if (trace_pthreaddbg) - TERM_FAO ("malloc_callback (!UL) -> !XA!/", size, res); - *(unsigned int *)res = len; - return (char *)res + 16; -} - -static void -free_callback (pthreadDebugClient_t caller_context, pthreadDebugAddr_t address) -{ - unsigned int status; - unsigned int res; - int len; - - res = (unsigned int)address - 16; - len = *(unsigned int *)res; - if (trace_pthreaddbg) - TERM_FAO ("free_callback (!XA)!/", address); - status = lib$free_vm (&len, &res, 0); - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); -} - -static int -speckthd_callback (pthreadDebugClient_t caller_context, - pthreadDebugSpecialType_t type, - pthreadDebugKId_t *kernel_tid) -{ - return ENOTSUP; -} - -static pthreadDebugCallbacks_t pthread_debug_callbacks = { - PTHREAD_DEBUG_VERSION, - read_callback, - write_callback, - suspend_callback, - resume_callback, - kthdinfo_callback, - hold_callback, - unhold_callback, - getfreg_callback, - setfreg_callback, - getreg_callback, - setreg_callback, - output_callback, - error_callback, - malloc_callback, - free_callback, - speckthd_callback -}; - -/* Name of the pthread shared library. */ -static const $DESCRIPTOR (pthread_rtl_desc, "PTHREAD$RTL"); - -/* List of symbols to extract from pthread debug library. */ -struct pthread_debug_entry -{ - const unsigned int namelen; - const __char_ptr32 name; - __void_ptr32 func; -}; - -#define DEBUG_ENTRY(str) { sizeof(str) - 1, str, 0 } - -static struct pthread_debug_entry pthread_debug_entries[] = { - DEBUG_ENTRY("pthreadDebugContextInit"), - DEBUG_ENTRY("pthreadDebugThdSeqInit"), - DEBUG_ENTRY("pthreadDebugThdSeqNext"), - DEBUG_ENTRY("pthreadDebugThdSeqDestroy"), - DEBUG_ENTRY("pthreadDebugThdGetInfo"), - DEBUG_ENTRY("pthreadDebugThdGetInfoAddr"), - DEBUG_ENTRY("pthreadDebugThdGetReg"), - DEBUG_ENTRY("pthreadDebugCmd") -}; - -/* Pthread debug context. */ -static pthreadDebugContext_t debug_context; - -/* Wrapper around pthread debug entry points. */ - -static int -pthread_debug_thd_seq_init (pthreadDebugId_t *id) -{ - return ((int (*)())pthread_debug_entries[1].func) - (debug_context, id); -} - -static int -pthread_debug_thd_seq_next (pthreadDebugId_t *id) -{ - return ((int (*)())pthread_debug_entries[2].func) - (debug_context, id); -} - -static int -pthread_debug_thd_seq_destroy (void) -{ - return ((int (*)())pthread_debug_entries[3].func) - (debug_context); -} - -static int -pthread_debug_thd_get_info (pthreadDebugId_t id, - pthreadDebugThreadInfo_t *info) -{ - return ((int (*)())pthread_debug_entries[4].func) - (debug_context, id, info); -} - -static int -pthread_debug_thd_get_info_addr (pthread_t thr, - pthreadDebugThreadInfo_t *info) -{ - return ((int (*)())pthread_debug_entries[5].func) - (debug_context, thr, info); -} - -static int -pthread_debug_thd_get_reg (pthreadDebugId_t thr, - pthreadDebugRegs_t *regs) -{ - return ((int (*)())pthread_debug_entries[6].func) - (debug_context, thr, regs); -} - -static int -stub_pthread_debug_cmd (const char *cmd) -{ - return ((int (*)())pthread_debug_entries[7].func) - (debug_context, cmd); -} - -/* Show all the threads. */ - -static void -threads_show (void) -{ - pthreadDebugId_t id; - pthreadDebugThreadInfo_t info; - int res; - - res = pthread_debug_thd_seq_init (&id); - if (res != 0) - { - TERM_FAO ("seq init failed, res=!SL!/", res); - return; - } - while (1) - { - if (pthread_debug_thd_get_info (id, &info) != 0) - { - TERM_FAO ("thd_get_info !SL failed!/", id); - break; - } - if (pthread_debug_thd_seq_next (&id) != 0) - break; - } - pthread_debug_thd_seq_destroy (); -} - -/* Initialize pthread support. */ - -static void -threads_init (void) -{ - static const $DESCRIPTOR (dbgext_desc, "PTHREAD$DBGEXT"); - static const $DESCRIPTOR (pthread_debug_desc, "PTHREAD$DBGSHR"); - static const $DESCRIPTOR (dbgsymtable_desc, "PTHREAD_DBG_SYMTABLE"); - int pthread_dbgext; - int status; - void *dbg_symtable; - int i; - void *caller_context = 0; - - status = lib$find_image_symbol - ((void *) &pthread_rtl_desc, (void *) &dbgext_desc, - (int *) &dbgext_func); - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); - - status = lib$find_image_symbol - ((void *) &pthread_rtl_desc, (void *) &dbgsymtable_desc, - (int *) &dbg_symtable); - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); - - /* Find entry points in pthread_debug. */ - for (i = 0; - i < sizeof (pthread_debug_entries) / sizeof (pthread_debug_entries[0]); - i++) - { - struct dsc$descriptor_s sym = - { pthread_debug_entries[i].namelen, - DSC$K_DTYPE_T, DSC$K_CLASS_S, - pthread_debug_entries[i].name }; - status = lib$find_image_symbol - ((void *) &pthread_debug_desc, (void *) &sym, - (int *) &pthread_debug_entries[i].func); - if (!(status & STS$M_SUCCESS)) - lib$signal (status); - } - - if (trace_pthreaddbg) - TERM_FAO ("debug symtable: !XH!/", dbg_symtable); - status = ((int (*)()) pthread_debug_entries[0].func) - (&caller_context, &pthread_debug_callbacks, dbg_symtable, &debug_context); - if (status != 0) - TERM_FAO ("cannot initialize pthread_debug: !UL!/", status); - TERM_FAO ("pthread debug done!/", 0); -} - -/* Convert an hexadecimal character to a nibble. Return -1 in case of - error. */ - -static int -hex2nibble (unsigned char h) -{ - if (h >= '0' && h <= '9') - return h - '0'; - if (h >= 'A' && h <= 'F') - return h - 'A' + 10; - if (h >= 'a' && h <= 'f') - return h - 'a' + 10; - return -1; -} - -/* Convert an hexadecimal 2 character string to a byte. Return -1 in case - of error. */ - -static int -hex2byte (const unsigned char *p) -{ - int h, l; - - h = hex2nibble (p[0]); - l = hex2nibble (p[1]); - if (h == -1 || l == -1) - return -1; - return (h << 4) | l; -} - -/* Convert a byte V to a 2 character strings P. */ - -static void -byte2hex (unsigned char *p, unsigned char v) -{ - p[0] = hex[v >> 4]; - p[1] = hex[v & 0xf]; -} - -/* Convert a quadword V to a 16 character strings P. */ - -static void -quad2hex (unsigned char *p, unsigned __int64 v) -{ - int i; - for (i = 0; i < 16; i++) - { - p[i] = hex[v >> 60]; - v <<= 4; - } -} - -static void -long2pkt (unsigned int v) -{ - int i; - - for (i = 0; i < 8; i++) - { - gdb_buf[gdb_blen + i] = hex[(v >> 28) & 0x0f]; - v <<= 4; - } - gdb_blen += 8; -} - -/* Generate an error packet. */ - -static void -packet_error (unsigned int err) -{ - gdb_buf[1] = 'E'; - byte2hex (gdb_buf + 2, err); - gdb_blen = 4; -} - -/* Generate an OK packet. */ - -static void -packet_ok (void) -{ - gdb_buf[1] = 'O'; - gdb_buf[2] = 'K'; - gdb_blen = 3; -} - -/* Append a register to the packet. */ - -static void -ireg2pkt (const unsigned char *p) -{ - int i; - - for (i = 0; i < 8; i++) - { - byte2hex (gdb_buf + gdb_blen, p[i]); - gdb_blen += 2; - } -} - -/* Append a C string (ASCIZ) to the packet. */ - -static void -str2pkt (const char *str) -{ - while (*str) - gdb_buf[gdb_blen++] = *str++; -} - -/* Extract a number fro the packet. */ - -static unsigned __int64 -pkt2val (const unsigned char *pkt, unsigned int *pos) -{ - unsigned __int64 res = 0; - unsigned int i; - - while (1) - { - int r = hex2nibble (pkt[*pos]); - - if (r < 0) - return res; - res = (res << 4) | r; - (*pos)++; - } -} - -/* Append LEN bytes from B to the current gdb packet (encode in binary). */ - -static void -mem2bin (const unsigned char *b, unsigned int len) -{ - unsigned int i; - for (i = 0; i < len; i++) - switch (b[i]) - { - case '#': - case '$': - case '}': - case '*': - case 0: - gdb_buf[gdb_blen++] = '}'; - gdb_buf[gdb_blen++] = b[i] ^ 0x20; - break; - default: - gdb_buf[gdb_blen++] = b[i]; - break; - } -} - -/* Append LEN bytes from B to the current gdb packet (encode in hex). */ - -static void -mem2hex (const unsigned char *b, unsigned int len) -{ - unsigned int i; - for (i = 0; i < len; i++) - { - byte2hex (gdb_buf + gdb_blen, b[i]); - gdb_blen += 2; - } -} - -/* Handle the 'q' packet. */ - -static void -handle_q_packet (const unsigned char *pkt, unsigned int pktlen) -{ - /* For qfThreadInfo and qsThreadInfo. */ - static unsigned int first_thread; - static unsigned int last_thread; - - static const char xfer_uib[] = "qXfer:uib:read:"; -#define XFER_UIB_LEN (sizeof (xfer_uib) - 1) - static const char qfthreadinfo[] = "qfThreadInfo"; -#define QFTHREADINFO_LEN (sizeof (qfthreadinfo) - 1) - static const char qsthreadinfo[] = "qsThreadInfo"; -#define QSTHREADINFO_LEN (sizeof (qsthreadinfo) - 1) - static const char qthreadextrainfo[] = "qThreadExtraInfo,"; -#define QTHREADEXTRAINFO_LEN (sizeof (qthreadextrainfo) - 1) - static const char qsupported[] = "qSupported:"; -#define QSUPPORTED_LEN (sizeof (qsupported) - 1) - - if (pktlen == 2 && pkt[1] == 'C') - { - /* Current thread. */ - gdb_buf[0] = '$'; - gdb_buf[1] = 'Q'; - gdb_buf[2] = 'C'; - gdb_blen = 3; - if (has_threads) - long2pkt ((unsigned long) get_teb ()); - return; - } - else if (pktlen > XFER_UIB_LEN - && ots$strcmp_eql (pkt, XFER_UIB_LEN, xfer_uib, XFER_UIB_LEN)) - { - /* Get unwind information block. */ - unsigned __int64 pc; - unsigned int pos = XFER_UIB_LEN; - unsigned int off; - unsigned int len; - union - { - unsigned char bytes[32]; - struct - { - unsigned __int64 code_start_va; - unsigned __int64 code_end_va; - unsigned __int64 uib_start_va; - unsigned __int64 gp_value; - } data; - } uei; - int res; - int i; - - packet_error (0); - - pc = pkt2val (pkt, &pos); - if (pkt[pos] != ':') - return; - pos++; - off = pkt2val (pkt, &pos); - if (pkt[pos] != ',' || off != 0) - return; - pos++; - len = pkt2val (pkt, &pos); - if (pkt[pos] != '#' || len != 0x20) - return; - - res = SYS$GET_UNWIND_ENTRY_INFO (pc, &uei.data, 0); - if (res == SS$_NODATA || res != SS$_NORMAL) - ots$fill (uei.bytes, sizeof (uei.bytes), 0); - - if (trace_unwind) - { - TERM_FAO ("Unwind request for !XH, status=!XL, uib=!XQ, GP=!XQ!/", - pc, res, uei.data.uib_start_va, uei.data.gp_value); - } - - gdb_buf[0] = '$'; - gdb_buf[1] = 'l'; - gdb_blen = 2; - mem2bin (uei.bytes, sizeof (uei.bytes)); - } - else if (pktlen == QFTHREADINFO_LEN - && ots$strcmp_eql (pkt, QFTHREADINFO_LEN, - qfthreadinfo, QFTHREADINFO_LEN)) - { - /* Get first thread(s). */ - gdb_buf[0] = '$'; - gdb_buf[1] = 'm'; - gdb_blen = 2; - - if (!has_threads) - { - gdb_buf[1] = 'l'; - return; - } - first_thread = thread_next (0); - last_thread = first_thread; - long2pkt (first_thread); - } - else if (pktlen == QSTHREADINFO_LEN - && ots$strcmp_eql (pkt, QSTHREADINFO_LEN, - qsthreadinfo, QSTHREADINFO_LEN)) - { - /* Get subsequent threads. */ - gdb_buf[0] = '$'; - gdb_buf[1] = 'm'; - gdb_blen = 2; - while (dbgext_func) - { - unsigned int res; - res = thread_next (last_thread); - if (res == first_thread) - break; - if (gdb_blen > 2) - gdb_buf[gdb_blen++] = ','; - long2pkt (res); - last_thread = res; - if (gdb_blen > sizeof (gdb_buf) - 16) - break; - } - - if (gdb_blen == 2) - gdb_buf[1] = 'l'; - } - else if (pktlen > QTHREADEXTRAINFO_LEN - && ots$strcmp_eql (pkt, QTHREADEXTRAINFO_LEN, - qthreadextrainfo, QTHREADEXTRAINFO_LEN)) - { - /* Get extra info about a thread. */ - pthread_t thr; - unsigned int pos = QTHREADEXTRAINFO_LEN; - pthreadDebugThreadInfo_t info; - int res; - - packet_error (0); - if (!has_threads) - return; - - thr = (pthread_t) pkt2val (pkt, &pos); - if (pkt[pos] != '#') - return; - res = pthread_debug_thd_get_info_addr (thr, &info); - if (res != 0) - { - TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", thr, res); - return; - } - gdb_buf[0] = '$'; - gdb_blen = 1; - mem2hex ((const unsigned char *)"VMS-thread", 11); - } - else if (pktlen > QSUPPORTED_LEN - && ots$strcmp_eql (pkt, QSUPPORTED_LEN, - qsupported, QSUPPORTED_LEN)) - { - /* Get supported features. */ - pthread_t thr; - unsigned int pos = QSUPPORTED_LEN; - pthreadDebugThreadInfo_t info; - int res; - - /* Ignore gdb features. */ - gdb_buf[0] = '$'; - gdb_blen = 1; - - str2pkt ("qXfer:uib:read+"); - return; - } - else - { - if (trace_pkt) - { - term_puts ("unknown <: "); - term_write ((char *)pkt, pktlen); - term_putnl (); - } - return; - } -} - -/* Handle the 'v' packet. */ - -static int -handle_v_packet (const unsigned char *pkt, unsigned int pktlen) -{ - static const char vcontq[] = "vCont?"; -#define VCONTQ_LEN (sizeof (vcontq) - 1) - - if (pktlen == VCONTQ_LEN - && ots$strcmp_eql (pkt, VCONTQ_LEN, vcontq, VCONTQ_LEN)) - { - gdb_buf[0] = '$'; - gdb_blen = 1; - - str2pkt ("vCont;c;s"); - return 0; - } - else - { - if (trace_pkt) - { - term_puts ("unknown <: "); - term_write ((char *)pkt, pktlen); - term_putnl (); - } - return 0; - } -} - -/* Get regs for the selected thread. */ - -static struct ia64_all_regs * -get_selected_regs (void) -{ - pthreadDebugRegs_t regs; - int res; - - if (selected_thread == 0 || selected_thread == get_teb ()) - return &excp_regs; - - if (selected_thread == sel_regs_pthread) - return &sel_regs; - - /* Read registers. */ - res = pthread_debug_thd_get_reg (selected_id, ®s); - if (res != 0) - { - /* FIXME: return NULL ? */ - return &excp_regs; - } - sel_regs_pthread = selected_thread; - sel_regs.gr[1].v = regs.gp; - sel_regs.gr[4].v = regs.r4; - sel_regs.gr[5].v = regs.r5; - sel_regs.gr[6].v = regs.r6; - sel_regs.gr[7].v = regs.r7; - sel_regs.gr[12].v = regs.sp; - sel_regs.br[0].v = regs.rp; - sel_regs.br[1].v = regs.b1; - sel_regs.br[2].v = regs.b2; - sel_regs.br[3].v = regs.b3; - sel_regs.br[4].v = regs.b4; - sel_regs.br[5].v = regs.b5; - sel_regs.ip.v = regs.ip; - sel_regs.bsp.v = regs.bspstore; /* FIXME: it is correct ? */ - sel_regs.pfs.v = regs.pfs; - sel_regs.pr.v = regs.pr; - return &sel_regs; -} - -/* Create a status packet. */ - -static void -packet_status (void) -{ - gdb_blen = 0; - if (has_threads) - { - str2pkt ("$T05thread:"); - long2pkt ((unsigned long) get_teb ()); - gdb_buf[gdb_blen++] = ';'; - } - else - str2pkt ("$S05"); -} - -/* Return 1 to continue. */ - -static int -handle_packet (unsigned char *pkt, unsigned int len) -{ - unsigned int pos; - - /* By default, reply unsupported. */ - gdb_buf[0] = '$'; - gdb_blen = 1; - - pos = 1; - switch (pkt[0]) - { - case '?': - if (len == 1) - { - packet_status (); - return 0; - } - break; - case 'c': - if (len == 1) - { - /* Clear psr.ss. */ - excp_regs.psr.v &= ~(unsigned __int64)PSR$M_SS; - return 1; - } - else - packet_error (0); - break; - case 'g': - if (len == 1) - { - unsigned int i; - struct ia64_all_regs *regs = get_selected_regs (); - unsigned char *p = regs->gr[0].b; - - for (i = 0; i < 8 * 32; i++) - byte2hex (gdb_buf + 1 + 2 * i, p[i]); - gdb_blen += 2 * 8 * 32; - return 0; - } - break; - case 'H': - if (pkt[1] == 'g') - { - int res; - unsigned __int64 val; - pthreadDebugThreadInfo_t info; - - pos++; - val = pkt2val (pkt, &pos); - if (pos != len) - { - packet_error (0); - return 0; - } - if (val == 0) - { - /* Default one. */ - selected_thread = get_teb (); - selected_id = 0; - } - else if (!has_threads) - { - packet_error (0); - return 0; - } - else - { - res = pthread_debug_thd_get_info_addr ((pthread_t) val, &info); - if (res != 0) - { - TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", val, res); - packet_error (0); - return 0; - } - selected_thread = info.teb; - selected_id = info.sequence; - } - packet_ok (); - break; - } - else if (pkt[1] == 'c' - && ((pkt[2] == '-' && pkt[3] == '1' && len == 4) - || (pkt[2] == '0' && len == 3))) - { - /* Silently accept 'Hc0' and 'Hc-1'. */ - packet_ok (); - break; - } - else - { - packet_error (0); - return 0; - } - case 'k': - SYS$EXIT (SS$_NORMAL); - break; - case 'm': - { - unsigned __int64 addr; - unsigned __int64 paddr; - unsigned int l; - unsigned int i; - - addr = pkt2val (pkt, &pos); - if (pkt[pos] != ',') - { - packet_error (0); - return 0; - } - pos++; - l = pkt2val (pkt, &pos); - if (pkt[pos] != '#') - { - packet_error (0); - return 0; - } - - /* Check access. */ - i = l + (addr & VMS_PAGE_MASK); - paddr = addr & ~VMS_PAGE_MASK; - while (1) - { - if (__prober (paddr, 0) != 1) - { - packet_error (2); - return 0; - } - if (i < VMS_PAGE_SIZE) - break; - i -= VMS_PAGE_SIZE; - paddr += VMS_PAGE_SIZE; - } - - /* Transfer. */ - for (i = 0; i < l; i++) - byte2hex (gdb_buf + 1 + 2 * i, ((unsigned char *)addr)[i]); - gdb_blen += 2 * l; - } - break; - case 'M': - { - unsigned __int64 addr; - unsigned __int64 paddr; - unsigned int l; - unsigned int i; - unsigned int oldprot; - - addr = pkt2val (pkt, &pos); - if (pkt[pos] != ',') - { - packet_error (0); - return 0; - } - pos++; - l = pkt2val (pkt, &pos); - if (pkt[pos] != ':') - { - packet_error (0); - return 0; - } - pos++; - page_set_rw (addr, l, &oldprot); - - /* Check access. */ - i = l + (addr & VMS_PAGE_MASK); - paddr = addr & ~VMS_PAGE_MASK; - while (1) - { - if (__probew (paddr, 0) != 1) - { - page_restore_rw (addr, l, oldprot); - return 0; - } - if (i < VMS_PAGE_SIZE) - break; - i -= VMS_PAGE_SIZE; - paddr += VMS_PAGE_SIZE; - } - - /* Write. */ - for (i = 0; i < l; i++) - { - int v = hex2byte (pkt + pos); - pos += 2; - ((unsigned char *)addr)[i] = v; - } - - /* Sync caches. */ - for (i = 0; i < l; i += 15) - __fc (addr + i); - __fc (addr + l); - - page_restore_rw (addr, l, oldprot); - packet_ok (); - } - break; - case 'p': - { - unsigned int num = 0; - unsigned int i; - struct ia64_all_regs *regs = get_selected_regs (); - - num = pkt2val (pkt, &pos); - if (pos != len) - { - packet_error (0); - return 0; - } - - switch (num) - { - case IA64_IP_REGNUM: - ireg2pkt (regs->ip.b); - break; - case IA64_BR0_REGNUM: - ireg2pkt (regs->br[0].b); - break; - case IA64_PSR_REGNUM: - ireg2pkt (regs->psr.b); - break; - case IA64_BSP_REGNUM: - ireg2pkt (regs->bsp.b); - break; - case IA64_CFM_REGNUM: - ireg2pkt (regs->cfm.b); - break; - case IA64_PFS_REGNUM: - ireg2pkt (regs->pfs.b); - break; - case IA64_PR_REGNUM: - ireg2pkt (regs->pr.b); - break; - default: - TERM_FAO ("gdbserv: unhandled reg !UW!/", num); - packet_error (0); - return 0; - } - } - break; - case 'q': - handle_q_packet (pkt, len); - break; - case 's': - if (len == 1) - { - /* Set psr.ss. */ - excp_regs.psr.v |= (unsigned __int64)PSR$M_SS; - return 1; - } - else - packet_error (0); - break; - case 'T': - /* Thread status. */ - if (!has_threads) - { - packet_ok (); - break; - } - else - { - int res; - unsigned __int64 val; - unsigned int fthr, thr; - - val = pkt2val (pkt, &pos); - /* Default is error (but only after parsing is complete). */ - packet_error (0); - if (pos != len) - break; - - /* Follow the list. This makes a O(n2) algorithm, but we don't really - have the choice. Note that pthread_debug_thd_get_info_addr - doesn't look reliable. */ - fthr = thread_next (0); - thr = fthr; - do - { - if (val == thr) - { - packet_ok (); - break; - } - thr = thread_next (thr); - } - while (thr != fthr); - } - break; - case 'v': - return handle_v_packet (pkt, len); - break; - case 'V': - if (len > 3 && pkt[1] == 'M' && pkt[2] == 'S' && pkt[3] == ' ') - { - /* Temporary extension. */ - if (has_threads) - { - pkt[len] = 0; - stub_pthread_debug_cmd ((char *)pkt + 4); - packet_ok (); - } - else - packet_error (0); - } - break; - default: - if (trace_pkt) - { - term_puts ("unknown <: "); - term_write ((char *)pkt, len); - term_putnl (); - } - break; - } - return 0; -} - -/* Raw write to gdb. */ - -static void -sock_write (const unsigned char *buf, int len) -{ - struct _iosb iosb; - unsigned int status; - - /* Write data to connection. */ - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - conn_channel, /* I/O channel. */ - IO$_WRITEVBLK, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - (char *)buf, /* P1 - buffer address. */ - len, /* P2 - buffer length. */ - 0, 0, 0, 0); - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to write data to gdb\n"); - LIB$SIGNAL (status); - } -} - -/* Compute the checksum and send the packet. */ - -static void -send_pkt (void) -{ - unsigned char chksum = 0; - unsigned int i; - - for (i = 1; i < gdb_blen; i++) - chksum += gdb_buf[i]; - - gdb_buf[gdb_blen] = '#'; - byte2hex (gdb_buf + gdb_blen + 1, chksum); - - sock_write (gdb_buf, gdb_blen + 3); - - if (trace_pkt > 1) - { - term_puts (">: "); - term_write ((char *)gdb_buf, gdb_blen + 3); - term_putnl (); - } -} - -/* Read and handle one command. Return 1 is execution must resume. */ - -static int -one_command (void) -{ - struct _iosb iosb; - unsigned int status; - unsigned int off; - unsigned int dollar_off = 0; - unsigned int sharp_off = 0; - unsigned int cmd_off; - unsigned int cmd_len; - - /* Wait for a packet. */ - while (1) - { - off = 0; - while (1) - { - /* Read data from connection. */ - status = sys$qiow (EFN$C_ENF, /* Event flag. */ - conn_channel, /* I/O channel. */ - IO$_READVBLK, /* I/O function code. */ - &iosb, /* I/O status block. */ - 0, /* Ast service routine. */ - 0, /* Ast parameter. */ - gdb_buf + off, /* P1 - buffer address. */ - sizeof (gdb_buf) - off, /* P2 - buffer leng. */ - 0, 0, 0, 0); - if (status & STS$M_SUCCESS) - status = iosb.iosb$w_status; - if (!(status & STS$M_SUCCESS)) - { - term_puts ("Failed to read data from connection\n" ); - LIB$SIGNAL (status); - } - -#ifdef RAW_DUMP - term_puts ("{: "); - term_write ((char *)gdb_buf + off, iosb.iosb$w_bcnt); - term_putnl (); -#endif - - gdb_blen = off + iosb.iosb$w_bcnt; - - if (off == 0) - { - /* Search for '$'. */ - for (dollar_off = 0; dollar_off < gdb_blen; dollar_off++) - if (gdb_buf[dollar_off] == '$') - break; - if (dollar_off >= gdb_blen) - { - /* Not found, discard the data. */ - off = 0; - continue; - } - /* Search for '#'. */ - for (sharp_off = dollar_off + 1; - sharp_off < gdb_blen; - sharp_off++) - if (gdb_buf[sharp_off] == '#') - break; - } - else if (sharp_off >= off) - { - /* Search for '#'. */ - for (; sharp_off < gdb_blen; sharp_off++) - if (gdb_buf[sharp_off] == '#') - break; - } - - /* Got packet with checksum. */ - if (sharp_off + 2 <= gdb_blen) - break; - - off = gdb_blen; - if (gdb_blen == sizeof (gdb_buf)) - { - /* Packet too large, discard. */ - off = 0; - } - } - - /* Validate and acknowledge a packet. */ - { - unsigned char chksum = 0; - unsigned int i; - int v; - - for (i = dollar_off + 1; i < sharp_off; i++) - chksum += gdb_buf[i]; - v = hex2byte (gdb_buf + sharp_off + 1); - if (v != chksum) - { - term_puts ("Discard bad checksum packet\n"); - continue; - } - else - { - sock_write ((const unsigned char *)"+", 1); - break; - } - } - } - - if (trace_pkt > 1) - { - term_puts ("<: "); - term_write ((char *)gdb_buf + dollar_off, sharp_off - dollar_off + 1); - term_putnl (); - } - - cmd_off = dollar_off + 1; - cmd_len = sharp_off - dollar_off - 1; - - if (handle_packet (gdb_buf + dollar_off + 1, sharp_off - dollar_off - 1) == 1) - return 1; - - send_pkt (); - return 0; -} - -/* Display the condition given by SIG64. */ - -static void -display_excp (struct chf64$signal_array *sig64, struct chf$mech_array *mech) -{ - unsigned int status; - char msg[160]; - unsigned short msglen; - $DESCRIPTOR (msg_desc, msg); - unsigned char outadr[4]; - - status = SYS$GETMSG (sig64->chf64$q_sig_name, &msglen, &msg_desc, 0, outadr); - if (status & STS$M_SUCCESS) - { - char msg2[160]; - unsigned short msg2len; - struct dsc$descriptor_s msg2_desc = - { sizeof (msg2), DSC$K_DTYPE_T, DSC$K_CLASS_S, msg2}; - msg_desc.dsc$w_length = msglen; - status = SYS$FAOL_64 (&msg_desc, &msg2len, &msg2_desc, - &sig64->chf64$q_sig_arg1); - if (status & STS$M_SUCCESS) - term_write (msg2, msg2len); - } - else - term_puts ("no message"); - term_putnl (); - - if (trace_excp > 1) - { - TERM_FAO (" Frame: !XH, Depth: !4SL, Esf: !XH!/", - mech->chf$q_mch_frame, mech->chf$q_mch_depth, - mech->chf$q_mch_esf_addr); - } -} - -/* Get all registers from current thread. */ - -static void -read_all_registers (struct chf$mech_array *mech) -{ - struct _intstk *intstk = - (struct _intstk *)mech->chf$q_mch_esf_addr; - struct chf64$signal_array *sig64 = - (struct chf64$signal_array *)mech->chf$ph_mch_sig64_addr; - unsigned int cnt = sig64->chf64$w_sig_arg_count; - unsigned __int64 pc = (&sig64->chf64$q_sig_name)[cnt - 2]; - - excp_regs.ip.v = pc; - excp_regs.psr.v = intstk->intstk$q_ipsr; - /* GDB and linux expects bsp to point after the current register frame. - Adjust. */ - { - unsigned __int64 bsp = intstk->intstk$q_bsp; - unsigned int sof = intstk->intstk$q_ifs & 0x7f; - unsigned int delta = ((bsp >> 3) & 0x3f) + sof; - excp_regs.bsp.v = bsp + ((sof + delta / 0x3f) << 3); - } - excp_regs.cfm.v = intstk->intstk$q_ifs & 0x3fffffffff; - excp_regs.pfs.v = intstk->intstk$q_pfs; - excp_regs.pr.v = intstk->intstk$q_preds; - excp_regs.gr[0].v = 0; - excp_regs.gr[1].v = intstk->intstk$q_gp; - excp_regs.gr[2].v = intstk->intstk$q_r2; - excp_regs.gr[3].v = intstk->intstk$q_r3; - excp_regs.gr[4].v = intstk->intstk$q_r4; - excp_regs.gr[5].v = intstk->intstk$q_r5; - excp_regs.gr[6].v = intstk->intstk$q_r6; - excp_regs.gr[7].v = intstk->intstk$q_r7; - excp_regs.gr[8].v = intstk->intstk$q_r8; - excp_regs.gr[9].v = intstk->intstk$q_r9; - excp_regs.gr[10].v = intstk->intstk$q_r10; - excp_regs.gr[11].v = intstk->intstk$q_r11; - excp_regs.gr[12].v = (unsigned __int64)intstk + intstk->intstk$l_stkalign; - excp_regs.gr[13].v = intstk->intstk$q_r13; - excp_regs.gr[14].v = intstk->intstk$q_r14; - excp_regs.gr[15].v = intstk->intstk$q_r15; - excp_regs.gr[16].v = intstk->intstk$q_r16; - excp_regs.gr[17].v = intstk->intstk$q_r17; - excp_regs.gr[18].v = intstk->intstk$q_r18; - excp_regs.gr[19].v = intstk->intstk$q_r19; - excp_regs.gr[20].v = intstk->intstk$q_r20; - excp_regs.gr[21].v = intstk->intstk$q_r21; - excp_regs.gr[22].v = intstk->intstk$q_r22; - excp_regs.gr[23].v = intstk->intstk$q_r23; - excp_regs.gr[24].v = intstk->intstk$q_r24; - excp_regs.gr[25].v = intstk->intstk$q_r25; - excp_regs.gr[26].v = intstk->intstk$q_r26; - excp_regs.gr[27].v = intstk->intstk$q_r27; - excp_regs.gr[28].v = intstk->intstk$q_r28; - excp_regs.gr[29].v = intstk->intstk$q_r29; - excp_regs.gr[30].v = intstk->intstk$q_r30; - excp_regs.gr[31].v = intstk->intstk$q_r31; - excp_regs.br[0].v = intstk->intstk$q_b0; - excp_regs.br[1].v = intstk->intstk$q_b1; - excp_regs.br[2].v = intstk->intstk$q_b2; - excp_regs.br[3].v = intstk->intstk$q_b3; - excp_regs.br[4].v = intstk->intstk$q_b4; - excp_regs.br[5].v = intstk->intstk$q_b5; - excp_regs.br[6].v = intstk->intstk$q_b6; - excp_regs.br[7].v = intstk->intstk$q_b7; -} - -/* Write all registers to current thread. FIXME: not yet complete. */ - -static void -write_all_registers (struct chf$mech_array *mech) -{ - struct _intstk *intstk = - (struct _intstk *)mech->chf$q_mch_esf_addr; - - intstk->intstk$q_ipsr = excp_regs.psr.v; -} - -/* Do debugging. Report status to gdb and execute commands. */ - -static void -do_debug (struct chf$mech_array *mech) -{ - struct _intstk *intstk = - (struct _intstk *)mech->chf$q_mch_esf_addr; - unsigned int old_ast; - unsigned int old_sch; - unsigned int status; - - /* Disable ast. */ - status = sys$setast (0); - switch (status) - { - case SS$_WASCLR: - old_ast = 0; - break; - case SS$_WASSET: - old_ast = 1; - break; - default: - /* Should never happen! */ - lib$signal (status); - } - - /* Disable thread scheduling. */ - if (has_threads) - old_sch = set_thread_scheduling (0); - - read_all_registers (mech); - - /* Send stop reply packet. */ - packet_status (); - send_pkt (); - - while (one_command () == 0) - ; - - write_all_registers (mech); - - /* Re-enable scheduling. */ - if (has_threads) - set_thread_scheduling (old_sch); - - /* Re-enable AST. */ - status = sys$setast (old_ast); - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); -} - -/* The condition handler. That's the core of the stub. */ - -static int -excp_handler (struct chf$signal_array *sig, - struct chf$mech_array *mech) -{ - struct chf64$signal_array *sig64 = - (struct chf64$signal_array *)mech->chf$ph_mch_sig64_addr; - unsigned int code = sig->chf$l_sig_name & STS$M_COND_ID; - unsigned int cnt = sig64->chf64$w_sig_arg_count; - unsigned __int64 pc; - unsigned int ret; - /* Self protection. FIXME: Should be per thread ? */ - static int in_handler = 0; - - /* Completely ignore some conditions (signaled indirectly by this stub). */ - switch (code) - { - case LIB$_KEYNOTFOU & STS$M_COND_ID: - return SS$_RESIGNAL_64; - default: - break; - } - - /* Protect against recursion. */ - in_handler++; - if (in_handler > 1) - { - if (in_handler == 2) - TERM_FAO ("gdbstub: exception in handler (pc=!XH)!!!/", - (&sig64->chf64$q_sig_name)[cnt - 2]); - sys$exit (sig->chf$l_sig_name); - } - - pc = (&sig64->chf64$q_sig_name)[cnt - 2]; - if (trace_excp) - TERM_FAO ("excp_handler: code: !XL, pc=!XH!/", code, pc); - - /* If break on the entry point, restore the bundle. */ - if (code == (SS$_BREAK & STS$M_COND_ID) - && pc == entry_pc - && entry_pc != 0) - { - static unsigned int entry_prot; - - if (trace_entry) - term_puts ("initial entry breakpoint\n"); - page_set_rw (entry_pc, 16, &entry_prot); - - ots$move ((void *)entry_pc, 16, entry_saved); - __fc (entry_pc); - page_restore_rw (entry_pc, 16, entry_prot); - } - - switch (code) - { - case SS$_ACCVIO & STS$M_COND_ID: - if (trace_excp <= 1) - display_excp (sig64, mech); - /* Fall through. */ - case SS$_BREAK & STS$M_COND_ID: - case SS$_OPCDEC & STS$M_COND_ID: - case SS$_TBIT & STS$M_COND_ID: - case SS$_DEBUG & STS$M_COND_ID: - if (trace_excp > 1) - { - int i; - struct _intstk *intstk = - (struct _intstk *)mech->chf$q_mch_esf_addr; - - display_excp (sig64, mech); - - TERM_FAO (" intstk: !XH!/", intstk); - for (i = 0; i < cnt + 1; i++) - TERM_FAO (" !XH!/", ((unsigned __int64 *)sig64)[i]); - } - do_debug (mech); - ret = SS$_CONTINUE_64; - break; - - default: - display_excp (sig64, mech); - ret = SS$_RESIGNAL_64; - break; - } - - in_handler--; - /* Discard selected thread registers. */ - sel_regs_pthread = 0; - return ret; -} - -/* Setup internal trace flags according to GDBSTUB$TRACE logical. */ - -static void -trace_init (void) -{ - unsigned int status, i, start; - unsigned short len; - char resstring[LNM$C_NAMLENGTH]; - static const $DESCRIPTOR (tabdesc, "LNM$DCL_LOGICAL"); - static const $DESCRIPTOR (logdesc, "GDBSTUB$TRACE"); - $DESCRIPTOR (sub_desc, resstring); - ILE3 item_lst[2]; - - item_lst[0].ile3$w_length = LNM$C_NAMLENGTH; - item_lst[0].ile3$w_code = LNM$_STRING; - item_lst[0].ile3$ps_bufaddr = resstring; - item_lst[0].ile3$ps_retlen_addr = &len; - item_lst[1].ile3$w_length = 0; - item_lst[1].ile3$w_code = 0; - - /* Translate the logical name. */ - status = SYS$TRNLNM (0, /* Attributes of the logical name. */ - (void *)&tabdesc, /* Logical name table. */ - (void *)&logdesc, /* Logical name. */ - 0, /* Access mode. */ - &item_lst); /* Item list. */ - if (status == SS$_NOLOGNAM) - return; - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); - - start = 0; - for (i = 0; i <= len; i++) - { - if ((i == len || resstring[i] == ',' || resstring[i] == ';') - && i != start) - { - int j; - - sub_desc.dsc$a_pointer = resstring + start; - sub_desc.dsc$w_length = i - start; - - for (j = 0; j < NBR_DEBUG_FLAGS; j++) - if (str$case_blind_compare (&sub_desc, - (void *)&debug_flags[j].name) == 0) - { - debug_flags[j].val++; - break; - } - if (j == NBR_DEBUG_FLAGS) - TERM_FAO ("GDBSTUB$TRACE: unknown directive !AS!/", &sub_desc); - - start = i + 1; - } - } - - TERM_FAO ("GDBSTUB$TRACE=!AD ->", len, resstring); - for (i = 0; i < NBR_DEBUG_FLAGS; i++) - if (debug_flags[i].val > 0) - TERM_FAO (" !AS=!ZL", &debug_flags[i].name, debug_flags[i].val); - term_putnl (); -} - - -/* Entry point. */ - -static int -stub_start (unsigned __int64 *progxfer, void *cli_util, - EIHD *imghdr, IFD *imgfile, - unsigned int linkflag, unsigned int cliflag) -{ - static int initialized; - int i; - int cnt; - int is_attached; - IMCB *imcb; - if (initialized) - term_puts ("gdbstub: re-entry\n"); - else - initialized = 1; - - /* When attached (through SS$_DEBUG condition), the number of arguments - is 4 and PROGXFER is the PC at interruption. */ - va_count (cnt); - is_attached = cnt == 4; - - term_init (); - - /* Hello banner. */ - term_puts ("Hello from gdb stub\n"); - - trace_init (); - - if (trace_entry && !is_attached) - { - TERM_FAO ("xfer: !XH, imghdr: !XH, ifd: !XH!/", - progxfer, imghdr, imgfile); - for (i = -2; i < 8; i++) - TERM_FAO (" at !2SW: !XH!/", i, progxfer[i]); - } - - /* Search for entry point. */ - if (!is_attached) - { - entry_pc = 0; - for (i = 0; progxfer[i]; i++) - entry_pc = progxfer[i]; - - if (trace_entry) - { - if (entry_pc == 0) - { - term_puts ("No entry point\n"); - return 0; - } - else - TERM_FAO ("Entry: !XH!/",entry_pc); - } - } - else - entry_pc = progxfer[0]; - - has_threads = 0; - for (imcb = ctl$gl_imglstptr->imcb$l_flink; - imcb != ctl$gl_imglstptr; - imcb = imcb->imcb$l_flink) - { - if (ots$strcmp_eql (pthread_rtl_desc.dsc$a_pointer, - pthread_rtl_desc.dsc$w_length, - imcb->imcb$t_log_image_name + 1, - imcb->imcb$t_log_image_name[0])) - has_threads = 1; - - if (trace_images) - { - unsigned int j; - LDRIMG *ldrimg = imcb->imcb$l_ldrimg; - LDRISD *ldrisd; - - TERM_FAO ("!XA-!XA ", - imcb->imcb$l_starting_address, - imcb->imcb$l_end_address); - - switch (imcb->imcb$b_act_code) - { - case IMCB$K_MAIN_PROGRAM: - term_puts ("prog"); - break; - case IMCB$K_MERGED_IMAGE: - term_puts ("mrge"); - break; - case IMCB$K_GLOBAL_IMAGE_SECTION: - term_puts ("glob"); - break; - default: - term_puts ("????"); - } - TERM_FAO (" !AD !40AC!/", - 1, "KESU" + (imcb->imcb$b_access_mode & 3), - imcb->imcb$t_log_image_name); - - if ((long) ldrimg < 0 || trace_images < 2) - continue; - ldrisd = ldrimg->ldrimg$l_segments; - for (j = 0; j < ldrimg->ldrimg$l_segcount; j++) - { - unsigned int flags = ldrisd[j].ldrisd$i_flags; - term_puts (" "); - term_putc (flags & 0x04 ? 'R' : '-'); - term_putc (flags & 0x02 ? 'W' : '-'); - term_putc (flags & 0x01 ? 'X' : '-'); - term_puts (flags & 0x01000000 ? " Prot" : " "); - term_puts (flags & 0x04000000 ? " Shrt" : " "); - term_puts (flags & 0x08000000 ? " Shrd" : " "); - TERM_FAO (" !XA-!XA!/", - ldrisd[j].ldrisd$p_base, - (unsigned __int64) ldrisd[j].ldrisd$p_base - + ldrisd[j].ldrisd$i_len - 1); - } - ldrisd = ldrimg->ldrimg$l_dyn_seg; - if (ldrisd) - TERM_FAO (" dynamic !XA-!XA!/", - ldrisd->ldrisd$p_base, - (unsigned __int64) ldrisd->ldrisd$p_base - + ldrisd->ldrisd$i_len - 1); - } - } - - if (has_threads) - threads_init (); - - /* Wait for connection. */ - sock_init (); - - /* Set primary exception vector. */ - { - unsigned int status; - status = sys$setexv (0, excp_handler, PSL$C_USER, (__void_ptr32) &prevhnd); - if (!(status & STS$M_SUCCESS)) - LIB$SIGNAL (status); - } - - if (is_attached) - { - return excp_handler ((struct chf$signal_array *) progxfer[2], - (struct chf$mech_array *) progxfer[3]); - } - - /* Change first instruction to set a breakpoint. */ - { - /* - 01 08 00 40 00 00 [MII] break.m 0x80001 - 00 00 00 02 00 00 nop.i 0x0 - 00 00 04 00 nop.i 0x0;; - */ - static const unsigned char initbp[16] = - { 0x01, 0x08, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x00 }; - unsigned int entry_prot; - unsigned int status; - - status = page_set_rw (entry_pc, 16, &entry_prot); - - if (!(status & STS$M_SUCCESS)) - { - if ((status & STS$M_COND_ID) == (SS$_NOT_PROCESS_VA & STS$M_COND_ID)) - { - /* Cannot write here. This can happen when pthreads are - used. */ - entry_pc = 0; - term_puts ("gdbstub: cannot set breakpoint on entry\n"); - } - else - LIB$SIGNAL (status); - } - - if (entry_pc != 0) - { - ots$move (entry_saved, 16, (void *)entry_pc); - ots$move ((void *)entry_pc, 16, (void *)initbp); - __fc (entry_pc); - page_restore_rw (entry_pc, 16, entry_prot); - } - } - - /* If it wasn't possible to set a breakpoint on the entry point, - accept gdb commands now. Note that registers are not updated. */ - if (entry_pc == 0) - { - while (one_command () == 0) - ; - } - - /* We will see! */ - return SS$_CONTINUE; -} - -/* Declare the entry point of this relocatable module. */ - -struct xfer_vector -{ - __int64 impure_start; - __int64 impure_end; - int (*entry) (); -}; - -#pragma __extern_model save -#pragma __extern_model strict_refdef "XFER_PSECT" -struct xfer_vector xfer_vector = {0, 0, stub_start}; -#pragma __extern_model restore diff --git a/gdb/symtab.c b/gdb/symtab.c index 58648a8779d..bc926ee3021 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -4040,10 +4040,7 @@ skip_prologue_sal (struct symtab_and_line *sal) while not getting into the function body. The functions end point and an increasing SAL line are used as - indicators of the prologue's endpoint. - - This code is based on the function refine_prologue_limit - (found in ia64). */ + indicators of the prologue's endpoint. */ CORE_ADDR skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) diff --git a/gdb/target.h b/gdb/target.h index 394e377d034..9d88ee00ffa 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -154,8 +154,6 @@ enum target_object /* Memory known to be part of the target code. This is cached even if it is not in a region marked as such. */ TARGET_OBJECT_CODE_MEMORY, - /* Kernel Unwind Table. See "ia64-tdep.c". */ - TARGET_OBJECT_UNWIND_TABLE, /* Transfer auxilliary vector. */ TARGET_OBJECT_AUXV, /* StackGhost cookie. See "sparc-tdep.c". */ diff --git a/gdb/testsuite/configure b/gdb/testsuite/configure index 3b0d4ed8ad3..7d6e9e8b8dd 100755 --- a/gdb/testsuite/configure +++ b/gdb/testsuite/configure @@ -2229,9 +2229,7 @@ else # The following exceptions are taken from Libtool 1.4.3. case $host_os in aix*) - if test $host_cpu != ia64; then - RPATH_ENVVAR=LIBPATH - fi ;; + RPATH_ENVVAR=LIBPATH ;; darwin* | rhapsody*) RPATH_ENVVAR=DYLD_LIBRARY_PATH ;; esac diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac index 8c0b60502c7..93040e1878d 100644 --- a/gdb/testsuite/configure.ac +++ b/gdb/testsuite/configure.ac @@ -64,9 +64,7 @@ else # The following exceptions are taken from Libtool 1.4.3. case $host_os in aix*) - if test $host_cpu != ia64; then - RPATH_ENVVAR=LIBPATH - fi ;; + RPATH_ENVVAR=LIBPATH ;; darwin* | rhapsody*) RPATH_ENVVAR=DYLD_LIBRARY_PATH ;; esac diff --git a/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.S b/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.S deleted file mode 100644 index eec63e5144b..00000000000 --- a/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.S +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2009-2024 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, see . - - This file is part of the gdb testsuite. - It tests displaced stepping over various insns that require special - handling. */ - - .text - .align 16 - .global main - .proc main -main: - mov r2=r12 - mov r14=1 - ;; -bundle: - /* Store value 1 into `long' variable on stack. */ - st8.rel [r2]=r14 - /* This long constant requires L-X slot in this bundle. */ - movl r14=0x7fffffff - ;; - /* Store value 0x7fffffff into `long' variable on stack. */ - st8.rel [r2]=r14 - mov r14=r0 - ;; - mov r8=r14 - mov r12=r2 - br.ret.sptk.many b0 - - .endp main - - .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.exp b/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.exp deleted file mode 100644 index 7a1e529eb8c..00000000000 --- a/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.exp +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2009-2024 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, see . - -require {istarget "ia64-*-*"} - -set testfile ia64-breakpoint-shadow -set srcfile ${testfile}.S -set binfile ${objdir}/${subdir}/${testfile} -if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { - untested "failed to compile" - return -1 -} - -clean_restart $binfile - -# We need to start the inferior to place the breakpoints in the memory at all. -if ![runto_main] { - return -1 -} - -# The default "auto" mode removes all the breakpoints when we stop (and not -# running the nonstop mode). We would not be able to test the shadow. -gdb_test "set breakpoint always-inserted on" -gdb_test "show breakpoint always-inserted" "Always inserted breakpoint mode is on." - -set match "\nDump of assembler code for function main:\r\n(.*)End of assembler dump.\r\n$gdb_prompt $" - -set test "disassembly without breakpoints" -gdb_test_multiple "disass main" $test { - -re $match { - set orig $expect_out(1,string) - pass $test - } -} - -set test "slot 0 breakpoint placed" -gdb_test_multiple "b bundle" $test { - -re "Breakpoint \[0-9\] at (0x\[0-9a-f\]*0):.*$gdb_prompt $" { - pass $test - set bpt2address $expect_out(1,string) - } -} - -if ![info exists bpt2address] { - return -1 -} - -gdb_test "b *($bpt2address + 1)" "Breakpoint \[0-9\] at .*" "slot 1 breakpoint placed" -gdb_test "b *($bpt2address + 2)" "Can't insert breakpoint for non-existing slot X" "slot 2 (slot X) breakpoint refusal" - -set test "disassembly with breakpoints" -gdb_test_multiple "disass main" $test { - -re $match { - set got $expect_out(1,string) - if [string equal -nocase $orig $got] { - pass $test - } else { - fail $test - } - } -} diff --git a/gdb/testsuite/gdb.asm/asm-source.exp b/gdb/testsuite/gdb.asm/asm-source.exp index 80c48ea03bd..f51de71d3b9 100644 --- a/gdb/testsuite/gdb.asm/asm-source.exp +++ b/gdb/testsuite/gdb.asm/asm-source.exp @@ -139,10 +139,6 @@ switch -glob -- [istarget] { "m68k-*-*" { set asm-arch m68k } - "ia64-*-*" { - set asm-arch ia64 - set debug-flags "-gdwarf-2" - } "iq2000-*-*" { set asm-arch iq2000 } diff --git a/gdb/testsuite/gdb.asm/ia64.inc b/gdb/testsuite/gdb.asm/ia64.inc deleted file mode 100644 index c42e398a40b..00000000000 --- a/gdb/testsuite/gdb.asm/ia64.inc +++ /dev/null @@ -1,51 +0,0 @@ - comment "subroutine prologue" - .macro gdbasm_enter - alloc r33=ar.pfs,0,2,0,0 - mov r32=b0 - nop.i 0 - .endm - - comment "subroutine epilogue" - .macro gdbasm_leave - nop.m 0 - mov ar.pfs=r33 - mov b0=r32 - nop.m 0 - nop.f 0 - br.ret.sptk.many b0 - .endm - - .macro gdbasm_call subr - nop.m 0 - nop.f 0 - br.call.sptk.many b0=\subr - .endm - - .macro gdbasm_several_nops - nop.m 0 - nop.i 0 - nop.i 0 - .endm - - comment "exit (0)" - .macro gdbasm_exit0 - break.m 0x0 - nop.m 0 - nop.i 0 - .endm - - comment "crt0 startup" - .macro gdbasm_startup - gdbasm_enter - mov r32=r0 - nop.i 0 - nop.i 0 - .endm - - comment "Declare a data variable" - .purgem gdbasm_datavar - .macro gdbasm_datavar name value - .data -\name: - .long \value - .endm diff --git a/gdb/testsuite/gdb.base/callfuncs.exp b/gdb/testsuite/gdb.base/callfuncs.exp index 494b6dfa96f..5e116139ceb 100644 --- a/gdb/testsuite/gdb.base/callfuncs.exp +++ b/gdb/testsuite/gdb.base/callfuncs.exp @@ -257,12 +257,7 @@ proc fetch_all_registers {test} { exp_continue } -re "^bspstore\[ \t\]+\[^\r\n\]+\r\n" { - if [istarget "ia64-*-*"] { - # Filter out bspstore which is specially tied to bsp, - # giving spurious differences. - } else { - lappend all_registers_lines $expect_out(0,string) - } + lappend all_registers_lines $expect_out(0,string) exp_continue } -re "^pstate\[ \t\]+\[^\r\n\]+\r\n" { diff --git a/gdb/testsuite/gdb.base/float.exp b/gdb/testsuite/gdb.base/float.exp index 49dc0a3299c..304a5c7b5da 100644 --- a/gdb/testsuite/gdb.base/float.exp +++ b/gdb/testsuite/gdb.base/float.exp @@ -55,8 +55,6 @@ if {[is_aarch64_target]} { } } elseif {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} { gdb_test "info float" "R7:.*Status Word:.*Opcode:.*" -} elseif {[istarget "ia64-*-*"]} { - gdb_test "info float" "f0.*f1.*f127.*" } elseif {[istarget "m68k-*-*"]} { gdb_test_multiple "info float" "info_float" { -re "fp0.*fp1.*fp7.*$gdb_prompt $" { diff --git a/gdb/testsuite/gdb.base/step-test.exp b/gdb/testsuite/gdb.base/step-test.exp index 6e6f89b7872..dca752e7d0a 100644 --- a/gdb/testsuite/gdb.base/step-test.exp +++ b/gdb/testsuite/gdb.base/step-test.exp @@ -60,11 +60,10 @@ gdb_test "step" ".*${decimal}.*myglob.*" "step into" # call? # On PA64, we end up at a different instruction than PA32. -# On IA-64, we also end up on callee instead of on the next line due +# On MIPS, we also end up on callee instead of on the next line due # to the restoration of the global pointer (which is a caller-save). -# Similarly on MIPS PIC targets. set test "step out" -if { [istarget "ia64-*-*"] || [istarget "mips*-*-*"]} { +if { [istarget "mips*-*-*"]} { gdb_test_multiple "finish" "$test" { -re ".*${decimal}.*a.*5.*= a.*3.*$gdb_prompt $" { pass "$test" @@ -153,10 +152,9 @@ gdb_test_multiple "finish" "$test" { } -re ".*${decimal}.*callee.*STEPI.*$gdb_prompt $" { # On PA64, we end up at a different instruction than PA32. - # On IA-64, we end up on callee instead of on the following line due + # On MIPS, we end up on callee instead of on the following line due # to the restoration of the global pointer. - # Similarly on MIPS PIC targets. - if { [istarget "ia64-*-*"] || [istarget "mips*-*-*"] } { + if { [istarget "mips*-*-*"] } { test_i "$test" "stepi" \ ".*${decimal}.*callee.*STEPI" ".*${decimal}.*callee.*NEXTI" } else { diff --git a/gdb/testsuite/gdb.dwarf2/pr10770.c b/gdb/testsuite/gdb.dwarf2/pr10770.c index 64dfc91ce75..b7e0ed4aa8e 100644 --- a/gdb/testsuite/gdb.dwarf2/pr10770.c +++ b/gdb/testsuite/gdb.dwarf2/pr10770.c @@ -4,7 +4,6 @@ /* HP-UX libunwind.so doesn't provide _UA_END_OF_STACK */ /* { dg-do run } */ /* { dg-options "-fexceptions" } */ -/* { dg-skip-if "" { "ia64-*-hpux11.*" } { "*" } { "" } } */ /* Verify DW_OP_* handling in the unwinder. */ #include diff --git a/gdb/testsuite/gdb.threads/clone-attach-detach.c b/gdb/testsuite/gdb.threads/clone-attach-detach.c index b07f0963cf1..7e01b41685d 100644 --- a/gdb/testsuite/gdb.threads/clone-attach-detach.c +++ b/gdb/testsuite/gdb.threads/clone-attach-detach.c @@ -50,12 +50,7 @@ main (int argc, char **argv) #define CLONE_FLAGS (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM) -#ifdef __ia64__ - clone_pid = __clone2 (clone_fn, stack, STACK_SIZE, CLONE_FLAGS, NULL); -#else clone_pid = clone (clone_fn, stack + STACK_SIZE, CLONE_FLAGS, NULL); -#endif - assert (clone_pid > 0); /* Wait for alarm. */ diff --git a/gdb/testsuite/gdb.threads/clone-thread_db.c b/gdb/testsuite/gdb.threads/clone-thread_db.c index 50843def3e9..cdcb786a87b 100644 --- a/gdb/testsuite/gdb.threads/clone-thread_db.c +++ b/gdb/testsuite/gdb.threads/clone-thread_db.c @@ -46,12 +46,7 @@ thread_fn (void *arg) stack = malloc (STACK_SIZE); assert (stack != NULL); -#ifdef __ia64__ - clone_pid = __clone2 (clone_fn, stack, STACK_SIZE, CLONE_VM, NULL); -#else clone_pid = clone (clone_fn, stack + STACK_SIZE, CLONE_VM, NULL); -#endif - assert (clone_pid > 0); /* Wait for child. */ diff --git a/gdb/testsuite/gdb.threads/ia64-sigill.c b/gdb/testsuite/gdb.threads/ia64-sigill.c deleted file mode 100644 index 183f376ce9b..00000000000 --- a/gdb/testsuite/gdb.threads/ia64-sigill.c +++ /dev/null @@ -1,371 +0,0 @@ -/* This testcase is part of GDB, the GNU debugger. - - Copyright 2010-2024 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, see . */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define gettid() syscall (__NR_gettid) - -/* Terminate always in the main task, it can lock up with SIGSTOPped GDB - otherwise. */ -#define TIMEOUT (gettid () == getpid() ? 10 : 15) - -static pid_t thread1_tid; -static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; - -static pid_t thread2_tid; -static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; - -static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; - -static pthread_barrier_t threads_started_barrier; - -/* Do not use alarm as it would create a ptrace event which would hang up us if - we are being traced by GDB which we stopped ourselves. */ - -static void timed_mutex_lock (pthread_mutex_t *mutex) -{ - int i; - struct timespec start, now; - - i = clock_gettime (CLOCK_MONOTONIC, &start); - assert (i == 0); - - do - { - i = pthread_mutex_trylock (mutex); - if (i == 0) - return; - assert (i == EBUSY); - - i = clock_gettime (CLOCK_MONOTONIC, &now); - assert (i == 0); - assert (now.tv_sec >= start.tv_sec); - } - while (now.tv_sec - start.tv_sec < TIMEOUT); - - fprintf (stderr, "Timed out waiting for internal lock!\n"); - exit (EXIT_FAILURE); -} - -static void * -thread_func (void *threadno_voidp) -{ - int threadno = (intptr_t) threadno_voidp; - int i; - - pthread_barrier_wait (&threads_started_barrier); - - switch (threadno) - { - case 1: - timed_mutex_lock (&thread1_tid_mutex); - - /* THREAD1_TID_MUTEX must be already locked to avoid race. */ - thread1_tid = gettid (); - - i = pthread_cond_signal (&thread1_tid_cond); - assert (i == 0); - i = pthread_mutex_unlock (&thread1_tid_mutex); - assert (i == 0); - - break; - - case 2: - timed_mutex_lock (&thread2_tid_mutex); - - /* THREAD2_TID_MUTEX must be already locked to avoid race. */ - thread2_tid = gettid (); - - i = pthread_cond_signal (&thread2_tid_cond); - assert (i == 0); - i = pthread_mutex_unlock (&thread2_tid_mutex); - assert (i == 0); - - break; - - default: - assert (0); - } - -#ifdef __ia64__ - asm volatile ("label:\n" - "nop.m 0\n" - "nop.i 0\n" - "nop.b 0\n"); -#endif - /* break-here */ - - /* Be sure the "t (tracing stop)" test can proceed for both threads. */ - timed_mutex_lock (&terminate_mutex); - i = pthread_mutex_unlock (&terminate_mutex); - assert (i == 0); - - return NULL; -} - -static const char * -proc_string (const char *filename, const char *line) -{ - FILE *f; - static char buf[LINE_MAX]; - size_t line_len = strlen (line); - - f = fopen (filename, "r"); - if (f == NULL) - { - fprintf (stderr, "fopen (\"%s\") for \"%s\": %s\n", filename, line, - strerror (errno)); - exit (EXIT_FAILURE); - } - while (errno = 0, fgets (buf, sizeof (buf), f)) - { - char *s; - - s = strchr (buf, '\n'); - assert (s != NULL); - *s = 0; - - if (strncmp (buf, line, line_len) != 0) - continue; - - if (fclose (f)) - { - fprintf (stderr, "fclose (\"%s\") for \"%s\": %s\n", filename, line, - strerror (errno)); - exit (EXIT_FAILURE); - } - - return &buf[line_len]; - } - if (errno != 0) - { - fprintf (stderr, "fgets (\"%s\": %s\n", filename, strerror (errno)); - exit (EXIT_FAILURE); - } - fprintf (stderr, "\"%s\": No line \"%s\" found.\n", filename, line); - exit (EXIT_FAILURE); -} - -static unsigned long -proc_ulong (const char *filename, const char *line) -{ - const char *s = proc_string (filename, line); - long retval; - char *end; - - errno = 0; - retval = strtol (s, &end, 10); - if (retval < 0 || retval >= LONG_MAX || (end && *end)) - { - fprintf (stderr, "\"%s\":\"%s\": %ld, %s\n", filename, line, retval, - strerror (errno)); - exit (EXIT_FAILURE); - } - return retval; -} - -static void -state_wait (pid_t process, const char *wanted) -{ - char *filename; - int i; - struct timespec start, now; - const char *state; - - i = asprintf (&filename, "/proc/%lu/status", (unsigned long) process); - assert (i > 0); - - i = clock_gettime (CLOCK_MONOTONIC, &start); - assert (i == 0); - - do - { - state = proc_string (filename, "State:\t"); - - /* torvalds/linux-2.6.git 464763cf1c6df632dccc8f2f4c7e50163154a2c0 - has changed "T (tracing stop)" to "t (tracing stop)". Make the GDB - testcase backward compatible with older Linux kernels. */ - if (strcmp (state, "T (tracing stop)") == 0) - state = "t (tracing stop)"; - - if (strcmp (state, wanted) == 0) - { - free (filename); - return; - } - - if (sched_yield ()) - { - perror ("sched_yield()"); - exit (EXIT_FAILURE); - } - - i = clock_gettime (CLOCK_MONOTONIC, &now); - assert (i == 0); - assert (now.tv_sec >= start.tv_sec); - } - while (now.tv_sec - start.tv_sec < TIMEOUT); - - fprintf (stderr, "Timed out waiting for PID %lu \"%s\" (now it is \"%s\")!\n", - (unsigned long) process, wanted, state); - exit (EXIT_FAILURE); -} - -static volatile pid_t tracer = 0; -static pthread_t thread1, thread2; - -static void -cleanup (void) -{ - printf ("Resuming GDB PID %lu.\n", (unsigned long) tracer); - - if (tracer) - { - int i; - int tracer_save = tracer; - - tracer = 0; - - i = kill (tracer_save, SIGCONT); - assert (i == 0); - } -} - -int -main (int argc, char **argv) -{ - int i; - int standalone = 0; - - if (argc == 2 && strcmp (argv[1], "-s") == 0) - standalone = 1; - else - assert (argc == 1); - - setbuf (stdout, NULL); - - timed_mutex_lock (&thread1_tid_mutex); - timed_mutex_lock (&thread2_tid_mutex); - - timed_mutex_lock (&terminate_mutex); - - pthread_barrier_init (&threads_started_barrier, NULL, 3); - - i = pthread_create (&thread1, NULL, thread_func, (void *) (intptr_t) 1); - assert (i == 0); - - i = pthread_create (&thread2, NULL, thread_func, (void *) (intptr_t) 2); - assert (i == 0); - - if (!standalone) - { - tracer = proc_ulong ("/proc/self/status", "TracerPid:\t"); - if (tracer == 0) - { - fprintf (stderr, "The testcase must be run by GDB!\n"); - exit (EXIT_FAILURE); - } - if (tracer != getppid ()) - { - fprintf (stderr, "The testcase parent must be our GDB tracer!\n"); - exit (EXIT_FAILURE); - } - } - - /* SIGCONT our debugger in the case of our crash as we would deadlock - otherwise. */ - - atexit (cleanup); - - /* Wait until all threads are seen running. On Linux (at least), - new threads start stopped, and the debugger must resume them. - Need to wait for that before stopping GDB. */ - pthread_barrier_wait (&threads_started_barrier); - - printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer); - - if (tracer) - { - i = kill (tracer, SIGSTOP); - assert (i == 0); - state_wait (tracer, "T (stopped)"); - } - - /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) and so - they could not trigger the breakpoint before GDB gets unstopped later. - Threads get resumed at pthread_cond_wait below. Use `while' loops for - protection against spurious pthread_cond_wait wakeups. */ - - printf ("Waiting till the threads initialize their TIDs.\n"); - - while (thread1_tid == 0) - { - i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex); - assert (i == 0); - } - - while (thread2_tid == 0) - { - i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex); - assert (i == 0); - } - - printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n", - (unsigned long) thread1_tid, (unsigned long) thread2_tid, - (unsigned long) getpid ()); - - printf ("Waiting till the threads get trapped by the breakpoint.\n"); - - if (tracer) - { - /* s390x-unknown-linux-gnu will fail with "R (running)". */ - - state_wait (thread1_tid, "t (tracing stop)"); - - state_wait (thread2_tid, "t (tracing stop)"); - } - - cleanup (); - - printf ("Joining the threads.\n"); - - i = pthread_mutex_unlock (&terminate_mutex); - assert (i == 0); - - i = pthread_join (thread1, NULL); - assert (i == 0); - - i = pthread_join (thread2, NULL); - assert (i == 0); - - printf ("Exiting.\n"); /* break-at-exit */ - - return EXIT_SUCCESS; -} diff --git a/gdb/testsuite/gdb.threads/ia64-sigill.exp b/gdb/testsuite/gdb.threads/ia64-sigill.exp deleted file mode 100644 index 05f998244f6..00000000000 --- a/gdb/testsuite/gdb.threads/ia64-sigill.exp +++ /dev/null @@ -1,77 +0,0 @@ -# This testcase is part of GDB, the GNU debugger. - -# Copyright 2010-2024 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, see . - -# Test SIGILL generated by some special cases of breakpoints on ia64. Problem -# was SIGILL being stored in non-current thread for later retrieval when its -# breakpoint has been already deleted. moribund locations are not active in -# the default all-stop mode. - -standard_testfile -if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" ${binfile} executable [list debug additional_flags=-lrt]] != "" } { - return -1 -} - -clean_restart $testfile - -if ![runto_main] { - return -1 -} - -set test "info addr label" -gdb_test_multiple $test $test { - -re "Symbol \"label\" is at 0x\[0-9a-f\]+0 in .*\r\n$gdb_prompt $" { - # Verify the label really starts at the start of ia64 bundle. - pass $test - - # ia64 generates SIGILL for breakpoint at B slot of an MIB bundle. - gdb_test "break *label+2" {Breakpoint [0-9]+ at 0x[0-9a-f]+2:.*} - } - -re "No symbol \"label\" in current context\\.\r\n$gdb_prompt $" { - pass $test - - # Either this target never generates non-SIGTRAP signals or they do - # not depend on the breakpoint address. Try any address. - gdb_breakpoint [gdb_get_line_number "break-here"] - } -} - -gdb_test_no_output {set $sigill_bpnum=$bpnum} - -gdb_breakpoint [gdb_get_line_number "break-at-exit"] - -gdb_test_no_output "set debug infrun 1" - -# The ia64 SIGILL signal is visible only in the linux-nat debug output. - -set prompt "$gdb_prompt \\\[infrun\\\] fetch_inferior_event: exit\r\n$" -gdb_test_multiple "continue" "continue" -prompt $prompt { - -re "Breakpoint \[0-9\]+,( .* in)? thread_func .*$prompt$" { - pass $gdb_test_name - } -} - -gdb_test_no_output {delete $sigill_bpnum} - -gdb_test_multiple "continue" "continue for the pending signal" -prompt $prompt { - -re "Breakpoint \[0-9\]+, .*break-at-exit.*\r\n$prompt$" { - # Breakpoint has been skipped in the other thread. - pass $gdb_test_name - } - -re " received signal .*\r\n$gdb_prompt $" { - fail $gdb_test_name - } -} diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 0d78691c381..9203ff5ab40 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -4572,7 +4572,6 @@ proc allow_hw_breakpoint_tests {} { # These targets support hardware breakpoints natively if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] - || [istarget "ia64-*-*"] || [istarget "arm*-*-*"] || [istarget "aarch64*-*-*"] || [istarget "s390*-*-*"] } { @@ -4596,7 +4595,6 @@ proc allow_hw_watchpoint_tests {} { # watchpoint support on Powerpc. if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] - || [istarget "ia64-*-*"] || [istarget "arm*-*-*"] || [istarget "aarch64*-*-*"] || ([istarget "powerpc*-*-linux*"] && [has_hw_wp_support]) diff --git a/gdb/top.c b/gdb/top.c index b93ef0a69b5..2b4a6402e70 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -1423,16 +1423,6 @@ This GDB was configured as follows:\n\ --with-jit-reader-dir=%s%s\n\ "), JIT_READER_DIR, JIT_READER_DIR_RELOCATABLE ? " (relocatable)" : ""); -#if HAVE_LIBUNWIND_IA64_H - gdb_printf (stream, _("\ - --with-libunwind-ia64\n\ -")); -#else - gdb_printf (stream, _("\ - --without-libunwind-ia64\n\ -")); -#endif - #if HAVE_LIBLZMA gdb_printf (stream, _("\ --with-lzma\n\ diff --git a/gdbserver/configure.srv b/gdbserver/configure.srv index 9e861a75088..b9d47845d8d 100644 --- a/gdbserver/configure.srv +++ b/gdbserver/configure.srv @@ -129,10 +129,6 @@ case "${gdbserver_host}" in srv_tgtobj="${srv_tgtobj} nat/netbsd-nat.o" srv_tgtobj="${srv_tgtobj} arch/i386.o" ;; - ia64-*-linux*) srv_regobj=reg-ia64.o - srv_tgtobj="$srv_linux_obj linux-ia64-low.o" - srv_linux_usrregs=yes - ;; loongarch*-*-linux*) srv_tgtobj="arch/loongarch.o linux-loongarch-low.o" srv_tgtobj="${srv_tgtobj} ${srv_linux_obj}" srv_linux_regsets=yes diff --git a/gdbserver/linux-ia64-low.cc b/gdbserver/linux-ia64-low.cc deleted file mode 100644 index b7c3c642eb3..00000000000 --- a/gdbserver/linux-ia64-low.cc +++ /dev/null @@ -1,395 +0,0 @@ -/* GNU/Linux/IA64 specific low level interface, for the remote server for GDB. - Copyright (C) 1995-2024 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 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, see . */ - -#include "linux-low.h" - -#ifdef HAVE_SYS_REG_H -#include -#endif - -/* Linux target op definitions for the IA64 architecture. */ - -class ia64_target : public linux_process_target -{ -public: - - const regs_info *get_regs_info () override; - - const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override; - -protected: - - void low_arch_setup () override; - - bool low_cannot_fetch_register (int regno) override; - - bool low_cannot_store_register (int regno) override; - - bool low_fetch_register (regcache *regcache, int regno) override; - - bool low_breakpoint_at (CORE_ADDR pc) override; -}; - -/* The singleton target ops object. */ - -static ia64_target the_ia64_target; - -const gdb_byte * -ia64_target::sw_breakpoint_from_kind (int kind, int *size) -{ - gdb_assert_not_reached ("target op sw_breakpoint_from_kind is not " - "implemented by this target"); -} - -bool -ia64_target::low_breakpoint_at (CORE_ADDR pc) -{ - gdb_assert_not_reached ("linux target op low_breakpoint_at is not " - "implemented by this target"); -} - -/* Defined in auto-generated file reg-ia64.c. */ -void init_registers_ia64 (void); -extern const struct target_desc *tdesc_ia64; - -#define ia64_num_regs 462 - -#include - -static int ia64_regmap[] = - { - /* general registers */ - -1, /* gr0 not available; i.e, it's always zero */ - PT_R1, - PT_R2, - PT_R3, - PT_R4, - PT_R5, - PT_R6, - PT_R7, - PT_R8, - PT_R9, - PT_R10, - PT_R11, - PT_R12, - PT_R13, - PT_R14, - PT_R15, - PT_R16, - PT_R17, - PT_R18, - PT_R19, - PT_R20, - PT_R21, - PT_R22, - PT_R23, - PT_R24, - PT_R25, - PT_R26, - PT_R27, - PT_R28, - PT_R29, - PT_R30, - PT_R31, - /* gr32 through gr127 not directly available via the ptrace interface */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* Floating point registers */ - -1, -1, /* f0 and f1 not available (f0 is +0.0 and f1 is +1.0) */ - PT_F2, - PT_F3, - PT_F4, - PT_F5, - PT_F6, - PT_F7, - PT_F8, - PT_F9, - PT_F10, - PT_F11, - PT_F12, - PT_F13, - PT_F14, - PT_F15, - PT_F16, - PT_F17, - PT_F18, - PT_F19, - PT_F20, - PT_F21, - PT_F22, - PT_F23, - PT_F24, - PT_F25, - PT_F26, - PT_F27, - PT_F28, - PT_F29, - PT_F30, - PT_F31, - PT_F32, - PT_F33, - PT_F34, - PT_F35, - PT_F36, - PT_F37, - PT_F38, - PT_F39, - PT_F40, - PT_F41, - PT_F42, - PT_F43, - PT_F44, - PT_F45, - PT_F46, - PT_F47, - PT_F48, - PT_F49, - PT_F50, - PT_F51, - PT_F52, - PT_F53, - PT_F54, - PT_F55, - PT_F56, - PT_F57, - PT_F58, - PT_F59, - PT_F60, - PT_F61, - PT_F62, - PT_F63, - PT_F64, - PT_F65, - PT_F66, - PT_F67, - PT_F68, - PT_F69, - PT_F70, - PT_F71, - PT_F72, - PT_F73, - PT_F74, - PT_F75, - PT_F76, - PT_F77, - PT_F78, - PT_F79, - PT_F80, - PT_F81, - PT_F82, - PT_F83, - PT_F84, - PT_F85, - PT_F86, - PT_F87, - PT_F88, - PT_F89, - PT_F90, - PT_F91, - PT_F92, - PT_F93, - PT_F94, - PT_F95, - PT_F96, - PT_F97, - PT_F98, - PT_F99, - PT_F100, - PT_F101, - PT_F102, - PT_F103, - PT_F104, - PT_F105, - PT_F106, - PT_F107, - PT_F108, - PT_F109, - PT_F110, - PT_F111, - PT_F112, - PT_F113, - PT_F114, - PT_F115, - PT_F116, - PT_F117, - PT_F118, - PT_F119, - PT_F120, - PT_F121, - PT_F122, - PT_F123, - PT_F124, - PT_F125, - PT_F126, - PT_F127, - /* predicate registers - we don't fetch these individually */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - /* branch registers */ - PT_B0, - PT_B1, - PT_B2, - PT_B3, - PT_B4, - PT_B5, - PT_B6, - PT_B7, - /* virtual frame pointer and virtual return address pointer */ - -1, -1, - /* other registers */ - PT_PR, - PT_CR_IIP, /* ip */ - PT_CR_IPSR, /* psr */ - PT_CFM, /* cfm */ - /* kernel registers not visible via ptrace interface (?) */ - -1, -1, -1, -1, -1, -1, -1, -1, - /* hole */ - -1, -1, -1, -1, -1, -1, -1, -1, - PT_AR_RSC, - PT_AR_BSP, - PT_AR_BSPSTORE, - PT_AR_RNAT, - -1, - -1, /* Not available: FCR, IA32 floating control register */ - -1, -1, - -1, /* Not available: EFLAG */ - -1, /* Not available: CSD */ - -1, /* Not available: SSD */ - -1, /* Not available: CFLG */ - -1, /* Not available: FSR */ - -1, /* Not available: FIR */ - -1, /* Not available: FDR */ - -1, - PT_AR_CCV, - -1, -1, -1, - PT_AR_UNAT, - -1, -1, -1, - PT_AR_FPSR, - -1, -1, -1, - -1, /* Not available: ITC */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, - PT_AR_PFS, - PT_AR_LC, - PT_AR_EC, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, - }; - -bool -ia64_target::low_cannot_store_register (int regno) -{ - return false; -} - -bool -ia64_target::low_cannot_fetch_register (int regno) -{ - return false; -} - -/* GDB register numbers. */ -#define IA64_GR0_REGNUM 0 -#define IA64_FR0_REGNUM 128 -#define IA64_FR1_REGNUM 129 - -bool -ia64_target::low_fetch_register (regcache *regcache, int regnum) -{ - /* r0 cannot be fetched but is always zero. */ - if (regnum == IA64_GR0_REGNUM) - { - const gdb_byte zero[8] = { 0 }; - - gdb_assert (sizeof (zero) == register_size (regcache->tdesc, regnum)); - supply_register (regcache, regnum, zero); - return true; - } - - /* fr0 cannot be fetched but is always zero. */ - if (regnum == IA64_FR0_REGNUM) - { - const gdb_byte f_zero[16] = { 0 }; - - gdb_assert (sizeof (f_zero) == register_size (regcache->tdesc, regnum)); - supply_register (regcache, regnum, f_zero); - return true; - } - - /* fr1 cannot be fetched but is always one (1.0). */ - if (regnum == IA64_FR1_REGNUM) - { - const gdb_byte f_one[16] = - { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 }; - - gdb_assert (sizeof (f_one) == register_size (regcache->tdesc, regnum)); - supply_register (regcache, regnum, f_one); - return true; - } - - return false; -} - -static struct usrregs_info ia64_usrregs_info = - { - ia64_num_regs, - ia64_regmap, - }; - -static struct regs_info myregs_info = - { - NULL, /* regset_bitmap */ - &ia64_usrregs_info - }; - -const regs_info * -ia64_target::get_regs_info () -{ - return &myregs_info; -} - -void -ia64_target::low_arch_setup () -{ - current_process ()->tdesc = tdesc_ia64; -} - -/* The linux target ops object. */ - -linux_process_target *the_linux_target = &the_ia64_target; - -void -initialize_low_arch (void) -{ - init_registers_ia64 (); -}