From 65aefbb89e5c7c229d046fbb90efe61ccea2f477 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Mon, 12 Jun 2023 23:26:05 +0300 Subject: [PATCH] Update HP libunwind to v1.7.0 --- src/native/external/libunwind-version.txt | 24 +- src/native/external/libunwind.cmake | 4 +- .../libunwind/.github/workflows/CI-unix.yml | 129 ++++ .../libunwind/.github/workflows/CI-win.yml | 37 ++ src/native/external/libunwind/.travis.yml | 84 --- src/native/external/libunwind/Makefile.am | 1 + src/native/external/libunwind/NEWS | 26 +- src/native/external/libunwind/README | 48 +- src/native/external/libunwind/acinclude.m4 | 1 - src/native/external/libunwind/configure.ac | 36 +- src/native/external/libunwind/doc/Makefile.am | 8 +- .../libunwind/doc/libunwind-dynamic.man | 576 +++++++++--------- .../libunwind/doc/libunwind-dynamic.tex | 18 +- .../external/libunwind/doc/libunwind.man | 15 +- .../external/libunwind/doc/libunwind.tex | 10 +- .../external/libunwind/doc/unw_backtrace.man | 25 +- .../external/libunwind/doc/unw_backtrace.tex | 9 +- .../external/libunwind/doc/unw_backtrace2.man | 1 + .../libunwind/doc/unw_get_proc_info.man | 8 +- .../libunwind/doc/unw_get_proc_info.tex | 4 +- .../libunwind/doc/unw_get_proc_info_by_ip.man | 16 +- .../libunwind/doc/unw_get_proc_info_by_ip.tex | 10 +- .../libunwind/doc/unw_get_proc_name.man | 6 +- .../libunwind/doc/unw_get_proc_name.tex | 2 +- .../libunwind/doc/unw_get_proc_name_by_ip.man | 139 +++++ .../libunwind/doc/unw_get_proc_name_by_ip.tex | 93 +++ .../external/libunwind/doc/unw_init_local.man | 24 +- .../external/libunwind/doc/unw_init_local.tex | 16 +- .../libunwind/doc/unw_reg_states_iterate.man | 6 +- .../libunwind/doc/unw_reg_states_iterate.tex | 2 +- src/native/external/libunwind/include/dwarf.h | 5 +- .../libunwind/include/libunwind-aarch64.h | 25 +- .../libunwind/include/libunwind-arm.h | 6 +- .../libunwind/include/libunwind-common.h.in | 24 +- .../libunwind/include/libunwind-dynamic.h | 2 +- .../libunwind/include/libunwind-loongarch64.h | 2 +- .../libunwind/include/libunwind-x86.h | 6 + .../external/libunwind/include/libunwind_i.h | 8 +- .../include/remote/freebsd-elf_common.h | 2 +- .../libunwind/include/tdep-arm/libunwind_i.h | 4 + .../libunwind/include/tdep-ia64/libunwind_i.h | 2 +- .../libunwind/include/tdep-x86/dwarf-config.h | 2 - .../libunwind/include/tdep-x86/libunwind_i.h | 73 +-- .../libunwind/scripts/qemu-test-driver | 156 +++++ .../external/libunwind/src/CMakeLists.txt | 4 +- src/native/external/libunwind/src/Makefile.am | 13 +- .../external/libunwind/src/aarch64/Ginit.c | 19 +- .../external/libunwind/src/aarch64/Gregs.c | 39 ++ .../libunwind/src/aarch64/Gstash_frame.c | 9 + .../external/libunwind/src/aarch64/Gstep.c | 129 ++-- .../external/libunwind/src/aarch64/init.h | 7 +- .../external/libunwind/src/aarch64/offsets.h | 7 + .../external/libunwind/src/aarch64/unwind_i.h | 4 + .../external/libunwind/src/arm/Gex_tables.c | 18 +- .../external/libunwind/src/arm/Gos-freebsd.c | 5 +- .../external/libunwind/src/arm/Gos-linux.c | 5 +- .../external/libunwind/src/arm/Gstash_frame.c | 9 + src/native/external/libunwind/src/arm/Gstep.c | 55 +- .../libunwind/src/coredump/_UCD_access_mem.c | 109 ++-- .../src/coredump/_UCD_access_reg_linux.c | 86 +-- .../libunwind/src/coredump/_UCD_create.c | 130 +--- .../libunwind/src/coredump/_UCD_destroy.c | 9 +- .../src/coredump/_UCD_elf_map_image.c | 24 +- .../src/coredump/_UCD_find_proc_info.c | 18 +- .../src/coredump/_UCD_get_mapinfo_linux.c | 144 +++-- .../src/coredump/_UCD_get_proc_name.c | 80 ++- .../coredump/_UCD_get_threadinfo_prstatus.c | 54 +- .../libunwind/src/coredump/_UCD_internal.h | 63 +- .../src/coredump/_UPT_access_fpreg.c | 21 +- .../libunwind/src/coredump/ucd_file_table.c | 275 +++++++++ .../libunwind/src/coredump/ucd_file_table.h | 83 +++ .../external/libunwind/src/dwarf/Gexpr.c | 5 +- .../external/libunwind/src/dwarf/Gfde.c | 14 +- .../libunwind/src/dwarf/Gfind_proc_info-lsb.c | 4 +- .../libunwind/src/dwarf/Gfind_unwind_table.c | 16 +- .../{mi => dwarf}/Gget_proc_info_in_range.c | 0 .../external/libunwind/src/dwarf/Gparser.c | 112 +++- .../{mi => dwarf}/Lget_proc_info_in_range.c | 0 src/native/external/libunwind/src/elfxx.c | 12 +- src/native/external/libunwind/src/elfxx.h | 1 - .../external/libunwind/src/ia64/Gscript.c | 2 +- .../external/libunwind/src/ia64/Gtables.c | 2 +- .../libunwind/src/loongarch64/Ginit.c | 21 +- .../libunwind/src/loongarch64/Gresume.c | 40 +- .../libunwind/src/loongarch64/Gstep.c | 8 +- .../libunwind/src/loongarch64/offsets.h | 12 +- .../libunwind/src/mi/Gget_proc_name.c | 11 +- .../external/libunwind/src/mi/backtrace.c | 47 +- src/native/external/libunwind/src/mi/init.c | 2 +- .../external/libunwind/src/mips/Gstep.c | 5 +- src/native/external/libunwind/src/os-linux.c | 20 +- .../external/libunwind/src/ppc32/Ginit.c | 12 + .../external/libunwind/src/ppc32/init.h | 2 +- .../external/libunwind/src/ppc32/setcontext.S | 9 - .../external/libunwind/src/ppc32/ucontext_i.h | 198 +++--- .../external/libunwind/src/ppc64/setcontext.S | 9 - .../libunwind/src/ptrace/_UPT_access_fpreg.c | 7 +- .../libunwind/src/ptrace/_UPT_reg_offset.c | 70 +-- .../src/remote/mac/missing-functions.c | 1 + .../external/libunwind/src/riscv/Gstep.c | 3 + .../external/libunwind/src/s390x/Gstep.c | 3 + src/native/external/libunwind/src/sh/Gstep.c | 5 +- .../libunwind/src/tilegx/Gis_signal_frame.c | 3 + .../external/libunwind/src/tilegx/Gstep.c | 2 +- .../external/libunwind/src/x86/Gos-freebsd.c | 4 + .../external/libunwind/src/x86/Gos-linux.c | 8 +- src/native/external/libunwind/src/x86/Gregs.c | 2 +- src/native/external/libunwind/src/x86/Gstep.c | 4 +- .../external/libunwind/src/x86_64/Ginit.c | 2 +- .../libunwind/src/x86_64/Gos-freebsd.c | 6 +- .../libunwind/src/x86_64/Gos-solaris.c | 4 + .../external/libunwind/src/x86_64/Gregs.c | 2 +- .../libunwind/src/x86_64/Gstash_frame.c | 8 +- .../external/libunwind/src/x86_64/Gstep.c | 31 +- .../external/libunwind/src/x86_64/Gtrace.c | 2 +- .../libunwind/tests/Garm64-test-sve-signal.c | 121 ++++ .../external/libunwind/tests/Gia64-test-nat.c | 1 + .../external/libunwind/tests/Gtest-bt.c | 23 +- .../external/libunwind/tests/Gtest-trace.c | 65 ++ .../libunwind/tests/Larm64-test-sve-signal.c | 5 + .../external/libunwind/tests/Makefile.am | 24 +- .../libunwind/tests/check-namespace.sh.in | 64 +- src/native/external/libunwind/tests/crasher.c | 4 +- .../libunwind/tests/run-coredump-unwind | 4 + .../libunwind/tests/test-coredump-unwind.c | 16 +- .../tests/x64-test-dwarf-expressions.S | 2 +- 126 files changed, 2872 insertions(+), 1302 deletions(-) create mode 100644 src/native/external/libunwind/.github/workflows/CI-unix.yml create mode 100644 src/native/external/libunwind/.github/workflows/CI-win.yml delete mode 100644 src/native/external/libunwind/.travis.yml delete mode 100644 src/native/external/libunwind/acinclude.m4 create mode 100644 src/native/external/libunwind/doc/unw_backtrace2.man create mode 100644 src/native/external/libunwind/doc/unw_get_proc_name_by_ip.man create mode 100644 src/native/external/libunwind/doc/unw_get_proc_name_by_ip.tex create mode 100755 src/native/external/libunwind/scripts/qemu-test-driver create mode 100644 src/native/external/libunwind/src/coredump/ucd_file_table.c create mode 100644 src/native/external/libunwind/src/coredump/ucd_file_table.h rename src/native/external/libunwind/src/{mi => dwarf}/Gget_proc_info_in_range.c (100%) rename src/native/external/libunwind/src/{mi => dwarf}/Lget_proc_info_in_range.c (100%) delete mode 100644 src/native/external/libunwind/src/ppc32/setcontext.S delete mode 100644 src/native/external/libunwind/src/ppc64/setcontext.S create mode 100644 src/native/external/libunwind/tests/Garm64-test-sve-signal.c create mode 100644 src/native/external/libunwind/tests/Larm64-test-sve-signal.c diff --git a/src/native/external/libunwind-version.txt b/src/native/external/libunwind-version.txt index d3fef9166e615..de52659948a1c 100644 --- a/src/native/external/libunwind-version.txt +++ b/src/native/external/libunwind-version.txt @@ -1,20 +1,6 @@ -v1.6.2 -https://github.com/libunwind/libunwind/commit/b3ca1b59a795a617877c01fe5d299ab7a07ff29d +v1.7.0 +https://github.com/libunwind/libunwind/commit/688caaf6ef9853cc26ad8bd1706804d48a0df0bc -Apply https://github.com/libunwind/libunwind/pull/317 -Apply https://github.com/libunwind/libunwind/pull/330 -Apply https://github.com/libunwind/libunwind/pull/333 -Apply https://github.com/libunwind/libunwind/pull/342 -Apply https://github.com/libunwind/libunwind/pull/353 -Apply https://github.com/libunwind/libunwind/pull/358 -Apply https://github.com/libunwind/libunwind/commit/7cf6e84bb86ff5840896b4910ccc3865d4f00ffb -Apply https://github.com/libunwind/libunwind/pull/365 -Apply https://github.com/libunwind/libunwind/pull/377 -Apply https://github.com/libunwind/libunwind/pull/382 -Apply https://github.com/libunwind/libunwind/pull/398 -Apply https://github.com/libunwind/libunwind/pull/400 -Apply https://github.com/libunwind/libunwind/pull/414 -Apply https://github.com/libunwind/libunwind/pull/416 - -For LoongArch64: -Apply https://github.com/libunwind/libunwind/pull/316 and https://github.com/libunwind/libunwind/pull/322 +Apply https://github.com/libunwind/libunwind/pull/457 +Apply https://github.com/libunwind/libunwind/pull/455 +Apply https://github.com/libunwind/libunwind/pull/460 diff --git a/src/native/external/libunwind.cmake b/src/native/external/libunwind.cmake index 73815d821588e..dc40fc28c1f5b 100644 --- a/src/native/external/libunwind.cmake +++ b/src/native/external/libunwind.cmake @@ -37,7 +37,7 @@ set(libunwind_la_SOURCES_generic # the source is excluded here to prevent name clash #mi/Gget_accessors.c mi/Gget_proc_info_by_ip.c mi/Gget_proc_name.c - mi/Gget_proc_info_in_range.c + dwarf/Gget_proc_info_in_range.c mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c mi/Gget_reg.c mi/Gset_reg.c mi/Gget_fpreg.c mi/Gset_fpreg.c @@ -117,7 +117,7 @@ set(libunwind_la_SOURCES_local_nounwind mi/Ldyn-extract.c mi/Lfind_dynamic_proc_info.c mi/Lget_accessors.c mi/Lget_proc_info_by_ip.c mi/Lget_proc_name.c - mi/Lget_proc_info_in_range.c + dwarf/Lget_proc_info_in_range.c mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c mi/Lget_reg.c mi/Lset_reg.c mi/Lget_fpreg.c mi/Lset_fpreg.c diff --git a/src/native/external/libunwind/.github/workflows/CI-unix.yml b/src/native/external/libunwind/.github/workflows/CI-unix.yml new file mode 100644 index 0000000000000..7d48b48daec03 --- /dev/null +++ b/src/native/external/libunwind/.github/workflows/CI-unix.yml @@ -0,0 +1,129 @@ +name: CI - Unix + +on: + pull_request: + paths: + - '**' + - '!README' + - '!INSTALL' + - '!NEWS' + - '!doc/**' + - '!.**' + - '.github/workflows/CI-unix.yml' + push: + branches: + - v[0-9].* + - master + +jobs: + build: + runs-on: ubuntu-latest + name: build-${{ join(matrix.*, ' ') }} + strategy: + fail-fast: false + matrix: + HOST: + - x86_64-linux-gnu + - x86-linux-gnu + - arm-linux-gnueabihf + - aarch64-linux-gnu + - mipsel-linux-gnu + - powerpc64-linux-gnu + OPT: + - O0 + - O3 + steps: + - uses: actions/checkout@v2 + - name: Setup + run: | + HOST=${{ matrix.HOST }} + if [ $HOST = 'x86-linux-gnu' ]; then + sudo apt-get update + sudo apt-get install -yqq -o=Dpkg::Use-Pty=0 g++-multilib + elif [ $HOST != 'x86_64-linux-gnu' ]; then + sudo apt-get update + sudo apt-get install -yqq -o=Dpkg::Use-Pty=0 g++-$HOST + fi + - name: Configure + run: | + set -x + HOST=${{ matrix.HOST }} + BUILD=x86_64-linux-gnu + if [ $HOST = 'x86-linux-gnu' ]; then + CFLAGS="-m32" + CXXFLAGS="-m32" + BUILD=x86-linux-gnu + fi + export CFLAGS="$CFLAGS -${{ matrix.OPT }}" + export CXXFLAGS="$CXXFLAGS -${{ matrix.OPT}}" + autoreconf -i + ./configure --build=$BUILD --host=$HOST + make -j8 + - name: Test (native) + if: ${{ success() && (matrix.HOST == 'x86_64-linux-gnu' || matrix.HOST == 'x86-linux-gnu') }} + run: | + set -x + sudo bash -c 'echo core.%p.%p > /proc/sys/kernel/core_pattern' + ulimit -c unlimited + make check -j32 + - name: Show Logs + if: ${{ failure() }} + run: | + cat tests/test-suite.log 2>/dev/null + + build-cross-qemu: + runs-on: ubuntu-latest + name: build-cross-qemu-${{ matrix.config.target }} + + strategy: + fail-fast: false + matrix: + config: + - {target: arm, toolchain: g++-arm-linux-gnueabi, host: arm-linux-gnueabi, qemu: arm } + - {target: armhf, toolchain: g++-arm-linux-gnueabihf, host: arm-linux-gnueabihf, qemu: arm } + - {target: aarch64, toolchain: g++-aarch64-linux-gnu, host: aarch64-linux-gnu, qemu: aarch64 } + - {target: riscv64, toolchain: g++-riscv64-linux-gnu, host: riscv64-linux-gnu, qemu: riscv64 } + - {target: ppc, toolchain: g++-powerpc-linux-gnu, host: powerpc-linux-gnu, qemu: ppc } + - {target: ppc64, toolchain: g++-powerpc64-linux-gnu, host: powerpc64-linux-gnu, qemu: ppc64 } + - {target: ppc64le, toolchain: g++-powerpc64le-linux-gnu, host: powerpc64le-linux-gnu, qemu: ppc64le } + - {target: s390x, toolchain: g++-s390x-linux-gnu, host: s390x-linux-gnu, qemu: s390x } + - {target: mips, toolchain: g++-mips-linux-gnu, host: mips-linux-gnu, qemu: mips } + - {target: mips64, toolchain: g++-mips64-linux-gnuabi64, host: mips64-linux-gnuabi64, qemu: mips64 } + - {target: mipsel, toolchain: g++-mipsel-linux-gnu, host: mipsel-linux-gnu, qemu: mipsel } + - {target: mips64el,toolchain: g++-mips64el-linux-gnuabi64, host: mips64el-linux-gnuabi64,qemu: mips64el } + + steps: + - uses: actions/checkout@v2 + - name: Install QEMU + # this ensure install latest qemu on ubuntu, apt get version is old + env: + QEMU_SRC: "http://archive.ubuntu.com/ubuntu/pool/universe/q/qemu" + QEMU_VER: "qemu-user-static_4\\.2-.*_amd64.deb$" + run: | + DEB=`curl -s $QEMU_SRC/ | grep -o -E 'href="([^"#]+)"' | cut -d'"' -f2 | grep $QEMU_VER | tail -1` + wget $QEMU_SRC/$DEB + sudo dpkg -i $DEB + - name: Install ${{ matrix.config.toolchain }} + run: | + sudo apt update + sudo apt install ${{ matrix.config.toolchain }} -y + - name: Configure with ${{ matrix.config.cc }} + run: | + set -x + autoreconf -i + BUILD=x86_64-linux-gnu + ./configure --build=$BUILD --host=${{ matrix.config.host }} --with-testdriver=$(pwd)/scripts/qemu-test-driver + - name: Build + run: | + make -j8 + - name: Test + run: | + set -x + sudo bash -c 'echo core.%p.%p > /proc/sys/kernel/core_pattern' + ulimit -c unlimited + CROSS_LIB="/usr/${{ matrix.config.host }}" + make -j8 check LOG_DRIVER_FLAGS="--qemu-arch ${{ matrix.config.qemu }}" LDFLAGS="-L$CROSS_LIB/lib -static" QEMU_LD_PREFIX="$CROSS_LIB" + - name: Show Logs + if: ${{ failure() }} + run: | + cat tests/test-suite.log 2>/dev/null diff --git a/src/native/external/libunwind/.github/workflows/CI-win.yml b/src/native/external/libunwind/.github/workflows/CI-win.yml new file mode 100644 index 0000000000000..7effb9b23af87 --- /dev/null +++ b/src/native/external/libunwind/.github/workflows/CI-win.yml @@ -0,0 +1,37 @@ +name: CI - Windows + +on: + pull_request: + paths: + - '**' + - '!README' + - '!INSTALL' + - '!NEWS' + - '!doc/**' + - '!.**' + - '.github/workflows/CI-win.yml' + push: + branches: + - v[0-9].* + - master + +jobs: + build-windows: + runs-on: windows-${{ matrix.config.server }} + name: build ${{ matrix.config.TARGET }} + strategy: + fail-fast: false + matrix: + config: + - {toolchain: Visual Studio 17 2022, arch: Win32, server: 2022, TARGET: arm-linux-gnueabihf} + - {toolchain: Visual Studio 17 2022, arch: x64, server: 2022, TARGET: aarch64-linux-gnu} + - {toolchain: Visual Studio 17 2022, arch: x64, server: 2022, TARGET: x86_64-linux-gnu} + steps: + - uses: actions/checkout@v2 + - name: Build + shell: cmd + env: + TARGET: ${{ matrix.config.TARGET }} + run: | + cmake -G "${{ matrix.config.toolchain }}" -A ${{ matrix.config.arch }} -S . -B bin/windows-${{ matrix.config.arch }}/${{ matrix.config.TARGET }} + cmake --build bin/windows-${{ matrix.config.arch }}/${{ matrix.config.TARGET }} diff --git a/src/native/external/libunwind/.travis.yml b/src/native/external/libunwind/.travis.yml deleted file mode 100644 index dd16ee24e9665..0000000000000 --- a/src/native/external/libunwind/.travis.yml +++ /dev/null @@ -1,84 +0,0 @@ -sudo: required -language: c -compiler: gcc -env: -- HOST=x86_64-linux-gnu OPT=-O0 -- HOST=x86-linux-gnu OPT=-O0 -- HOST=arm-linux-gnueabihf OPT=-O0 -- HOST=aarch64-linux-gnu OPT=-O0 -- HOST=mipsel-linux-gnu OPT=-O0 -- HOST=powerpc64-linux-gnu OPT=-O0 -- HOST=x86_64-linux-gnu OPT=-O2 -- HOST=x86-linux-gnu OPT=-O2 -- HOST=arm-linux-gnueabihf OPT=-O2 -- HOST=aarch64-linux-gnu OPT=-O2 -- HOST=mipsel-linux-gnu OPT=-O2 -- HOST=powerpc64-linux-gnu OPT=-O2 -- HOST=x86_64-linux-gnu OPT=-O3 -- HOST=x86-linux-gnu OPT=-O3 -- HOST=arm-linux-gnueabihf OPT=-O3 -- HOST=aarch64-linux-gnu OPT=-O3 -- HOST=mipsel-linux-gnu OPT=-O3 -- HOST=powerpc64-linux-gnu OPT=-O3 - -linux-s390x: &linux-s390x - os: linux - arch: s390x - env: HOST=s390x-linux-gnu BUILD=s390x-linux-gnu - script: - - | - CFLAGS="$OPT" - CXXFLAGS="$OPT" - export CFLAGS CXXFLAGS - - autoreconf -i - - ./configure - - make -j32 - - ulimit -c unlimited - - make check -j32 - -windows-remote-only: &windows-remote-only - os: windows - compiler: msvc - script: - - cmake -G "Visual Studio 15 2017" -A ${WINHOST} -S . -B bin/windows-${WINHOST}/${TARGET} - - cmake --build bin/windows-${WINHOST}/${TARGET} - -script: -- | - BUILD=x86_64-linux-gnu - export BUILD - if [ $HOST = 'x86-linux-gnu' ]; then - sudo apt-get update - sudo apt-get install -yqq -o=Dpkg::Use-Pty=0 g++-multilib - CFLAGS=" -m32" - CXXFLAGS=" -m32" - export CFLAGS CXXFLAGS - elif [ $HOST != 'x86_64-linux-gnu' ]; then - sudo apt-get update - sudo apt-get install -yqq -o=Dpkg::Use-Pty=0 g++-$HOST - CC=$HOST-gcc - CXX=$HOST-g++ - export CC CXX - fi -- | - CFLAGS="$CFLAGS $OPT" - CXXFLAGS="$CXXFLAGS $OPT" - export CFLAGS CXXFLAGS -- autoreconf -i -- ./configure CC=$CC CXX=$CXX CFLAGS="$CFLAGS" CXXFLAGS="$CXXFLAGS" --build=$BUILD --host=$HOST -- make -j32 -- sudo bash -c 'echo core.%p.%p > /proc/sys/kernel/core_pattern' -- ulimit -c unlimited -- if [ $HOST = 'x86_64-linux-gnu' ]; then make check -j32; fi - -after_failure: cat tests/test-suite.log 2>/dev/null - -jobs: - include: - - <<: *linux-s390x - - <<: *windows-remote-only - env: WINHOST=x64 TARGET=x86_64-linux-gnu - - <<: *windows-remote-only - env: WINHOST=Win32 TARGET=arm-linux-gnueabihf - - <<: *windows-remote-only - env: WINHOST=x64 TARGET=aarch64-linux-gnu diff --git a/src/native/external/libunwind/Makefile.am b/src/native/external/libunwind/Makefile.am index 718e8dad909e0..0d5eee057fb38 100644 --- a/src/native/external/libunwind/Makefile.am +++ b/src/native/external/libunwind/Makefile.am @@ -1,3 +1,4 @@ +ACLOCAL_AMFLAGS = -I m4 include_HEADERS = include/libunwind-dynamic.h if BUILD_PTRACE diff --git a/src/native/external/libunwind/NEWS b/src/native/external/libunwind/NEWS index ae6cbcfb0b57d..adf449ed7f31d 100644 --- a/src/native/external/libunwind/NEWS +++ b/src/native/external/libunwind/NEWS @@ -28,11 +28,11 @@ * News for v1.0: -** Fast unwind (rbp, rsp, rip only) on x86_64 with a fallback to +** Fast unwind (rbp, rsp, rip only) on x86_64 with a fallback to slow code path (Lassi Tuura) ** Improved local and remote unwinding on ARM (Ken Werner) ** Testing, stability and many fixes on x86 (Paul Pluzhnikov) -** FreeBSD port and clean separation of OS specific bits +** FreeBSD port and clean separation of OS specific bits (Konstantin Belousov) ** Thanks for all the bug reports, contributions and testing! @@ -108,7 +108,7 @@ * News for v0.98: ** Update libunwind to be compliant with the updated/expanded - ia64 unwind specificiation by HJ Lu [1]. This is needed for + ia64 unwind specification by HJ Lu [1]. This is needed for GCC 3.4 compatibility. [1] http://www.kernel.org/pub/linux/devel/gcc/unwind/ @@ -116,7 +116,7 @@ ** Initial support for x86-64 has been added courtesy of Max Asbock. Along with this came a bunch of DWARF2 unwinder fixes. -** A new rountine unw_strerror() has been added courtesy of +** A new routine unw_strerror() has been added courtesy of Thomas Hallgren. ** Including now defines 4 macros that can be used @@ -188,40 +188,40 @@ at IBM and it is expected that this support will be merged into the official tree soon. - + * News for v0.96: ** _Unwind_*() routines defined by the C++ ABI are now included in libunwind. - + * News for v0.95: ** Bigger, better, faster, or so the theory goes. - + * News for v0.93: ** More bug-fixes & improved HP-UX support. - + * News for v0.92: ** Bug-fix release. IA-64 unwinder can now be built with Intel compiler (ECC). - + * News for v0.91: ** Lots of documentation updates ** Some portability fixes. - + * News for v0.9: ** The libunwind API is mostly feature-complete at this point (hence the version jump from v0.2 to v0.9). - + * News for v0.2: ** Automated configuration/build with autoconf and automake. @@ -236,12 +236,12 @@ e.g., useful for building a debugger that can support multiple targets such as x86, ia64, etc.) - + * News for v0.1: ** Added support for exception handling. - + * News for v0.0: ** It's a brand new package. diff --git a/src/native/external/libunwind/README b/src/native/external/libunwind/README index 10734ef492aa9..26e1a9607c637 100644 --- a/src/native/external/libunwind/README +++ b/src/native/external/libunwind/README @@ -1,6 +1,7 @@ # libunwind -[![Build Status](https://travis-ci.org/libunwind/libunwind.svg?branch=master)](https://travis-ci.org/libunwind/libunwind) +[![CI - Unix](https://github.com/libunwind/libunwind/actions/workflows/CI-unix.yml/badge.svg)](https://github.com/libunwind/libunwind/actions/workflows/CI-unix.yml) +[![CI - Windows](https://github.com/libunwind/libunwind/actions/workflows/CI-win.yml/badge.svg)](https://github.com/libunwind/libunwind/actions/workflows/CI-win.yml) This library supports several architecture/operating-system combinations: @@ -16,13 +17,15 @@ This library supports several architecture/operating-system combinations: | Linux | IA-64 | ✓ | | Linux | PARISC | Works well, but C library missing unwind-info | | Linux | Tilegx | 64-bit mode only | -| Linux | MIPS | Newly added | +| Linux | MIPS | ✓ | | Linux | RISC-V | 64-bit only | | Linux | LoongArch | 64-bit only | | HP-UX | IA-64 | Mostly works, but known to have serious limitations | | FreeBSD | x86-64 | ✓ | | FreeBSD | x86 | ✓ | | FreeBSD | AArch64 | ✓ | +| FreeBSD | PPC32 | ✓ | +| FreeBSD | PPC64 | ✓ | | Solaris | x86-64 | ✓ | ## Libc Requirements @@ -59,9 +62,9 @@ In general, this library can be built and installed with the following commands: $ autoreconf -i # Needed only for building from git. Depends on libtool. - $ ./configure + $ ./configure --prefix=PREFIX $ make - $ make install prefix=PREFIX + $ make install where `PREFIX` is the installation prefix. By default, a prefix of `/usr/local` is used, such that `libunwind.a` is installed in @@ -91,18 +94,6 @@ libunwind should be configured and installed on HP-UX like this: Caveat: Unwinding of 32-bit (ILP32) binaries is not supported at the moment. -### Workaround for older versions of GCC - -GCC v3.0 and GCC v3.2 ship with a bad version of `sys/types.h`. The -workaround is to issue the following commands before running -`configure`: - - $ mkdir $top_dir/include/sys - $ cp /usr/include/sys/types.h $top_dir/include/sys - -GCC v3.3.2 or later have been fixed and do not require this -workaround. - ### Building for PowerPC64 / Linux For building for power64 you should use: @@ -138,27 +129,6 @@ After building the library, you can run a set of regression tests with: $ make check -### Expected results on IA-64 Linux - -Unless you have a very recent C library and compiler installed, it is -currently expected to have the following tests fail on IA-64 Linux: - -* `Gtest-init` (should pass starting with glibc-2.3.x/gcc-3.4) -* `Ltest-init` (should pass starting with glibc-2.3.x/gcc-3.4) -* `test-ptrace` (should pass starting with glibc-2.3.x/gcc-3.4) -* `run-ia64-test-dyn1` (should pass starting with glibc-2.3.x) - -This does not mean that libunwind cannot be used with older compilers -or C libraries, it just means that for certain corner cases, unwinding -will fail. Since they're corner cases, it is not likely for -applications to trigger them. - -Note: If you get lots of errors in `Gia64-test-nat` and `Lia64-test-nat`, it's -almost certainly a sign of an old assembler. The GNU assembler used -to encode previous-stack-pointer-relative offsets incorrectly. -This bug was fixed on 21-Sep-2004 so any later assembler will be -fine. - ### Expected results on x86 Linux The following tests are expected to fail on x86 Linux: @@ -174,10 +144,6 @@ The following tests are expected to fail on x86-64 Linux: ### Expected results on PARISC Linux -Caveat: GCC v3.4 or newer is needed on PA-RISC Linux. Earlier -versions of the compiler failed to generate the exception-handling -program header (`GNU_EH_FRAME`) needed for unwinding. - The following tests are expected to fail on x86-64 Linux: * `Gtest-bt` (backtrace truncated at `kill()` due to lack of unwind-info) diff --git a/src/native/external/libunwind/acinclude.m4 b/src/native/external/libunwind/acinclude.m4 deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/src/native/external/libunwind/acinclude.m4 +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/native/external/libunwind/configure.ac b/src/native/external/libunwind/configure.ac index 8f7cfda01c7fc..d97e50652d349 100644 --- a/src/native/external/libunwind/configure.ac +++ b/src/native/external/libunwind/configure.ac @@ -1,14 +1,18 @@ +dnl Process this file with autoconf to produce a configure script. + define(pkg_major, 1) -define(pkg_minor, 6) -define(pkg_extra, 2) +define(pkg_minor, 7) +define(pkg_extra, 0) define(pkg_maintainer, libunwind-devel@nongnu.org) -define(mkvers, $1.$2.$3) -dnl Process this file with autoconf to produce a configure script. +define(mkvers, $1.$2$3) + AC_INIT([libunwind],[mkvers(pkg_major, pkg_minor, pkg_extra)],[pkg_maintainer]) AC_CONFIG_SRCDIR(src/mi/backtrace.c) AC_CONFIG_AUX_DIR(config) +AC_CONFIG_MACRO_DIRS([m4]) AC_CANONICAL_TARGET -AM_INIT_AUTOMAKE([1.6 subdir-objects]) +AM_INIT_AUTOMAKE([1.7 subdir-objects -Wall]) +AM_SILENT_RULES([yes]) AM_MAINTAINER_MODE AC_CONFIG_HEADERS([include/config.h]) @@ -34,10 +38,10 @@ esac dnl Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS(asm/ptrace_offsets.h asm/ptrace.h endian.h sys/endian.h sys/param.h \ - execinfo.h ia64intrin.h sys/uc_access.h unistd.h signal.h sys/types.h \ - sys/procfs.h sys/ptrace.h sys/syscall.h byteswap.h elf.h sys/elf.h \ - link.h sys/link.h) +AC_CHECK_HEADERS(asm/ptrace_offsets.h asm/ptrace.h asm/vsyscall.h endian.h sys/endian.h \ + sys/param.h execinfo.h ia64intrin.h sys/uc_access.h unistd.h signal.h \ + sys/types.h sys/procfs.h sys/ptrace.h sys/syscall.h byteswap.h elf.h \ + sys/elf.h link.h sys/link.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -48,7 +52,7 @@ AC_CHECK_SIZEOF(off_t) CPPFLAGS="${CPPFLAGS} -D_GNU_SOURCE" AC_CHECK_MEMBERS([struct dl_phdr_info.dlpi_subs],,,[#include ]) -AC_CHECK_TYPES([struct elf_prstatus, struct prstatus], [], [], +AC_CHECK_TYPES([struct elf_prstatus, struct prstatus, procfs_status, elf_fpregset_t], [], [], [$ac_includes_default #if HAVE_SYS_PROCFS_H # include @@ -69,7 +73,7 @@ PT_STEP, PT_SYSCALL], [], [], dnl Checks for library functions. AC_CHECK_FUNCS(dl_iterate_phdr dl_phdr_removals_counter dlmodinfo getunwind \ - ttrace mincore pipe2) + ttrace mincore pipe2 sigaltstack) AC_MSG_CHECKING([if building with AltiVec]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ @@ -335,7 +339,7 @@ AM_CONDITIONAL(HAVE_ZLIB, test x$enable_zlibdebuginfo = xyes) AC_MSG_CHECKING([whether to support UNW_CACHE_PER_THREAD]) AC_ARG_ENABLE([per-thread-cache], -AS_HELP_STRING([--enable-per-thread-cache], [build with support for UNW_CACHE_PER_THREAD (which imposes a hight TLS memory usage) (default: disabled)])) +AS_HELP_STRING([--enable-per-thread-cache], [build with support for UNW_CACHE_PER_THREAD (which imposes a high TLS memory usage) (default: disabled)])) AC_MSG_RESULT([$enable_per_thread_cache]) AS_IF([test x$enable_per_thread_cache = xyes], [ AC_DEFINE(HAVE___CACHE_PER_THREAD, 1, @@ -428,6 +432,12 @@ case "$ac_cv_search_backtrace" in *) BACKTRACELIB="";; esac +AC_ARG_WITH([testdriver], + [AS_HELP_STRING([--with-testdriver], + [use designated test driver instead of default LOG_DRIVER])], + [], + [with_testdriver=\$\(top_srcdir\)/config/test-driver]) +AC_SUBST([UNW_TESTDRIVER], $with_testdriver) AC_SUBST(build_arch) AC_SUBST(target_os) @@ -446,7 +456,7 @@ AC_SUBST(DLLIB) AC_SUBST(BACKTRACELIB) AC_PATH_PROG([LATEX2MAN],[latex2man]) -if test "x$LATEX2MAN" = "x"; then +if test "x$LATEX2MAN" = "x" && test "x$enable_documentation" = "xyes"; then AC_MSG_WARN([latex2man not found. Install latex2man. Disabling docs.]) enable_documentation="no"; fi diff --git a/src/native/external/libunwind/doc/Makefile.am b/src/native/external/libunwind/doc/Makefile.am index c20a4576ee8c9..2252978dcd79f 100644 --- a/src/native/external/libunwind/doc/Makefile.am +++ b/src/native/external/libunwind/doc/Makefile.am @@ -9,6 +9,7 @@ man3_MANS = libunwind.man libunwind-dynamic.man libunwind-ia64.man \ unw_get_proc_info_by_ip.man \ unw_get_proc_info_in_range.man \ unw_get_proc_name.man \ + unw_get_proc_name_by_ip.man \ unw_get_fpreg.man \ unw_get_reg.man \ unw_getcontext.man \ @@ -40,6 +41,7 @@ EXTRA_DIST = NOTES libunwind.trans \ unw_get_proc_info_by_ip.tex \ unw_get_proc_info_in_range.tex \ unw_get_proc_name.tex \ + unw_get_proc_name_by_ip.tex \ unw_get_fpreg.tex \ unw_get_reg.tex \ unw_getcontext.tex \ @@ -64,16 +66,16 @@ L2M_CMD = $(L2M) -t $(srcdir)/libunwind.trans L2H_CMD = $(L2M) -H -t $(srcdir)/libunwind.trans .tex.man: - $(L2M_CMD) $< $@ + $(AM_V_GEN)$(L2M_CMD) $< $@ -cp $@ $(srcdir)/$@ -html: +html-local: for n in $(man3_MANS); do \ page=`basename $$n .man`; \ $(L2H_CMD) $(srcdir)/$$page.tex "$$page(3).raw"; \ done -pdf: +pdf-local: for n in $(man3_MANS); do \ page=`basename $$n .man`; \ $(L2P) $(srcdir)/$$page.tex "$$page(3).pdf"; \ diff --git a/src/native/external/libunwind/doc/libunwind-dynamic.man b/src/native/external/libunwind/doc/libunwind-dynamic.man index 7c7507cb1089d..68c66f3a32984 100644 --- a/src/native/external/libunwind/doc/libunwind-dynamic.man +++ b/src/native/external/libunwind/doc/libunwind-dynamic.man @@ -1,5 +1,5 @@ '\" t -.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007 +.\" Manual page created with latex2man on Sun Aug 29 23:45:06 CEST 2021 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW @@ -10,479 +10,479 @@ .fi .. -.TH "LIBUNWIND\-DYNAMIC" "3" "16 August 2007" "Programming Library " "Programming Library " +.TH "LIBUNWIND\-DYNAMIC" "3" "29 August 2021" "Programming Library " "Programming Library " .SH NAME libunwind\-dynamic -\-\- libunwind\-support for runtime\-generated code +\-\- libunwind\-support for runtime\-generated code .PP .SH INTRODUCTION .PP For libunwind -to do its job, it needs to be able to reconstruct +to do its job, it needs to be able to reconstruct the \fIframe state\fP -of each frame in a call\-chain. The frame state -describes the subset of the machine\-state that consists of the +of each frame in a call\-chain. The frame state +describes the subset of the machine\-state that consists of the \fIframe registers\fP -(typically the instruction\-pointer and the -stack\-pointer) and all callee\-saved registers (preserved registers). -The frame state describes each register either by providing its -current value (for frame registers) or by providing the location at -which the current value is stored (callee\-saved registers). +(typically the instruction\-pointer and the +stack\-pointer) and all callee\-saved registers (preserved registers). +The frame state describes each register either by providing its +current value (for frame registers) or by providing the location at +which the current value is stored (callee\-saved registers). .PP -For statically generated code, the compiler normally takes care of +For statically generated code, the compiler normally takes care of emitting \fIunwind\-info\fP -which provides the minimum amount of -information needed to reconstruct the frame\-state for each instruction -in a procedure. For dynamically generated code, the runtime code -generator must use the dynamic unwind\-info interface provided by +which provides the minimum amount of +information needed to reconstruct the frame\-state for each instruction +in a procedure. For dynamically generated code, the runtime code +generator must use the dynamic unwind\-info interface provided by libunwind -to supply the equivalent information. This manual -page describes the format of this information in detail. +to supply the equivalent information. This manual +page describes the format of this information in detail. .PP For the purpose of this discussion, a \fIprocedure\fP -is defined to +is defined to be an arbitrary piece of \fIcontiguous\fP -code. Normally, each -procedure directly corresponds to a function in the source\-language -but this is not strictly required. For example, a runtime -code\-generator could translate a given function into two separate -(discontiguous) procedures: one for frequently\-executed (hot) code and -one for rarely\-executed (cold) code. Similarly, simple -source\-language functions (usually leaf functions) may get translated -into code for which the default unwind\-conventions apply and for such -code, it is not strictly necessary to register dynamic unwind\-info. +code. Normally, each +procedure directly corresponds to a function in the source\-language +but this is not strictly required. For example, a runtime +code\-generator could translate a given function into two separate +(discontiguous) procedures: one for frequently\-executed (hot) code and +one for rarely\-executed (cold) code. Similarly, simple +source\-language functions (usually leaf functions) may get translated +into code for which the default unwind\-conventions apply and for such +code, it is not strictly necessary to register dynamic unwind\-info. .PP A procedure logically consists of a sequence of \fIregions\fP\&. -Regions are nested in the sense that the frame state at the end of one -region is, by default, assumed to be the frame state for the next -region. Each region is thought of as being divided into a +Regions are nested in the sense that the frame state at the end of one +region is, by default, assumed to be the frame state for the next +region. Each region is thought of as being divided into a \fIprologue\fP, a \fIbody\fP, and an \fIepilogue\fP\&. -Each of them -can be empty. If non\-empty, the prologue sets up the frame state for -the body. For example, the prologue may need to allocate some space -on the stack and save certain callee\-saved registers. The body -performs the actual work of the procedure but does not change the -frame state in any way. If non\-empty, the epilogue restores the -previous frame state and as such it undoes or cancels the effect of -the prologue. In fact, a single epilogue may undo the effect of the -prologues of several (nested) regions. -.PP -We should point out that even though the prologue, body, and epilogue -are logically separate entities, optimizing code\-generators will -generally interleave instructions from all three entities. For this +Each of them +can be empty. If non\-empty, the prologue sets up the frame state for +the body. For example, the prologue may need to allocate some space +on the stack and save certain callee\-saved registers. The body +performs the actual work of the procedure but does not change the +frame state in any way. If non\-empty, the epilogue restores the +previous frame state and as such it undoes or cancels the effect of +the prologue. In fact, a single epilogue may undo the effect of the +prologues of several (nested) regions. +.PP +We should point out that even though the prologue, body, and epilogue +are logically separate entities, optimizing code\-generators will +generally interleave instructions from all three entities. For this reason, the dynamic unwind\-info interface of libunwind -makes no -distinction whatsoever between prologue and body. Similarly, the -exact set of instructions that make up an epilogue is also irrelevant. -The only point in the epilogue that needs to be described explicitly -by the dynamic unwind\-info is the point at which the stack\-pointer -gets restored. The reason this point needs to be described is that -once the stack\-pointer is restored, all values saved in the -deallocated portion of the stack frame become invalid and hence +makes no +distinction whatsoever between prologue and body. Similarly, the +exact set of instructions that make up an epilogue is also irrelevant. +The only point in the epilogue that needs to be described explicitly +by the dynamic unwind\-info is the point at which the stack\-pointer +gets restored. The reason this point needs to be described is that +once the stack\-pointer is restored, all values saved in the +deallocated portion of the stack frame become invalid and hence libunwind -needs to know about it. The portion of the frame -state not saved on the stack is assume to remain valid through the end -of the region. For this reason, there is usually no need to describe -instructions which restore the contents of callee\-saved registers. -.PP -Within a region, each instruction that affects the frame state in some -fashion needs to be described with an operation descriptor. For this -purpose, each instruction in the region is assigned a unique index. -Exactly how this index is derived depends on the architecture. For -example, on RISC and EPIC\-style architecture, instructions have a -fixed size so it\&'s possible to simply number the instructions. In -contrast, most CISC use variable\-length instruction encodings, so it -is usually necessary to use a byte\-offset as the index. Given the -instruction index, the operation descriptor specifies the effect of -the instruction in an abstract manner. For example, it might express -that the instruction stores calle\-saved register r1 -at offset 16 -in the stack frame. +needs to know about it. The portion of the frame +state not saved on the stack is assumed to remain valid through the end +of the region. For this reason, there is usually no need to describe +instructions which restore the contents of callee\-saved registers. +.PP +Within a region, each instruction that affects the frame state in some +fashion needs to be described with an operation descriptor. For this +purpose, each instruction in the region is assigned a unique index. +Exactly how this index is derived depends on the architecture. For +example, on RISC and EPIC\-style architecture, instructions have a +fixed size so it\&'s possible to simply number the instructions. In +contrast, most CISC use variable\-length instruction encodings, so it +is usually necessary to use a byte\-offset as the index. Given the +instruction index, the operation descriptor specifies the effect of +the instruction in an abstract manner. For example, it might express +that the instruction stores callee\-saved register r1 +at offset 16 +in the stack frame. .PP .SH PROCEDURES .PP -A runtime code\-generator registers the dynamic unwind\-info of a +A runtime code\-generator registers the dynamic unwind\-info of a procedure by setting up a structure of type unw_dyn_info_t and calling _U_dyn_register(), -passing the address of the -structure as the sole argument. The members of the +passing the address of the +structure as the sole argument. The members of the unw_dyn_info_t -structure are described below: +structure are described below: .TP void *next Private to libunwind\&. -Must not be used -by the application. +Must not be used +by the application. .TP void *prev Private to libunwind\&. -Must not be used -by the application. +Must not be used +by the application. .TP unw_word_t start_ip - The start\-address of the -instructions of the procedure (remember: procedure are defined to be -contiguous pieces of code, so a single code\-range is sufficient). + The start\-address of the +instructions of the procedure (remember: procedure are defined to be +contiguous pieces of code, so a single code\-range is sufficient). .TP unw_word_t end_ip - The end\-address of the -instructions of the procedure (non\-inclusive, that is, + The end\-address of the +instructions of the procedure (non\-inclusive, that is, end_ip\-start_ip -is the size of the procedure in -bytes). +is the size of the procedure in +bytes). .TP unw_word_t gp - The global\-pointer value in use -for this procedure. The exact meaing of the global\-pointer is -architecture\-specific and on some architecture, it is not used at -all. + The global\-pointer value in use +for this procedure. The exact meaning of the global\-pointer is +architecture\-specific and on some architecture, it is not used at +all. .TP int32_t format - The format of the unwind\-info. + The format of the unwind\-info. This member can be one of UNW_INFO_FORMAT_DYNAMIC, UNW_INFO_FORMAT_TABLE, -or +or UNW_INFO_FORMAT_REMOTE_TABLE\&. .TP union u - This union contains one sub\-member -structure for every possible unwind\-info format: + This union contains one sub\-member +structure for every possible unwind\-info format: .RS .TP unw_dyn_proc_info_t pi - This member is used + This member is used for format UNW_INFO_FORMAT_DYNAMIC\&. .TP unw_dyn_table_info_t ti - This member is used + This member is used for format UNW_INFO_FORMAT_TABLE\&. .TP unw_dyn_remote_table_info_t rti - This member + This member is used for format UNW_INFO_FORMAT_REMOTE_TABLE\&. .RE .RS .PP -The format of these sub\-members is described in detail below. +The format of these sub\-members is described in detail below. .RE .PP .SS PROC\-INFO FORMAT .PP -This is the preferred dynamic unwind\-info format and it is generally -the one used by full\-blown runtime code\-generators. In this format, -the details of a procedure are described by a structure of type +This is the preferred dynamic unwind\-info format and it is generally +the one used by full\-blown runtime code\-generators. In this format, +the details of a procedure are described by a structure of type unw_dyn_proc_info_t\&. -This structure contains the following -members: +This structure contains the following +members: .PP .RE .TP unw_word_t name_ptr - The address of a -(human\-readable) name of the procedure or 0 if no such name is -available. If non\-zero, The string stored at this address must be -ASCII NUL terminated. For source languages that use name\-mangling -(such as C++ or Java) the string stored at this address should be + The address of a +(human\-readable) name of the procedure or 0 if no such name is +available. If non\-zero, the string stored at this address must be +ASCII NUL terminated. For source languages that use name\-mangling +(such as C++ or Java) the string stored at this address should be the \fIdemangled\fP -version of the name. +version of the name. .PP .TP unw_word_t handler - The address of the -personality\-routine for this procedure. Personality\-routines are -used in conjunction with exception handling. See the C++ ABI draft -(http://www.codesourcery.com/cxx\-abi/) for an overview and a -description of the personality routine. If the procedure has no + The address of the +personality\-routine for this procedure. Personality\-routines are +used in conjunction with exception handling. See the C++ ABI draft +(http://www.codesourcery.com/cxx\-abi/) for an overview and a +description of the personality routine. If the procedure has no personality routine, handler -must be set to 0. +must be set to 0. .PP .TP uint32_t flags - A bitmask of flags. At the -moment, no flags have been defined and this member must be -set to 0. + A bitmask of flags. At the +moment, no flags have been defined and this member must be +set to 0. .PP .TP unw_dyn_region_info_t *regions - A NULL\-terminated -linked list of region\-descriptors. See section ``Region -descriptors\&'' below for more details. + A NULL\-terminated +linked list of region\-descriptors. See section ``Region +descriptors\&'' below for more details. .PP .SS TABLE\-INFO FORMAT .PP -This format is generally used when the dynamically generated code was -derived from static code and the unwind\-info for the dynamic and the -static versions is identical. For example, this format can be useful -when loading statically\-generated code into an address\-space in a -non\-standard fashion (i.e., through some means other than +This format is generally used when the dynamically generated code was +derived from static code and the unwind\-info for the dynamic and the +static versions are identical. For example, this format can be useful +when loading statically\-generated code into an address\-space in a +non\-standard fashion (i.e., through some means other than dlopen()). -In this format, the details of a group of procedures +In this format, the details of a group of procedures is described by a structure of type unw_dyn_table_info\&. -This structure contains the following members: +This structure contains the following members: .PP .TP unw_word_t name_ptr - The address of a -(human\-readable) name of the procedure or 0 if no such name is -available. If non\-zero, The string stored at this address must be -ASCII NUL terminated. For source languages that use name\-mangling -(such as C++ or Java) the string stored at this address should be + The address of a +(human\-readable) name of the procedure or 0 if no such name is +available. If non\-zero, the string stored at this address must be +ASCII NUL terminated. For source languages that use name\-mangling +(such as C++ or Java) the string stored at this address should be the \fIdemangled\fP -version of the name. +version of the name. .PP .TP unw_word_t segbase - The segment\-base value -that needs to be added to the segment\-relative values stored in the -unwind\-info. The exact meaning of this value is -architecture\-specific. + The segment\-base value +that needs to be added to the segment\-relative values stored in the +unwind\-info. The exact meaning of this value is +architecture\-specific. .PP .TP unw_word_t table_len - The length of the + The length of the unwind\-info (table_data) -counted in units of words +counted in units of words (unw_word_t). .PP .TP unw_word_t table_data - A pointer to the actual -data encoding the unwind\-info. The exact format is -architecture\-specific (see architecture\-specific sections below). + A pointer to the actual +data encoding the unwind\-info. The exact format is +architecture\-specific (see architecture\-specific sections below). .PP .SS REMOTE TABLE\-INFO FORMAT .PP -The remote table\-info format has the same basic purpose as the regular +The remote table\-info format has the same basic purpose as the regular table\-info format. The only difference is that when libunwind -uses the unwind\-info, it will keep the table data in the target -address\-space (which may be remote). Consequently, the type of the +uses the unwind\-info, it will keep the table data in the target +address\-space (which may be remote). Consequently, the type of the table_data member is unw_word_t -rather than a pointer. +rather than a pointer. This implies that libunwind -will have to access the table\-data +will have to access the table\-data via the address\-space\&'s access_mem() -call\-back, rather than -through a direct memory reference. -.PP -From the point of view of a runtime\-code generator, the remote -table\-info format offers no advantage and it is expected that such -generators will describe their procedures either with the proc\-info -format or the normal table\-info format. The main reason that the -remote table\-info format exists is to enable the +call\-back, rather than +through a direct memory reference. +.PP +From the point of view of a runtime\-code generator, the remote +table\-info format offers no advantage and it is expected that such +generators will describe their procedures either with the proc\-info +format or the normal table\-info format. The main reason that the +remote table\-info format exists is to enable the address\-space\-specific find_proc_info() -callback (see +callback (see unw_create_addr_space(3)) -to return unwind tables whose -data remains in remote memory. This can speed up unwinding (e.g., for -a debugger) because it reduces the amount of data that needs to be -loaded from remote memory. +to return unwind tables whose +data remains in remote memory. This can speed up unwinding (e.g., for +a debugger) because it reduces the amount of data that needs to be +loaded from remote memory. .PP .SH REGIONS DESCRIPTORS .PP -A region descriptor is a variable length structure that describes how -each instruction in the region affects the frame state. Of course, -most instructions in a region usualy do not change the frame state and -for those, nothing needs to be recorded in the region descriptor. A -region descriptor is a structure of type +A region descriptor is a variable length structure that describes how +each instruction in the region affects the frame state. Of course, +most instructions in a region usually do not change the frame state and +for those, nothing needs to be recorded in the region descriptor. A +region descriptor is a structure of type unw_dyn_region_info_t -and has the following members: +and has the following members: .TP unw_dyn_region_info_t *next - A pointer to the + A pointer to the next region. If this is the last region, next is NULL\&. .TP int32_t insn_count - The length of the region in -instructions. Each instruction is assumed to have a fixed size (see -architecture\-specific sections for details). The value of + The length of the region in +instructions. Each instruction is assumed to have a fixed size (see +architecture\-specific sections for details). The value of insn_count -may be negative in the last region of a procedure +may be negative in the last region of a procedure (i.e., it may be negative only if next is NULL). -A +A negative value indicates that the region covers the last \fIN\fP instructions of the procedure, where \fIN\fP -is the absolute value +is the absolute value of insn_count\&. .TP uint32_t op_count - The (allocated) length of + The (allocated) length of the op_count -array. +array. .TP unw_dyn_op_t op - An array of dynamic unwind -directives. See Section ``Dynamic unwind directives\&'' for a -description of the directives. + An array of dynamic unwind +directives. See Section ``Dynamic unwind directives\&'' for a +description of the directives. .PP A region descriptor with an insn_count -of zero is an +of zero is an \fIempty region\fP -and such regions are perfectly legal. In fact, -empty regions can be useful to establish a particular frame state -before the start of another region. -.PP -A single region list can be shared across multiple procedures provided -those procedures share a common prologue and epilogue (their bodies -may differ, of course). Normally, such procedures consist of a canned -prologue, the body, and a canned epilogue. This could be described by -two regions: one covering the prologue and one covering the epilogue. -Since the body length is variable, the latter region would need to +and such regions are perfectly legal. In fact, +empty regions can be useful to establish a particular frame state +before the start of another region. +.PP +A single region list can be shared across multiple procedures provided +those procedures share a common prologue and epilogue (their bodies +may differ, of course). Normally, such procedures consist of a canned +prologue, the body, and a canned epilogue. This could be described by +two regions: one covering the prologue and one covering the epilogue. +Since the body length is variable, the latter region would need to specify a negative value in insn_count -such that +such that libunwind -knows that the region covers the end of the procedure +knows that the region covers the end of the procedure (up to the address specified by end_ip). .PP -The region descriptor is a variable length structure to make it -possible to allocate all the necessary memory with a single -memory\-allocation request. To facilitate the allocation of a region +The region descriptor is a variable length structure to make it +possible to allocate all the necessary memory with a single +memory\-allocation request. To facilitate the allocation of a region descriptors libunwind -provides a helper routine with the -following synopsis: +provides a helper routine with the +following synopsis: .PP size_t _U_dyn_region_size(int op_count); .PP -This routine returns the number of bytes needed to hold a region +This routine returns the number of bytes needed to hold a region descriptor with space for op_count -unwind directives. Note +unwind directives. Note that the length of the op -array does not have to match exactly -with the number of directives in a region. Instead, it is sufficient +array does not have to match exactly +with the number of directives in a region. Instead, it is sufficient if the op -array contains at least as many entries as there are -directives, since the end of the directives can always be indicated +array contains at least as many entries as there are +directives, since the end of the directives can always be indicated with the UNW_DYN_STOP -directive. +directive. .PP .SH DYNAMIC UNWIND DIRECTIVES .PP -A dynamic unwind directive describes how the frame state changes -at a particular point within a region. The description is in +A dynamic unwind directive describes how the frame state changes +at a particular point within a region. The description is in the form of a structure of type unw_dyn_op_t\&. -This -structure has the following members: +This +structure has the following members: .TP int8_t tag - The operation tag. Must be one + The operation tag. Must be one of the unw_dyn_operation_t -values described below. +values described below. .TP int8_t qp - The qualifying predicate that controls -whether or not this directive is active. This is useful for -predicated architecturs such as IA\-64 or ARM, where the contents of -another (callee\-saved) register determines whether or not an -instruction is executed (takes effect). If the directive is always -active, this member should be set to the manifest constant + The qualifying predicate that controls +whether or not this directive is active. This is useful for +predicated architectures such as IA\-64 or ARM, where the contents of +another (callee\-saved) register determines whether or not an +instruction is executed (takes effect). If the directive is always +active, this member should be set to the manifest constant _U_QP_TRUE -(this constant is defined for all -architectures, predicated or not). +(this constant is defined for all +architectures, predicated or not). .TP int16_t reg - The number of the register affected -by the instruction. + The number of the register affected +by the instruction. .TP int32_t when - The region\-relative number of -the instruction to which this directive applies. For example, -a value of 0 means that the effect described by this directive -has taken place once the first instruction in the region has -executed. + The region\-relative number of +the instruction to which this directive applies. For example, +a value of 0 means that the effect described by this directive +has taken place once the first instruction in the region has +executed. .TP unw_word_t val - The value to be applied by the -operation tag. The exact meaning of this value varies by tag. See -Section ``Operation tags\&'' below. + The value to be applied by the +operation tag. The exact meaning of this value varies by tag. See +Section ``Operation tags\&'' below. .PP -It is perfectly legitimate to specify multiple dynamic unwind +It is perfectly legitimate to specify multiple dynamic unwind directives with the same when -value, if a particular instruction -has a complex effect on the frame state. +value, if a particular instruction +has a complex effect on the frame state. .PP -Empty regions by definition contain no actual instructions and as such -the directives are not tied to a particular instruction. By +Empty regions by definition contain no actual instructions and as such +the directives are not tied to a particular instruction. By convention, the when -member should be set to 0, however. +member should be set to 0, however. .PP -There is no need for the dynamic unwind directives to appear +There is no need for the dynamic unwind directives to appear in order of increasing when -values. If the directives happen to -be sorted in that order, it may result in slightly faster execution, -but a runtime code\-generator should not go to extra lengths just to -ensure that the directives are sorted. +values. If the directives happen to +be sorted in that order, it may result in slightly faster execution, +but a runtime code\-generator should not go to extra lengths just to +ensure that the directives are sorted. .PP IMPLEMENTATION NOTE: should libunwind -implementations for -certain architectures prefer the list of unwind directives to be -sorted, it is recommended that such implementations first check -whether the list happens to be sorted already and, if not, sort the -directives explicitly before the first use. With this approach, the -overhead of explicit sorting is only paid when there is a real benefit -and if the runtime code\-generator happens to generated sorted lists -naturally, the performance penalty is limited to a simple O(N) check. +implementations for +certain architectures prefer the list of unwind directives to be +sorted, it is recommended that such implementations first check +whether the list happens to be sorted already and, if not, sort the +directives explicitly before the first use. With this approach, the +overhead of explicit sorting is only paid when there is a real benefit +and if the runtime code\-generator happens to generate sorted lists +naturally, the performance penalty is limited to a simple O(N) check. .PP .SS OPERATIONS TAGS .PP -The possible operation tags are defined by enumeration type +The possible operation tags are defined by enumeration type unw_dyn_operation_t -which defines the following -values: +which defines the following +values: .PP .TP UNW_DYN_STOP - Marks the end of the dynamic unwind + Marks the end of the dynamic unwind directive list. All remaining entries in the op -array of the -region\-descriptor are ignored. This tag is guaranteed to have a -value of 0. +array of the +region\-descriptor are ignored. This tag is guaranteed to have a +value of 0. .PP .TP UNW_DYN_SAVE_REG - Marks an instruction which saves + Marks an instruction which saves register reg to register val\&. .PP .TP UNW_DYN_SPILL_FP_REL - Marks an instruction which + Marks an instruction which spills register reg -to a frame\-pointer\-relative location. The -frame\-pointer\-relative offset is given by the value stored in member +to a frame\-pointer\-relative location. The +frame\-pointer\-relative offset is given by the value stored in member val\&. -See the architecture\-specific sections for a description -of the stack frame layout. +See the architecture\-specific sections for a description +of the stack frame layout. .PP .TP UNW_DYN_SPILL_SP_REL - Marks an instruction which + Marks an instruction which spills register reg -to a stack\-pointer\-relative location. The -stack\-pointer\-relative offset is given by the value stored in member +to a stack\-pointer\-relative location. The +stack\-pointer\-relative offset is given by the value stored in member val\&. -See the architecture\-specific sections for a description -of the stack frame layout. +See the architecture\-specific sections for a description +of the stack frame layout. .PP .TP UNW_DYN_ADD - Marks an instruction which adds + Marks an instruction which adds the constant value val to register reg\&. -To add subtract -a constant value, store the two\&'s\-complement of the value in +To add subtract +a constant value, store the two\&'s\-complement of the value in val\&. -The set of registers that can be specified for this tag -is described in the architecture\-specific sections below. +The set of registers that can be specified for this tag +is described in the architecture\-specific sections below. .PP .TP UNW_DYN_POP_FRAMES @@ -496,29 +496,29 @@ UNW_DYN_COPY_STATE .TP UNW_DYN_ALIAS .PP -unw_dyn_op_t -.PP -_U_dyn_op_save_reg(); -_U_dyn_op_spill_fp_rel(); -_U_dyn_op_spill_sp_rel(); -_U_dyn_op_add(); -_U_dyn_op_pop_frames(); -_U_dyn_op_label_state(); -_U_dyn_op_copy_state(); -_U_dyn_op_alias(); -_U_dyn_op_stop(); +unw_dyn_op_t +.PP +_U_dyn_op_save_reg(); +_U_dyn_op_spill_fp_rel(); +_U_dyn_op_spill_sp_rel(); +_U_dyn_op_add(); +_U_dyn_op_pop_frames(); +_U_dyn_op_label_state(); +_U_dyn_op_copy_state(); +_U_dyn_op_alias(); +_U_dyn_op_stop(); .PP .SH IA\-64 SPECIFICS .PP -\- meaning of segbase member in table\-info/table\-remote\-info format -\- format of table_data in table\-info/table\-remote\-info format -\- instruction size: each bundle is counted as 3 instructions, regardless -of template (MLX) -\- describe stack\-frame layout, especially with regards to sp\-relative -and fp\-relative addressing -\- UNW_DYN_ADD can only add to ``sp\&'' (always a negative value); use -POP_FRAMES otherwise +\- meaning of segbase member in table\-info/table\-remote\-info format +\- format of table_data in table\-info/table\-remote\-info format +\- instruction size: each bundle is counted as 3 instructions, regardless +of template (MLX) +\- describe stack\-frame layout, especially with regards to sp\-relative +and fp\-relative addressing +\- UNW_DYN_ADD can only add to ``sp\&'' (always a negative value); use +POP_FRAMES otherwise .PP .SH SEE ALSO diff --git a/src/native/external/libunwind/doc/libunwind-dynamic.tex b/src/native/external/libunwind/doc/libunwind-dynamic.tex index 21e895a34f30c..a3b7762b24715 100644 --- a/src/native/external/libunwind/doc/libunwind-dynamic.tex +++ b/src/native/external/libunwind/doc/libunwind-dynamic.tex @@ -64,7 +64,7 @@ \section{Introduction} once the stack-pointer is restored, all values saved in the deallocated portion of the stack frame become invalid and hence \Prog{libunwind} needs to know about it. The portion of the frame -state not saved on the stack is assume to remain valid through the end +state not saved on the stack is assumed to remain valid through the end of the region. For this reason, there is usually no need to describe instructions which restore the contents of callee-saved registers. @@ -78,7 +78,7 @@ \section{Introduction} is usually necessary to use a byte-offset as the index. Given the instruction index, the operation descriptor specifies the effect of the instruction in an abstract manner. For example, it might express -that the instruction stores calle-saved register \Var{r1} at offset 16 +that the instruction stores callee-saved register \Var{r1} at offset 16 in the stack frame. \section{Procedures} @@ -101,7 +101,7 @@ \section{Procedures} \Var{end\_ip}-\Var{start\_ip} is the size of the procedure in bytes). \item[\Type{unw\_word\_t} \Var{gp}] The global-pointer value in use - for this procedure. The exact meaing of the global-pointer is + for this procedure. The exact meaning of the global-pointer is architecture-specific and on some architecture, it is not used at all. \item[\Type{int32\_t} \Var{format}] The format of the unwind-info. @@ -132,7 +132,7 @@ \subsection{Proc-info format} \item[\Type{unw\_word\_t} \Var{name\_ptr}] The address of a (human-readable) name of the procedure or 0 if no such name is - available. If non-zero, The string stored at this address must be + available. If non-zero, the string stored at this address must be ASCII NUL terminated. For source languages that use name-mangling (such as C++ or Java) the string stored at this address should be the \emph{demangled} version of the name. @@ -158,7 +158,7 @@ \subsection{Table-info format} This format is generally used when the dynamically generated code was derived from static code and the unwind-info for the dynamic and the -static versions is identical. For example, this format can be useful +static versions are identical. For example, this format can be useful when loading statically-generated code into an address-space in a non-standard fashion (i.e., through some means other than \Func{dlopen}()). In this format, the details of a group of procedures @@ -168,7 +168,7 @@ \subsection{Table-info format} \item[\Type{unw\_word\_t} \Var{name\_ptr}] The address of a (human-readable) name of the procedure or 0 if no such name is - available. If non-zero, The string stored at this address must be + available. If non-zero, the string stored at this address must be ASCII NUL terminated. For source languages that use name-mangling (such as C++ or Java) the string stored at this address should be the \emph{demangled} version of the name. @@ -214,7 +214,7 @@ \section{Regions descriptors} A region descriptor is a variable length structure that describes how each instruction in the region affects the frame state. Of course, -most instructions in a region usualy do not change the frame state and +most instructions in a region usually do not change the frame state and for those, nothing needs to be recorded in the region descriptor. A region descriptor is a structure of type \Type{unw\_dyn\_region\_info\_t} and has the following members: @@ -278,7 +278,7 @@ \section{Dynamic unwind directives} of the \Type{unw\_dyn\_operation\_t} values described below. \item[\Type{int8\_t} \Var{qp}] The qualifying predicate that controls whether or not this directive is active. This is useful for - predicated architecturs such as IA-64 or ARM, where the contents of + predicated architectures such as IA-64 or ARM, where the contents of another (callee-saved) register determines whether or not an instruction is executed (takes effect). If the directive is always active, this member should be set to the manifest constant @@ -315,7 +315,7 @@ \section{Dynamic unwind directives} whether the list happens to be sorted already and, if not, sort the directives explicitly before the first use. With this approach, the overhead of explicit sorting is only paid when there is a real benefit -and if the runtime code-generator happens to generated sorted lists +and if the runtime code-generator happens to generate sorted lists naturally, the performance penalty is limited to a simple O(N) check. \subsection{Operations tags} diff --git a/src/native/external/libunwind/doc/libunwind.man b/src/native/external/libunwind/doc/libunwind.man index 02ab6b8937481..837e6e31e9a2d 100644 --- a/src/native/external/libunwind/doc/libunwind.man +++ b/src/native/external/libunwind/doc/libunwind.man @@ -1,5 +1,5 @@ '\" t -.\" Manual page created with latex2man on Thu Jan 12 06:50:29 PST 2017 +.\" Manual page created with latex2man on Sun Aug 29 23:45:06 CEST 2021 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW @@ -10,7 +10,7 @@ .fi .. -.TH "LIBUNWIND" "3" "12 January 2017" "Programming Library " "Programming Library " +.TH "LIBUNWIND" "3" "29 August 2021" "Programming Library " "Programming Library " .SH NAME libunwind \-\- a (mostly) platform\-independent unwind API @@ -215,8 +215,9 @@ frame as the only argument. Normally, libunwind supports both local and remote unwinding (the latter will be explained in the next section). However, if you -tell libunwind that your program only needs local unwinding, then a -special implementation can be selected which may run much faster than +tell libunwind +that your program only needs local unwinding, then +a special implementation can be selected which may run much faster than the generic implementation which supports both kinds of unwinding. To select this optimized version, simply define the macro UNW_LOCAL_ONLY @@ -357,7 +358,7 @@ targeting a cross\-platform will result in a link\-time error All libunwind routines are thread\-safe. What this means is that multiple threads may use libunwind -simulatenously. +simultaneously. However, any given cursor may be accessed by only one thread at any given time. .PP @@ -431,11 +432,11 @@ select the exact caching policy in use for a given address\-space object. In particular, by selecting the policy UNW_CACHE_NONE, it is possible to turn off caching -completely, therefore eliminating the risk of stale data alltogether +completely, therefore eliminating the risk of stale data altogether (at the cost of slower execution). By default, caching is enabled for local unwinding only. The cache size can be dynamically changed with unw_set_cache_size(), -which also fluches the current cache. +which also flushes the current cache. .PP .SH FILES diff --git a/src/native/external/libunwind/doc/libunwind.tex b/src/native/external/libunwind/doc/libunwind.tex index 6cbb4766336dd..8809ba5a36f83 100644 --- a/src/native/external/libunwind/doc/libunwind.tex +++ b/src/native/external/libunwind/doc/libunwind.tex @@ -128,8 +128,8 @@ \section{Local Unwinding} Normally, \Prog{libunwind} supports both local and remote unwinding (the latter will be explained in the next section). However, if you -tell libunwind that your program only needs local unwinding, then a -special implementation can be selected which may run much faster than +tell \Prog{libunwind} that your program only needs local unwinding, then +a special implementation can be selected which may run much faster than the generic implementation which supports both kinds of unwinding. To select this optimized version, simply define the macro \Const{UNW\_LOCAL\_ONLY} before including the headerfile @@ -238,7 +238,7 @@ \section{Thread- and Signal-Safety} All \Prog{libunwind} routines are thread-safe. What this means is -that multiple threads may use \Prog{libunwind} simulatenously. +that multiple threads may use \Prog{libunwind} simultaneously. However, any given cursor may be accessed by only one thread at any given time. @@ -293,10 +293,10 @@ \section{Caching of Unwind Info} select the exact caching policy in use for a given address-space object. In particular, by selecting the policy \Const{UNW\_CACHE\_NONE}, it is possible to turn off caching -completely, therefore eliminating the risk of stale data alltogether +completely, therefore eliminating the risk of stale data altogether (at the cost of slower execution). By default, caching is enabled for local unwinding only. The cache size can be dynamically changed with -\Func{unw\_set\_cache\_size}(), which also fluches the current cache. +\Func{unw\_set\_cache\_size}(), which also flushes the current cache. \section{Files} diff --git a/src/native/external/libunwind/doc/unw_backtrace.man b/src/native/external/libunwind/doc/unw_backtrace.man index 5699bbfe2881d..e1a4a9dfcad76 100644 --- a/src/native/external/libunwind/doc/unw_backtrace.man +++ b/src/native/external/libunwind/doc/unw_backtrace.man @@ -1,5 +1,7 @@ +.\" *********************************** start of \input{common.tex} +.\" *********************************** end of \input{common.tex} '\" t -.\" Manual page created with latex2man on Fri Aug 31 13:39:04 EEST 2012 +.\" Manual page created with latex2man on Thu Jan 5 15:33:00 2023 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW @@ -10,7 +12,7 @@ .fi .. -.TH "UNW\\_BACKTRACE" "3" "31 August 2012" "Programming Library " "Programming Library " +.TH "UNW\\_BACKTRACE" "3" "05 January 2023" "Programming Library " "Programming Library " .SH NAME unw_backtrace \-\- return backtrace for the calling program @@ -25,6 +27,12 @@ int unw_backtrace(void **buffer, int size); .br +int +unw_backtrace2(void **buffer, +int size, +unw_context_t *ctxt, +int flag); +.br .PP #include .br @@ -44,7 +52,7 @@ addresses in the array pointed by buffer\&. The routine is only available for local unwinding. .PP -Note that many (but not all) systems provide practically identical function +Note that many (but not all) systems provide a practically identical function called backtrace(). The prototype for this function is usually obtained by including the @@ -61,6 +69,17 @@ is linked against libunwind, it may end up calling unw_backtrace(). .PP +In case you want to obtain the backtrace from a specific unw_context_t, +you can call unw_backtrace2 +with that context passing 0 +for flag. +If the unw_context_t +is known to be a signal frame (i.e., from the third argument +in a sigaction handler on linux), unw_backtrace2 +can be used to collect +only the frames before the signal frame passing the UNW_INIT_SIGNAL_FRAME +flag. +.PP .SH RETURN VALUE .PP diff --git a/src/native/external/libunwind/doc/unw_backtrace.tex b/src/native/external/libunwind/doc/unw_backtrace.tex index c383eeb37a166..3e5152b6ef0bb 100644 --- a/src/native/external/libunwind/doc/unw_backtrace.tex +++ b/src/native/external/libunwind/doc/unw_backtrace.tex @@ -13,6 +13,7 @@ \section{Synopsis} \File{\#include $<$libunwind.h$>$}\\ \Type{int} \Func{unw\_backtrace}(\Type{void~**}\Var{buffer}, \Type{int}~\Var{size});\\ +\Type{int} \Func{unw\_backtrace2}(\Type{void~**}\Var{buffer}, \Type{int}~\Var{size}, \Type{unw_context_t~*}\Var{ctxt}, \Type{int}~\Var{flag});\\ \File{\#include $<$execinfo.h$>$}\\ @@ -24,7 +25,7 @@ \section{Description} the calling program. The routine fills up to \Var{size} addresses in the array pointed by \Var{buffer}. The routine is only available for local unwinding. -Note that many (but not all) systems provide practically identical function +Note that many (but not all) systems provide a practically identical function called \Func{backtrace}(). The prototype for this function is usually obtained by including the \File{$<$execinfo.h$>$} header file -- a prototype for \Func{backtrace}() is not provided by \Prog{libunwind}. \Prog{libunwind} weakly @@ -32,6 +33,12 @@ \section{Description} calling \Func{backtrace}() is linked against \Prog{libunwind}, it may end up calling \Func{unw\_backtrace}(). +In case you want to obtain the backtrace from a specific \Type{unw\_context\_t}, +you can call \Func{unw\_backtrace2} with that context passing \Const{0} for flag. +If the \Type{unw\_context_t} is known to be a signal frame (i.e., from the third argument +in a sigaction handler on linux), \Func{unw\_backtrace2} can be used to collect +only the frames before the signal frame passing the \Const{UNW\_INIT\_SIGNAL\_FRAME} flag. + \section{Return Value} The routine returns the number of addresses stored in the array pointed by diff --git a/src/native/external/libunwind/doc/unw_backtrace2.man b/src/native/external/libunwind/doc/unw_backtrace2.man new file mode 100644 index 0000000000000..922fea9e721c8 --- /dev/null +++ b/src/native/external/libunwind/doc/unw_backtrace2.man @@ -0,0 +1 @@ +.so man3/unw_backtrace.3 diff --git a/src/native/external/libunwind/doc/unw_get_proc_info.man b/src/native/external/libunwind/doc/unw_get_proc_info.man index 09eadee27ad1a..5853e1ea8e443 100644 --- a/src/native/external/libunwind/doc/unw_get_proc_info.man +++ b/src/native/external/libunwind/doc/unw_get_proc_info.man @@ -1,5 +1,5 @@ '\" t -.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007 +.\" Manual page created with latex2man on Sun Aug 29 23:45:06 CEST 2021 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW @@ -10,7 +10,7 @@ .fi .. -.TH "UNW\\_GET\\_PROC\\_INFO" "3" "16 August 2007" "Programming Library " "Programming Library " +.TH "UNW\\_GET\\_PROC\\_INFO" "3" "29 August 2021" "Programming Library " "Programming Library " .SH NAME unw_get_proc_info \-\- get info on current procedure @@ -96,7 +96,7 @@ format is equal to UNW_INFO_FORMAT_DYNAMIC\&. If the unwind\-info consists of a (target\-specific) unwind table, it is -equal to to UNW_INFO_FORMAT_TABLE\&. +equal to UNW_INFO_FORMAT_TABLE\&. All other values are reserved for future use by libunwind\&. This member exists @@ -138,7 +138,7 @@ may return an undefined value in this member. Note that for the purposes of libunwind, the code of a procedure is assumed to occupy a single, contiguous range of -addresses. For this reason, it is alwas possible to describe the +addresses. For this reason, it is always possible to describe the extent of a procedure with the start_ip and end_ip members. If a single function/routine is split into multiple, diff --git a/src/native/external/libunwind/doc/unw_get_proc_info.tex b/src/native/external/libunwind/doc/unw_get_proc_info.tex index 72621f1a6510f..00377e4177d31 100644 --- a/src/native/external/libunwind/doc/unw_get_proc_info.tex +++ b/src/native/external/libunwind/doc/unw_get_proc_info.tex @@ -53,7 +53,7 @@ \section{Description} procedure. If the unwind-info consists of dynamic procedure info, \Var{format} is equal to \Const{UNW\_INFO\_FORMAT\_DYNAMIC}. If the unwind-info consists of a (target-specific) unwind table, it is - equal to to \Const{UNW\_INFO\_FORMAT\_TABLE}. All other values are + equal to \Const{UNW\_INFO\_FORMAT\_TABLE}. All other values are reserved for future use by \Prog{libunwind}. This member exists for use by the \Func{find\_proc\_info}() call-back (see \Func{unw\_create\_addr\_space}(3)). The @@ -75,7 +75,7 @@ \section{Description} \end{description} Note that for the purposes of \Prog{libunwind}, the code of a procedure is assumed to occupy a single, contiguous range of -addresses. For this reason, it is alwas possible to describe the +addresses. For this reason, it is always possible to describe the extent of a procedure with the \Var{start\_ip} and \Var{end\_ip} members. If a single function/routine is split into multiple, discontiguous pieces, \Prog{libunwind} will treat each piece as a diff --git a/src/native/external/libunwind/doc/unw_get_proc_info_by_ip.man b/src/native/external/libunwind/doc/unw_get_proc_info_by_ip.man index a347a1d008911..35771d0107a77 100644 --- a/src/native/external/libunwind/doc/unw_get_proc_info_by_ip.man +++ b/src/native/external/libunwind/doc/unw_get_proc_info_by_ip.man @@ -1,5 +1,5 @@ '\" t -.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" Manual page created with latex2man on Sun Aug 29 23:45:06 CEST 2021 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW @@ -10,7 +10,7 @@ .fi .. -.TH "UNW\\_GET\\_PROC\\_INFO\\_BY\\_IP" "3" "16 August 2007" "Programming Library " "Programming Library " +.TH "UNW\\_GET\\_PROC\\_INFO\\_BY\\_IP" "3" "29 August 2021" "Programming Library " "Programming Library " .SH NAME unw_get_proc_info_by_ip \-\- get procedure info by IP @@ -42,7 +42,7 @@ even if it is not part of the current call\-chain. However, since it is more flexible, it also tends to run slower (and often much slower) than unw_get_proc_info(). .PP -The routine expects the followins arguments: as +The routine expects the following arguments: as is the address\-space in which the instruction\-pointer should be looked up. For a look\-up in the local address\-space, @@ -68,7 +68,7 @@ argument. Note that for the purposes of libunwind, the code of a procedure is assumed to occupy a single, contiguous range of -addresses. For this reason, it is alwas possible to describe the +addresses. For this reason, it is always possible to describe the extent of a procedure with the start_ip and end_ip members. If a single function/routine is split into multiple, @@ -86,7 +86,7 @@ below is returned. .SH THREAD AND SIGNAL SAFETY .PP -unw_get_proc_info() +unw_get_proc_info_by_ip() is thread\-safe. If the local address\-space is passed in argument as, this routine is also @@ -108,9 +108,9 @@ UNW_EBADVERSION The unwind\-info for the procedure has version or format that is not understood by libunwind\&. .PP -In addition, unw_get_proc_info() -may return any error -returned by the access_mem() +In addition, unw_get_proc_info_by_ip() +may return any +error returned by the access_mem() call\-back (see unw_create_addr_space(3)). .PP diff --git a/src/native/external/libunwind/doc/unw_get_proc_info_by_ip.tex b/src/native/external/libunwind/doc/unw_get_proc_info_by_ip.tex index 5e1d5d247ebf2..3c7c4af01db64 100644 --- a/src/native/external/libunwind/doc/unw_get_proc_info_by_ip.tex +++ b/src/native/external/libunwind/doc/unw_get_proc_info_by_ip.tex @@ -25,7 +25,7 @@ \section{Description} is more flexible, it also tends to run slower (and often much slower) than \Func{unw\_get\_proc\_info}(). -The routine expects the followins arguments: \Var{as} is the +The routine expects the following arguments: \Var{as} is the address-space in which the instruction-pointer should be looked up. For a look-up in the local address-space, \Var{unw\_local\_addr\_space} can be passed for this argument. @@ -41,7 +41,7 @@ \section{Description} Note that for the purposes of \Prog{libunwind}, the code of a procedure is assumed to occupy a single, contiguous range of -addresses. For this reason, it is alwas possible to describe the +addresses. For this reason, it is always possible to describe the extent of a procedure with the \Var{start\_ip} and \Var{end\_ip} members. If a single function/routine is split into multiple, discontiguous pieces, \Prog{libunwind} will treat each piece as a @@ -55,7 +55,7 @@ \section{Return Value} \section{Thread and Signal Safety} -\Func{unw\_get\_proc\_info}() is thread-safe. If the local +\Func{unw\_get\_proc\_info\_by\_ip}() is thread-safe. If the local address-space is passed in argument \Var{as}, this routine is also safe to use from a signal handler. @@ -68,8 +68,8 @@ \section{Errors} \item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has version or format that is not understood by \Prog{libunwind}. \end{Description} -In addition, \Func{unw\_get\_proc\_info}() may return any error -returned by the \Func{access\_mem}() call-back (see +In addition, \Func{unw\_get\_proc\_info\_by\_ip}() may return any +error returned by the \Func{access\_mem}() call-back (see \Func{unw\_create\_addr\_space}(3)). \section{See Also} diff --git a/src/native/external/libunwind/doc/unw_get_proc_name.man b/src/native/external/libunwind/doc/unw_get_proc_name.man index 8b2bd06eaf084..0240604823bc0 100644 --- a/src/native/external/libunwind/doc/unw_get_proc_name.man +++ b/src/native/external/libunwind/doc/unw_get_proc_name.man @@ -1,5 +1,5 @@ '\" t -.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" Manual page created with latex2man on Sun Aug 29 23:45:06 CEST 2021 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW @@ -10,7 +10,7 @@ .fi .. -.TH "UNW\\_GET\\_PROC\\_NAME" "3" "16 August 2007" "Programming Library " "Programming Library " +.TH "UNW\\_GET\\_PROC\\_NAME" "3" "29 August 2021" "Programming Library " "Programming Library " .SH NAME unw_get_proc_name \-\- get name of current procedure @@ -59,7 +59,7 @@ between procedure names and ordinary labels. Furthermore, if symbol information has been stripped from a program, procedure names may be completely unavailable or may be limited to those exported via a dynamic symbol table. In such cases, unw_get_proc_name() -may return the name of a label or a preceeding (nearby) procedure. +may return the name of a label or a preceding (nearby) procedure. However, the offset returned through offp is always relative to the returned name, which ensures that the value (address) of the diff --git a/src/native/external/libunwind/doc/unw_get_proc_name.tex b/src/native/external/libunwind/doc/unw_get_proc_name.tex index c413990880dcd..028d671672806 100644 --- a/src/native/external/libunwind/doc/unw_get_proc_name.tex +++ b/src/native/external/libunwind/doc/unw_get_proc_name.tex @@ -34,7 +34,7 @@ \section{Description} information has been stripped from a program, procedure names may be completely unavailable or may be limited to those exported via a dynamic symbol table. In such cases, \Func{unw\_get\_proc\_name}() -may return the name of a label or a preceeding (nearby) procedure. +may return the name of a label or a preceding (nearby) procedure. However, the offset returned through \Var{offp} is always relative to the returned name, which ensures that the value (address) of the returned name plus the returned offset will always be equal to the diff --git a/src/native/external/libunwind/doc/unw_get_proc_name_by_ip.man b/src/native/external/libunwind/doc/unw_get_proc_name_by_ip.man new file mode 100644 index 0000000000000..70b10aaead2a1 --- /dev/null +++ b/src/native/external/libunwind/doc/unw_get_proc_name_by_ip.man @@ -0,0 +1,139 @@ +'\" t +.\" Manual page created with latex2man on Mon Aug 30 08:48:42 CEST 2021 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_GET\\_PROC\\_NAME\\_BY\\_IP" "3" "30 August 2021" "Programming Library " "Programming Library " +.SH NAME +unw_get_proc_name_by_ip +\-\- get procedure name +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_get_proc_name_by_ip(unw_addr_space_t as, +unw_word_t ip, +char *bufp, +size_t +len, +unw_word_t *offp, +void *arg); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_get_proc_name_by_ip() +routine returns the name of +a procedure just like unw_get_proc_name(), +except that the +name is looked up by instruction\-pointer (IP) instead of a cursor. +.PP +The routine expects the following arguments: as +is the +address\-space in which the instruction\-pointer should be looked up. +For a look\-up in the local address\-space, +unw_local_addr_space +can be passed for this argument. +Argument ip +is the instruction\-pointer for which the procedure +name should be looked up. The bufp +argument is a pointer to +a character buffer that is at least len +bytes long. This buffer +is used to return the name of the procedure. The offp +argument +is a pointer to a word that is used to return the byte\-offset of the +instruction\-pointer relative to the start of the procedure. +Lastly, arg +is the address\-space argument that should be used +when accessing the address\-space. It has the same purpose as the +argument of the same name for unw_init_remote(). +When +accessing the local address\-space (first argument is +unw_local_addr_space), +NULL +must be passed for this +argument. +.PP +Note that on some platforms there is no reliable way to distinguish +between procedure names and ordinary labels. Furthermore, if symbol +information has been stripped from a program, procedure names may be +completely unavailable or may be limited to those exported via a +dynamic symbol table. In such cases, +unw_get_proc_name_by_ip() +may return the name of a label +or a preceding (nearby) procedure. However, the offset returned +through offp +is always relative to the returned name, which +ensures that the value (address) of the returned name plus the +returned offset will always be equal to the instruction\-pointer +ip\&. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_get_proc_name_by_ip() +returns 0. Otherwise the negative value of one of the error\-codes +below is returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_get_proc_name_by_ip() +is thread\-safe. If the local +address\-space is passed in argument as, +this routine is also +safe to use from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_ENOINFO + Libunwind +was unable to determine +the name of the procedure. +.TP +UNW_ENOMEM + The procedure name is too long to fit +in the buffer provided. A truncated version of the name has been +returned. +.PP +In addition, unw_get_proc_name_by_ip() +may return any error +returned by the access_mem() +call\-back (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_create_addr_space(3), +unw_get_proc_name(3), +unw_init_remote(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/src/native/external/libunwind/doc/unw_get_proc_name_by_ip.tex b/src/native/external/libunwind/doc/unw_get_proc_name_by_ip.tex new file mode 100644 index 0000000000000..cb59768070bc1 --- /dev/null +++ b/src/native/external/libunwind/doc/unw_get_proc_name_by_ip.tex @@ -0,0 +1,93 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_get\_proc\_name\_by\_ip}{David Mosberger-Tang}{Programming Library}{unw\_get\_proc\_name}unw\_get\_proc\_name\_by\_ip -- get procedure name +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_get\_proc\_name\_by\_ip}(\Type{unw\_addr\_space\_t~}\Var{as}, \Type{unw\_word\_t~}\Var{ip}, \Type{char~*}\Var{bufp}, \Type{size\_t} \Var{len}, \Type{unw\_word\_t~*}\Var{offp}, \Type{void~*}\Var{arg});\\ + +\section{Description} + +The \Func{unw\_get\_proc\_name\_by\_ip}() routine returns the name of +a procedure just like \Func{unw\_get\_proc\_name}(), except that the +name is looked up by instruction-pointer (IP) instead of a cursor. + +The routine expects the following arguments: \Var{as} is the +address-space in which the instruction-pointer should be looked up. +For a look-up in the local address-space, +\Var{unw\_local\_addr\_space} can be passed for this argument. +Argument \Var{ip} is the instruction-pointer for which the procedure +name should be looked up. The \Var{bufp} argument is a pointer to +a character buffer that is at least \Var{len} bytes long. This buffer +is used to return the name of the procedure. The \Var{offp} argument +is a pointer to a word that is used to return the byte-offset of the +instruction-pointer relative to the start of the procedure. +Lastly, \Var{arg} is the address-space argument that should be used +when accessing the address-space. It has the same purpose as the +argument of the same name for \Func{unw\_init\_remote}(). When +accessing the local address-space (first argument is +\Var{unw\_local\_addr\_space}), \Const{NULL} must be passed for this +argument. + +Note that on some platforms there is no reliable way to distinguish +between procedure names and ordinary labels. Furthermore, if symbol +information has been stripped from a program, procedure names may be +completely unavailable or may be limited to those exported via a +dynamic symbol table. In such cases, +\Func{unw\_get\_proc\_name\_by\_ip}() may return the name of a label +or a preceding (nearby) procedure. However, the offset returned +through \Var{offp} is always relative to the returned name, which +ensures that the value (address) of the returned name plus the +returned offset will always be equal to the instruction-pointer +\Var{ip}. + +\section{Return Value} + +On successful completion, \Func{unw\_get\_proc\_name\_by\_ip}() +returns 0. Otherwise the negative value of one of the error-codes +below is returned. + +\section{Thread and Signal Safety} + +\Func{unw\_get\_proc\_name\_by\_ip}() is thread-safe. If the local +address-space is passed in argument \Var{as}, this routine is also +safe to use from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to determine + the name of the procedure. +\item[\Const{UNW\_ENOMEM}] The procedure name is too long to fit + in the buffer provided. A truncated version of the name has been + returned. +\end{Description} +In addition, \Func{unw\_get\_proc\_name\_by\_ip}() may return any error +returned by the \Func{access\_mem}() call-back (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_create\_addr\_space(3)}, +\SeeAlso{unw\_get\_proc\_name(3)}, +\SeeAlso{unw\_init\_remote(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/src/native/external/libunwind/doc/unw_init_local.man b/src/native/external/libunwind/doc/unw_init_local.man index 301dd6f93bdf0..8b33c90ccfd72 100644 --- a/src/native/external/libunwind/doc/unw_init_local.man +++ b/src/native/external/libunwind/doc/unw_init_local.man @@ -1,5 +1,5 @@ '\" t -.\" Manual page created with latex2man on Wed Aug 16 12:11:05 PDT 2017 +.\" Manual page created with latex2man on Sun Aug 29 23:45:06 CEST 2021 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW @@ -10,7 +10,7 @@ .fi .. -.TH "UNW\\_INIT\\_LOCAL" "3" "16 August 2017" "Programming Library " "Programming Library " +.TH "UNW\\_INIT\\_LOCAL" "3" "29 August 2021" "Programming Library " "Programming Library " .SH NAME unw_init_local \-\- initialize cursor for local unwinding @@ -44,11 +44,13 @@ As such, the machine\-state pointed to by ctxt identifies the initial stack frame at which unwinding starts. The machine\-state is expected to be one provided by a call to -unw_getcontext; as such, the instruction pointer may point to the -instruction after the last instruction of a function, and libunwind -will back\-up the instruction pointer before beginning a walk up the -call stack. The machine\-state must remain valid for the duration for -which the cursor c +unw_getcontext(); +as such, the instruction pointer may point to +the instruction after the last instruction of a function, and +libunwind +will back\-up the instruction pointer before beginning +a walk up the call stack. The machine\-state must remain valid for the +duration for which the cursor c is in use. .PP The unw_init_local() @@ -66,11 +68,13 @@ including , whereas unw_init_remote() is not. .PP -If the unw_context_t is known to be a signal frame (i.e., from the -third argument in a sigaction handler on linux), +If the unw_context_t +is known to be a signal frame (i.e., +from the third argument in a sigaction handler on linux), unw_init_local2() should be used for correct initialization -on some platforms, passing the UNW_INIT_SIGNAL_FRAME flag. +on some platforms, passing the UNW_INIT_SIGNAL_FRAME +flag. .PP .SH RETURN VALUE diff --git a/src/native/external/libunwind/doc/unw_init_local.tex b/src/native/external/libunwind/doc/unw_init_local.tex index ff0d03bc77db0..aaba0ca75d4dd 100644 --- a/src/native/external/libunwind/doc/unw_init_local.tex +++ b/src/native/external/libunwind/doc/unw_init_local.tex @@ -22,11 +22,11 @@ \section{Description} pointed to by \Var{ctxt}. As such, the machine-state pointed to by \Var{ctxt} identifies the initial stack frame at which unwinding starts. The machine-state is expected to be one provided by a call to -unw_getcontext; as such, the instruction pointer may point to the -instruction after the last instruction of a function, and libunwind -will back-up the instruction pointer before beginning a walk up the -call stack. The machine-state must remain valid for the duration for -which the cursor \Var{c} is in use. +\Func{unw\_getcontext}(); as such, the instruction pointer may point to +the instruction after the last instruction of a function, and +\Prog{libunwind} will back-up the instruction pointer before beginning +a walk up the call stack. The machine-state must remain valid for the +duration for which the cursor \Var{c} is in use. The \Func{unw\_init\_local}() routine can be used only for unwinding in the address space of the current process (i.e., for local unwinding). @@ -37,10 +37,10 @@ \section{Description} including \File{$<$libunwind.h$>$}, whereas \Func{unw\_init\_remote}() is not. -If the unw_context_t is known to be a signal frame (i.e., from the -third argument in a sigaction handler on linux), +If the \Type{unw\_context\_t} is known to be a signal frame (i.e., +from the third argument in a sigaction handler on linux), \Func{unw\_init\_local2}() should be used for correct initialization -on some platforms, passing the UNW_INIT_SIGNAL_FRAME flag. +on some platforms, passing the \Const{UNW\_INIT\_SIGNAL\_FRAME} flag. \section{Return Value} diff --git a/src/native/external/libunwind/doc/unw_reg_states_iterate.man b/src/native/external/libunwind/doc/unw_reg_states_iterate.man index e328ad2e38cdf..0c18cf964c1eb 100644 --- a/src/native/external/libunwind/doc/unw_reg_states_iterate.man +++ b/src/native/external/libunwind/doc/unw_reg_states_iterate.man @@ -1,5 +1,5 @@ '\" t -.\" Manual page created with latex2man on Wed Aug 16 11:09:44 PDT 2017 +.\" Manual page created with latex2man on Sun Aug 29 23:45:06 CEST 2021 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW @@ -10,7 +10,7 @@ .fi .. -.TH "UNW\\_REG\\_STATES\\_ITERATE" "3" "16 August 2017" "Programming Library " "Programming Library " +.TH "UNW\\_REG\\_STATES\\_ITERATE" "3" "29 August 2021" "Programming Library " "Programming Library " .SH NAME unw_reg_states_iterate \-\- get register state info on current procedure @@ -53,7 +53,7 @@ unw_word_t end_ip); .PP The callback function may be invoked several times for each call of unw_reg_states_iterate\&. -Each call is associcated with a instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range. For each invocation, the arguments to the callback function are: +Each call is associated with an instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range. For each invocation, the arguments to the callback function are: .TP void * token The token value passed to unw_reg_states_callback\&. diff --git a/src/native/external/libunwind/doc/unw_reg_states_iterate.tex b/src/native/external/libunwind/doc/unw_reg_states_iterate.tex index 36c9b548a25d7..c350b53394ab0 100644 --- a/src/native/external/libunwind/doc/unw_reg_states_iterate.tex +++ b/src/native/external/libunwind/doc/unw_reg_states_iterate.tex @@ -28,7 +28,7 @@ \section{Description} \Type{size\_t} \Var{reg\_states\_data\_size}, \Type{unw\_word\_t} \Var{start\_ip}, \Type{unw\_word\_t} \Var{end\_ip}); -The callback function may be invoked several times for each call of \Func{unw\_reg\_states\_iterate}. Each call is associcated with a instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range. For each invocation, the arguments to the callback function are: +The callback function may be invoked several times for each call of \Func{unw\_reg\_states\_iterate}. Each call is associated with an instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range. For each invocation, the arguments to the callback function are: \begin{description} \item[\Type{void~*} \Var{token}] The token value passed to \Var{unw\_reg\_states\_callback}. \\ \item[\Type{void~*} \Var{reg\_states\_data}] A pointer to data about diff --git a/src/native/external/libunwind/include/dwarf.h b/src/native/external/libunwind/include/dwarf.h index 175c419bbe394..dd9014b7177bc 100644 --- a/src/native/external/libunwind/include/dwarf.h +++ b/src/native/external/libunwind/include/dwarf.h @@ -231,6 +231,7 @@ typedef enum DWARF_WHERE_REG, /* register saved in another register */ DWARF_WHERE_EXPR, /* register saved */ DWARF_WHERE_VAL_EXPR, /* register has computed value */ + DWARF_WHERE_CFA, /* register is set to the computed cfa value */ } dwarf_where_t; @@ -313,7 +314,7 @@ typedef struct dwarf_cursor void *as_arg; /* argument to address-space callbacks */ unw_addr_space_t as; /* reference to per-address-space info */ - unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */ + unw_word_t cfa; /* canonical frame address; aka frame-pointer */ unw_word_t ip; /* instruction pointer */ unw_word_t args_size; /* size of arguments */ unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS]; @@ -421,7 +422,7 @@ extern int dwarf_search_unwind_table (unw_addr_space_t as, int need_unwind_info, void *arg); extern int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, - char *path, unw_word_t segbase, unw_word_t mapoff, + const char *path, unw_word_t segbase, unw_word_t mapoff, unw_word_t ip); extern void dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg); diff --git a/src/native/external/libunwind/include/libunwind-aarch64.h b/src/native/external/libunwind/include/libunwind-aarch64.h index a7c71ed1cfde7..63be0530a4e8d 100644 --- a/src/native/external/libunwind/include/libunwind-aarch64.h +++ b/src/native/external/libunwind/include/libunwind-aarch64.h @@ -37,11 +37,7 @@ extern "C" { #include #ifndef UNW_EMPTY_STRUCT -# ifdef __GNUC__ -# define UNW_EMPTY_STRUCT -# else -# define UNW_EMPTY_STRUCT uint8_t unused; -# endif +# define UNW_EMPTY_STRUCT uint8_t unused; #endif #define UNW_TARGET aarch64 @@ -123,6 +119,12 @@ typedef enum UNW_AARCH64_PC, UNW_AARCH64_PSTATE, + /* Pseudo-register */ + UNW_AARCH64_RA_SIGN_STATE = 34, + + /* SVE Vector Granule pseudo register */ + UNW_AARCH64_VG = 46, + /* 128-bit FP/Advanced SIMD registers. */ UNW_AARCH64_V0 = 64, UNW_AARCH64_V1, @@ -168,7 +170,7 @@ typedef enum UNW_TDEP_IP = UNW_AARCH64_X30, UNW_TDEP_SP = UNW_AARCH64_SP, - UNW_TDEP_EH = UNW_AARCH64_X0, + UNW_TDEP_EH = UNW_AARCH64_X0 } aarch64_regnum_t; @@ -226,15 +228,24 @@ typedef struct #else /* On AArch64, we can directly use ucontext_t as the unwind context. */ typedef ucontext_t unw_tdep_context_t; +#if defined(__FreeBSD__) +typedef ucontext_t unw_fpsimd_context_t; +#endif #endif #include "libunwind-common.h" #include "libunwind-dynamic.h" +#if defined(__FreeBSD__) +#define UNW_BASE register uint64_t unw_base __asm__ ("x0") = (uint64_t) unw_ctx->uc_mcontext.mc_gpregs.gp_x[0]; +#else +#define UNW_BASE register uint64_t unw_base __asm__ ("x0") = (uint64_t) unw_ctx->uc_mcontext.regs; +#endif + #define unw_tdep_getcontext(uc) ({ \ unw_tdep_context_t *unw_ctx = (uc); \ - register uint64_t unw_base __asm__ ("x0") = (uint64_t) unw_ctx->uc_mcontext.regs; \ + UNW_BASE \ __asm__ __volatile__ ( \ "stp x0, x1, [%[base], #0]\n" \ "stp x2, x3, [%[base], #16]\n" \ diff --git a/src/native/external/libunwind/include/libunwind-arm.h b/src/native/external/libunwind/include/libunwind-arm.h index 1fe6a9eec7cee..4ac1fd38258e6 100644 --- a/src/native/external/libunwind/include/libunwind-arm.h +++ b/src/native/external/libunwind/include/libunwind-arm.h @@ -33,11 +33,7 @@ extern "C" { #include #ifndef UNW_EMPTY_STRUCT -# ifdef __GNUC__ -# define UNW_EMPTY_STRUCT -# else -# define UNW_EMPTY_STRUCT uint8_t unused; -# endif +# define UNW_EMPTY_STRUCT uint8_t unused; #endif #define UNW_TARGET arm diff --git a/src/native/external/libunwind/include/libunwind-common.h.in b/src/native/external/libunwind/include/libunwind-common.h.in index a6965ff28fc2e..7360a0284b25d 100644 --- a/src/native/external/libunwind/include/libunwind-common.h.in +++ b/src/native/external/libunwind/include/libunwind-common.h.in @@ -101,7 +101,7 @@ unw_caching_policy_t; typedef enum { - UNW_INIT_SIGNAL_FRAME = 1, /* We know this is a signal frame */ + UNW_INIT_SIGNAL_FRAME = 1 /* We know this is a signal frame */ } unw_init_local2_flags_t; @@ -207,6 +207,24 @@ typedef struct unw_accessors NULL. */ int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t, unw_word_t *, void *); + + /* Optional call back to return a mask to be used with pointer + * authentication on arm64. + * + * The on bits in the returned mask indicate which bits in a return address + * are part of a pointer authentication code. These are the bits in the + * return address to turn off so that the calling frame can be found + * for the unwinding to continue. + * + * The return value must be host-endian. e.g. if the target is big-endian + * and the host is little endian, the implementation of this function + * must byte swap. + * + * This callback is optional and may be set to NULL. In this case all + * the bits in the return address are used, as if no masking were done. + */ + unw_word_t (*ptrauth_insn_mask) (unw_addr_space_t, void *); + } unw_accessors_t; @@ -255,6 +273,7 @@ unw_save_loc_t; #define unw_get_save_loc UNW_OBJ(get_save_loc) #define unw_is_signal_frame UNW_OBJ(is_signal_frame) #define unw_get_proc_name UNW_OBJ(get_proc_name) +#define unw_get_proc_name_by_ip UNW_OBJ(get_proc_name_by_ip) #define unw_set_caching_policy UNW_OBJ(set_caching_policy) #define unw_set_cache_size UNW_OBJ(set_cache_size) #define unw_regname UNW_ARCH_OBJ(regname) @@ -293,7 +312,10 @@ extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t); extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *); extern int unw_is_signal_frame (unw_cursor_t *); extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); +extern int unw_get_proc_name_by_ip (unw_addr_space_t, unw_word_t, char *, + size_t, unw_word_t *, void *); extern const char *unw_strerror (int); extern int unw_backtrace (void **, int); +extern int unw_backtrace2 (void **, int, unw_context_t*, int); extern unw_addr_space_t unw_local_addr_space; diff --git a/src/native/external/libunwind/include/libunwind-dynamic.h b/src/native/external/libunwind/include/libunwind-dynamic.h index dc31b12efc9d0..a26f2c9962c5c 100644 --- a/src/native/external/libunwind/include/libunwind-dynamic.h +++ b/src/native/external/libunwind/include/libunwind-dynamic.h @@ -77,7 +77,7 @@ typedef enum UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */ UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */ UNW_INFO_FORMAT_ARM_EXIDX, /* ARM specific unwind info */ - UNW_INFO_FORMAT_IP_OFFSET, /* Like UNW_INFO_FORMAT_REMOTE_TABLE, but + UNW_INFO_FORMAT_IP_OFFSET /* Like UNW_INFO_FORMAT_REMOTE_TABLE, but table entries are considered relative to di->start_ip, rather than di->segbase */ diff --git a/src/native/external/libunwind/include/libunwind-loongarch64.h b/src/native/external/libunwind/include/libunwind-loongarch64.h index 806cf7dfa330a..1e9366ed3ed2b 100644 --- a/src/native/external/libunwind/include/libunwind-loongarch64.h +++ b/src/native/external/libunwind/include/libunwind-loongarch64.h @@ -88,7 +88,7 @@ typedef enum UNW_LOONGARCH64_R30, UNW_LOONGARCH64_R31, - UNW_LOONGARCH64_PC = 32, + UNW_LOONGARCH64_PC = 33, /* FIXME: Other registers! */ diff --git a/src/native/external/libunwind/include/libunwind-x86.h b/src/native/external/libunwind/include/libunwind-x86.h index 40fe0464f2f6c..d3b741d3f3f9f 100644 --- a/src/native/external/libunwind/include/libunwind-x86.h +++ b/src/native/external/libunwind/include/libunwind-x86.h @@ -34,6 +34,10 @@ extern "C" { #include #include +#ifndef UNW_EMPTY_STRUCT +# define UNW_EMPTY_STRUCT uint8_t unused; +#endif + #define UNW_TARGET x86 #define UNW_TARGET_X86 1 @@ -158,6 +162,7 @@ x86_regnum_t; typedef struct unw_tdep_save_loc { /* Additional target-dependent info on a save location. */ + UNW_EMPTY_STRUCT } unw_tdep_save_loc_t; @@ -169,6 +174,7 @@ typedef ucontext_t unw_tdep_context_t; typedef struct { /* no x86-specific auxiliary proc-info */ + UNW_EMPTY_STRUCT } unw_tdep_proc_info_t; diff --git a/src/native/external/libunwind/include/libunwind_i.h b/src/native/external/libunwind/include/libunwind_i.h index dadf82412fc7e..3ca146258f6d2 100644 --- a/src/native/external/libunwind/include/libunwind_i.h +++ b/src/native/external/libunwind/include/libunwind_i.h @@ -132,7 +132,7 @@ byte_order_is_big_endian(int byte_order) } static inline int -target_is_big_endian() +target_is_big_endian(void) { return byte_order_is_big_endian(UNW_BYTE_ORDER); } @@ -172,7 +172,7 @@ target_is_big_endian() /* Type of a mask that can be used to inhibit preemption. At the userlevel, preemption is caused by signals and hence sigset_t is - appropriate. In constrast, the Linux kernel uses "unsigned long" + appropriate. In contrast, the Linux kernel uses "unsigned long" to hold the processor "flags" instead. */ typedef sigset_t intrmask_t; @@ -355,6 +355,10 @@ static inline void invalidate_edi (struct elf_dyn_info *edi) #include "tdep/libunwind_i.h" +#ifndef TDEP_DWARF_SP +#define TDEP_DWARF_SP UNW_TDEP_SP +#endif + #ifndef tdep_get_func_addr # define tdep_get_func_addr(as,addr,v) (*(v) = addr, 0) #endif diff --git a/src/native/external/libunwind/include/remote/freebsd-elf_common.h b/src/native/external/libunwind/include/remote/freebsd-elf_common.h index b3520edda1f98..080a52d6d090f 100644 --- a/src/native/external/libunwind/include/remote/freebsd-elf_common.h +++ b/src/native/external/libunwind/include/remote/freebsd-elf_common.h @@ -628,7 +628,7 @@ typedef struct { #define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ #define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ #define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ -#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB special */ #define R_IA_64_SUB 0x85 /* immediate64 A - S */ #define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ #define R_IA_64_LDXMOV 0x87 /* immediate22 special */ diff --git a/src/native/external/libunwind/include/tdep-arm/libunwind_i.h b/src/native/external/libunwind/include/tdep-arm/libunwind_i.h index 88ebfb0693326..5bd28c953a619 100644 --- a/src/native/external/libunwind/include/tdep-arm/libunwind_i.h +++ b/src/native/external/libunwind/include/tdep-arm/libunwind_i.h @@ -256,6 +256,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) #define tdep_init_done UNW_OBJ(init_done) #define tdep_init UNW_OBJ(init) #define arm_find_proc_info UNW_OBJ(find_proc_info) +#define arm_find_proc_info2 UNW_OBJ(find_proc_info2) #define arm_put_unwind_info UNW_OBJ(put_unwind_info) /* Platforms that support UNW_INFO_FORMAT_TABLE need to define tdep_search_unwind_table. */ @@ -297,6 +298,9 @@ extern void tdep_init (void); extern int arm_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, int need_unwind_info, void *arg); +extern int arm_find_proc_info2 (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, + void *arg, int methods); extern void arm_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg); extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, diff --git a/src/native/external/libunwind/include/tdep-ia64/libunwind_i.h b/src/native/external/libunwind/include/tdep-ia64/libunwind_i.h index 8cb8fea22792f..5b0defc8ef109 100644 --- a/src/native/external/libunwind/include/tdep-ia64/libunwind_i.h +++ b/src/native/external/libunwind/include/tdep-ia64/libunwind_i.h @@ -152,7 +152,7 @@ struct cursor unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */ unw_proc_info_t pi; /* info about current procedure */ - /* In case of stack-discontiguities, such as those introduced by + /* In case of stack discontiguities, such as those introduced by signal-delivery on an alternate signal-stack (see sigaltstack(2)), we use the following data-structure to keep track of the register-backing-store areas across on which the diff --git a/src/native/external/libunwind/include/tdep-x86/dwarf-config.h b/src/native/external/libunwind/include/tdep-x86/dwarf-config.h index f76f9c1c4eb2f..11398e4e62294 100644 --- a/src/native/external/libunwind/include/tdep-x86/dwarf-config.h +++ b/src/native/external/libunwind/include/tdep-x86/dwarf-config.h @@ -43,9 +43,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ typedef struct dwarf_loc { unw_word_t val; -#ifndef UNW_LOCAL_ONLY unw_word_t type; /* see X86_LOC_TYPE_* macros. */ -#endif } dwarf_loc_t; diff --git a/src/native/external/libunwind/include/tdep-x86/libunwind_i.h b/src/native/external/libunwind/include/tdep-x86/libunwind_i.h index d4c5ccdb172ad..ad4edc2f5ac84 100644 --- a/src/native/external/libunwind/include/tdep-x86/libunwind_i.h +++ b/src/native/external/libunwind/include/tdep-x86/libunwind_i.h @@ -84,15 +84,26 @@ dwarf_get_uc(const struct dwarf_cursor *cursor) } #define DWARF_GET_LOC(l) ((l).val) +# define DWARF_LOC_TYPE_MEM (0 << 0) +# define DWARF_LOC_TYPE_FP (1 << 0) +# define DWARF_LOC_TYPE_REG (1 << 1) +# define DWARF_LOC_TYPE_VAL (1 << 2) -#ifdef UNW_LOCAL_ONLY +# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) +# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) +# define DWARF_IS_MEM_LOC(l) ((l).type == DWARF_LOC_TYPE_MEM) +# define DWARF_IS_VAL_LOC(l) (((l).type & DWARF_LOC_TYPE_VAL) != 0) + +# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) # define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 +# define DWARF_IS_NULL_LOC(l) \ + ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) +# define DWARF_VAL_LOC(c,v) DWARF_LOC ((v), DWARF_LOC_TYPE_VAL) +# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), DWARF_LOC_TYPE_MEM) + +#ifdef UNW_LOCAL_ONLY # define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ tdep_uc_addr(dwarf_get_uc(c), (r)), 0)) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) # define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ tdep_uc_addr(dwarf_get_uc(c), (r)), 0)) @@ -114,35 +125,8 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) return 0; } -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - #else /* !UNW_LOCAL_ONLY */ -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) # define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) # define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ | DWARF_LOC_TYPE_FP)) @@ -192,38 +176,33 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) 1, c->as_arg); } +#endif /* !UNW_LOCAL_ONLY */ + static inline int dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) { if (DWARF_IS_NULL_LOC (loc)) return -UNW_EBADREG; - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - if (DWARF_IS_REG_LOC (loc)) return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, 0, c->as_arg); - else + if (DWARF_IS_MEM_LOC (loc)) return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, 0, c->as_arg); + assert(DWARF_IS_VAL_LOC (loc)); + *val = DWARF_GET_LOC (loc); + return 0; } static inline int dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) { + assert(!DWARF_IS_VAL_LOC (loc)); + if (DWARF_IS_NULL_LOC (loc)) return -UNW_EBADREG; - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - if (DWARF_IS_REG_LOC (loc)) return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, 1, c->as_arg); @@ -232,7 +211,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) 1, c->as_arg); } -#endif /* !UNW_LOCAL_ONLY */ +// For historical reasons, the DWARF numbering does not match the libunwind +// numbering, necessitating this override +#define TDEP_DWARF_SP 4 #define tdep_getcontext_trace unw_getcontext #define tdep_init_done UNW_OBJ(init_done) diff --git a/src/native/external/libunwind/scripts/qemu-test-driver b/src/native/external/libunwind/scripts/qemu-test-driver new file mode 100755 index 0000000000000..6b49d824baa0e --- /dev/null +++ b/src/native/external/libunwind/scripts/qemu-test-driver @@ -0,0 +1,156 @@ +#! /bin/sh +# qemu-test-driver - testsuite driver script modified to use qemu + +scriptversion=2013-07-13.22; # UTC + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/src/native/external/libunwind/src/CMakeLists.txt b/src/native/external/libunwind/src/CMakeLists.txt index b63f5b3105e86..eee31afa6aae4 100644 --- a/src/native/external/libunwind/src/CMakeLists.txt +++ b/src/native/external/libunwind/src/CMakeLists.txt @@ -53,7 +53,6 @@ SET(libunwind_la_SOURCES_generic # the source is excluded here to prevent name clash #mi/Gget_accessors.c mi/Gget_proc_info_by_ip.c mi/Gget_proc_name.c - mi/Gget_proc_info_in_range.c mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c mi/Gget_reg.c mi/Gset_reg.c mi/Gget_fpreg.c mi/Gset_fpreg.c @@ -137,7 +136,6 @@ SET(libunwind_la_SOURCES_local_nounwind mi/Ldyn-extract.c mi/Lfind_dynamic_proc_info.c mi/Lget_accessors.c mi/Lget_proc_info_by_ip.c mi/Lget_proc_name.c - mi/Lget_proc_info_in_range.c mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c mi/Lget_reg.c mi/Lset_reg.c mi/Lget_fpreg.c mi/Lset_fpreg.c @@ -158,12 +156,14 @@ SET(libunwind_dwarf_local_la_SOURCES dwarf/Lexpr.c dwarf/Lfde.c dwarf/Lparser.c dwarf/Lpe.c dwarf/Lfind_proc_info-lsb.c dwarf/Lfind_unwind_table.c + dwarf/Lget_proc_info_in_range.c ) SET(libunwind_dwarf_generic_la_SOURCES dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c dwarf/Gfind_proc_info-lsb.c dwarf/Gfind_unwind_table.c + dwarf/Gget_proc_info_in_range.c ) SET(libunwind_elf32_la_SOURCES diff --git a/src/native/external/libunwind/src/Makefile.am b/src/native/external/libunwind/src/Makefile.am index cf788f27852e3..9bfb5ded1a52f 100644 --- a/src/native/external/libunwind/src/Makefile.am +++ b/src/native/external/libunwind/src/Makefile.am @@ -61,6 +61,7 @@ libunwind_coredump_la_SOURCES = \ coredump/_UCD_find_proc_info.c \ coredump/_UCD_get_proc_name.c \ coredump/_UCD_corefile_elf.c \ + coredump/ucd_file_table.c \ \ coredump/_UPT_elf.c \ coredump/_UPT_access_fpreg.c \ @@ -70,7 +71,9 @@ libunwind_coredump_la_SOURCES = \ libunwind_coredump_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \ -version-info $(COREDUMP_SO_VERSION) libunwind_coredump_la_LIBADD = $(LIBLZMA) $(LIBZ) -noinst_HEADERS += coredump/_UCD_internal.h coredump/_UCD_lib.h +noinst_HEADERS += coredump/_UCD_internal.h \ + coredump/_UCD_lib.h \ + coredump/ucd_file_table.h ### libunwind-setjmp: libunwind_setjmp_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \ @@ -107,7 +110,6 @@ libunwind_la_SOURCES_generic = \ mi/Gdyn-extract.c mi/Gdyn-remote.c mi/Gfind_dynamic_proc_info.c \ mi/Gget_accessors.c \ mi/Gget_proc_info_by_ip.c mi/Gget_proc_name.c \ - mi/Gget_proc_info_in_range.c \ mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \ mi/Gget_reg.c mi/Gset_reg.c \ mi/Gget_fpreg.c mi/Gset_fpreg.c \ @@ -137,7 +139,6 @@ libunwind_la_SOURCES_local_nounwind = \ mi/Ldyn-extract.c mi/Lfind_dynamic_proc_info.c \ mi/Lget_accessors.c \ mi/Lget_proc_info_by_ip.c mi/Lget_proc_name.c \ - mi/Lget_proc_info_in_range.c \ mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c \ mi/Lget_reg.c mi/Lset_reg.c \ mi/Lget_fpreg.c mi/Lset_fpreg.c \ @@ -164,13 +165,15 @@ libunwind_dwarf_common_la_SOURCES = dwarf/global.c libunwind_dwarf_local_la_SOURCES = \ dwarf/Lexpr.c dwarf/Lfde.c dwarf/Lparser.c dwarf/Lpe.c \ dwarf/Lfind_proc_info-lsb.c \ - dwarf/Lfind_unwind_table.c + dwarf/Lfind_unwind_table.c \ + dwarf/Lget_proc_info_in_range.c libunwind_dwarf_local_la_LIBADD = libunwind-dwarf-common.la libunwind_dwarf_generic_la_SOURCES = \ dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c \ dwarf/Gfind_proc_info-lsb.c \ - dwarf/Gfind_unwind_table.c + dwarf/Gfind_unwind_table.c \ + dwarf/Gget_proc_info_in_range.c libunwind_dwarf_generic_la_LIBADD = libunwind-dwarf-common.la if USE_DWARF diff --git a/src/native/external/libunwind/src/aarch64/Ginit.c b/src/native/external/libunwind/src/aarch64/Ginit.c index e1d19afb58039..57f484674f201 100644 --- a/src/native/external/libunwind/src/aarch64/Ginit.c +++ b/src/native/external/libunwind/src/aarch64/Ginit.c @@ -46,15 +46,24 @@ unw_addr_space_t unw_local_addr_space = &local_addr_space; static inline void * uc_addr (unw_tdep_context_t *uc, int reg) { + if (reg == UNW_AARCH64_VG) + { + /* + * Support for saving the vector length in the context needs to be + * added to get_context() for this path to work. + */ + Debug(1, "Accessing VG register from context is not supported\n"); + return NULL; + } #ifdef __FreeBSD__ if (reg >= UNW_AARCH64_X0 && reg < UNW_AARCH64_X30) return &uc->uc_mcontext.mc_gpregs.gp_x[reg]; else if (reg == UNW_AARCH64_X30) return &uc->uc_mcontext.mc_gpregs.gp_lr; else if (reg == UNW_AARCH64_SP) - return &uc->uc_mcontext.sp; + return &uc->uc_mcontext.mc_gpregs.gp_sp; else if (reg == UNW_AARCH64_PC) - return &uc->uc_mcontext.gp_elr; + return &uc->uc_mcontext.mc_gpregs.gp_elr; else if (reg >= UNW_AARCH64_V0 && reg <= UNW_AARCH64_V31) return &GET_FPCTX(uc)->uc_mcontext.mc_fpregs.fp_q[reg - UNW_AARCH64_V0]; else @@ -427,6 +436,11 @@ get_static_proc_name (unw_addr_space_t as, unw_word_t ip, return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp); } +static unw_word_t empty_ptrauth_mask(unw_addr_space_t addr_space_unused, void *as_arg_unused) +{ + return 0; +} + HIDDEN void aarch64_local_addr_space_init (void) { @@ -440,6 +454,7 @@ aarch64_local_addr_space_init (void) local_addr_space.acc.access_fpreg = access_fpreg; local_addr_space.acc.resume = aarch64_local_resume; local_addr_space.acc.get_proc_name = get_static_proc_name; + local_addr_space.acc.ptrauth_insn_mask = empty_ptrauth_mask; local_addr_space.big_endian = target_is_big_endian(); unw_flush_cache (&local_addr_space, 0, 0); } diff --git a/src/native/external/libunwind/src/aarch64/Gregs.c b/src/native/external/libunwind/src/aarch64/Gregs.c index a8843734459b5..54fc2f3f143ac 100644 --- a/src/native/external/libunwind/src/aarch64/Gregs.c +++ b/src/native/external/libunwind/src/aarch64/Gregs.c @@ -24,6 +24,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "dwarf_i.h" #include "unwind_i.h" HIDDEN int @@ -88,6 +89,44 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, case UNW_AARCH64_PSTATE: loc = c->dwarf.loc[reg]; break; + case UNW_AARCH64_RA_SIGN_STATE: + Debug (1, "Reading from ra sign state not supported: %u\n", reg); + return -UNW_EBADREG; + + case UNW_AARCH64_VG: + if (write) + { + Debug (1, "Writing to VG pseudo register not supported\n"); + return -UNW_EBADREG; + } + + if (DWARF_IS_REG_LOC(c->dwarf.loc[reg])) + loc = c->dwarf.loc[reg]; + else + { + unw_addr_space_t as = c->dwarf.as; + unw_accessors_t *a = unw_get_accessors_int (as); + void *arg = c->dwarf.as_arg; + unw_word_t addr = DWARF_GET_LOC (c->dwarf.loc[reg]); + uint16_t val16; + + /* + * If it's a memory location it means it must be in the signal context + * and it's saved as VL rather than VG so it needs to be scaled. + * + * linux/Documentation/arm64/sve.rst: + * * Vector length (VL) = size of a Z-register in bytes + * + * https://github.com/ARM-software/abi-aa/blob/main/aadwarf64/aadwarf64.rst: + * * Vector granule (VG) = Size in bits of the SVE vector registers + * in the current call frame divided by 64. + */ + int ret = dwarf_readu16 (as, a, &addr, &val16, arg); + if (!ret) + *valp = (val16 * 8) / 64; + return ret; + } + break; case UNW_AARCH64_SP: if (write) diff --git a/src/native/external/libunwind/src/aarch64/Gstash_frame.c b/src/native/external/libunwind/src/aarch64/Gstash_frame.c index 6689af1a61d56..c6f370a442853 100644 --- a/src/native/external/libunwind/src/aarch64/Gstash_frame.c +++ b/src/native/external/libunwind/src/aarch64/Gstash_frame.c @@ -58,16 +58,19 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) && rs->ret_addr_column == LR && (rs->reg.where[FP] == DWARF_WHERE_UNDEF || rs->reg.where[FP] == DWARF_WHERE_SAME + || rs->reg.where[FP] == DWARF_WHERE_CFA || (rs->reg.where[FP] == DWARF_WHERE_CFAREL && labs(rs->reg.val[FP]) < (1 << 29) && rs->reg.val[FP]+1 != 0)) && (rs->reg.where[LR] == DWARF_WHERE_UNDEF || rs->reg.where[LR] == DWARF_WHERE_SAME + || rs->reg.where[LR] == DWARF_WHERE_CFA || (rs->reg.where[LR] == DWARF_WHERE_CFAREL && labs(rs->reg.val[LR]) < (1 << 29) && rs->reg.val[LR]+1 != 0)) && (rs->reg.where[SP] == DWARF_WHERE_UNDEF || rs->reg.where[SP] == DWARF_WHERE_SAME + || rs->reg.where[SP] == DWARF_WHERE_CFA || (rs->reg.where[SP] == DWARF_WHERE_CFAREL && labs(rs->reg.val[SP]) < (1 << 29) && rs->reg.val[SP]+1 != 0))) @@ -82,6 +85,12 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) f->lr_cfa_offset = rs->reg.val[LR]; if (rs->reg.where[SP] == DWARF_WHERE_CFAREL) f->sp_cfa_offset = rs->reg.val[SP]; + if (rs->reg.where[FP] == DWARF_WHERE_CFA) + f->fp_cfa_offset = 0; + if (rs->reg.where[LR] == DWARF_WHERE_CFA) + f->lr_cfa_offset = 0; + if (rs->reg.where[SP] == DWARF_WHERE_CFA) + f->sp_cfa_offset = 0; Debug (4, " standard frame\n"); } else diff --git a/src/native/external/libunwind/src/aarch64/Gstep.c b/src/native/external/libunwind/src/aarch64/Gstep.c index 92e2a66634ca4..f4ef369d3a109 100644 --- a/src/native/external/libunwind/src/aarch64/Gstep.c +++ b/src/native/external/libunwind/src/aarch64/Gstep.c @@ -24,6 +24,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "dwarf_i.h" #include "unwind_i.h" #include "offsets.h" @@ -51,11 +52,63 @@ is_plt_entry (struct dwarf_cursor *c) return ret; } +/* + * Save the location of VL (vector length) from the signal frame to the VG (vector + * granule) register if it exists, otherwise do nothing. If there is an error, + * the location is also not modified. + */ +static int +get_sve_vl_signal_loc (struct dwarf_cursor* dwarf, unw_word_t sc_addr) +{ + uint32_t size; + unw_addr_space_t as = dwarf->as; + unw_accessors_t *a = unw_get_accessors_int (as); + void *arg = dwarf->as_arg; + unw_word_t res_addr = sc_addr + LINUX_SC_RESERVED_OFF; + + /* + * Max possible size of reserved section is 4096. Jump by size of each record + * until the SVE signal context section is found. + */ + for(unw_word_t section_off = 0; section_off < 4096; section_off += size) + { + uint32_t magic; + int ret; + unw_word_t item_addr = res_addr + section_off + LINUX_SC_RESERVED_MAGIC_OFF; + if ((ret = dwarf_readu32(as, a, &item_addr, &magic, arg)) < 0) + return ret; + item_addr = res_addr + section_off + LINUX_SC_RESERVED_SIZE_OFF; + if ((ret = dwarf_readu32(as, a, &item_addr, &size, arg)) < 0) + return ret; + + switch(magic) + { + case 0: + /* End marker, size must be 0 */ + return size ? -UNW_EUNSPEC : 1; + + /* Magic number marking the SVE context section */ + case 0x53564501: + /* Must be big enough so that the 16 bit VL value can be accessed */ + if (size < LINUX_SC_RESERVED_SVE_VL_OFF + 2) + return -UNW_EUNSPEC; + dwarf->loc[UNW_AARCH64_VG] = DWARF_MEM_LOC(c->dwarf, res_addr + section_off + + LINUX_SC_RESERVED_SVE_VL_OFF); + return 1; + + default: + /* Don't care about any of the other sections */ + break; + } + } + return 1; +} + static int aarch64_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - int ret; + int i, ret; unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); @@ -82,43 +135,47 @@ aarch64_handle_signal_frame (unw_cursor_t *cursor) c->frame_info.frame_type = UNW_AARCH64_FRAME_SIGRETURN; c->frame_info.cfa_reg_offset = sc_addr - sp_addr; + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ - c->dwarf.loc[UNW_AARCH64_X0] = DWARF_LOC (sc_addr + LINUX_SC_X0_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X1] = DWARF_LOC (sc_addr + LINUX_SC_X1_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X2] = DWARF_LOC (sc_addr + LINUX_SC_X2_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X3] = DWARF_LOC (sc_addr + LINUX_SC_X3_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X4] = DWARF_LOC (sc_addr + LINUX_SC_X4_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X5] = DWARF_LOC (sc_addr + LINUX_SC_X5_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X6] = DWARF_LOC (sc_addr + LINUX_SC_X6_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X7] = DWARF_LOC (sc_addr + LINUX_SC_X7_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X8] = DWARF_LOC (sc_addr + LINUX_SC_X8_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X9] = DWARF_LOC (sc_addr + LINUX_SC_X9_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X10] = DWARF_LOC (sc_addr + LINUX_SC_X10_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X11] = DWARF_LOC (sc_addr + LINUX_SC_X11_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X12] = DWARF_LOC (sc_addr + LINUX_SC_X12_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X13] = DWARF_LOC (sc_addr + LINUX_SC_X13_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X14] = DWARF_LOC (sc_addr + LINUX_SC_X14_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X15] = DWARF_LOC (sc_addr + LINUX_SC_X15_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X16] = DWARF_LOC (sc_addr + LINUX_SC_X16_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X17] = DWARF_LOC (sc_addr + LINUX_SC_X17_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X18] = DWARF_LOC (sc_addr + LINUX_SC_X18_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X19] = DWARF_LOC (sc_addr + LINUX_SC_X19_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X20] = DWARF_LOC (sc_addr + LINUX_SC_X20_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X21] = DWARF_LOC (sc_addr + LINUX_SC_X21_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X22] = DWARF_LOC (sc_addr + LINUX_SC_X22_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X23] = DWARF_LOC (sc_addr + LINUX_SC_X23_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X24] = DWARF_LOC (sc_addr + LINUX_SC_X24_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X25] = DWARF_LOC (sc_addr + LINUX_SC_X25_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X26] = DWARF_LOC (sc_addr + LINUX_SC_X26_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X27] = DWARF_LOC (sc_addr + LINUX_SC_X27_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X28] = DWARF_LOC (sc_addr + LINUX_SC_X28_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X29] = DWARF_LOC (sc_addr + LINUX_SC_X29_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X30] = DWARF_LOC (sc_addr + LINUX_SC_X30_OFF, 0); - c->dwarf.loc[UNW_AARCH64_SP] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0); - c->dwarf.loc[UNW_AARCH64_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); - c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_LOC (sc_addr + LINUX_SC_PSTATE_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X0] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X0_OFF); + c->dwarf.loc[UNW_AARCH64_X1] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X1_OFF); + c->dwarf.loc[UNW_AARCH64_X2] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X2_OFF); + c->dwarf.loc[UNW_AARCH64_X3] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X3_OFF); + c->dwarf.loc[UNW_AARCH64_X4] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X4_OFF); + c->dwarf.loc[UNW_AARCH64_X5] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X5_OFF); + c->dwarf.loc[UNW_AARCH64_X6] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X6_OFF); + c->dwarf.loc[UNW_AARCH64_X7] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X7_OFF); + c->dwarf.loc[UNW_AARCH64_X8] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X8_OFF); + c->dwarf.loc[UNW_AARCH64_X9] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X9_OFF); + c->dwarf.loc[UNW_AARCH64_X10] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X10_OFF); + c->dwarf.loc[UNW_AARCH64_X11] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X11_OFF); + c->dwarf.loc[UNW_AARCH64_X12] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X12_OFF); + c->dwarf.loc[UNW_AARCH64_X13] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X13_OFF); + c->dwarf.loc[UNW_AARCH64_X14] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X14_OFF); + c->dwarf.loc[UNW_AARCH64_X15] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X15_OFF); + c->dwarf.loc[UNW_AARCH64_X16] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X16_OFF); + c->dwarf.loc[UNW_AARCH64_X17] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X17_OFF); + c->dwarf.loc[UNW_AARCH64_X18] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X18_OFF); + c->dwarf.loc[UNW_AARCH64_X19] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X19_OFF); + c->dwarf.loc[UNW_AARCH64_X20] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X20_OFF); + c->dwarf.loc[UNW_AARCH64_X21] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X21_OFF); + c->dwarf.loc[UNW_AARCH64_X22] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X22_OFF); + c->dwarf.loc[UNW_AARCH64_X23] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X23_OFF); + c->dwarf.loc[UNW_AARCH64_X24] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X24_OFF); + c->dwarf.loc[UNW_AARCH64_X25] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X25_OFF); + c->dwarf.loc[UNW_AARCH64_X26] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X26_OFF); + c->dwarf.loc[UNW_AARCH64_X27] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X27_OFF); + c->dwarf.loc[UNW_AARCH64_X28] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X28_OFF); + c->dwarf.loc[UNW_AARCH64_X29] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X29_OFF); + c->dwarf.loc[UNW_AARCH64_X30] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_X30_OFF); + c->dwarf.loc[UNW_AARCH64_SP] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_SP_OFF); + c->dwarf.loc[UNW_AARCH64_PC] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_PC_OFF); + c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_PSTATE_OFF); + c->dwarf.loc[UNW_AARCH64_VG] = DWARF_NULL_LOC; /* Set SP/CFA and PC/IP. */ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa); @@ -127,7 +184,7 @@ aarch64_handle_signal_frame (unw_cursor_t *cursor) c->dwarf.pi_valid = 0; c->dwarf.use_prev_instr = 0; - return 1; + return get_sve_vl_signal_loc (&c->dwarf, sc_addr); } int diff --git a/src/native/external/libunwind/src/aarch64/init.h b/src/native/external/libunwind/src/aarch64/init.h index 5dab60bb64ed7..e761329685bce 100644 --- a/src/native/external/libunwind/src/aarch64/init.h +++ b/src/native/external/libunwind/src/aarch64/init.h @@ -30,6 +30,9 @@ common_init (struct cursor *c, unsigned use_prev_instr) { int ret, i; + for (i = UNW_AARCH64_PSTATE + 1; i < UNW_AARCH64_V0; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_AARCH64_X0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X0); c->dwarf.loc[UNW_AARCH64_X1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X1); c->dwarf.loc[UNW_AARCH64_X2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X2); @@ -65,6 +68,7 @@ common_init (struct cursor *c, unsigned use_prev_instr) c->dwarf.loc[UNW_AARCH64_PC] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_PC); c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_PSTATE); + c->dwarf.loc[UNW_AARCH64_VG] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_VG); c->dwarf.loc[UNW_AARCH64_V0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V0); c->dwarf.loc[UNW_AARCH64_V1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V1); c->dwarf.loc[UNW_AARCH64_V2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V2); @@ -98,9 +102,6 @@ common_init (struct cursor *c, unsigned use_prev_instr) c->dwarf.loc[UNW_AARCH64_V30] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V30); c->dwarf.loc[UNW_AARCH64_V31] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V31); - for (i = UNW_AARCH64_PSTATE + 1; i < UNW_AARCH64_V0; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); if (ret < 0) return ret; diff --git a/src/native/external/libunwind/src/aarch64/offsets.h b/src/native/external/libunwind/src/aarch64/offsets.h index e78251d0a8f82..52291edb33d9c 100644 --- a/src/native/external/libunwind/src/aarch64/offsets.h +++ b/src/native/external/libunwind/src/aarch64/offsets.h @@ -47,3 +47,10 @@ #define LINUX_SC_SP_OFF 0x100 #define LINUX_SC_PC_OFF 0x108 #define LINUX_SC_PSTATE_OFF 0x110 +#define LINUX_SC_RESERVED_OFF 0x120 + +// struct _aarch64_ctx { __u32 magic; __u32 size; }; +// struct sve_context { struct _aarch64_ctx head; __u16 vl; __u16 __reserved[3]; }; +#define LINUX_SC_RESERVED_MAGIC_OFF 0x0 +#define LINUX_SC_RESERVED_SIZE_OFF 0x4 +#define LINUX_SC_RESERVED_SVE_VL_OFF 0x8 \ No newline at end of file diff --git a/src/native/external/libunwind/src/aarch64/unwind_i.h b/src/native/external/libunwind/src/aarch64/unwind_i.h index db7e29dd722e9..9305846f879e9 100644 --- a/src/native/external/libunwind/src/aarch64/unwind_i.h +++ b/src/native/external/libunwind/src/aarch64/unwind_i.h @@ -59,6 +59,10 @@ extern int aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, } while (0) #endif +#if defined(__FreeBSD__) +#define GET_FPCTX(uc) ((unw_tdep_context_t *)(&uc->uc_mcontext.mc_spare)) +#else #define GET_FPCTX(uc) ((unw_fpsimd_context_t *)(&uc->uc_mcontext.__reserved)) +#endif #endif /* unwind_i_h */ diff --git a/src/native/external/libunwind/src/arm/Gex_tables.c b/src/native/external/libunwind/src/arm/Gex_tables.c index 7c1f29a0c9f9a..40cd15346f32d 100644 --- a/src/native/external/libunwind/src/arm/Gex_tables.c +++ b/src/native/external/libunwind/src/arm/Gex_tables.c @@ -508,18 +508,20 @@ arm_phdr_cb (struct dl_phdr_info *info, size_t size, void *data) } HIDDEN int -arm_find_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, int need_unwind_info, void *arg) +arm_find_proc_info2 (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, void *arg, + int methods) { int ret = -1; intrmask_t saved_mask; Debug (14, "looking for IP=0x%lx\n", (long) ip); - if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) + if (UNW_TRY_METHOD (UNW_ARM_METHOD_DWARF) && (methods & UNW_ARM_METHOD_DWARF)) ret = dwarf_find_proc_info (as, ip, pi, need_unwind_info, arg); - if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) + if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX) && + (methods & UNW_ARM_METHOD_EXIDX)) { struct arm_cb_data cb_data; @@ -542,6 +544,14 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip, return ret; } +HIDDEN int +arm_find_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, void *arg) +{ + return arm_find_proc_info2 (as, ip, pi, need_unwind_info, arg, + UNW_ARM_METHOD_ALL); +} + HIDDEN void arm_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) { diff --git a/src/native/external/libunwind/src/arm/Gos-freebsd.c b/src/native/external/libunwind/src/arm/Gos-freebsd.c index a1069223a507d..1566a813b1f36 100644 --- a/src/native/external/libunwind/src/arm/Gos-freebsd.c +++ b/src/native/external/libunwind/src/arm/Gos-freebsd.c @@ -38,7 +38,7 @@ HIDDEN int arm_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - int ret, fmt; + int i, ret, fmt; unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); @@ -70,6 +70,9 @@ arm_handle_signal_frame (unw_cursor_t *cursor) c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN; c->frame_info.cfa_reg_offset = sc_addr - sp_addr; + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ diff --git a/src/native/external/libunwind/src/arm/Gos-linux.c b/src/native/external/libunwind/src/arm/Gos-linux.c index 260e086f6953e..197030307efd0 100644 --- a/src/native/external/libunwind/src/arm/Gos-linux.c +++ b/src/native/external/libunwind/src/arm/Gos-linux.c @@ -33,7 +33,7 @@ HIDDEN int arm_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - int ret; + int i, ret; unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); @@ -93,6 +93,9 @@ arm_handle_signal_frame (unw_cursor_t *cursor) c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN; c->frame_info.cfa_reg_offset = sc_addr - sp_addr; + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ diff --git a/src/native/external/libunwind/src/arm/Gstash_frame.c b/src/native/external/libunwind/src/arm/Gstash_frame.c index c5a76b86d0a96..a30d24cfe3947 100644 --- a/src/native/external/libunwind/src/arm/Gstash_frame.c +++ b/src/native/external/libunwind/src/arm/Gstash_frame.c @@ -58,16 +58,19 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) && rs->ret_addr_column == LR && (rs->reg.where[R7] == DWARF_WHERE_UNDEF || rs->reg.where[R7] == DWARF_WHERE_SAME + || rs->reg.where[R7] == DWARF_WHERE_CFA || (rs->reg.where[R7] == DWARF_WHERE_CFAREL && labs(rs->reg.val[R7]) < (1 << 29) && rs->reg.val[R7]+1 != 0)) && (rs->reg.where[LR] == DWARF_WHERE_UNDEF || rs->reg.where[LR] == DWARF_WHERE_SAME + || rs->reg.where[R7] == DWARF_WHERE_CFA || (rs->reg.where[LR] == DWARF_WHERE_CFAREL && labs(rs->reg.val[LR]) < (1 << 29) && rs->reg.val[LR]+1 != 0)) && (rs->reg.where[SP] == DWARF_WHERE_UNDEF || rs->reg.where[SP] == DWARF_WHERE_SAME + || rs->reg.where[SP] == DWARF_WHERE_CFA || (rs->reg.where[SP] == DWARF_WHERE_CFAREL && labs(rs->reg.val[SP]) < (1 << 29) && rs->reg.val[SP]+1 != 0))) @@ -82,6 +85,12 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) f->lr_cfa_offset = rs->reg.val[LR]; if (rs->reg.where[SP] == DWARF_WHERE_CFAREL) f->sp_cfa_offset = rs->reg.val[SP]; + if (rs->reg.where[R7] == DWARF_WHERE_CFA) + f->r7_cfa_offset = 0; + if (rs->reg.where[LR] == DWARF_WHERE_CFA) + f->lr_cfa_offset = 0; + if (rs->reg.where[SP] == DWARF_WHERE_CFA) + f->sp_cfa_offset = 0; Debug (4, " standard frame\n"); } else diff --git a/src/native/external/libunwind/src/arm/Gstep.c b/src/native/external/libunwind/src/arm/Gstep.c index 895e8a892afce..e4ada651bce81 100644 --- a/src/native/external/libunwind/src/arm/Gstep.c +++ b/src/native/external/libunwind/src/arm/Gstep.c @@ -54,17 +54,22 @@ arm_exidx_step (struct cursor *c) c->dwarf.as_arg); if (ret == -UNW_ENOINFO) { +#ifdef UNW_LOCAL_ONLY + if ((ret = arm_find_proc_info2 (c->dwarf.as, ip, &c->dwarf.pi, + 1, c->dwarf.as_arg, + UNW_ARM_METHOD_EXIDX)) < 0) + return ret; +#else if ((ret = tdep_find_proc_info (&c->dwarf, ip, 1)) < 0) return ret; +#endif } if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX) return -UNW_ENOINFO; ret = arm_exidx_extract (&c->dwarf, buf); - if (ret == -UNW_ESTOPUNWIND) - return 0; - else if (ret < 0) + if (ret < 0) return ret; ret = arm_exidx_decode (buf, ret, &c->dwarf); @@ -88,6 +93,7 @@ unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret = -UNW_EUNSPEC; + int has_stopunwind = 0; Debug (1, "(cursor=%p)\n", c); @@ -95,17 +101,31 @@ unw_step (unw_cursor_t *cursor) if (unw_is_signal_frame (cursor) > 0) return arm_handle_signal_frame (cursor); + /* First, try extbl-based unwinding. */ + if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) + { + ret = arm_exidx_step (c); + Debug(1, "arm_exidx_step()=%d\n", ret); + if (ret > 0) + return 1; + if (ret == 0) + return ret; + if (ret == -UNW_ESTOPUNWIND) + has_stopunwind = 1; + } + #ifdef CONFIG_DEBUG_FRAME - /* First, try DWARF-based unwinding. */ + /* Second, try DWARF-based unwinding. */ if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) { + Debug (13, "%s(ret=%d), trying extbl\n", + UNW_TRY_METHOD(UNW_ARM_METHOD_EXIDX) ? "arm_exidx_step() failed " : "", + ret); ret = dwarf_step (&c->dwarf); Debug(1, "dwarf_step()=%d\n", ret); if (likely (ret > 0)) return 1; - else if (unlikely (ret == -UNW_ESTOPUNWIND)) - return ret; if (ret < 0 && ret != -UNW_ENOINFO) { @@ -115,18 +135,9 @@ unw_step (unw_cursor_t *cursor) } #endif /* CONFIG_DEBUG_FRAME */ - /* Next, try extbl-based unwinding. */ - if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) - { - Debug (13, "%s(ret=%d), trying extbl\n", - UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) ? "dwarf_step() failed " : "", - ret); - ret = arm_exidx_step (c); - if (ret > 0) - return 1; - if (ret == -UNW_ESTOPUNWIND || ret == 0) - return ret; - } + // Before trying the fallback, if any unwind info tell us to stop, do that. + if (has_stopunwind) + return -UNW_ESTOPUNWIND; /* Fall back on APCS frame parsing. Note: This won't work in case the ARM EABI is used. */ @@ -139,13 +150,13 @@ unw_step (unw_cursor_t *cursor) if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME)) { Debug (13, "%s%s%s%s(ret=%d), trying frame-chain\n", - UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) ? "dwarf_step() " : "", - (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) && UNW_TRY_METHOD(UNW_ARM_METHOD_EXIDX)) ? "and " : "", UNW_TRY_METHOD(UNW_ARM_METHOD_EXIDX) ? "arm_exidx_step() " : "", - (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) || UNW_TRY_METHOD(UNW_ARM_METHOD_EXIDX)) ? "failed " : "", + (UNW_TRY_METHOD(UNW_ARM_METHOD_EXIDX) && UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) ? "and " : "", + UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) ? "dwarf_step() " : "", + (UNW_TRY_METHOD(UNW_ARM_METHOD_EXIDX) || UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) ? "failed " : "", ret); ret = UNW_ESUCCESS; - /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */ + /* EXIDX and/or DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */ unw_word_t instr, i; dwarf_loc_t ip_loc, fp_loc; unw_word_t frame; diff --git a/src/native/external/libunwind/src/coredump/_UCD_access_mem.c b/src/native/external/libunwind/src/coredump/_UCD_access_mem.c index 1fdbd128ffc1e..cdfc622028352 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_access_mem.c +++ b/src/native/external/libunwind/src/coredump/_UCD_access_mem.c @@ -23,76 +23,83 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "_UCD_lib.h" #include "_UCD_internal.h" +#include "ucd_file_table.h" int -_UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val, - int write, void *arg) +_UCD_access_mem (unw_addr_space_t as, + unw_word_t addr, + unw_word_t *val, + int write, + void *arg) { if (write) { - Debug(0, "write is not supported\n"); + Debug (0, "write is not supported\n"); return -UNW_EINVAL; } struct UCD_info *ui = arg; - unw_word_t addr_last = addr + sizeof(*val)-1; - coredump_phdr_t *phdr; + unw_word_t addr_last = addr + sizeof (*val) - 1; + unsigned i; + for (i = 0; i < ui->phdrs_count; i++) { - phdr = &ui->phdrs[i]; - if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz) + coredump_phdr_t *phdr = &ui->phdrs[i]; + + /* First check the (in-memory) backup file image. */ + if (phdr->p_backing_file_index != ucd_file_no_index) { - goto found; - } - } - Debug(1, "addr 0x%llx is unmapped\n", (unsigned long long)addr); - return -UNW_EINVAL; + ucd_file_t *ucd_file = ucd_file_table_at (&ui->ucd_file_table, phdr->p_backing_file_index); - found: ; + if (ucd_file == NULL) + { + Debug (0, "invalid backing file index for phdr[%d]\n", i); + return -UNW_EINVAL; + } - const char *filename UNUSED; - off_t fileofs; - int fd; - if (addr_last >= phdr->p_vaddr + phdr->p_filesz) - { - /* This part of mapped address space is not present in coredump file */ - /* Do we have it in the backup file? */ - if (phdr->backing_fd < 0) + off_t image_offset = addr - phdr->p_vaddr; + + if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + ucd_file->size) + { + memcpy (val, ucd_file->image + image_offset, sizeof (*val)); + Debug (16, "%#010llx <- [addr:%#010llx file:%s]\n", + (unsigned long long) (*val), + (unsigned long long)image_offset, + ucd_file->filename); + return UNW_ESUCCESS; + } + } + + /* Next, check the on-disk corefile. */ + if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz) { - Debug(1, "access to not-present data in phdr[%d]: addr:0x%llx\n", - i, (unsigned long long)addr - ); - return -UNW_EINVAL; + off_t fileofs = phdr->p_offset + (addr - phdr->p_vaddr); + + if (lseek (ui->coredump_fd, fileofs, SEEK_SET) != fileofs) + { + Debug (0, "error %d in lseek(\"%s\", %lld): %s\n", + errno, ui->coredump_filename, (long long)fileofs, strerror (errno)); + return -UNW_EINVAL; + } + + if (read (ui->coredump_fd, val, sizeof (*val)) != sizeof (*val)) + { + Debug (0, "error %d in read(\"%s\", %lld): %s\n", + errno, ui->coredump_filename, (long long)sizeof (*val), strerror (errno)); + return -UNW_EINVAL; + } + + Debug (16, "0x%llx <- [addr:0x%llx fileofs:0x%llx file:%s]\n", + (unsigned long long) (*val), + (unsigned long long)addr, + (unsigned long long)fileofs, + ui->coredump_filename); + return UNW_ESUCCESS; } - filename = phdr->backing_filename; - fileofs = addr - phdr->p_vaddr; - fd = phdr->backing_fd; - goto read; } - filename = ui->coredump_filename; - fileofs = phdr->p_offset + (addr - phdr->p_vaddr); - fd = ui->coredump_fd; - read: - if (lseek(fd, fileofs, SEEK_SET) != fileofs) - goto read_error; - if (read(fd, val, sizeof(*val)) != sizeof(*val)) - goto read_error; - - Debug(1, "0x%llx <- [addr:0x%llx fileofs:0x%llx]\n", - (unsigned long long)(*val), - (unsigned long long)addr, - (unsigned long long)fileofs - ); - return 0; - - read_error: - Debug(1, "access out of file: addr:0x%llx fileofs:%llx file:'%s'\n", - (unsigned long long)addr, - (unsigned long long)fileofs, - filename - ); + Debug (0, "addr %#010llx is unmapped\n", (unsigned long long)addr); return -UNW_EINVAL; } diff --git a/src/native/external/libunwind/src/coredump/_UCD_access_reg_linux.c b/src/native/external/libunwind/src/coredump/_UCD_access_reg_linux.c index 99c28a4cfa078..bb6826168e884 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_access_reg_linux.c +++ b/src/native/external/libunwind/src/coredump/_UCD_access_reg_linux.c @@ -54,9 +54,6 @@ _UCD_access_reg (unw_addr_space_t as, #elif defined(UNW_TARGET_TILEGX) if (regnum > UNW_TILEGX_CFA) goto badreg; -#elif defined(UNW_TARGET_S390X) - if (regnum > UNW_S390X_R15) - goto badreg; #elif defined(UNW_TARGET_IA64) || defined(UNW_TARGET_HPPA) || defined(UNW_TARGET_PPC32) || defined(UNW_TARGET_PPC64) if (regnum >= ARRAY_SIZE(ui->prstatus->pr_reg)) goto badreg; @@ -70,37 +67,37 @@ _UCD_access_reg (unw_addr_space_t as, static const uint8_t remap_regs[] = { - [UNW_LOONGARCH64_R0] = LOONGARCH64_EF_R0, - [UNW_LOONGARCH64_R1] = LOONGARCH64_EF_R1, - [UNW_LOONGARCH64_R2] = LOONGARCH64_EF_R2, - [UNW_LOONGARCH64_R3] = LOONGARCH64_EF_R3, - [UNW_LOONGARCH64_R4] = LOONGARCH64_EF_R4, - [UNW_LOONGARCH64_R5] = LOONGARCH64_EF_R5, - [UNW_LOONGARCH64_R6] = LOONGARCH64_EF_R6, - [UNW_LOONGARCH64_R7] = LOONGARCH64_EF_R7, - [UNW_LOONGARCH64_R8] = LOONGARCH64_EF_R8, - [UNW_LOONGARCH64_R9] = LOONGARCH64_EF_R9, - [UNW_LOONGARCH64_R10] = LOONGARCH64_EF_R10, - [UNW_LOONGARCH64_R11] = LOONGARCH64_EF_R11, - [UNW_LOONGARCH64_R12] = LOONGARCH64_EF_R12, - [UNW_LOONGARCH64_R13] = LOONGARCH64_EF_R13, - [UNW_LOONGARCH64_R14] = LOONGARCH64_EF_R14, - [UNW_LOONGARCH64_R15] = LOONGARCH64_EF_R15, - [UNW_LOONGARCH64_R16] = LOONGARCH64_EF_R16, - [UNW_LOONGARCH64_R17] = LOONGARCH64_EF_R17, - [UNW_LOONGARCH64_R18] = LOONGARCH64_EF_R18, - [UNW_LOONGARCH64_R19] = LOONGARCH64_EF_R19, - [UNW_LOONGARCH64_R20] = LOONGARCH64_EF_R20, - [UNW_LOONGARCH64_R21] = LOONGARCH64_EF_R21, - [UNW_LOONGARCH64_R22] = LOONGARCH64_EF_R22, - [UNW_LOONGARCH64_R23] = LOONGARCH64_EF_R23, - [UNW_LOONGARCH64_R24] = LOONGARCH64_EF_R24, - [UNW_LOONGARCH64_R25] = LOONGARCH64_EF_R25, - [UNW_LOONGARCH64_R28] = LOONGARCH64_EF_R28, - [UNW_LOONGARCH64_R29] = LOONGARCH64_EF_R29, - [UNW_LOONGARCH64_R30] = LOONGARCH64_EF_R30, - [UNW_LOONGARCH64_R31] = LOONGARCH64_EF_R31, - [UNW_LOONGARCH64_PC] = LOONGARCH64_EF_CSR_EPC, + [UNW_LOONGARCH64_R0] = LOONGARCH_EF_R0, + [UNW_LOONGARCH64_R1] = LOONGARCH_EF_R1, + [UNW_LOONGARCH64_R2] = LOONGARCH_EF_R2, + [UNW_LOONGARCH64_R3] = LOONGARCH_EF_R3, + [UNW_LOONGARCH64_R4] = LOONGARCH_EF_R4, + [UNW_LOONGARCH64_R5] = LOONGARCH_EF_R5, + [UNW_LOONGARCH64_R6] = LOONGARCH_EF_R6, + [UNW_LOONGARCH64_R7] = LOONGARCH_EF_R7, + [UNW_LOONGARCH64_R8] = LOONGARCH_EF_R8, + [UNW_LOONGARCH64_R9] = LOONGARCH_EF_R9, + [UNW_LOONGARCH64_R10] = LOONGARCH_EF_R10, + [UNW_LOONGARCH64_R11] = LOONGARCH_EF_R11, + [UNW_LOONGARCH64_R12] = LOONGARCH_EF_R12, + [UNW_LOONGARCH64_R13] = LOONGARCH_EF_R13, + [UNW_LOONGARCH64_R14] = LOONGARCH_EF_R14, + [UNW_LOONGARCH64_R15] = LOONGARCH_EF_R15, + [UNW_LOONGARCH64_R16] = LOONGARCH_EF_R16, + [UNW_LOONGARCH64_R17] = LOONGARCH_EF_R17, + [UNW_LOONGARCH64_R18] = LOONGARCH_EF_R18, + [UNW_LOONGARCH64_R19] = LOONGARCH_EF_R19, + [UNW_LOONGARCH64_R20] = LOONGARCH_EF_R20, + [UNW_LOONGARCH64_R21] = LOONGARCH_EF_R21, + [UNW_LOONGARCH64_R22] = LOONGARCH_EF_R22, + [UNW_LOONGARCH64_R23] = LOONGARCH_EF_R23, + [UNW_LOONGARCH64_R24] = LOONGARCH_EF_R24, + [UNW_LOONGARCH64_R25] = LOONGARCH_EF_R25, + [UNW_LOONGARCH64_R28] = LOONGARCH_EF_R28, + [UNW_LOONGARCH64_R29] = LOONGARCH_EF_R29, + [UNW_LOONGARCH64_R30] = LOONGARCH_EF_R30, + [UNW_LOONGARCH64_R31] = LOONGARCH_EF_R31, + [UNW_LOONGARCH64_PC] = LOONGARCH_EF_CSR_ERA, }; #else #if defined(UNW_TARGET_MIPS) @@ -138,6 +135,27 @@ _UCD_access_reg (unw_addr_space_t as, [UNW_MIPS_R31] = EF_REG31, [UNW_MIPS_PC] = EF_CP0_EPC, }; +#elif defined(UNW_TARGET_S390X) + static const uint8_t remap_regs[] = + { + [UNW_S390X_IP] = offsetof(struct user_regs_struct, psw.addr) / sizeof(long), + [UNW_S390X_R0] = offsetof(struct user_regs_struct, gprs[0]) / sizeof(long), + [UNW_S390X_R1] = offsetof(struct user_regs_struct, gprs[1]) / sizeof(long), + [UNW_S390X_R2] = offsetof(struct user_regs_struct, gprs[2]) / sizeof(long), + [UNW_S390X_R3] = offsetof(struct user_regs_struct, gprs[3]) / sizeof(long), + [UNW_S390X_R4] = offsetof(struct user_regs_struct, gprs[4]) / sizeof(long), + [UNW_S390X_R5] = offsetof(struct user_regs_struct, gprs[5]) / sizeof(long), + [UNW_S390X_R6] = offsetof(struct user_regs_struct, gprs[6]) / sizeof(long), + [UNW_S390X_R7] = offsetof(struct user_regs_struct, gprs[7]) / sizeof(long), + [UNW_S390X_R8] = offsetof(struct user_regs_struct, gprs[8]) / sizeof(long), + [UNW_S390X_R9] = offsetof(struct user_regs_struct, gprs[9]) / sizeof(long), + [UNW_S390X_R10] = offsetof(struct user_regs_struct, gprs[10]) / sizeof(long), + [UNW_S390X_R11] = offsetof(struct user_regs_struct, gprs[11]) / sizeof(long), + [UNW_S390X_R12] = offsetof(struct user_regs_struct, gprs[12]) / sizeof(long), + [UNW_S390X_R13] = offsetof(struct user_regs_struct, gprs[13]) / sizeof(long), + [UNW_S390X_R14] = offsetof(struct user_regs_struct, gprs[14]) / sizeof(long), + [UNW_S390X_R15] = offsetof(struct user_regs_struct, gprs[15]) / sizeof(long), + }; #elif defined(UNW_TARGET_X86) static const uint8_t remap_regs[] = { diff --git a/src/native/external/libunwind/src/coredump/_UCD_create.c b/src/native/external/libunwind/src/coredump/_UCD_create.c index 9b4b7fe39b851..784d046251390 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_create.c +++ b/src/native/external/libunwind/src/coredump/_UCD_create.c @@ -142,9 +142,7 @@ _UCD_create(const char *filename) cur->p_filesz = hdr64.p_filesz; cur->p_memsz = hdr64.p_memsz ; cur->p_align = hdr64.p_align ; - /* cur->backing_filename = NULL; - done by memset */ - cur->backing_fd = -1; - cur->backing_filesize = hdr64.p_filesz; + cur->p_backing_file_index = -1; i++; cur++; } @@ -167,9 +165,7 @@ _UCD_create(const char *filename) cur->p_filesz = hdr32.p_filesz; cur->p_memsz = hdr32.p_memsz ; cur->p_align = hdr32.p_align ; - /* cur->backing_filename = NULL; - done by memset */ - cur->backing_fd = -1; - cur->backing_filesize = hdr32.p_memsz; + cur->p_backing_file_index = -1; i++; cur++; } @@ -181,6 +177,10 @@ _UCD_create(const char *filename) goto err; } + ret = ucd_file_table_init(&ui->ucd_file_table); + if (ret != UNW_ESUCCESS) { + Debug(0, "error initializing backing file table\n"); + } ret = _UCD_get_mapinfo(ui, phdrs, size); if (ret != UNW_ESUCCESS) { Debug(0, "failure retrieving file mapping from core file\n"); @@ -192,23 +192,17 @@ _UCD_create(const char *filename) { if (cur->p_type == PT_LOAD) { - Debug(2, " ofs:%08llx va:%08llx filesize:%08llx memsize:%08llx flg:%x", + Debug(2, "phdr[%u] ofs:%#010llx va:%#010llx filesize:%#010llx memsize:%#010llx flg:%#04x bf_idx=%d %s %s\n", + i, (unsigned long long) cur->p_offset, (unsigned long long) cur->p_vaddr, (unsigned long long) cur->p_filesz, (unsigned long long) cur->p_memsz, - cur->p_flags - ); - if (cur->p_filesz < cur->p_memsz) - { - Debug(2, " partial"); - } - if (cur->p_flags & PF_X) - { - Debug(2, " executable"); - } + cur->p_flags, + cur->p_backing_file_index, + (cur->p_filesz < cur->p_memsz)?"partial":" ", + (cur->p_flags & PF_X)?"exec":" "); } - Debug(2, "\n"); cur++; } @@ -218,7 +212,10 @@ _UCD_create(const char *filename) goto err; } - ui->prstatus = &ui->threads[0]; + ui->prstatus = &ui->threads[0].prstatus; +#ifdef HAVE_ELF_FPREGSET_T + ui->fpregset = &ui->threads[0].fpregset; +#endif return ui; @@ -234,96 +231,29 @@ int _UCD_get_num_threads(struct UCD_info *ui) void _UCD_select_thread(struct UCD_info *ui, int n) { - if (n >= 0 && n < ui->n_threads) - ui->prstatus = &ui->threads[n]; + if (n >= 0 && n < ui->n_threads) { + ui->prstatus = &ui->threads[n].prstatus; +#ifdef HAVE_ELF_FPREGSET_T + ui->fpregset = &ui->threads[n].fpregset; +#endif + } } pid_t _UCD_get_pid(struct UCD_info *ui) { +#if defined(HAVE_PROCFS_STATUS) + return ui->prstatus->pid; +#else return ui->prstatus->pr_pid; +#endif } int _UCD_get_cursig(struct UCD_info *ui) { - return ui->prstatus->pr_cursig; -} - -int _UCD_add_backing_file_at_segment(struct UCD_info *ui, int phdr_no, const char *filename) -{ - if ((unsigned)phdr_no >= ui->phdrs_count) - { - Debug(0, "There is no segment %d in this coredump\n", phdr_no); - return -1; - } - - struct coredump_phdr *phdr = &ui->phdrs[phdr_no]; - if (phdr->backing_filename) - { - Debug(0, "Backing file already added to segment %d\n", phdr_no); - return -1; - } - - int fd = open(filename, O_RDONLY); - if (fd < 0) - { - Debug(0, "Can't open '%s'\n", filename); - return -1; - } - - phdr->backing_fd = fd; - phdr->backing_filename = strdup(filename); - - struct stat statbuf; - if (fstat(fd, &statbuf) != 0) - { - Debug(0, "Can't stat '%s'\n", filename); - goto err; - } - phdr->backing_filesize = (uoff_t)statbuf.st_size; - - if (phdr->p_flags != (PF_X | PF_R)) - { - Debug(1, "Note: phdr[%u] is not r-x: flags are 0x%x\n", - phdr_no, phdr->p_flags); - } - - if (phdr->backing_filesize > phdr->p_memsz) - { - /* This is expected */ - Debug(2, "Note: phdr[%u] is %lld bytes, file is larger: %lld bytes\n", - phdr_no, - (unsigned long long)phdr->p_memsz, - (unsigned long long)phdr->backing_filesize - ); - } -//TODO: else loudly complain? Maybe even fail? - - /* Success */ +#if defined(HAVE_PROCFS_STATUS) return 0; - - err: - if (phdr->backing_fd >= 0) - { - close(phdr->backing_fd); - phdr->backing_fd = -1; - } - free(phdr->backing_filename); - phdr->backing_filename = NULL; - return -1; +#else + return ui->prstatus->pr_cursig; +#endif } -int _UCD_add_backing_file_at_vaddr(struct UCD_info *ui, - unsigned long vaddr, - const char *filename) -{ - unsigned i; - for (i = 0; i < ui->phdrs_count; i++) - { - struct coredump_phdr *phdr = &ui->phdrs[i]; - if (phdr->p_vaddr != vaddr) - continue; - /* It seems to match. Add it. */ - return _UCD_add_backing_file_at_segment(ui, i, filename); - } - return -1; -} diff --git a/src/native/external/libunwind/src/coredump/_UCD_destroy.c b/src/native/external/libunwind/src/coredump/_UCD_destroy.c index ddc36ec8986aa..c767aa445f977 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_destroy.c +++ b/src/native/external/libunwind/src/coredump/_UCD_destroy.c @@ -35,14 +35,7 @@ _UCD_destroy (struct UCD_info *ui) invalidate_edi (&ui->edi); - unsigned i; - for (i = 0; i < ui->phdrs_count; i++) - { - struct coredump_phdr *phdr = &ui->phdrs[i]; - free(phdr->backing_filename); - if (phdr->backing_fd >= 0) - close(phdr->backing_fd); - } + ucd_file_table_dispose(&ui->ucd_file_table); free(ui->phdrs); free(ui->note_phdr); diff --git a/src/native/external/libunwind/src/coredump/_UCD_elf_map_image.c b/src/native/external/libunwind/src/coredump/_UCD_elf_map_image.c index 99fd25e83a962..ea36745a6a026 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_elf_map_image.c +++ b/src/native/external/libunwind/src/coredump/_UCD_elf_map_image.c @@ -29,13 +29,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "_UCD_lib.h" #include "_UCD_internal.h" +#include "ucd_file_table.h" static coredump_phdr_t * CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr) { struct elf_image *ei = &ui->edi.ei; - if (phdr->backing_fd < 0) + if (phdr->p_backing_file_index == ucd_file_no_index) { /* Note: coredump file contains only phdr->p_filesz bytes. * We want to map bigger area (phdr->p_memsz bytes) to make sure @@ -45,6 +46,7 @@ CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr) ei->image = mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, ui->coredump_fd, phdr->p_offset); if (ei->image == MAP_FAILED) { + Debug(0, "error %d in mmap(): %s\n", errno, strerror(errno)); ei->image = NULL; return NULL; } @@ -56,21 +58,19 @@ CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr) munmap(remainder_base, remainder_len); } } else { - /* We have a backing file for this segment. - * This file is always longer than phdr->p_memsz, - * and if phdr->p_filesz !=0, first phdr->p_filesz bytes in coredump - * are the same as first bytes in the file. (Thus no need to map coredump) - * We map the entire file: - * unwinding may need data which is past phdr->p_memsz bytes. - */ + ucd_file_t *ucd_file = ucd_file_table_at(&ui->ucd_file_table, phdr->p_backing_file_index); + if (ucd_file == NULL) + { + Debug(0, "error retrieving backing file for index %d\n", phdr->p_backing_file_index); + return NULL; + } /* addr, length, prot, flags, fd, fd_offset */ - ei->image = mmap(NULL, phdr->backing_filesize, PROT_READ, MAP_PRIVATE, phdr->backing_fd, 0); - if (ei->image == MAP_FAILED) + ei->image = ucd_file_map (ucd_file); + if (ei->image == NULL) { - ei->image = NULL; return NULL; } - ei->size = phdr->backing_filesize; + ei->size = ucd_file->size; } /* Check ELF header for sanity */ diff --git a/src/native/external/libunwind/src/coredump/_UCD_find_proc_info.c b/src/native/external/libunwind/src/coredump/_UCD_find_proc_info.c index 35e1624ced63e..fae61d9fd4d3c 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_find_proc_info.c +++ b/src/native/external/libunwind/src/coredump/_UCD_find_proc_info.c @@ -53,6 +53,9 @@ get_unwind_info(struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip) && ip >= ui->edi.di_debug.start_ip && ip < ui->edi.di_debug.end_ip)) return 0; + /* The invalidate_edi call unmaps memory it doesn't own, so just null it out + instead. */ + ui->edi.ei.image = NULL; invalidate_edi (&ui->edi); /* Used to be tdep_get_elf_image() in ptrace unwinding code */ @@ -62,17 +65,22 @@ get_unwind_info(struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip) Debug(1, "returns error: _UCD_get_elf_image failed\n"); return -UNW_ENOINFO; } + + ucd_file_t *ucd_file = ucd_file_table_at(&ui->ucd_file_table, phdr->p_backing_file_index); + if (ucd_file == NULL) + { + Debug(0, "no backing file for index %d\n", phdr->p_backing_file_index); + return -UNW_ENOINFO; + } + /* segbase: where it is mapped in virtual memory */ - /* mapoff: offset in the file */ segbase = phdr->p_vaddr; - /*mapoff = phdr->p_offset; WRONG! phdr->p_offset is the offset in COREDUMP file */ + /* mapoff doesn't matter since the entire file is loaded */ mapoff = 0; -///FIXME. text segment is USUALLY, not always, at offset 0 in the binary/.so file. -// ensure that at initialization. /* Here, SEGBASE is the starting-address of the (mmap'ped) segment which covers the IP we're looking for. */ - if (tdep_find_unwind_table(&ui->edi, as, phdr->backing_filename, segbase, mapoff, ip) < 0) + if (tdep_find_unwind_table(&ui->edi, as, ucd_file->filename, segbase, mapoff, ip) < 0) { Debug(1, "returns error: tdep_find_unwind_table failed\n"); return -UNW_ENOINFO; diff --git a/src/native/external/libunwind/src/coredump/_UCD_get_mapinfo_linux.c b/src/native/external/libunwind/src/coredump/_UCD_get_mapinfo_linux.c index 0df2107fb31b2..0d04f01a86840 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_get_mapinfo_linux.c +++ b/src/native/external/libunwind/src/coredump/_UCD_get_mapinfo_linux.c @@ -3,17 +3,17 @@ */ /* This file is part of libunwind. - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -43,60 +43,105 @@ * containing the mapped file names. They are ordered correspondingly to each * entry in the map structure array. */ -typedef struct { +struct core_nt_file_hdr_s +{ unsigned long count; unsigned long pagesz; -} linux_mapinfo_hdr_t; +}; +typedef struct core_nt_file_hdr_s core_nt_file_hdr_t; -typedef struct { +struct core_nt_file_entry_s +{ unsigned long start; unsigned long end; unsigned long offset; -} linux_mapinfo_t; +}; +typedef struct core_nt_file_entry_s core_nt_file_entry_t; + + +static const char deleted[] = "(deleted)"; +static const size_t deleted_len = sizeof (deleted); +static const size_t mapinfo_offset = sizeof (core_nt_file_hdr_t); /** - * Map a file note to program headers + * Handle the CORE/NT_FILE note type. + * @param[in] desc The note-specific data + * @param[in] arg The user-supplied callback argument * - * If a NT_FILE note is recognized, parse it and add the resulting backing files - * to the program header list. + * The CORE/NT_FILE note type contains a list of start/end virtual addresses + * within the core file and an associated filename. The purpose is to map + * various segments loaded into memory from ELF files with the ELF file from + * which those segments were loaded. + * + * This function links the file namess mapped in the CORE/NT_FILE note with + * the program headers in the core file through the UCD_info file table. * * Any file names that end in the string "(deleted)" are ignored. */ static int -_handle_file_note(uint32_t n_namesz, uint32_t n_descsz, uint32_t n_type, char *name, uint8_t *desc, void *arg) +_handle_nt_file_note (uint8_t *desc, void *arg) { struct UCD_info *ui = (struct UCD_info *)arg; -#ifdef NT_FILE - if (n_type == NT_FILE) - { - Debug(0, "found a PT_FILE note\n"); - static const char * deleted = "(deleted)"; - size_t deleted_len = strlen(deleted); - static const size_t mapinfo_offset = sizeof(linux_mapinfo_hdr_t); - - linux_mapinfo_hdr_t *mapinfo = (linux_mapinfo_hdr_t *)desc; - linux_mapinfo_t *maps = (linux_mapinfo_t *)(desc + mapinfo_offset); - char *strings = (char *)(desc + mapinfo_offset + sizeof(linux_mapinfo_t)*mapinfo->count); - for (unsigned long i = 0; i < mapinfo->count; ++i) + core_nt_file_hdr_t *mapinfo = (core_nt_file_hdr_t *)desc; + core_nt_file_entry_t *maps = (core_nt_file_entry_t *) (desc + mapinfo_offset); + char *strings = (char *) (desc + mapinfo_offset + sizeof (core_nt_file_entry_t) * mapinfo->count); + + for (unsigned long i = 0; i < mapinfo->count; ++i) { - size_t len = strlen(strings); + size_t len = strlen (strings); + for (unsigned p = 0; p < ui->phdrs_count; ++p) - { - if (ui->phdrs[p].p_type == PT_LOAD - && maps[i].start >= ui->phdrs[p].p_vaddr - && maps[i].end <= ui->phdrs[p].p_vaddr + ui->phdrs[p].p_filesz) - { - if (len > deleted_len && memcmp(strings + len - deleted_len, deleted, deleted_len)) - { - _UCD_add_backing_file_at_segment(ui, p, strings); - } - break; - } - } + { + if (ui->phdrs[p].p_type == PT_LOAD + && maps[i].start >= ui->phdrs[p].p_vaddr + && maps[i].end <= ui->phdrs[p].p_vaddr + ui->phdrs[p].p_memsz) + { + if (len > deleted_len && memcmp (strings + len - deleted_len, deleted, deleted_len)) + { + ui->phdrs[p].p_backing_file_index = ucd_file_table_insert (&ui->ucd_file_table, strings); + Debug (3, "adding '%s' at index %d\n", strings, ui->phdrs[p].p_backing_file_index); + } + + break; + } + } + strings += (len + 1); } - } + + return UNW_ESUCCESS; +} + +/** + * Callback to handle notes. + * @param[in] n_namesz size of name data + * @param[in] n_descsz size of desc data + * @param[in] n_type type of note + * @param[in] name zero-terminated string, n_namesz bytes plus alignment padding + * @param[in] desc note-specific data, n_descsz bytes plus alignment padding + * @param[in] arg user-supplied callback argument + * + * Add additional note types here for fun and frolicks. Right now the only note + * type handled is the CORE/NT_FILE note used on GNU/Linux. FreeBSD uses a + * FreeBSD/NT_PROCSTAT_VMMAP note and QNX uses a QNX/QNT_DEBUG_LINK_MAP note for + * similar purposes. Other target OSes probably use something else. + * + * Note interpretation requires both name and type. + */ +static int +_handle_pt_note_segment (uint32_t n_namesz, + uint32_t n_descsz, + uint32_t n_type, + char *name, + uint8_t *desc, + void *arg) +{ +#ifdef NT_FILE + if (n_type == NT_FILE && strcmp (name, "CORE") == 0) + { + return _handle_nt_file_note (desc, arg); + } #endif return UNW_ESUCCESS; } @@ -111,24 +156,25 @@ _handle_file_note(uint32_t n_namesz, uint32_t n_descsz, uint32_t n_type, char *n * fail. */ int -_UCD_get_mapinfo(struct UCD_info *ui, coredump_phdr_t *phdrs, unsigned phdr_size) +_UCD_get_mapinfo (struct UCD_info *ui, coredump_phdr_t *phdrs, unsigned phdr_size) { int ret = UNW_ESUCCESS; /* it's OK if there are no file mappings */ for (unsigned i = 0; i < phdr_size; ++i) - { - if (phdrs[i].p_type == PT_NOTE) { - uint8_t *segment; - size_t segment_size; - ret = _UCD_elf_read_segment(ui, &phdrs[i], &segment, &segment_size); - if (ret == UNW_ESUCCESS) - { - _UCD_elf_visit_notes(segment, segment_size, _handle_file_note, ui); - free(segment); - } + if (phdrs[i].p_type == PT_NOTE) + { + uint8_t *segment; + size_t segment_size; + ret = _UCD_elf_read_segment (ui, &phdrs[i], &segment, &segment_size); + + if (ret == UNW_ESUCCESS) + { + _UCD_elf_visit_notes (segment, segment_size, _handle_pt_note_segment, ui); + free (segment); + } + } } - } return ret; } diff --git a/src/native/external/libunwind/src/coredump/_UCD_get_proc_name.c b/src/native/external/libunwind/src/coredump/_UCD_get_proc_name.c index cd5ee8922324f..cff587b0d1a33 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_get_proc_name.c +++ b/src/native/external/libunwind/src/coredump/_UCD_get_proc_name.c @@ -24,6 +24,57 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "_UCD_lib.h" #include "_UCD_internal.h" +#if defined(HAVE_ELF_H) +# include +#elif defined(HAVE_SYS_ELF_H) +# include +#endif + + +static off_t +_get_text_offset (uint8_t *image) +{ + off_t offset = 0; + typedef union + { + Elf32_Ehdr h32; + Elf64_Ehdr h64; + } elf_header_t; + + elf_header_t *elf_header = (elf_header_t *)image; + bool _64bits = (elf_header->h32.e_ident[EI_CLASS] == ELFCLASS64); + off_t e_phofs = _64bits ? elf_header->h64.e_phoff : elf_header->h32.e_phoff; + unsigned e_phnum = _64bits ? elf_header->h64.e_phnum : elf_header->h32.e_phnum; + + for (unsigned i = 0; i < e_phnum; ++i) + { + if (_64bits) + { + Elf64_Phdr *phdr = (Elf64_Phdr *) (image + e_phofs); + + if (phdr[i].p_type == PT_LOAD && (phdr[i].p_flags & PF_X) == PF_X) + { + offset = phdr[i].p_offset; + break; + } + } + + else + { + Elf32_Phdr *phdr = (Elf32_Phdr *) (image + e_phofs); + + if ((phdr[i].p_flags & PF_X) == PF_X) + { + offset = phdr[i].p_offset; + break; + } + } + } + + Debug (4, "returning offset %ld\n", (long)offset); + return offset; +} + /* Find the ELF image that contains IP and return the "closest" procedure name, if there is one. With some caching, this could be @@ -31,30 +82,28 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ sensitive to the performance of this routine, why bother... */ static int elf_w (CD_get_proc_name) (struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp) + char *buf, size_t buf_len, unw_word_t *offp) { unsigned long segbase, mapoff; int ret; - - /* We're about to map an elf image. If there is an elf image currently mapped, - then make sure to unmap it. */ - invalidate_edi(&ui->edi); - + /* We're about to map an elf image. + The call will unmap memory it doesn't own, so just null it out and avoid + that. */ + ui->edi.ei.image = NULL; + invalidate_edi (&ui->edi); /* Used to be tdep_get_elf_image() in ptrace unwinding code */ - coredump_phdr_t *cphdr = _UCD_get_elf_image(ui, ip); + coredump_phdr_t *cphdr = _UCD_get_elf_image (ui, ip); + if (!cphdr) { - Debug(1, "returns error: _UCD_get_elf_image failed\n"); + Debug (1, "returns error: _UCD_get_elf_image failed\n"); return -UNW_ENOINFO; } - /* segbase: where it is mapped in virtual memory */ - /* mapoff: offset in the file */ - segbase = cphdr->p_vaddr; - /*mapoff = phdr->p_offset; WRONG! phdr->p_offset is the offset in COREDUMP file */ - mapoff = 0; - - ret = elf_w (get_proc_name_in_image) (as, &ui->edi.ei, segbase, mapoff, ip, buf, buf_len, offp); + segbase = 0; /* everything is relative to the beginning of the ELF file */ + /* Adjust IP to be relative to start of the .text section of the ELF file */ + ip = ip - cphdr->p_vaddr + _get_text_offset (ui->edi.ei.image); + ret = elf_w (get_proc_name_in_image) (as, &ui->edi.ei, segbase, ip, buf, buf_len, offp); return ret; } @@ -63,7 +112,6 @@ _UCD_get_proc_name (unw_addr_space_t as, unw_word_t ip, char *buf, size_t buf_len, unw_word_t *offp, void *arg) { struct UCD_info *ui = arg; - #if UNW_ELF_CLASS == UNW_ELFCLASS64 return _Uelf64_CD_get_proc_name (ui, as, ip, buf, buf_len, offp); #elif UNW_ELF_CLASS == UNW_ELFCLASS32 diff --git a/src/native/external/libunwind/src/coredump/_UCD_get_threadinfo_prstatus.c b/src/native/external/libunwind/src/coredump/_UCD_get_threadinfo_prstatus.c index 455525661c5bc..4644d1b1b6f8d 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_get_threadinfo_prstatus.c +++ b/src/native/external/libunwind/src/coredump/_UCD_get_threadinfo_prstatus.c @@ -62,9 +62,15 @@ _save_thread_notes(uint32_t n_namesz, uint32_t n_descsz, uint32_t n_type, char * struct UCD_info *ui = (struct UCD_info *)arg; if (n_type == NT_PRSTATUS) { - memcpy(&ui->threads[ui->n_threads], desc, sizeof(struct PRSTATUS_STRUCT)); + memcpy(&ui->threads[ui->n_threads].prstatus, desc, sizeof(UCD_proc_status_t)); ++ui->n_threads; } + if (n_type == NT_FPREGSET) + { +#ifdef HAVE_ELF_FPREGSET_T + memcpy(&ui->threads[ui->n_threads-1].fpregset, desc, sizeof(elf_fpregset_t)); +#endif + } return UNW_ESUCCESS; } @@ -89,33 +95,33 @@ _UCD_get_threadinfo(struct UCD_info *ui, coredump_phdr_t *phdrs, unsigned phdr_s int ret = -UNW_ENOINFO; for (unsigned i = 0; i < phdr_size; ++i) - { - Debug(8, "phdr[%03d]: type:%d", i, phdrs[i].p_type); - if (phdrs[i].p_type == PT_NOTE) { - size_t thread_count = 0; - uint8_t *segment; - size_t segment_size; - ret = _UCD_elf_read_segment(ui, &phdrs[i], &segment, &segment_size); - if (ret == UNW_ESUCCESS) - { - _UCD_elf_visit_notes(segment, segment_size, _count_thread_notes, &thread_count); - Debug(2, "found %zu threads\n", thread_count); + Debug(8, "phdr[%03d]: type:%d", i, phdrs[i].p_type); + if (phdrs[i].p_type == PT_NOTE) + { + size_t thread_count = 0; + uint8_t *segment; + size_t segment_size; + ret = _UCD_elf_read_segment(ui, &phdrs[i], &segment, &segment_size); + if (ret == UNW_ESUCCESS) + { + _UCD_elf_visit_notes(segment, segment_size, _count_thread_notes, &thread_count); + Debug(2, "found %zu threads\n", thread_count); - size_t new_size = sizeof(struct PRSTATUS_STRUCT) * (ui->n_threads + thread_count); - ui->threads = realloc(ui->threads, new_size); - if (ui->threads == NULL) - { - Debug(0, "error allocating %zu bytes of memory \n", new_size); - free(segment); - return -UNW_EUNSPEC; - } - _UCD_elf_visit_notes(segment, segment_size, _save_thread_notes, ui); + size_t new_size = sizeof(struct UCD_thread_info) * (ui->n_threads + thread_count); + ui->threads = realloc(ui->threads, new_size); + if (ui->threads == NULL) + { + Debug(0, "error allocating %zu bytes of memory \n", new_size); + free(segment); + return -UNW_EUNSPEC; + } + _UCD_elf_visit_notes(segment, segment_size, _save_thread_notes, ui); - free(segment); - } + free(segment); + } + } } - } return ret; } diff --git a/src/native/external/libunwind/src/coredump/_UCD_internal.h b/src/native/external/libunwind/src/coredump/_UCD_internal.h index f51502052949b..3a9434ab0244b 100644 --- a/src/native/external/libunwind/src/coredump/_UCD_internal.h +++ b/src/native/external/libunwind/src/coredump/_UCD_internal.h @@ -34,6 +34,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_SYS_PROCFS_H #include /* struct elf_prstatus */ #endif +#ifdef HAVE_ASM_PTRACE_H +#include /* struct user_regs_struct on s390x */ +#endif #include #include #include @@ -43,6 +46,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "libunwind_i.h" +#include "ucd_file_table.h" #if SIZEOF_OFF_T == 4 @@ -59,41 +63,52 @@ typedef uint64_t uoff_t; */ struct coredump_phdr { - uint32_t p_type; - uint32_t p_flags; - uoff_t p_offset; - uoff_t p_vaddr; - uoff_t p_filesz; - uoff_t p_memsz; - uoff_t p_align; - /* Data for backing file. If backing_fd < 0, there is no file */ - uoff_t backing_filesize; - char *backing_filename; /* for error meesages only */ - int backing_fd; + uint32_t p_type; + uint32_t p_flags; + uoff_t p_offset; + uoff_t p_vaddr; + uoff_t p_filesz; + uoff_t p_memsz; + uoff_t p_align; + ucd_file_index_t p_backing_file_index; }; typedef struct coredump_phdr coredump_phdr_t; #if defined(HAVE_STRUCT_ELF_PRSTATUS) -#define PRSTATUS_STRUCT elf_prstatus +typedef struct elf_prstatus UCD_proc_status_t; #elif defined(HAVE_STRUCT_PRSTATUS) -#define PRSTATUS_STRUCT prstatus +typedef struct prstatus UCD_proc_status_t; +#elif defined(HAVE_PROCFS_STATUS) +typedef procfs_status UCD_proc_status_t; #else -#define PRSTATUS_STRUCT non_existent +# error UCD_proc_status_t undefined +#endif + +struct UCD_thread_info + { + UCD_proc_status_t prstatus; +#ifdef HAVE_ELF_FPREGSET_T + elf_fpregset_t fpregset; #endif + }; struct UCD_info { - int big_endian; /* bool */ - int coredump_fd; - char *coredump_filename; /* for error meesages only */ - coredump_phdr_t *phdrs; /* array, allocated */ - unsigned phdrs_count; - void *note_phdr; /* allocated or NULL */ - struct PRSTATUS_STRUCT *prstatus; /* points inside note_phdr */ - int n_threads; - struct PRSTATUS_STRUCT *threads; - struct elf_dyn_info edi; + int big_endian; /* bool */ + int coredump_fd; + char *coredump_filename; /* for error meesages only */ + coredump_phdr_t *phdrs; /* array, allocated */ + unsigned phdrs_count; + ucd_file_table_t ucd_file_table; + void *note_phdr; /* allocated or NULL */ + UCD_proc_status_t *prstatus; /* points inside note_phdr */ +#ifdef HAVE_ELF_FPREGSET_T + elf_fpregset_t *fpregset; +#endif + int n_threads; + struct UCD_thread_info *threads; + struct elf_dyn_info edi; }; diff --git a/src/native/external/libunwind/src/coredump/_UPT_access_fpreg.c b/src/native/external/libunwind/src/coredump/_UPT_access_fpreg.c index 0b8b86ac9072a..a6d0bcea43769 100644 --- a/src/native/external/libunwind/src/coredump/_UPT_access_fpreg.c +++ b/src/native/external/libunwind/src/coredump/_UPT_access_fpreg.c @@ -28,7 +28,26 @@ int _UCD_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, int write, void *arg) { + struct UCD_info *ui UNUSED = arg; + + if (write) + { + Debug(0, "write is not supported\n"); + return -UNW_EINVAL; + } + +#ifdef __s390x__ + if (reg < UNW_S390X_F0 || reg > UNW_S390X_F15) + { + Debug(0, "bad regnum:%d\n", reg); + return -UNW_EINVAL; + } + + *val = ui->fpregset->fprs[reg - UNW_S390X_F0].d; + return 0; +#else print_error (__func__); - print_error (" not implemented\n"); + print_error (" not implemented for this architecture\n"); return -UNW_EINVAL; +#endif } diff --git a/src/native/external/libunwind/src/coredump/ucd_file_table.c b/src/native/external/libunwind/src/coredump/ucd_file_table.c new file mode 100644 index 0000000000000..cde693db58aa7 --- /dev/null +++ b/src/native/external/libunwind/src/coredump/ucd_file_table.c @@ -0,0 +1,275 @@ +/* + * Copyright 2022 Blackberry Limited. + * Contributed by Stephen M. Webb + * + * This file is part of libunwind, a platform-independent unwind library. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ucd_file_table.h" + +#include +#include +#include +#include +#include +#include + + +/** + * Initialize a UCD file object. + * @param[in] ucd_file The `ucd_file_t` object to initialize. + * @param[in] filename Name of a file. + * + * Stores the filename in the object and sets the fd to an uninitialized state. + * + * @returns UNW_ESUCCESS on success, a negated `unw_error_t` code otherwise. + */ +unw_error_t +ucd_file_init (ucd_file_t *ucd_file, char const *filename) +{ + size_t name_size = strlen (filename) + 1; + ucd_file->filename = malloc (name_size); + if (ucd_file->filename == NULL) + { + Debug (0, "error %d from malloc(): %s\n", errno, strerror (errno)); + return (unw_error_t) - UNW_ENOMEM; + } + memcpy ((char *)ucd_file->filename, filename, name_size); + ucd_file->fd = -1; + ucd_file->size = 0; + ucd_file->image = NULL; + + return UNW_ESUCCESS; +} + + +/** + * Dispose of a UCD file object. + * @param[in] ucd_file The UCD file to dispose. + * + * Releases any resources sued and sets the object to an uninitialized state. + * + * @returns UNW_ESUCCESS always. + */ +unw_error_t +ucd_file_dispose (ucd_file_t *ucd_file) +{ + ucd_file_unmap(ucd_file); + if (ucd_file->filename != NULL) + { + free ((char *)ucd_file->filename); + ucd_file->filename = NULL; + } + + return UNW_ESUCCESS; +} + + +/** + * Opens a UCD file and gets its size + */ +static void +_ucd_file_open (ucd_file_t *ucd_file) +{ + ucd_file->fd = open(ucd_file->filename, O_RDONLY); + if (ucd_file->fd == -1) + { + Debug(0, "error %d in open(%s): %s\n", errno, ucd_file->filename, strerror(errno)); + } + + struct stat sbuf; + int sstat = fstat(ucd_file->fd, &sbuf); + if (sstat != 0) + { + Debug(0, "error %d in fstat(%s): %s\n", errno, ucd_file->filename, strerror(errno)); + close(ucd_file->fd); + ucd_file->fd = -1; + } + ucd_file->size = sbuf.st_size; +} + + +/** + * Memory-maps a UCD file + */ +uint8_t * +ucd_file_map (ucd_file_t *ucd_file) +{ + if (ucd_file->image != NULL) + { + Debug(0, "warning, file \"%s\" already loaded\n", ucd_file->filename); + return ucd_file->image; + } + + if (ucd_file->fd == -1) + { + _ucd_file_open (ucd_file); + } + + ucd_file->image = mmap(NULL, ucd_file->size, PROT_READ, MAP_PRIVATE, ucd_file->fd, 0); + if (ucd_file->image == MAP_FAILED) + { + Debug(0, "error %d in mmap(%s): %s\n", errno, ucd_file->filename, strerror(errno)); + ucd_file->image = NULL; + return NULL; + } + return ucd_file->image; +} + + +void +ucd_file_unmap (ucd_file_t *ucd_file) +{ + if (ucd_file->image != NULL) + { + munmap(ucd_file->image, ucd_file->size); + ucd_file->image = NULL; + ucd_file->size = 0; + } + if (ucd_file->fd != -1) + { + close(ucd_file->fd); + ucd_file->fd = -1; + } +} + + +/** + * Initialize a UCD file table. + * @param[in] ucd_file_table The UCD file table to initialize. + * + * @returns UNW_ESUCCESS on success, a negated `unw_error_t` code otherwise. + */ +unw_error_t +ucd_file_table_init (ucd_file_table_t *ucd_file_table) +{ + ucd_file_table->uft_count = 0; + ucd_file_table->uft_size = 2; + ucd_file_table->uft_files = calloc (ucd_file_table->uft_size, + sizeof (ucd_file_t)); + + if (ucd_file_table->uft_files == NULL) + { + Debug (0, "error %d from malloc(): %s\n", errno, strerror (errno)); + return (unw_error_t) - UNW_ENOMEM; + } + + return UNW_ESUCCESS; +} + + +/** + * Dispose of a UCD file table object. + * @param[in] ucd_file_table The UCD file table to dispose. + * + * Releases any resources used and sets the object to an uninitialized state. + * + * @returns UNW_ESUCCESS always. + */ +unw_error_t +ucd_file_table_dispose (ucd_file_table_t *ucd_file_table) +{ + if (ucd_file_table->uft_files != NULL) + { + for (size_t i = 0; i < ucd_file_table->uft_count; ++i) + { + ucd_file_dispose(&ucd_file_table->uft_files[i]); + } + free (ucd_file_table->uft_files); + ucd_file_table->uft_files = NULL; + } + + ucd_file_table->uft_count = 0; + ucd_file_table->uft_size = 0; + + return UNW_ESUCCESS; +} + + +/** + * Insert a new entry in a UCD file table. + * @param[in] ucd_file_table A UCD file table + * @param[in] filename The filename to add. + * + * This table doe not allow duplicates: if a filename is already in the table, + * the index of that entry is returned, otherwise a new entry is created and + * the index of the new entry is returned. + * + * @returns the index of the newly-added UCD file, a negative `unw_error_t` + * code indicating failure otherwise. + */ +ucd_file_index_t ucd_file_table_insert (ucd_file_table_t *ucd_file_table, + char const *filename) +{ + for (int i = 0; i < (int)ucd_file_table->uft_count; ++i) + { + if (strcmp (ucd_file_table->uft_files[i].filename, filename) == 0) + { + return i; + } + } + + ucd_file_index_t index = ucd_file_table->uft_count; + ++ucd_file_table->uft_count; + + if (ucd_file_table->uft_count >= ucd_file_table->uft_size) + { + size_t new_size = ucd_file_table->uft_size * 2; + ucd_file_table->uft_files = realloc (ucd_file_table->uft_files, + new_size * sizeof (ucd_file_t)); + if (ucd_file_table->uft_files == NULL) + { + Debug (0, "error %d from malloc(): %s\n", errno, strerror (errno)); + return (unw_error_t) - UNW_ENOMEM; + } + + ucd_file_table->uft_size = new_size; + } + + unw_error_t err = ucd_file_init (&ucd_file_table->uft_files[index], filename); + if (err != UNW_ESUCCESS) + { + return err; + } + return index; +} + + +/** + * Get an indicated entry from a UCD file table. + * @param[in] ucd_file_table A UCD file table + * @param[in] index Indicate which entry to retrieve. + * + * @returns a pointer to the indicated UCD file, NULL if the index is out of + * range. + */ +ucd_file_t * +ucd_file_table_at (ucd_file_table_t *ucd_file_table, + ucd_file_index_t index) +{ + if (0 <= index && index < (int)ucd_file_table->uft_count) + { + return &ucd_file_table->uft_files[index]; + } + + return NULL; +} + diff --git a/src/native/external/libunwind/src/coredump/ucd_file_table.h b/src/native/external/libunwind/src/coredump/ucd_file_table.h new file mode 100644 index 0000000000000..a22b15e15d79d --- /dev/null +++ b/src/native/external/libunwind/src/coredump/ucd_file_table.h @@ -0,0 +1,83 @@ +/* + * Copyright 2022 Blackberry Limited. + * Contributed by Stephen M. Webb + * + * This file is part of libunwind, a platform-independent unwind library. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef include_ucd_file_table_h_ +#define include_ucd_file_table_h_ + +#include "libunwind_i.h" + +#include +#include +/** + * Describes a backing file. + * + * A *backing file* is usually the ELF image file that was the source of a + * particular PT_LOAD segment in memory: it could be the program executable or + * it could be a shared library, either resolved through the dynamic loader at + * program start or later through dl_open(). + * + * There may be one or more in-memory segments associated with the same backing + * file. + */ +struct ucd_file_s + { + char const *filename; /**< Name of the file */ + int fd; /**< File descriptor of the file if open, -1 otherwise */ + off_t size; /**< File size in bytyes */ + uint8_t *image; /**< Memory-mapped file image */ + }; + +typedef struct ucd_file_s ucd_file_t; + +HIDDEN unw_error_t ucd_file_init(ucd_file_t *ucd_file, char const *filename); +HIDDEN unw_error_t ucd_file_dispose(ucd_file_t *ucd_file); +HIDDEN uint8_t *ucd_file_map(ucd_file_t *ucd_file); +HIDDEN void ucd_file_unmap(ucd_file_t *ucd_file); + + +/** + * A table of backing files. + * + * Each entry in this table should be unique. + * + * This table is dynamically sized and should grow as required. + */ +struct ucd_file_table_s + { + size_t uft_count; /**< number of valid entries in table */ + size_t uft_size; /**< size (in entries) of the table storage */ + ucd_file_t *uft_files; /**< the table data */ + }; + +typedef struct ucd_file_table_s ucd_file_table_t; +typedef int ucd_file_index_t; +static const ucd_file_index_t ucd_file_no_index = -1; + +HIDDEN unw_error_t ucd_file_table_init(ucd_file_table_t *ucd_file_table); +HIDDEN unw_error_t ucd_file_table_dispose(ucd_file_table_t *ucd_file_table); +HIDDEN ucd_file_index_t ucd_file_table_insert(ucd_file_table_t *ucd_file_table, char const *filename); +HIDDEN ucd_file_t *ucd_file_table_at(ucd_file_table_t *ucd_file_table, ucd_file_index_t index); + +#endif /* include_ucd_file_table_h_ */ diff --git a/src/native/external/libunwind/src/dwarf/Gexpr.c b/src/native/external/libunwind/src/dwarf/Gexpr.c index 977c5593747b0..882f4dac9642b 100644 --- a/src/native/external/libunwind/src/dwarf/Gexpr.c +++ b/src/native/external/libunwind/src/dwarf/Gexpr.c @@ -265,7 +265,7 @@ if (stackerror) \ return -UNW_EINVAL; \ } -// Removed the parentheses on the asignment +// Removed the parentheses on the assignment // to allow the extra stack error check // when x is evaluated # define push(x) \ @@ -578,7 +578,8 @@ if (stackerror) \ case DW_OP_neg: Debug (15, "OP_neg\n"); - push (~pop () + 1); + tmp1 = pop (); + push (~tmp1 + 1); break; case DW_OP_not: diff --git a/src/native/external/libunwind/src/dwarf/Gfde.c b/src/native/external/libunwind/src/dwarf/Gfde.c index 9250b895eabeb..3847d0a03c079 100644 --- a/src/native/external/libunwind/src/dwarf/Gfde.c +++ b/src/native/external/libunwind/src/dwarf/Gfde.c @@ -48,6 +48,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr, int is_debug_frame, void *arg) { uint8_t version, ch, augstr[5], fde_encoding, handler_encoding; + uint8_t address_size, segment_size; unw_word_t len, cie_end_addr, aug_size; uint32_t u32val; uint64_t u64val; @@ -138,6 +139,15 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr, augstr[i++] = ch; } + if (version > 3) + { + if((ret = dwarf_readu8(as, a, &addr, &address_size, arg)) < 0) + return ret; + + if((ret = dwarf_readu8(as, a, &addr, &segment_size, arg)) < 0) + return ret; + } + if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->code_align, arg)) < 0 || (ret = dwarf_read_sleb128 (as, a, &addr, &dci->data_align, arg)) < 0) return ret; @@ -213,8 +223,8 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr, return 0; } -/* Extract proc-info from the FDE starting at adress ADDR. - +/* Extract proc-info from the FDE starting at address ADDR. + Pass BASE as zero for eh_frame behaviour, or a pointer to debug_frame base for debug_frame behaviour. */ diff --git a/src/native/external/libunwind/src/dwarf/Gfind_proc_info-lsb.c b/src/native/external/libunwind/src/dwarf/Gfind_proc_info-lsb.c index d907aad5e8788..8ead48f096fdd 100644 --- a/src/native/external/libunwind/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/native/external/libunwind/src/dwarf/Gfind_proc_info-lsb.c @@ -658,7 +658,7 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr) { if (p_dynamic) { - /* For dynamicly linked executables and shared libraries, + /* For dynamically linked executables and shared libraries, DT_PLTGOT is the value that data-relative addresses are relative to for that object. We call this the "gp". */ Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base); @@ -966,7 +966,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, if (as == unw_local_addr_space) { e = lookup (table, table_len, ip - ip_base - di->load_offset); - if (e && &e[1] < &table[table_len]) + if (e && &e[1] < &table[table_len / sizeof (unw_word_t)]) last_ip = e[1].start_ip_offset + ip_base + di->load_offset; else last_ip = di->end_ip; diff --git a/src/native/external/libunwind/src/dwarf/Gfind_unwind_table.c b/src/native/external/libunwind/src/dwarf/Gfind_unwind_table.c index a6198ad2f3189..fb20fea0da449 100644 --- a/src/native/external/libunwind/src/dwarf/Gfind_unwind_table.c +++ b/src/native/external/libunwind/src/dwarf/Gfind_unwind_table.c @@ -37,7 +37,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, - char *path, unw_word_t segbase, unw_word_t mapoff, + const char *path, unw_word_t segbase, unw_word_t mapoff, unw_word_t ip) { Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL; @@ -50,7 +50,7 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, unw_accessors_t *a; Elf_W(Ehdr) *ehdr; #if UNW_TARGET_ARM - const Elf_W(Phdr) *parm_exidx = NULL; + const Elf_W(Phdr) *param_exidx = NULL; #endif int i, ret, found = 0; @@ -73,7 +73,7 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, if (phdr[i].p_vaddr + phdr[i].p_memsz > end_ip) end_ip = phdr[i].p_vaddr + phdr[i].p_memsz; - if (phdr[i].p_offset == mapoff) + if ((phdr[i].p_flags & PF_X) == PF_X) ptxt = phdr + i; if ((uintptr_t) edi->ei.image + phdr->p_filesz > max_load_addr) max_load_addr = (uintptr_t) edi->ei.image + phdr->p_filesz; @@ -92,7 +92,7 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, #if UNW_TARGET_ARM case PT_ARM_EXIDX: - parm_exidx = phdr + i; + param_exidx = phdr + i; break; #endif @@ -112,7 +112,7 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, { if (pdyn) { - /* For dynamicly linked executables and shared libraries, + /* For dynamically linked executables and shared libraries, DT_PLTGOT is the value that data-relative addresses are relative to for that object. We call this the "gp". */ Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(pdyn->p_offset @@ -212,14 +212,14 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, } #if UNW_TARGET_ARM - if (parm_exidx) + if (param_exidx) { edi->di_arm.format = UNW_INFO_FORMAT_ARM_EXIDX; edi->di_arm.start_ip = start_ip; edi->di_arm.end_ip = end_ip; edi->di_arm.u.rti.name_ptr = to_unw_word (path); - edi->di_arm.u.rti.table_data = load_base + parm_exidx->p_vaddr; - edi->di_arm.u.rti.table_len = parm_exidx->p_memsz; + edi->di_arm.u.rti.table_data = load_base + param_exidx->p_vaddr; + edi->di_arm.u.rti.table_len = param_exidx->p_memsz; found = 1; } #endif diff --git a/src/native/external/libunwind/src/mi/Gget_proc_info_in_range.c b/src/native/external/libunwind/src/dwarf/Gget_proc_info_in_range.c similarity index 100% rename from src/native/external/libunwind/src/mi/Gget_proc_info_in_range.c rename to src/native/external/libunwind/src/dwarf/Gget_proc_info_in_range.c diff --git a/src/native/external/libunwind/src/dwarf/Gparser.c b/src/native/external/libunwind/src/dwarf/Gparser.c index 68edbf9aa545b..b7f83ca2dad59 100644 --- a/src/native/external/libunwind/src/dwarf/Gparser.c +++ b/src/native/external/libunwind/src/dwarf/Gparser.c @@ -87,6 +87,13 @@ empty_rstate_stack(dwarf_stackable_reg_state_t **rs_stack) pop_rstate_stack(rs_stack); } +#ifdef UNW_TARGET_AARCH64 + +static void +aarch64_negate_ra_sign_state(dwarf_state_record_t *sr); + +#endif + /* Run a CFI program to update the register state. */ static int run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, @@ -404,6 +411,11 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, (regnum - 16) * sizeof (unw_word_t)); Debug (15, "CFA_GNU_window_save\n"); break; +#elif UNW_TARGET_AARCH64 + /* This is a specific opcode on aarch64, DW_CFA_AARCH64_negate_ra_state */ + Debug (15, "DW_CFA_AARCH64_negate_ra_state\n"); + aarch64_negate_ra_sign_state(sr); + break; #else /* FALL THROUGH */ #endif @@ -508,6 +520,9 @@ setup_fde (struct dwarf_cursor *c, dwarf_state_record_t *sr) for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i) set_reg (sr, i, DWARF_WHERE_SAME, 0); + // SP defaults to CFA (but is overridable) + set_reg (sr, TDEP_DWARF_SP, DWARF_WHERE_CFA, 0); + struct dwarf_cie_info *dci = c->pi.unwind_info; sr->rs_current.ret_addr_column = dci->ret_addr_column; unw_word_t addr = dci->cie_instr_start; @@ -764,6 +779,61 @@ eval_location_expr (struct dwarf_cursor *c, unw_word_t stack_val, unw_addr_space return 0; } + +#ifdef UNW_TARGET_AARCH64 +#include "libunwind-aarch64.h" + +static void +aarch64_negate_ra_sign_state(dwarf_state_record_t *sr) +{ + unw_word_t ra_sign_state = sr->rs_current.reg.val[UNW_AARCH64_RA_SIGN_STATE]; + ra_sign_state ^= 0x1; + set_reg(sr, UNW_AARCH64_RA_SIGN_STATE, DWARF_WHERE_SAME, ra_sign_state); +} + +static unw_word_t +aarch64_strip_pac_remote(unw_accessors_t *a, unw_addr_space_t as, void *arg, unw_word_t old_ip) +{ + if (a->ptrauth_insn_mask) + { + unw_word_t ip, insn_mask; + + insn_mask = a->ptrauth_insn_mask(as, arg); + ip = old_ip & (~insn_mask); + + Debug(15, "stripping pac from address, before: %lx, after: %lx\n", old_ip, ip); + return ip; + } + else + { + Debug(15, "return address %lx might be signed, but no means to obtain mask\n", old_ip); + return old_ip; + } +} + +static unw_word_t +aarch64_strip_pac_local(unw_word_t in_addr) +{ + unw_word_t out_addr = in_addr; + +#if defined(__aarch64__) && !defined(UNW_REMOTE_ONLY) + // Strip the PAC with XPACLRI instruction + register unsigned long long x30 __asm__("x30") = in_addr; + __asm__("hint 0x7" : "+r" (x30)); + out_addr = x30; +#endif + + return out_addr; +} + +static unw_word_t +aarch64_get_ra_sign_state(struct dwarf_reg_state *rs) +{ + return rs->reg.val[UNW_AARCH64_RA_SIGN_STATE]; +} + +#endif + static int apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) { @@ -775,6 +845,15 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) int i, ret; void *arg; + /* In the case that we have incorrect CFI, the return address column may be + * outside the valid range of data and will read invalid data. Protect + * against the errant read and indicate that we have a bad frame. */ + if (rs->ret_addr_column >= DWARF_NUM_PRESERVED_REGS) { + Dprintf ("%s: return address entry %zu is outside of range of CIE", + __FUNCTION__, rs->ret_addr_column); + return -UNW_EBADFRAME; + } + prev_ip = c->ip; prev_cfa = c->cfa; @@ -792,14 +871,14 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) /* As a special-case, if the stack-pointer is the CFA and the stack-pointer wasn't saved, popping the CFA implicitly pops the stack-pointer as well. */ - if ((rs->reg.val[DWARF_CFA_REG_COLUMN] == UNW_TDEP_SP) - && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg.val)) - && (rs->reg.where[UNW_TDEP_SP] == DWARF_WHERE_SAME)) + if ((rs->reg.val[DWARF_CFA_REG_COLUMN] == TDEP_DWARF_SP) + && (TDEP_DWARF_SP < ARRAY_SIZE(rs->reg.val)) + && (DWARF_IS_NULL_LOC(c->loc[TDEP_DWARF_SP]))) cfa = c->cfa; else { regnum = dwarf_to_unw_regnum (rs->reg.val[DWARF_CFA_REG_COLUMN]); - if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0) + if ((ret = unw_get_reg (dwarf_to_cursor(c), regnum, &cfa)) < 0) return ret; } cfa += rs->reg.val[DWARF_CFA_OFF_COLUMN]; @@ -836,6 +915,10 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) case DWARF_WHERE_SAME: break; + case DWARF_WHERE_CFA: + new_loc[i] = DWARF_VAL_LOC (c, cfa); + break; + case DWARF_WHERE_CFAREL: new_loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg.val[i]); break; @@ -885,6 +968,19 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) ret = dwarf_get (c, c->loc[rs->ret_addr_column], &ip); if (ret < 0) return ret; +#ifdef UNW_TARGET_AARCH64 + if (aarch64_get_ra_sign_state(rs)) + { + if (c->as != unw_local_addr_space) + { + ip = aarch64_strip_pac_remote(a, as, arg, ip); + } + else + { + ip = aarch64_strip_pac_local(ip); + } + } +#endif c->ip = ip; ret = 1; } @@ -953,13 +1049,11 @@ find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr) cache->links[c->prev_rs].hint = index + 1; c->prev_rs = index; } + if (ret >= 0) + tdep_reuse_frame (c, cache->links[index].signal_frame); put_rs_cache (c->as, cache, &saved_mask); } - if (ret < 0) - return ret; - if (cache) - tdep_reuse_frame (c, cache->links[index].signal_frame); - return 0; + return ret; } /* The function finds the saved locations and applies the register diff --git a/src/native/external/libunwind/src/mi/Lget_proc_info_in_range.c b/src/native/external/libunwind/src/dwarf/Lget_proc_info_in_range.c similarity index 100% rename from src/native/external/libunwind/src/mi/Lget_proc_info_in_range.c rename to src/native/external/libunwind/src/dwarf/Lget_proc_info_in_range.c diff --git a/src/native/external/libunwind/src/elfxx.c b/src/native/external/libunwind/src/elfxx.c index 321cfb979b761..92bcde32cdb31 100644 --- a/src/native/external/libunwind/src/elfxx.c +++ b/src/native/external/libunwind/src/elfxx.c @@ -158,14 +158,13 @@ elf_w (lookup_symbol) (unw_addr_space_t as, } static Elf_W (Addr) -elf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase, - unsigned long mapoff) +elf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase) { Elf_W (Addr) offset = 0; Elf_W (Ehdr) *ehdr; Elf_W (Phdr) *phdr; int i; - // mapoff is obtained from mmap informations, so is always aligned on a page size. + // mapoff is obtained from mmap information, so it is always aligned on a page size. // PT_LOAD program headers p_offset however is not guaranteed to be aligned on a // page size, ld.lld generate libraries where this is not the case. So we must // make sure we compare both values with the same alignment. @@ -175,7 +174,7 @@ elf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase, phdr = (Elf_W (Phdr) *) ((char *) ei->image + ehdr->e_phoff); for (i = 0; i < ehdr->e_phnum; ++i) - if (phdr[i].p_type == PT_LOAD && (phdr[i].p_offset & pagesize_alignment_mask) == mapoff) + if (phdr[i].p_type == PT_LOAD && phdr[i].p_flags & PF_X) { offset = segbase - phdr[i].p_vaddr + (phdr[i].p_offset & (~pagesize_alignment_mask)); break; @@ -276,7 +275,6 @@ elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi) HIDDEN int elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei, unsigned long segbase, - unsigned long mapoff, unw_word_t ip, char *buf, size_t buf_len, unw_word_t *offp) { @@ -284,7 +282,7 @@ elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei, Elf_W (Addr) min_dist = ~(Elf_W (Addr))0; int ret; - load_offset = elf_w (get_load_offset) (ei, segbase, mapoff); + load_offset = elf_w (get_load_offset) (ei, segbase); ret = elf_w (lookup_symbol) (as, ip, ei, load_offset, buf, buf_len, &min_dist); /* If the ELF image has MiniDebugInfo embedded in it, look up the symbol in @@ -328,7 +326,7 @@ elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip, if (ret < 0) return ret; - ret = elf_w (get_proc_name_in_image) (as, &ei, segbase, mapoff, ip, buf, buf_len, offp); + ret = elf_w (get_proc_name_in_image) (as, &ei, segbase, ip, buf, buf_len, offp); munmap (ei.image, ei.size); ei.image = NULL; diff --git a/src/native/external/libunwind/src/elfxx.h b/src/native/external/libunwind/src/elfxx.h index fe5fcbcdfd4df..cd36eb42451b2 100644 --- a/src/native/external/libunwind/src/elfxx.h +++ b/src/native/external/libunwind/src/elfxx.h @@ -50,7 +50,6 @@ extern int elf_w (get_proc_name) (unw_addr_space_t as, extern int elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei, unsigned long segbase, - unsigned long mapoff, unw_word_t ip, char *buf, size_t buf_len, unw_word_t *offp); diff --git a/src/native/external/libunwind/src/ia64/Gscript.c b/src/native/external/libunwind/src/ia64/Gscript.c index ea5ac15f53ed1..1af6a8554becf 100644 --- a/src/native/external/libunwind/src/ia64/Gscript.c +++ b/src/native/external/libunwind/src/ia64/Gscript.c @@ -287,7 +287,7 @@ compile_reg (struct ia64_state_record *sr, int i, struct ia64_reg_info *r, { case IA64_WHERE_FR: /* Note: There is no need to handle NaT-bit info here - (indepent of is_preserved_gr), because for floating-point + (independent of is_preserved_gr), because for floating-point NaTs are represented as NaTVal, so the NaT-info never needs to be consulated. */ if (rval >= 2 && rval <= 5) diff --git a/src/native/external/libunwind/src/ia64/Gtables.c b/src/native/external/libunwind/src/ia64/Gtables.c index f5e8f2d8f4da8..e6ac519780d58 100644 --- a/src/native/external/libunwind/src/ia64/Gtables.c +++ b/src/native/external/libunwind/src/ia64/Gtables.c @@ -531,7 +531,7 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr) if (p_dynamic) { - /* For dynamicly linked executables and shared libraries, + /* For dynamically linked executables and shared libraries, DT_PLTGOT is the gp value for that object. */ Elf64_Dyn *dyn = (Elf64_Dyn *)(p_dynamic->p_vaddr + load_base); for (; dyn->d_tag != DT_NULL; ++dyn) diff --git a/src/native/external/libunwind/src/loongarch64/Ginit.c b/src/native/external/libunwind/src/loongarch64/Ginit.c index 555e8d806f73b..8994e2eea090d 100644 --- a/src/native/external/libunwind/src/loongarch64/Ginit.c +++ b/src/native/external/libunwind/src/loongarch64/Ginit.c @@ -83,8 +83,6 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, return 0; } -#define PAGE_SIZE 4096 -#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1)) static int mem_validate_pipe[2] = {-1, -1}; @@ -196,11 +194,14 @@ tdep_init_mem_validate (void) #ifdef HAVE_MINCORE unsigned char present = 1; - unw_word_t addr = PAGE_START((unw_word_t)&present); + size_t len = unw_page_size; + unw_word_t addr = uwn_page_start((unw_word_t)&present); unsigned char mvec[1]; int ret; - while ((ret = mincore ((void*)addr, PAGE_SIZE, (unsigned char *)mvec)) == -1 && - errno == EAGAIN) {} + while ((ret = mincore ((void*)addr, len, (unsigned char *)mvec)) == -1 && + errno == EAGAIN) + { + } if (ret == 0) { Debug(1, "using mincore to validate memory\n"); @@ -292,14 +293,8 @@ cache_valid_mem(unw_word_t addr) static int validate_mem (unw_word_t addr) { - size_t len; - - if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) - len = PAGE_SIZE; - else - len = PAGE_SIZE * 2; - - addr = PAGE_START(addr); + size_t len = unw_page_size; + addr = uwn_page_start(addr); if (addr == 0) return -1; diff --git a/src/native/external/libunwind/src/loongarch64/Gresume.c b/src/native/external/libunwind/src/loongarch64/Gresume.c index 9a9c717e6b890..d669daa5bf7fa 100644 --- a/src/native/external/libunwind/src/loongarch64/Gresume.c +++ b/src/native/external/libunwind/src/loongarch64/Gresume.c @@ -41,31 +41,25 @@ loongarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) { /* Since there are no signals involved here we restore EH and non scratch registers only. */ - unsigned long sp = uc->uc_mcontext.__gregs[3]; - unsigned long ra = uc->uc_mcontext.__gregs[1]; - + register void *gregs asm("$t0") = uc->uc_mcontext.__gregs; asm volatile ( - "move $t0, %0\n" - "move $t1, %1\n" - "move $t2, %2\n" - "ld.d $fp, $t0, 22*8\n" - "ld.d $s0, $t0, 23*8\n" - "ld.d $s1, $t0, 24*8\n" - "ld.d $s2, $t0, 25*8\n" - "ld.d $s3, $t0, 26*8\n" - "ld.d $s4, $t0, 27*8\n" - "ld.d $s5, $t0, 28*8\n" - "ld.d $s6, $t0, 29*8\n" - "ld.d $s7, $t0, 30*8\n" - "ld.d $s8, $t0, 31*8\n" - "move $ra, $t2\n" - "move $sp, $t1\n" - "jirl $r0, $ra, 0\n" + "ld.d $ra, %0, 8\n" + "ld.d $sp, %0, 3*8\n" + "ld.d $fp, %0, 22*8\n" + "ld.d $s0, %0, 23*8\n" + "ld.d $s1, %0, 24*8\n" + "ld.d $s2, %0, 25*8\n" + "ld.d $s3, %0, 26*8\n" + "ld.d $s4, %0, 27*8\n" + "ld.d $s5, %0, 28*8\n" + "ld.d $s6, %0, 29*8\n" + "ld.d $s7, %0, 30*8\n" + "ld.d $s8, %0, 31*8\n" + "jr $ra\n" : - : "r" (uc->uc_mcontext.__gregs), - "r" (sp), - "r" (ra) + : "r" (gregs) ); + unreachable(); } else /* c->sigcontext_format == LOONGARCH64_SCF_LINUX_RT_SIGFRAME */ { @@ -81,7 +75,7 @@ loongarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) asm volatile ( "move $sp, %0\n" - "jirl $r0, %1, 0\n" + "jr %1\n" : : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc) ); } diff --git a/src/native/external/libunwind/src/loongarch64/Gstep.c b/src/native/external/libunwind/src/loongarch64/Gstep.c index 5743694b416e1..96789cba81ba9 100644 --- a/src/native/external/libunwind/src/loongarch64/Gstep.c +++ b/src/native/external/libunwind/src/loongarch64/Gstep.c @@ -33,11 +33,10 @@ loongarch64_handle_signal_frame (unw_cursor_t *cursor) struct cursor *c = (struct cursor *) cursor; unw_word_t sc_addr, sp_addr = c->dwarf.cfa; unw_word_t ra, fp; - int ret; + int i, ret; if (unw_is_signal_frame (cursor)) { - sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) + - LINUX_UC_MCONTEXT_OFF; + sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; } else { c->sigcontext_format = LOONGARCH64_SCF_NONE; return -UNW_EUNSPEC; @@ -51,6 +50,9 @@ loongarch64_handle_signal_frame (unw_cursor_t *cursor) c->sigcontext_pc = c->dwarf.ip; c->sigcontext_format = LOONGARCH64_SCF_LINUX_RT_SIGFRAME; + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ diff --git a/src/native/external/libunwind/src/loongarch64/offsets.h b/src/native/external/libunwind/src/loongarch64/offsets.h index 9e46cff61acae..8657a119dd928 100644 --- a/src/native/external/libunwind/src/loongarch64/offsets.h +++ b/src/native/external/libunwind/src/loongarch64/offsets.h @@ -4,19 +4,15 @@ /* Offsets for LoongArch64 Linux "ucontext_t": */ -/* First 24 bytes in sigframe are argument save space and padding for -what used to be signal trampolines. Ref: arch/loongarch/kernel/signal.c */ -#define LINUX_SF_TRAMP_SIZE 0x18 - # define LINUX_UC_FLAGS_OFF 0x0 /* offsetof(struct ucontext_t, __uc_flags) */ # define LINUX_UC_LINK_OFF 0x8 /* offsetof(struct ucontext_t, uc_link) */ # define LINUX_UC_STACK_OFF 0x10 /* offsetof(struct ucontext_t, uc_stack) */ # define LINUX_UC_SIGMASK_OFF 0x28 /* offsetof(struct ucontext_t, uc_sigmask) */ -# define LINUX_UC_MCONTEXT_OFF 0xc0 /* offsetof(struct ucontext_t, uc_mcontext) */ +# define LINUX_UC_MCONTEXT_OFF 0xb0 /* offsetof(struct ucontext_t, uc_mcontext) */ -# define LINUX_UC_MCONTEXT_PC 0xc0 /* offsetof(struct ucontext_t, uc_mcontext.__pc) */ -# define LINUX_UC_MCONTEXT_GREGS 0xc8 /* offsetof(struct ucontext_t, uc_mcontext.__gregs) */ -/* Offsets for AArch64 Linux "struct sigcontext": */ +# define LINUX_UC_MCONTEXT_PC 0xb0 /* offsetof(struct ucontext_t, uc_mcontext.__pc) */ +# define LINUX_UC_MCONTEXT_GREGS 0xb8 /* offsetof(struct ucontext_t, uc_mcontext.__gregs) */ +/* Offsets for LoongArch64 Linux "struct sigcontext": */ #define LINUX_SC_R0_OFF (LINUX_UC_MCONTEXT_GREGS - LINUX_UC_MCONTEXT_OFF) #define LINUX_SC_R1_OFF (LINUX_SC_R0_OFF + 1*8) #define LINUX_SC_R2_OFF (LINUX_SC_R0_OFF + 2*8) diff --git a/src/native/external/libunwind/src/mi/Gget_proc_name.c b/src/native/external/libunwind/src/mi/Gget_proc_name.c index 0b77fa59523cd..15fbbc8fa7d6b 100644 --- a/src/native/external/libunwind/src/mi/Gget_proc_name.c +++ b/src/native/external/libunwind/src/mi/Gget_proc_name.c @@ -45,9 +45,10 @@ intern_string (unw_addr_space_t as, unw_accessors_t *a, return -UNW_ENOMEM; } -static inline int -get_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, void *arg) +int +unw_get_proc_name_by_ip (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) { unw_accessors_t *a = unw_get_accessors_int (as); unw_proc_info_t pi; @@ -116,8 +117,8 @@ unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len, #endif - error = get_proc_name (tdep_get_as (c), ip, buf, buf_len, offp, - tdep_get_as_arg (c)); + error = unw_get_proc_name_by_ip (tdep_get_as (c), ip, buf, buf_len, offp, + tdep_get_as_arg (c)); #if !defined(__ia64__) if (c->dwarf.use_prev_instr && offp != NULL && error == 0) *offp += 1; diff --git a/src/native/external/libunwind/src/mi/backtrace.c b/src/native/external/libunwind/src/mi/backtrace.c index b28151370cdcc..e532b79d8202a 100644 --- a/src/native/external/libunwind/src/mi/backtrace.c +++ b/src/native/external/libunwind/src/mi/backtrace.c @@ -33,15 +33,16 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* See glibc manual for a description of this function. */ static ALWAYS_INLINE int -slow_backtrace (void **buffer, int size, unw_context_t *uc) +slow_backtrace (void **buffer, int size, unw_context_t *uc, int flag) { unw_cursor_t cursor; unw_word_t ip; int n = 0; - if (unlikely (unw_init_local (&cursor, uc) < 0)) + if (unlikely (unw_init_local2 (&cursor, uc, flag) < 0)) return 0; + while (unw_step (&cursor) > 0) { if (n >= size) @@ -69,12 +70,52 @@ unw_backtrace (void **buffer, int size) if (unlikely (tdep_trace (&cursor, buffer, &n) < 0)) { unw_getcontext (&uc); - return slow_backtrace (buffer, size, &uc); + return slow_backtrace (buffer, size, &uc, 0); } return n; } +int +unw_backtrace2 (void **buffer, int size, unw_context_t* uc2, int flag) +{ + if (size == 0) + return 0; + + if (uc2 == NULL) + return unw_backtrace(buffer, size); + + unw_cursor_t cursor; + // need to copy, because the context will be modified by tdep_trace + unw_context_t uc = *(unw_context_t*)uc2; + + if (unlikely (unw_init_local2 (&cursor, &uc, flag) < 0)) + return 0; + + // get the first ip from the context + unw_word_t ip; + + if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0) + return 0; + + buffer[0] = (void *) (uintptr_t)ip; + + // update buffer info to collect the rest of the IPs + buffer = buffer+1; + int remaining_size = size-1; + + int n = remaining_size; + + // returns the number of frames collected by tdep_trace or slow_backtrace + // and add 1 to it (the one we retrieved above) + if (unlikely (tdep_trace (&cursor, buffer, &n) < 0)) + { + return slow_backtrace (buffer, remaining_size, &uc, flag) + 1; + } + + return n + 1; +} + #ifdef CONFIG_WEAK_BACKTRACE extern int backtrace (void **buffer, int size) WEAK ALIAS(unw_backtrace); diff --git a/src/native/external/libunwind/src/mi/init.c b/src/native/external/libunwind/src/mi/init.c index aa9319981d5fa..e4431eeb2012b 100644 --- a/src/native/external/libunwind/src/mi/init.c +++ b/src/native/external/libunwind/src/mi/init.c @@ -41,7 +41,7 @@ long unwi_debug_level; #endif /* UNW_DEBUG */ long unw_page_size; static void -unw_init_page_size () +unw_init_page_size (void) { errno = 0; long result = sysconf (_SC_PAGESIZE); diff --git a/src/native/external/libunwind/src/mips/Gstep.c b/src/native/external/libunwind/src/mips/Gstep.c index 79fea71f4de1f..3706cfc245b68 100644 --- a/src/native/external/libunwind/src/mips/Gstep.c +++ b/src/native/external/libunwind/src/mips/Gstep.c @@ -32,7 +32,7 @@ mips_handle_signal_frame (unw_cursor_t *cursor) struct cursor *c = (struct cursor *) cursor; unw_word_t sc_addr, sp_addr = c->dwarf.cfa; unw_word_t ra, fp; - int ret; + int i, ret; switch (unw_is_signal_frame (cursor)) { case 1: @@ -51,6 +51,9 @@ mips_handle_signal_frame (unw_cursor_t *cursor) c->sigcontext_addr = sc_addr; + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Update the dwarf cursor. */ c->dwarf.loc[UNW_MIPS_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); c->dwarf.loc[UNW_MIPS_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); diff --git a/src/native/external/libunwind/src/os-linux.c b/src/native/external/libunwind/src/os-linux.c index c42d2c5fcfcdd..f61050c82c2a3 100644 --- a/src/native/external/libunwind/src/os-linux.c +++ b/src/native/external/libunwind/src/os-linux.c @@ -26,10 +26,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include +#include +#include +#include #include "libunwind_i.h" #include "os-linux.h" +#define FULL_PATH_BUFF_SZ 1024 + int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, unsigned long *segbase, unsigned long *mapoff, @@ -41,7 +46,7 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, char root[sizeof ("/proc/0123456789/root")], *cp; char *full_path; struct stat st; - + char full_path_buff[FULL_PATH_BUFF_SZ]; if (maps_init (&mi, pid) < 0) return -1; @@ -69,7 +74,16 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, if (!stat(root, &st) && S_ISDIR(st.st_mode)) { - full_path = (char*) malloc (strlen (root) + strlen (mi.path) + 1); + size_t _len = strlen(root) + strlen(mi.path) + 1; + if(_len >= FULL_PATH_BUFF_SZ) + { + full_path = (char*) malloc(_len); + } + else + { + snprintf(full_path_buff, FULL_PATH_BUFF_SZ, "%s%s", root, mi.path); + full_path = &full_path_buff[0]; + } if (!full_path) full_path = mi.path; else @@ -85,7 +99,7 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, } rc = elf_map_image (ei, full_path); - if (full_path && full_path != mi.path) + if (full_path && full_path != mi.path && full_path != &full_path_buff[0]) free (full_path); maps_close (&mi); diff --git a/src/native/external/libunwind/src/ppc32/Ginit.c b/src/native/external/libunwind/src/ppc32/Ginit.c index 7b45455807c89..d978a77526532 100644 --- a/src/native/external/libunwind/src/ppc32/Ginit.c +++ b/src/native/external/libunwind/src/ppc32/Ginit.c @@ -48,12 +48,20 @@ uc_addr (ucontext_t *uc, int reg) void *addr; if ((unsigned) (reg - UNW_PPC32_R0) < 32) +#if defined(__linux__) addr = &uc->uc_mcontext.uc_regs->gregs[reg - UNW_PPC32_R0]; +#elif defined(__FreeBSD__) + addr = &uc->uc_mcontext.mc_gpr[reg - UNW_PPC32_R0]; +#endif else if ( ((unsigned) (reg - UNW_PPC32_F0) < 32) && ((unsigned) (reg - UNW_PPC32_F0) >= 0) ) +#if defined(__linux__) addr = &uc->uc_mcontext.uc_regs->fpregs.fpregs[reg - UNW_PPC32_F0]; + #elif defined(__FreeBSD__) + addr = &uc->uc_mcontext.mc_fpreg[reg - UNW_PPC32_F0]; +#endif else { @@ -76,7 +84,11 @@ uc_addr (ucontext_t *uc, int reg) default: return NULL; } +#if defined(__linux__) addr = &uc->uc_mcontext.uc_regs->gregs[gregs_idx]; +#elif defined(__FreeBSD__) + addr = &uc->uc_mcontext.mc_gpr[gregs_idx]; +#endif } return addr; } diff --git a/src/native/external/libunwind/src/ppc32/init.h b/src/native/external/libunwind/src/ppc32/init.h index 87a69b1450ae1..17650d7adb868 100644 --- a/src/native/external/libunwind/src/ppc32/init.h +++ b/src/native/external/libunwind/src/ppc32/init.h @@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" -/* Here is the "common" init, for remote and local debuging" */ +/* Here is the "common" init, for remote and local debugging" */ static inline int common_init_ppc32 (struct cursor *c, unsigned use_prev_instr) diff --git a/src/native/external/libunwind/src/ppc32/setcontext.S b/src/native/external/libunwind/src/ppc32/setcontext.S deleted file mode 100644 index b54378a9dc249..0000000000000 --- a/src/native/external/libunwind/src/ppc32/setcontext.S +++ /dev/null @@ -1,9 +0,0 @@ - .global _UI_setcontext - -_UI_setcontext: - retq - -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/src/native/external/libunwind/src/ppc32/ucontext_i.h b/src/native/external/libunwind/src/ppc32/ucontext_i.h index c6ba806a00caa..64f8ed878ad8e 100644 --- a/src/native/external/libunwind/src/ppc32/ucontext_i.h +++ b/src/native/external/libunwind/src/ppc32/ucontext_i.h @@ -29,6 +29,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "compiler.h" #include +#if defined(__linux__) + /* These values were derived by reading /usr/src/linux-2.6.18-1.8/arch/um/include/sysdep-ppc/ptrace.h and /usr/src/linux-2.6.18-1.8/arch/powerpc/kernel/ppc32.h @@ -42,87 +44,127 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ //#define MQ_IDX 36 #define LINK_IDX 36 +#define _UC_MCONTEXT_GPR(x) ( (void *)&dmy_ctxt.uc_mcontext.gregs[x] - (void *)&dmy_ctxt) ) +#define _UC_MCONTEXT_FPR(x) ( ((void *)&dmy_ctxt.uc_mcontext.fpregs[x] - (void *)&dmy_ctxt) ) + /* These are dummy structures used only for obtaining the offsets of the various structure members. */ static ucontext_t dmy_ctxt UNUSED; -#define UC_MCONTEXT_GREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[0] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[1] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[2] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[3] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[4] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[5] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[6] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[7] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[8] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[9] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[10] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[11] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[12] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[13] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[14] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[15] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[16] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[17] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[18] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[19] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[20] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[21] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[22] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[23] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[24] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[25] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[26] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[27] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[28] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[29] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[30] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[31] - (void *)&dmy_ctxt) - -#define UC_MCONTEXT_GREGS_MSR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[MSR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_ORIG_GPR3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[ORIG_GPR3_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_CTR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[CTR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_LINK ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[LINK_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_XER ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[XER_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_CCR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[CCR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_SOFTE ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[SOFTE_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_TRAP ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[TRAP_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_DAR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[DAR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_DSISR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[DSISR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_RESULT ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[RESULT_IDX] - (void *)&dmy_ctxt) - -#define UC_MCONTEXT_FREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[0] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[1] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[2] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[3] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[4] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[5] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[6] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[7] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[8] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[9] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[10] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[11] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[12] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[13] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[14] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[15] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[16] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[17] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[18] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[19] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[20] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[21] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[22] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[23] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[24] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[25] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[26] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[27] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[28] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[29] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[30] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[31] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_FPSCR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[32] - (void *)&dmy_ctxt) +#elif defined(__FreeBSD__) + /* See /usr/src/sys/powerpc/include/ucontext.h. + FreeBSD uses a different structure than Linux. +*/ + +#define NIP_IDX 36 +#define MSR_IDX 37 +//#define ORIG_GPR3_IDX +#define CTR_IDX 35 +#define LINK_IDX 32 +#define XER_IDX 34 +#define CCR_IDX 33 +//#define SOFTE_IDX +//#define TRAP_IDX +#define DAR_IDX 39 +#define DSISR_IDX 40 +//#define RESULT_IDX + +#define _UC_MCONTEXT_GPR(_x) ( ((void *)&dmy_ctxt.mc_gpr[_x] - (void *)&dmy_ctxt) ) +#define _UC_MCONTEXT_FPR(_x) ( ((void *)&dmy_ctxt.mc_fpreg[_x] - (void *)&dmy_ctxt) ) + +/* These are dummy structures used only for obtaining the offsets of the + various structure members. */ +static struct __mcontext dmy_ctxt; + +#else +#error "Not implemented!" +#endif + +#define UC_MCONTEXT_GREGS_R0 _UC_MCONTEXT_GPR(0) +#define UC_MCONTEXT_GREGS_R1 _UC_MCONTEXT_GPR(1) +#define UC_MCONTEXT_GREGS_R2 _UC_MCONTEXT_GPR(2) +#define UC_MCONTEXT_GREGS_R3 _UC_MCONTEXT_GPR(3) +#define UC_MCONTEXT_GREGS_R4 _UC_MCONTEXT_GPR(4) +#define UC_MCONTEXT_GREGS_R5 _UC_MCONTEXT_GPR(5) +#define UC_MCONTEXT_GREGS_R6 _UC_MCONTEXT_GPR(6) +#define UC_MCONTEXT_GREGS_R7 _UC_MCONTEXT_GPR(7) +#define UC_MCONTEXT_GREGS_R8 _UC_MCONTEXT_GPR(8) +#define UC_MCONTEXT_GREGS_R9 _UC_MCONTEXT_GPR(9) +#define UC_MCONTEXT_GREGS_R10 _UC_MCONTEXT_GPR(10) +#define UC_MCONTEXT_GREGS_R11 _UC_MCONTEXT_GPR(11) +#define UC_MCONTEXT_GREGS_R12 _UC_MCONTEXT_GPR(12) +#define UC_MCONTEXT_GREGS_R13 _UC_MCONTEXT_GPR(13) +#define UC_MCONTEXT_GREGS_R14 _UC_MCONTEXT_GPR(14) +#define UC_MCONTEXT_GREGS_R15 _UC_MCONTEXT_GPR(15) +#define UC_MCONTEXT_GREGS_R16 _UC_MCONTEXT_GPR(16) +#define UC_MCONTEXT_GREGS_R17 _UC_MCONTEXT_GPR(17) +#define UC_MCONTEXT_GREGS_R18 _UC_MCONTEXT_GPR(18) +#define UC_MCONTEXT_GREGS_R19 _UC_MCONTEXT_GPR(19) +#define UC_MCONTEXT_GREGS_R20 _UC_MCONTEXT_GPR(20) +#define UC_MCONTEXT_GREGS_R21 _UC_MCONTEXT_GPR(21) +#define UC_MCONTEXT_GREGS_R22 _UC_MCONTEXT_GPR(22) +#define UC_MCONTEXT_GREGS_R23 _UC_MCONTEXT_GPR(23) +#define UC_MCONTEXT_GREGS_R24 _UC_MCONTEXT_GPR(24) +#define UC_MCONTEXT_GREGS_R25 _UC_MCONTEXT_GPR(25) +#define UC_MCONTEXT_GREGS_R26 _UC_MCONTEXT_GPR(26) +#define UC_MCONTEXT_GREGS_R27 _UC_MCONTEXT_GPR(27) +#define UC_MCONTEXT_GREGS_R28 _UC_MCONTEXT_GPR(28) +#define UC_MCONTEXT_GREGS_R29 _UC_MCONTEXT_GPR(29) +#define UC_MCONTEXT_GREGS_R30 _UC_MCONTEXT_GPR(30) +#define UC_MCONTEXT_GREGS_R31 _UC_MCONTEXT_GPR(31) +#define UC_MCONTEXT_GREGS_NIP _UC_MCONTEXT_GPR(NIP_IDX) +#define UC_MCONTEXT_GREGS_MSR _UC_MCONTEXT_GPR(MSR_IDX) +#ifdef ORIG_GPR3_IDX +#define UC_MCONTEXT_GREGS_ORIG_GPR3 _UC_MCONTEXT_GPR(ORIG_GPR3_IDX) +#endif +#define UC_MCONTEXT_GREGS_CTR _UC_MCONTEXT_GPR(CTR_IDX) +#define UC_MCONTEXT_GREGS_LINK _UC_MCONTEXT_GPR(LINK_IDX) +#define UC_MCONTEXT_GREGS_XER _UC_MCONTEXT_GPR(XER_IDX) +#define UC_MCONTEXT_GREGS_CCR _UC_MCONTEXT_GPR(CCR_IDX) +#ifdef SOFTE_IDX +#define UC_MCONTEXT_GREGS_SOFTE _UC_MCONTEXT_GPR(SOFTE_IDX) +#endif +#ifdef TRAP_IDX +#define UC_MCONTEXT_GREGS_TRAP _UC_MCONTEXT_GPR(TRAP_IDX) +#endif +#define UC_MCONTEXT_GREGS_DAR _UC_MCONTEXT_GPR(DAR_IDX) +#define UC_MCONTEXT_GREGS_DSISR _UC_MCONTEXT_GPR(DSISR_IDX) +#ifdef RESULT_IDX +#define UC_MCONTEXT_GREGS_RESULT _UC_MCONTEXT_GPR(RESULT_IDX) +#endif + +#define UC_MCONTEXT_FREGS_R0 _UC_MCONTEXT_FPR(0) +#define UC_MCONTEXT_FREGS_R1 _UC_MCONTEXT_FPR(1) +#define UC_MCONTEXT_FREGS_R2 _UC_MCONTEXT_FPR(2) +#define UC_MCONTEXT_FREGS_R3 _UC_MCONTEXT_FPR(3) +#define UC_MCONTEXT_FREGS_R4 _UC_MCONTEXT_FPR(4) +#define UC_MCONTEXT_FREGS_R5 _UC_MCONTEXT_FPR(5) +#define UC_MCONTEXT_FREGS_R6 _UC_MCONTEXT_FPR(6) +#define UC_MCONTEXT_FREGS_R7 _UC_MCONTEXT_FPR(7) +#define UC_MCONTEXT_FREGS_R8 _UC_MCONTEXT_FPR(8) +#define UC_MCONTEXT_FREGS_R9 _UC_MCONTEXT_FPR(9) +#define UC_MCONTEXT_FREGS_R10 _UC_MCONTEXT_FPR(10) +#define UC_MCONTEXT_FREGS_R11 _UC_MCONTEXT_FPR(11) +#define UC_MCONTEXT_FREGS_R12 _UC_MCONTEXT_FPR(12) +#define UC_MCONTEXT_FREGS_R13 _UC_MCONTEXT_FPR(13) +#define UC_MCONTEXT_FREGS_R14 _UC_MCONTEXT_FPR(14) +#define UC_MCONTEXT_FREGS_R15 _UC_MCONTEXT_FPR(15) +#define UC_MCONTEXT_FREGS_R16 _UC_MCONTEXT_FPR(16) +#define UC_MCONTEXT_FREGS_R17 _UC_MCONTEXT_FPR(17) +#define UC_MCONTEXT_FREGS_R18 _UC_MCONTEXT_FPR(18) +#define UC_MCONTEXT_FREGS_R19 _UC_MCONTEXT_FPR(19) +#define UC_MCONTEXT_FREGS_R20 _UC_MCONTEXT_FPR(20) +#define UC_MCONTEXT_FREGS_R21 _UC_MCONTEXT_FPR(21) +#define UC_MCONTEXT_FREGS_R22 _UC_MCONTEXT_FPR(22) +#define UC_MCONTEXT_FREGS_R23 _UC_MCONTEXT_FPR(23) +#define UC_MCONTEXT_FREGS_R24 _UC_MCONTEXT_FPR(24) +#define UC_MCONTEXT_FREGS_R25 _UC_MCONTEXT_FPR(25) +#define UC_MCONTEXT_FREGS_R26 _UC_MCONTEXT_FPR(26) +#define UC_MCONTEXT_FREGS_R27 _UC_MCONTEXT_FPR(27) +#define UC_MCONTEXT_FREGS_R28 _UC_MCONTEXT_FPR(28) +#define UC_MCONTEXT_FREGS_R29 _UC_MCONTEXT_FPR(29) +#define UC_MCONTEXT_FREGS_R30 _UC_MCONTEXT_FPR(30) +#define UC_MCONTEXT_FREGS_R31 _UC_MCONTEXT_FPR(31) +#define UC_MCONTEXT_FREGS_FPSCR _UC_MCONTEXT_FPR(32) #endif diff --git a/src/native/external/libunwind/src/ppc64/setcontext.S b/src/native/external/libunwind/src/ppc64/setcontext.S deleted file mode 100644 index ffc2500a51738..0000000000000 --- a/src/native/external/libunwind/src/ppc64/setcontext.S +++ /dev/null @@ -1,9 +0,0 @@ - .global _UI_setcontext - -_UI_setcontext: - blr - -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/src/native/external/libunwind/src/ptrace/_UPT_access_fpreg.c b/src/native/external/libunwind/src/ptrace/_UPT_access_fpreg.c index 178a97c0d88f8..3b993ed15fcde 100644 --- a/src/native/external/libunwind/src/ptrace/_UPT_access_fpreg.c +++ b/src/native/external/libunwind/src/ptrace/_UPT_access_fpreg.c @@ -90,6 +90,9 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, #elif defined(__powerpc64__) if ((unsigned) reg < UNW_PPC64_F0 || (unsigned) reg > UNW_PPC64_F31) return -UNW_EBADREG; +#elif defined(__powerpc__) + if ((unsigned) reg < UNW_PPC32_F0 || (unsigned) reg > UNW_PPC32_F31) + return -UNW_EBADREG; #else #error Fix me #endif @@ -107,7 +110,7 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, memcpy(&fpreg.fpr[reg], val, sizeof(unw_fpreg_t)); #elif defined(__aarch64__) memcpy(&fpreg.fp_q[reg], val, sizeof(unw_fpreg_t)); -#elif defined(__powerpc64__) +#elif defined(__powerpc__) memcpy(&fpreg.fpreg[reg], val, sizeof(unw_fpreg_t)); #else #error Fix me @@ -123,7 +126,7 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, memcpy(val, &fpreg.fpr[reg], sizeof(unw_fpreg_t)); #elif defined(__aarch64__) memcpy(val, &fpreg.fp_q[reg], sizeof(unw_fpreg_t)); -#elif defined(__powerpc64__) +#elif defined(__powerpc__) memcpy(val, &fpreg.fpreg[reg], sizeof(unw_fpreg_t)); #else #error Fix me diff --git a/src/native/external/libunwind/src/ptrace/_UPT_reg_offset.c b/src/native/external/libunwind/src/ptrace/_UPT_reg_offset.c index 57e9c4aa11f11..ea13e6de88cf8 100644 --- a/src/native/external/libunwind/src/ptrace/_UPT_reg_offset.c +++ b/src/native/external/libunwind/src/ptrace/_UPT_reg_offset.c @@ -36,7 +36,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ # include #endif -#if defined(__powerpc64__) && defined(__FreeBSD__) +#if defined(__powerpc__) && defined(__FreeBSD__) #define PT_R0 0 #define PT_R1 1 #define PT_R2 2 @@ -70,10 +70,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define PT_R30 30 #define PT_R31 31 #define PT_NIP 32 +#define PT_CCR 33 #define PT_CTR 35 #define PT_LNK 36 #define PT_XER 37 #define PT_FPR0 48 +#define PT_FPSCR (PT_FPR0 + 2*32 + 1) #define PT_VR0 82 #define PT_VSCR (PT_VR0 + 32*2 + 1) #define PT_VRSAVE (PT_VR0 + 33*2) @@ -757,39 +759,39 @@ const int _UPT_reg_offset[UNW_REG_LAST + 1] = #elif defined(UNW_TARGET_LOONGARCH64) # include - [UNW_LOONGARCH64_R0] = LOONGARCH64_EF_R0, - [UNW_LOONGARCH64_R1] = LOONGARCH64_EF_R1, - [UNW_LOONGARCH64_R2] = LOONGARCH64_EF_R2, - [UNW_LOONGARCH64_R3] = LOONGARCH64_EF_R3, - [UNW_LOONGARCH64_R4] = LOONGARCH64_EF_R4, - [UNW_LOONGARCH64_R5] = LOONGARCH64_EF_R5, - [UNW_LOONGARCH64_R6] = LOONGARCH64_EF_R6, - [UNW_LOONGARCH64_R7] = LOONGARCH64_EF_R7, - [UNW_LOONGARCH64_R8] = LOONGARCH64_EF_R8, - [UNW_LOONGARCH64_R9] = LOONGARCH64_EF_R9, - [UNW_LOONGARCH64_R10] = LOONGARCH64_EF_R10, - [UNW_LOONGARCH64_R11] = LOONGARCH64_EF_R11, - [UNW_LOONGARCH64_R12] = LOONGARCH64_EF_R12, - [UNW_LOONGARCH64_R13] = LOONGARCH64_EF_R13, - [UNW_LOONGARCH64_R14] = LOONGARCH64_EF_R14, - [UNW_LOONGARCH64_R15] = LOONGARCH64_EF_R15, - [UNW_LOONGARCH64_R16] = LOONGARCH64_EF_R16, - [UNW_LOONGARCH64_R17] = LOONGARCH64_EF_R17, - [UNW_LOONGARCH64_R18] = LOONGARCH64_EF_R18, - [UNW_LOONGARCH64_R19] = LOONGARCH64_EF_R19, - [UNW_LOONGARCH64_R20] = LOONGARCH64_EF_R20, - [UNW_LOONGARCH64_R21] = LOONGARCH64_EF_R21, - [UNW_LOONGARCH64_R22] = LOONGARCH64_EF_R22, - [UNW_LOONGARCH64_R23] = LOONGARCH64_EF_R23, - [UNW_LOONGARCH64_R24] = LOONGARCH64_EF_R24, - [UNW_LOONGARCH64_R25] = LOONGARCH64_EF_R25, - [UNW_LOONGARCH64_R26] = LOONGARCH64_EF_R26, - [UNW_LOONGARCH64_R27] = LOONGARCH64_EF_R27, - [UNW_LOONGARCH64_R28] = LOONGARCH64_EF_R28, - [UNW_LOONGARCH64_R29] = LOONGARCH64_EF_R29, - [UNW_LOONGARCH64_R30] = LOONGARCH64_EF_R30, - [UNW_LOONGARCH64_R31] = LOONGARCH64_EF_R31, - [UNW_LOONGARCH64_PC] = LOONGARCH64_EF_CSR_EPC + [UNW_LOONGARCH64_R0] = LOONGARCH_EF_R0, + [UNW_LOONGARCH64_R1] = LOONGARCH_EF_R1, + [UNW_LOONGARCH64_R2] = LOONGARCH_EF_R2, + [UNW_LOONGARCH64_R3] = LOONGARCH_EF_R3, + [UNW_LOONGARCH64_R4] = LOONGARCH_EF_R4, + [UNW_LOONGARCH64_R5] = LOONGARCH_EF_R5, + [UNW_LOONGARCH64_R6] = LOONGARCH_EF_R6, + [UNW_LOONGARCH64_R7] = LOONGARCH_EF_R7, + [UNW_LOONGARCH64_R8] = LOONGARCH_EF_R8, + [UNW_LOONGARCH64_R9] = LOONGARCH_EF_R9, + [UNW_LOONGARCH64_R10] = LOONGARCH_EF_R10, + [UNW_LOONGARCH64_R11] = LOONGARCH_EF_R11, + [UNW_LOONGARCH64_R12] = LOONGARCH_EF_R12, + [UNW_LOONGARCH64_R13] = LOONGARCH_EF_R13, + [UNW_LOONGARCH64_R14] = LOONGARCH_EF_R14, + [UNW_LOONGARCH64_R15] = LOONGARCH_EF_R15, + [UNW_LOONGARCH64_R16] = LOONGARCH_EF_R16, + [UNW_LOONGARCH64_R17] = LOONGARCH_EF_R17, + [UNW_LOONGARCH64_R18] = LOONGARCH_EF_R18, + [UNW_LOONGARCH64_R19] = LOONGARCH_EF_R19, + [UNW_LOONGARCH64_R20] = LOONGARCH_EF_R20, + [UNW_LOONGARCH64_R21] = LOONGARCH_EF_R21, + [UNW_LOONGARCH64_R22] = LOONGARCH_EF_R22, + [UNW_LOONGARCH64_R23] = LOONGARCH_EF_R23, + [UNW_LOONGARCH64_R24] = LOONGARCH_EF_R24, + [UNW_LOONGARCH64_R25] = LOONGARCH_EF_R25, + [UNW_LOONGARCH64_R26] = LOONGARCH_EF_R26, + [UNW_LOONGARCH64_R27] = LOONGARCH_EF_R27, + [UNW_LOONGARCH64_R28] = LOONGARCH_EF_R28, + [UNW_LOONGARCH64_R29] = LOONGARCH_EF_R29, + [UNW_LOONGARCH64_R30] = LOONGARCH_EF_R30, + [UNW_LOONGARCH64_R31] = LOONGARCH_EF_R31, + [UNW_LOONGARCH64_PC] = LOONGARCH_EF_CSR_ERA #else # error Fix me. #endif diff --git a/src/native/external/libunwind/src/remote/mac/missing-functions.c b/src/native/external/libunwind/src/remote/mac/missing-functions.c index ea75dbd5b5821..f0a7b3f53f27b 100644 --- a/src/native/external/libunwind/src/remote/mac/missing-functions.c +++ b/src/native/external/libunwind/src/remote/mac/missing-functions.c @@ -1,5 +1,6 @@ /* Copyright (C) 2022 Hewlett-Packard Co. Contributed by David Mosberger-Tang . + This file is part of libunwind. Permission is hereby granted, free of charge, to any person obtaining diff --git a/src/native/external/libunwind/src/riscv/Gstep.c b/src/native/external/libunwind/src/riscv/Gstep.c index 5126b0efd7d8b..28687a8f0b3af 100644 --- a/src/native/external/libunwind/src/riscv/Gstep.c +++ b/src/native/external/libunwind/src/riscv/Gstep.c @@ -53,6 +53,9 @@ riscv_handle_signal_frame (unw_cursor_t *cursor) return -UNW_EUNSPEC; #endif + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ diff --git a/src/native/external/libunwind/src/s390x/Gstep.c b/src/native/external/libunwind/src/s390x/Gstep.c index 0b79580b256bc..c6b644177cd40 100644 --- a/src/native/external/libunwind/src/s390x/Gstep.c +++ b/src/native/external/libunwind/src/s390x/Gstep.c @@ -64,6 +64,9 @@ s390x_handle_signal_frame (unw_cursor_t *cursor) c->sigcontext_addr = sc_addr; + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ diff --git a/src/native/external/libunwind/src/sh/Gstep.c b/src/native/external/libunwind/src/sh/Gstep.c index 60d7ec2ba9f6e..2c6a96c50c6d3 100644 --- a/src/native/external/libunwind/src/sh/Gstep.c +++ b/src/native/external/libunwind/src/sh/Gstep.c @@ -31,7 +31,7 @@ static int sh_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - int ret; + int i, ret; unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); @@ -63,6 +63,9 @@ sh_handle_signal_frame (unw_cursor_t *cursor) c->sigcontext_addr = sc_addr; + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ diff --git a/src/native/external/libunwind/src/tilegx/Gis_signal_frame.c b/src/native/external/libunwind/src/tilegx/Gis_signal_frame.c index 5452c2cb2aaf1..eea00e47fc177 100644 --- a/src/native/external/libunwind/src/tilegx/Gis_signal_frame.c +++ b/src/native/external/libunwind/src/tilegx/Gis_signal_frame.c @@ -96,6 +96,9 @@ tilegx_handle_signal_frame (unw_cursor_t *cursor) C_ABI_SAVE_AREA_SIZE; sc_addr = c->sigcontext_addr + LINUX_UC_MCONTEXT_OFF; + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Update the dwarf cursor. Set the location of the registers to the corresponding addresses of the uc_mcontext / sigcontext structure contents. */ diff --git a/src/native/external/libunwind/src/tilegx/Gstep.c b/src/native/external/libunwind/src/tilegx/Gstep.c index c748dbc588a85..b4456897bed0a 100644 --- a/src/native/external/libunwind/src/tilegx/Gstep.c +++ b/src/native/external/libunwind/src/tilegx/Gstep.c @@ -35,7 +35,7 @@ unw_step (unw_cursor_t *cursor) Debug (1, "(cursor=%p, ip=0x%016lx, sp=0x%016lx)\n", c, c->dwarf.ip, c->dwarf.cfa); - /* Special handling the singal frame. */ + /* Special handling the signal frame. */ if (unw_is_signal_frame (cursor) > 0) return tilegx_handle_signal_frame (cursor); diff --git a/src/native/external/libunwind/src/x86/Gos-freebsd.c b/src/native/external/libunwind/src/x86/Gos-freebsd.c index 7dd0140463859..28e6722af161a 100644 --- a/src/native/external/libunwind/src/x86/Gos-freebsd.c +++ b/src/native/external/libunwind/src/x86/Gos-freebsd.c @@ -124,6 +124,9 @@ x86_handle_signal_frame (unw_cursor_t *cursor) return 0; } + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + c->dwarf.loc[EIP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0); c->dwarf.loc[ESP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0); c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EAX_OFF, 0); @@ -138,6 +141,7 @@ x86_handle_signal_frame (unw_cursor_t *cursor) c->dwarf.loc[ST0] = DWARF_NULL_LOC; } else if (c->sigcontext_format == X86_SCF_FREEBSD_SYSCALL) { c->dwarf.loc[EIP] = DWARF_LOC (c->dwarf.cfa, 0); + c->dwarf.loc[ESP] = DWARF_VAL_LOC (c, c->dwarf.cfa + 4); c->dwarf.loc[EAX] = DWARF_NULL_LOC; c->dwarf.cfa += 4; c->dwarf.use_prev_instr = 1; diff --git a/src/native/external/libunwind/src/x86/Gos-linux.c b/src/native/external/libunwind/src/x86/Gos-linux.c index d448dce7357bd..0908e3a11d6ca 100644 --- a/src/native/external/libunwind/src/x86/Gos-linux.c +++ b/src/native/external/libunwind/src/x86/Gos-linux.c @@ -73,7 +73,7 @@ HIDDEN int x86_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - int ret; + int i, ret; /* c->esp points at the arguments to the handler. Without SA_SIGINFO, the arguments consist of a signal number @@ -123,6 +123,9 @@ x86_handle_signal_frame (unw_cursor_t *cursor) return 0; } + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + c->dwarf.loc[EAX] = DWARF_LOC (sc_addr + LINUX_SC_EAX_OFF, 0); c->dwarf.loc[ECX] = DWARF_LOC (sc_addr + LINUX_SC_ECX_OFF, 0); c->dwarf.loc[EDX] = DWARF_LOC (sc_addr + LINUX_SC_EDX_OFF, 0); @@ -130,9 +133,6 @@ x86_handle_signal_frame (unw_cursor_t *cursor) c->dwarf.loc[EBP] = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0); c->dwarf.loc[ESI] = DWARF_LOC (sc_addr + LINUX_SC_ESI_OFF, 0); c->dwarf.loc[EDI] = DWARF_LOC (sc_addr + LINUX_SC_EDI_OFF, 0); - c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC; - c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC; - c->dwarf.loc[ST0] = DWARF_NULL_LOC; c->dwarf.loc[EIP] = DWARF_LOC (sc_addr + LINUX_SC_EIP_OFF, 0); c->dwarf.loc[ESP] = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0); diff --git a/src/native/external/libunwind/src/x86/Gregs.c b/src/native/external/libunwind/src/x86/Gregs.c index 4a9592617d0d4..9446d6c62c646 100644 --- a/src/native/external/libunwind/src/x86/Gregs.c +++ b/src/native/external/libunwind/src/x86/Gregs.c @@ -53,7 +53,6 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, break; case UNW_X86_CFA: - case UNW_X86_ESP: if (write) return -UNW_EREADONLYREG; *valp = c->dwarf.cfa; @@ -81,6 +80,7 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, case UNW_X86_ECX: loc = c->dwarf.loc[ECX]; break; case UNW_X86_EBX: loc = c->dwarf.loc[EBX]; break; + case UNW_X86_ESP: loc = c->dwarf.loc[ESP]; break; case UNW_X86_EBP: loc = c->dwarf.loc[EBP]; break; case UNW_X86_ESI: loc = c->dwarf.loc[ESI]; break; case UNW_X86_EDI: loc = c->dwarf.loc[EDI]; break; diff --git a/src/native/external/libunwind/src/x86/Gstep.c b/src/native/external/libunwind/src/x86/Gstep.c index 129b739a3e78f..061dcbaaa2809 100644 --- a/src/native/external/libunwind/src/x86/Gstep.c +++ b/src/native/external/libunwind/src/x86/Gstep.c @@ -47,7 +47,7 @@ unw_step (unw_cursor_t *cursor) { /* DWARF failed, let's see if we can follow the frame-chain or skip over the signal trampoline. */ - struct dwarf_loc ebp_loc, eip_loc; + struct dwarf_loc ebp_loc, eip_loc, esp_loc; /* We could get here because of missing/bad unwind information. Validate all addresses before dereferencing. */ @@ -77,6 +77,7 @@ unw_step (unw_cursor_t *cursor) c->dwarf.cfa); ebp_loc = DWARF_LOC (c->dwarf.cfa, 0); + esp_loc = DWARF_VAL_LOC (c, c->dwarf.cfa + 8); eip_loc = DWARF_LOC (c->dwarf.cfa + 4, 0); c->dwarf.cfa += 8; @@ -87,6 +88,7 @@ unw_step (unw_cursor_t *cursor) c->dwarf.loc[i] = DWARF_NULL_LOC; c->dwarf.loc[EBP] = ebp_loc; + c->dwarf.loc[ESP] = esp_loc; c->dwarf.loc[EIP] = eip_loc; c->dwarf.use_prev_instr = 1; } diff --git a/src/native/external/libunwind/src/x86_64/Ginit.c b/src/native/external/libunwind/src/x86_64/Ginit.c index e75f92a5f3901..88146a3e78156 100644 --- a/src/native/external/libunwind/src/x86_64/Ginit.c +++ b/src/native/external/libunwind/src/x86_64/Ginit.c @@ -79,7 +79,7 @@ static int mem_validate_pipe[2] = {-1, -1}; static inline void do_pipe2 (int pipefd[2]) { - pipe2 (pipefd, O_CLOEXEC | O_NONBLOCK); + int result UNUSED = pipe2 (pipefd, O_CLOEXEC | O_NONBLOCK); } #else static inline void diff --git a/src/native/external/libunwind/src/x86_64/Gos-freebsd.c b/src/native/external/libunwind/src/x86_64/Gos-freebsd.c index 91a465c6c50bd..e8f04381679f0 100644 --- a/src/native/external/libunwind/src/x86_64/Gos-freebsd.c +++ b/src/native/external/libunwind/src/x86_64/Gos-freebsd.c @@ -92,7 +92,7 @@ x86_64_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; unw_word_t ucontext; - int ret; + int i, ret; if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME) { @@ -108,6 +108,9 @@ x86_64_handle_signal_frame (unw_cursor_t *cursor) return ret; } + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); @@ -133,6 +136,7 @@ x86_64_handle_signal_frame (unw_cursor_t *cursor) c->dwarf.loc[RCX] = c->dwarf.loc[R10]; /* rsp_loc = DWARF_LOC(c->dwarf.cfa - 8, 0); */ /* rbp_loc = c->dwarf.loc[RBP]; */ + c->dwarf.loc[RSP] = DWARF_VAL_LOC (c, c->dwarf.cfa + 8); c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", diff --git a/src/native/external/libunwind/src/x86_64/Gos-solaris.c b/src/native/external/libunwind/src/x86_64/Gos-solaris.c index 75258d61d8755..a9957ba8c9d76 100644 --- a/src/native/external/libunwind/src/x86_64/Gos-solaris.c +++ b/src/native/external/libunwind/src/x86_64/Gos-solaris.c @@ -51,6 +51,7 @@ x86_64_handle_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; unw_word_t ucontext = c->dwarf.cfa + sizeof (struct sigframe); + int i; if (c->sigcontext_format != X86_64_SCF_SOLARIS_SIGFRAME) return -UNW_EBADFRAME; @@ -69,6 +70,9 @@ x86_64_handle_signal_frame (unw_cursor_t *cursor) return ret; } + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); diff --git a/src/native/external/libunwind/src/x86_64/Gregs.c b/src/native/external/libunwind/src/x86_64/Gregs.c index baf8a24f0b912..dff5bcbe74b6e 100644 --- a/src/native/external/libunwind/src/x86_64/Gregs.c +++ b/src/native/external/libunwind/src/x86_64/Gregs.c @@ -79,7 +79,6 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, break; case UNW_X86_64_CFA: - case UNW_X86_64_RSP: if (write) return -UNW_EREADONLYREG; *valp = c->dwarf.cfa; @@ -107,6 +106,7 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, case UNW_X86_64_RCX: loc = c->dwarf.loc[RCX]; break; case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break; + case UNW_X86_64_RSP: loc = c->dwarf.loc[RSP]; break; case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break; case UNW_X86_64_RSI: loc = c->dwarf.loc[RSI]; break; case UNW_X86_64_RDI: loc = c->dwarf.loc[RDI]; break; diff --git a/src/native/external/libunwind/src/x86_64/Gstash_frame.c b/src/native/external/libunwind/src/x86_64/Gstash_frame.c index 2a44f873e9edf..6b980a9830b1b 100644 --- a/src/native/external/libunwind/src/x86_64/Gstash_frame.c +++ b/src/native/external/libunwind/src/x86_64/Gstash_frame.c @@ -45,7 +45,7 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) rs->reg.where[RBP] == DWARF_WHERE_EXPR) { /* Check for GCC generated alignment frame for rsp. A simple * def_cfa_expr that loads a constant offset from rbp, where the - * addres of the rip was pushed on the stack */ + * address of the rip was pushed on the stack */ unw_word_t cfa_addr = rs->reg.val[DWARF_CFA_REG_COLUMN]; unw_word_t rbp_addr = rs->reg.val[RBP]; unw_word_t cfa_offset; @@ -71,11 +71,13 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) && DWARF_GET_LOC(d->loc[rs->ret_addr_column]) == d->cfa-8 && (rs->reg.where[RBP] == DWARF_WHERE_UNDEF || rs->reg.where[RBP] == DWARF_WHERE_SAME + || rs->reg.where[RBP] == DWARF_WHERE_CFA || (rs->reg.where[RBP] == DWARF_WHERE_CFAREL && labs((long) rs->reg.val[RBP]) < (1 << 14) && rs->reg.val[RBP]+1 != 0)) && (rs->reg.where[RSP] == DWARF_WHERE_UNDEF || rs->reg.where[RSP] == DWARF_WHERE_SAME + || rs->reg.where[RSP] == DWARF_WHERE_CFA || (rs->reg.where[RSP] == DWARF_WHERE_CFAREL && labs((long) rs->reg.val[RSP]) < (1 << 14) && rs->reg.val[RSP]+1 != 0))) @@ -88,6 +90,10 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) f->rbp_cfa_offset = rs->reg.val[RBP]; if (rs->reg.where[RSP] == DWARF_WHERE_CFAREL) f->rsp_cfa_offset = rs->reg.val[RSP]; + if (rs->reg.where[RBP] == DWARF_WHERE_CFA) + f->rbp_cfa_offset = 0; + if (rs->reg.where[RSP] == DWARF_WHERE_CFA) + f->rsp_cfa_offset = 0; Debug (4, " standard frame\n"); } diff --git a/src/native/external/libunwind/src/x86_64/Gstep.c b/src/native/external/libunwind/src/x86_64/Gstep.c index bbc3d9847e8f7..146c27ee49f92 100644 --- a/src/native/external/libunwind/src/x86_64/Gstep.c +++ b/src/native/external/libunwind/src/x86_64/Gstep.c @@ -25,6 +25,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifdef HAVE_ASM_VSYSCALL_H +#include +#endif + #include "libunwind_i.h" #include "unwind_i.h" #include @@ -53,6 +57,20 @@ is_plt_entry (struct dwarf_cursor *c) return ret; } +static int +is_vsyscall (struct dwarf_cursor *c) +{ +#if defined(VSYSCALL_START) && defined(VSYSCALL_END) + return c->ip >= VSYSCALL_START && c->ip < VSYSCALL_END; +#elif defined(VSYSCALL_ADDR) + /* Linux 3.16 removes `VSYSCALL_START` and `VSYSCALL_END`. Assume + a single page is mapped for vsyscalls. */ + return c->ip >= VSYSCALL_ADDR && c->ip < VSYSCALL_ADDR + sysconf(_SC_PAGESIZE); +#else + return 0; +#endif +} + int unw_step (unw_cursor_t *cursor) { @@ -141,6 +159,15 @@ unw_step (unw_cursor_t *cursor) c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); c->dwarf.cfa += 8; } + else if (is_vsyscall (&c->dwarf)) + { + Debug (2, "in vsyscall region\n"); + c->frame_info.cfa_reg_offset = 8; + c->frame_info.cfa_reg_rsp = -1; + c->frame_info.frame_type = UNW_X86_64_FRAME_GUESSED; + c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); + c->dwarf.cfa += 8; + } else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) { for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) @@ -193,7 +220,7 @@ unw_step (unw_cursor_t *cursor) Debug (2, "new_ip 0x%lx looks valid\n", new_ip); rip_fixup_success = 1; c->frame_info.cfa_reg_offset = 8; - c->frame_info.cfa_reg_rsp = 1; + c->frame_info.cfa_reg_rsp = -1; c->frame_info.rbp_cfa_offset = -1; c->frame_info.rsp_cfa_offset = -1; c->frame_info.frame_type = UNW_X86_64_FRAME_OTHER; @@ -223,7 +250,7 @@ unw_step (unw_cursor_t *cursor) Debug (2, "RIP fixup didn't work, falling back\n"); unw_word_t rbp1 = 0; rbp_loc = DWARF_LOC(rbp, 0); - rsp_loc = DWARF_NULL_LOC; + rsp_loc = DWARF_VAL_LOC(c, rbp + 16); rip_loc = DWARF_LOC (rbp + 8, 0); ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1); Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n", diff --git a/src/native/external/libunwind/src/x86_64/Gtrace.c b/src/native/external/libunwind/src/x86_64/Gtrace.c index 963a858f27f5a..7f8964199b61b 100644 --- a/src/native/external/libunwind/src/x86_64/Gtrace.c +++ b/src/native/external/libunwind/src/x86_64/Gtrace.c @@ -404,7 +404,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size) int maxdepth = 0; int depth = 0; int ret; - int validate = 0; + int validate UNUSED = 0; /* Check input parametres. */ if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0)) diff --git a/src/native/external/libunwind/tests/Garm64-test-sve-signal.c b/src/native/external/libunwind/tests/Garm64-test-sve-signal.c new file mode 100644 index 0000000000000..52cb9ac6099da --- /dev/null +++ b/src/native/external/libunwind/tests/Garm64-test-sve-signal.c @@ -0,0 +1,121 @@ +/* + * Verify that unwinding from a signal handler works when variable width + * SVE registers are pushed onto the stack + */ + +#if defined(__ARM_FEATURE_SVE) && defined(__ARM_FEATURE_SVE_VECTOR_OPERATORS) + +#include +#include +#include +#include +#include +#include +#include +#include + +int64_t z[100]; + +void signal_handler(int signum) +{ + unw_cursor_t cursor; + unw_context_t context; + + const char* expected[] = { + "signal_frame", + "kill", + "sum", + "square", + "main", + }; + + unw_getcontext(&context); + unw_init_local(&cursor, &context); + + for (unsigned int depth = 0; depth < sizeof(expected) / sizeof(expected[0]); ++depth) + { + unw_word_t offset, pc; + int unw_rc = unw_step(&cursor); + if (unw_rc <= 0) { + printf("Frame: %d unw_step error: %d\n", depth, unw_rc); + exit(-1); + } + + unw_rc = unw_get_reg(&cursor, UNW_REG_IP, &pc); + if (pc == 0 || unw_rc != 0) { + printf("Frame: %d unw_get_reg error: %d\n", depth, unw_rc); + exit(-1); + } + + char sym[256]; + unw_rc = unw_is_signal_frame(&cursor); + if (unw_rc > 0) + { + strcpy(sym, "signal_frame"); + } + else if (unw_rc < 0) + { + printf("Frame: %d unw_is_signal_frame error: %d\n", depth, unw_rc); + exit(-1); + } + else + { + unw_rc = unw_get_proc_name(&cursor, sym, sizeof(sym), &offset); + if (unw_rc) + { + printf("Frame: %d unw_get_proc_name error: %d\n", depth, unw_rc); + exit(-1); + } + } + + if (strcmp(sym, expected[depth]) != 0) + { + printf("Frame: %d expected %s but found %s\n", depth, expected[depth], sym); + exit(-1); + } + } + + exit(0); /* PASS */ +} + +int64_t sum(svint64_t z0) +{ + int64_t ret = svaddv_s64(svptrue_b64(), z0); + kill (getpid (), SIGUSR1); + return ret; +} + +int64_t square(svint64_t z0) +{ + int64_t res = 0; + for (int i = 0; i < 100; ++i) + { + z0 = svmul_s64_z(svptrue_b64(), z0, z0); + res += sum(z0); + } + return res; +} + +int main() +{ + signal(SIGUSR1, signal_handler); + for (unsigned int i = 0; i < sizeof(z) / sizeof(z[0]); ++i) + z[i] = rand(); + + svint64_t z0 = svld1(svptrue_b64(), &z[0]); + square(z0); + + /* + * Shouldn't get here, exit is called from signal handler + */ + printf("Signal handler wasn't called\n"); + return -1; +} + +#else /* !__ARM_FEATURE_SVE */ +int +main () +{ + return 77; /* SKIP */ +} +#endif diff --git a/src/native/external/libunwind/tests/Gia64-test-nat.c b/src/native/external/libunwind/tests/Gia64-test-nat.c index 58099d621679e..acc814b46a7f6 100644 --- a/src/native/external/libunwind/tests/Gia64-test-nat.c +++ b/src/native/external/libunwind/tests/Gia64-test-nat.c @@ -26,6 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* This file tests corner-cases of NaT-bit handling. */ #include +#include #include #include #include diff --git a/src/native/external/libunwind/tests/Gtest-bt.c b/src/native/external/libunwind/tests/Gtest-bt.c index d5b484478705c..809970db93d57 100644 --- a/src/native/external/libunwind/tests/Gtest-bt.c +++ b/src/native/external/libunwind/tests/Gtest-bt.c @@ -1,6 +1,7 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2001-2004 Hewlett-Packard Co Contributed by David Mosberger-Tang + Copyright 2022 Blackberry Limited. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -189,17 +190,21 @@ sighandler (int signal, void *siginfo UNUSED, void *context) } # endif #elif UNW_TARGET_X86 -#if defined __linux__ || defined __sun +# if defined __linux__ || defined __sun printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]); -#elif defined __FreeBSD__ +# elif defined __FreeBSD__ printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_eip); -#endif +# endif #elif UNW_TARGET_X86_64 -#if defined __linux__ || defined __sun +# if defined __linux__ || defined __sun printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_RIP]); -#elif defined __FreeBSD__ +# elif defined __FreeBSD__ printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_rip); -#endif +# endif +#elif UNW_TARGET_AARCH64 +# if defined(__QNXNTO__) + fprintf (stderr, " @ %#010lx", (unsigned long) uc->uc_mcontext.cpu.elr); +# endif /* defined(__QNXNTO__) */ #endif printf ("\n"); } @@ -210,7 +215,9 @@ int main (int argc, char **argv UNUSED) { struct sigaction act; +#ifdef HAVE_SIGALTSTACK stack_t stk; +#endif /* HAVE_SIGALTSTACK */ verbose = (argc > 1); @@ -229,6 +236,7 @@ main (int argc, char **argv UNUSED) printf ("\nBacktrace across signal handler:\n"); kill (getpid (), SIGTERM); +#ifdef HAVE_SIGALTSTACK if (verbose) printf ("\nBacktrace across signal handler on alternate stack:\n"); stk.ss_sp = malloc (SIG_STACK_SIZE); @@ -245,6 +253,7 @@ main (int argc, char **argv UNUSED) if (sigaction (SIGTERM, &act, NULL) < 0) panic ("sigaction: %s\n", strerror (errno)); kill (getpid (), SIGTERM); +#endif /* HAVE_SIGALTSTACK */ if (num_errors > 0) { @@ -255,9 +264,11 @@ main (int argc, char **argv UNUSED) printf ("SUCCESS.\n"); signal (SIGTERM, SIG_DFL); +#ifdef HAVE_SIGALTSTACK stk.ss_flags = SS_DISABLE; sigaltstack (&stk, NULL); free (stk.ss_sp); +#endif /* HAVE_SIGALTSTACK */ return 0; } diff --git a/src/native/external/libunwind/tests/Gtest-trace.c b/src/native/external/libunwind/tests/Gtest-trace.c index 48667bb9f4df3..5f22f1fb77986 100644 --- a/src/native/external/libunwind/tests/Gtest-trace.c +++ b/src/native/external/libunwind/tests/Gtest-trace.c @@ -139,6 +139,64 @@ do_backtrace (void) } } +void +do_backtrace_with_context(void *context) +{ + unw_word_t ip; + int ret = -UNW_ENOINFO; + int depth = 0; + int i, m; + + if (verbose) + printf ("\tnormal trace:\n"); + + if (unw_init_local2 (&cursor, (unw_context_t*)context, UNW_INIT_SIGNAL_FRAME) < 0) + panic ("unw_init_local2 failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + addresses[0][depth] = (void *) ip; + } + while ((ret = unw_step (&cursor)) > 0 && ++depth < 128); + + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + printf ("FAILURE: unw_step() returned %d for ip=%lx\n", ret, (long) ip); + ++num_errors; + } + + if (verbose) + for (i = 0; i < depth; ++i) + printf ("\t #%-3d ip=%p\n", i, addresses[0][i]); + + if (verbose) + printf ("\n\tvia unw_backtrace2():\n"); + + m = unw_backtrace2 (addresses[1], 128, (unw_context_t*)context, UNW_INIT_SIGNAL_FRAME); + + if (verbose) + for (i = 0; i < m; ++i) + printf ("\t #%-3d ip=%p\n", i, addresses[1][i]); + + if (m != depth+1) + { + printf ("FAILURE: unw_step() loop and unw_backtrace2() depths differ: %d vs. %d\n", depth, m); + ++num_errors; + } + + if (m == depth + 1) + for (i = 0; i < depth; ++i) + /* Allow one in difference in comparison, trace returns adjusted addresses. */ + if (labs((unw_word_t) addresses[0][i] - (unw_word_t) addresses[1][i]) > 1) + { + printf ("FAILURE: unw_step() loop and uwn_backtrace2() addresses differ at %d: %p vs. %p\n", + i, addresses[0][i], addresses[1][i]); + ++num_errors; + } +} + void foo (long val UNUSED) { @@ -222,13 +280,16 @@ sighandler (int signal, void *siginfo UNUSED, void *context) printf ("\n"); } do_backtrace(); + do_backtrace_with_context(context); } int main (int argc, char **argv UNUSED) { struct sigaction act; +#ifdef HAVE_SIGALTSTACK stack_t stk; +#endif /* HAVE_SIGALTSTACK */ verbose = (argc > 1); @@ -247,6 +308,7 @@ main (int argc, char **argv UNUSED) printf ("\nBacktrace across signal handler:\n"); kill (getpid (), SIGTERM); +#ifdef HAVE_SIGALTSTACK if (verbose) printf ("\nBacktrace across signal handler on alternate stack:\n"); stk.ss_sp = malloc (SIG_STACK_SIZE); @@ -263,6 +325,7 @@ main (int argc, char **argv UNUSED) if (sigaction (SIGTERM, &act, NULL) < 0) panic ("sigaction: %s\n", strerror (errno)); kill (getpid (), SIGTERM); +#endif /* HAVE_SIGALTSTACK */ if (num_errors > 0) { @@ -274,9 +337,11 @@ main (int argc, char **argv UNUSED) printf ("SUCCESS.\n"); signal (SIGTERM, SIG_DFL); +#ifdef HAVE_SIGALTSTACK stk.ss_flags = SS_DISABLE; sigaltstack (&stk, NULL); free (stk.ss_sp); +#endif /* HAVE_SIGALTSTACK */ return 0; } diff --git a/src/native/external/libunwind/tests/Larm64-test-sve-signal.c b/src/native/external/libunwind/tests/Larm64-test-sve-signal.c new file mode 100644 index 0000000000000..f13580450a0a2 --- /dev/null +++ b/src/native/external/libunwind/tests/Larm64-test-sve-signal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Garm64-test-sve-signal.c" +#endif diff --git a/src/native/external/libunwind/tests/Makefile.am b/src/native/external/libunwind/tests/Makefile.am index c783fc312db8e..c074107008d7d 100644 --- a/src/native/external/libunwind/tests/Makefile.am +++ b/src/native/external/libunwind/tests/Makefile.am @@ -1,6 +1,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/include AM_CFLAGS = -fno-optimize-sibling-calls +LOG_DRIVER = $(SHELL) $(UNW_TESTDRIVER) + EXTRA_DIST = run-ia64-test-dyn1 run-ptrace-mapper run-ptrace-misc \ run-check-namespace run-coredump-unwind \ run-coredump-unwind-mdi check-namespace.sh.in \ @@ -44,13 +46,17 @@ if ARCH_X86_64 endif #ARCH X86_64 endif #!ARCH_PPC64 endif #!ARCH_IA64 + +if ARCH_AARCH64 + check_PROGRAMS_arch += Garm64-test-sve-signal Larm64-test-sve-signal +endif + check_PROGRAMS_cdep += Gtest-bt Ltest-bt Gtest-exc Ltest-exc \ Gtest-init Ltest-init \ Gtest-concurrent Ltest-concurrent \ Gtest-resume-sig Ltest-resume-sig \ Gtest-resume-sig-rt Ltest-resume-sig-rt \ Gtest-trace Ltest-trace \ - Ltest-init-local-signal \ Ltest-mem-validate \ test-async-sig test-flush-cache test-init-remote \ test-mem test-reg-state Ltest-varargs \ @@ -58,6 +64,11 @@ endif #!ARCH_IA64 noinst_PROGRAMS_cdep += forker Gperf-simple Lperf-simple \ Gperf-trace Lperf-trace +# unw_init_local2() is not implemented on ia64 +if !ARCH_IA64 + check_PROGRAMS_cdep += Ltest-init-local-signal +endif + if BUILD_PTRACE check_SCRIPTS_cdep += run-ptrace-mapper run-ptrace-misc check_PROGRAMS_cdep += test-ptrace @@ -125,6 +136,10 @@ if ARCH_ARM XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) endif +if ARCH_LOONGARCH64 +XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) +endif + # This is meant for multilib binaries, -m32. # ptrace gives EBADREG when testing, # but generally everything else works. @@ -155,6 +170,10 @@ Gx64_test_dwarf_expressions_SOURCES = Gx64-test-dwarf-expressions.c \ Lx64_test_dwarf_expressions_SOURCES = Lx64-test-dwarf-expressions.c \ x64-test-dwarf-expressions.S +Garm64_test_sve_signal_SOURCES = Garm64-test-sve-signal.c +Larm64_test_sve_signal_SOURCES = Larm64-test-sve-signal.c +Garm64_test_sve_signal_CFLAGS = -fno-inline -march=native +Larm64_test_sve_signal_CFLAGS = -fno-inline -march=native Gtest_init_SOURCES = Gtest-init.cxx Ltest_init_SOURCES = Ltest-init.cxx @@ -255,3 +274,6 @@ ppc64_test_altivec_LDADD = $(LIBUNWIND) Gx64_test_dwarf_expressions_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) Lx64_test_dwarf_expressions_LDADD = $(LIBUNWIND_local) + +Garm64_test_sve_signal_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Larm64_test_sve_signal_LDADD = $(LIBUNWIND_local) diff --git a/src/native/external/libunwind/tests/check-namespace.sh.in b/src/native/external/libunwind/tests/check-namespace.sh.in index e86b91774bc3b..a1b28a7ba37b0 100644 --- a/src/native/external/libunwind/tests/check-namespace.sh.in +++ b/src/native/external/libunwind/tests/check-namespace.sh.in @@ -93,7 +93,7 @@ filter_misc () { ignore _gp fi - if [ ${os} == "solaris2.11" ]; then + if [ ${os} = "solaris2.11" ]; then ignore _PROCEDURE_LINKAGE_TABLE_ ignore _etext fi @@ -109,6 +109,7 @@ check_local_unw_abi () { match _UL${plat}_get_proc_info_by_ip match _UL${plat}_get_proc_info_in_range match _UL${plat}_get_proc_name + match _UL${plat}_get_proc_name_by_ip match _UL${plat}_get_reg match _UL${plat}_get_save_loc match _UL${plat}_init_local @@ -125,7 +126,8 @@ check_local_unw_abi () { match _U${plat}_flush_cache match _U${plat}_get_accessors - match _U${plat}_getcontext + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path match _U${plat}_regname match _U${plat}_strerror @@ -135,79 +137,70 @@ check_local_unw_abi () { match unw_backtrace @CONFIG_WEAK_BACKTRACE_TRUE@match backtrace + match unw_backtrace2 case ${plat} in arm) - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path + match _U${plat}_getcontext match _U${plat}_is_fpreg match _UL${plat}_search_unwind_table match _UL${plat}_dwarf_search_unwind_table match _UL${plat}_dwarf_find_unwind_table ;; hppa) + match _U${plat}_getcontext match _UL${plat}_dwarf_search_unwind_table match _UL${plat}_dwarf_find_unwind_table - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path match _U${plat}_setcontext ;; ia64) + match _U${plat}_getcontext match _UL${plat}_search_unwind_table - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path ;; x86) - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path + match _U${plat}_getcontext match _U${plat}_is_fpreg match _UL${plat}_dwarf_search_unwind_table match _UL${plat}_dwarf_find_unwind_table ;; x86_64) - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path + match _U${plat}_getcontext match _U${plat}_is_fpreg match _UL${plat}_dwarf_search_unwind_table match _UL${plat}_dwarf_find_unwind_table match _U${plat}_setcontext ;; ppc*) + match _U${plat}_getcontext match _U${plat}_get_func_addr - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path match _U${plat}_is_fpreg match _UL${plat}_dwarf_search_unwind_table match _UL${plat}_dwarf_find_unwind_table ;; - tilegx) - match _U${plat}_is_fpreg + tilegx) + match _U${plat}_getcontext + match _U${plat}_is_fpreg match _UL${plat}_dwarf_search_unwind_table match _UL${plat}_dwarf_find_unwind_table - match _UL${plat}_local_addr_space_init - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path - match ${plat}_lock - ;; + match _UL${plat}_local_addr_space_init + match ${plat}_lock + ;; s390x) - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path + match _U${plat}_getcontext match _U${plat}_is_fpreg match _UL${plat}_dwarf_search_unwind_table match _UL${plat}_dwarf_find_unwind_table match _U${plat}_setcontext ;; riscv) - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path + match _U${plat}_getcontext match _U${plat}_is_fpreg match _UL${plat}_dwarf_search_unwind_table match _UL${plat}_dwarf_find_unwind_table match _U${plat}_setcontext ;; loongarch64) - match _U${plat}_get_elf_image - match _U${plat}_get_exe_image_path + match _U${plat}_getcontext match _U${plat}_is_fpreg match _UL${plat}_dwarf_search_unwind_table match _UL${plat}_dwarf_find_unwind_table @@ -237,6 +230,7 @@ check_generic_unw_abi () { match _U${plat}_get_proc_info_by_ip match _U${plat}_get_proc_info_in_range match _U${plat}_get_proc_name + match _U${plat}_get_proc_name_by_ip match _U${plat}_get_reg match _U${plat}_get_save_loc match _U${plat}_init_local @@ -303,15 +297,15 @@ check_generic_unw_abi () { match _U${plat}_dwarf_search_unwind_table match _U${plat}_dwarf_find_unwind_table ;; - tilegx) - match _U${plat}_dwarf_search_unwind_table + tilegx) + match _U${plat}_dwarf_search_unwind_table match _U${plat}_dwarf_find_unwind_table - match _U${plat}_get_elf_image + match _U${plat}_get_elf_image match _U${plat}_get_exe_image_path - match _U${plat}_is_fpreg - match _U${plat}_local_addr_space_init - match ${plat}_lock - ;; + match _U${plat}_is_fpreg + match _U${plat}_local_addr_space_init + match ${plat}_lock + ;; s390x) match _U${plat}_is_fpreg match _U${plat}_get_elf_image @@ -337,6 +331,8 @@ check_generic_unw_abi () { match _U${plat}_is_fpreg match _U${plat}_dwarf_search_unwind_table match _U${plat}_dwarf_find_unwind_table + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path ;; esac diff --git a/src/native/external/libunwind/tests/crasher.c b/src/native/external/libunwind/tests/crasher.c index bb99e339c2639..e19e2d691ed31 100644 --- a/src/native/external/libunwind/tests/crasher.c +++ b/src/native/external/libunwind/tests/crasher.c @@ -88,7 +88,7 @@ write_maps(char *fname) #ifdef __GNUC__ #ifndef __clang__ -// Gcc >= 8 became too good at inlining aliase c into b when using -O2 or -O3, +// Gcc >= 8 became too good at inlining alias c into b when using -O2 or -O3, // so force -O1 in all cases, otherwise a frame will be missing in the tests. #pragma GCC optimize "-O1" #endif @@ -110,7 +110,7 @@ int NOINLINE b(int x) int r; compiler_barrier(); - + if (x) r = a(); else diff --git a/src/native/external/libunwind/tests/run-coredump-unwind b/src/native/external/libunwind/tests/run-coredump-unwind index ddaac6a439449..690362bdae466 100755 --- a/src/native/external/libunwind/tests/run-coredump-unwind +++ b/src/native/external/libunwind/tests/run-coredump-unwind @@ -49,6 +49,10 @@ fi ./crasher backing_files ) 2>/dev/null COREFILE=$TEMPDIR/core* +if ! test -f "$COREFILE"; then + echo "crasher process did not produce coredump, test skipped" + exit 77 +fi # magic option -testcase enables checking for the specific contents of the stack ./test-coredump-unwind $COREFILE -testcase `cat $TEMPDIR/backing_files` diff --git a/src/native/external/libunwind/tests/test-coredump-unwind.c b/src/native/external/libunwind/tests/test-coredump-unwind.c index 93d9a0ee61747..5c29600492d18 100644 --- a/src/native/external/libunwind/tests/test-coredump-unwind.c +++ b/src/native/external/libunwind/tests/test-coredump-unwind.c @@ -141,7 +141,7 @@ static void verror_msg_helper(const char *s, if (flags & LOGMODE_STDIO) { fflush(stdout); - write(STDERR_FILENO, msg, used + msgeol_len); + ssize_t written UNUSED = write(STDERR_FILENO, msg, used + msgeol_len); } msg[used] = '\0'; /* remove msg_eol (usually "\n") */ if (flags & LOGMODE_SYSLOG) @@ -244,8 +244,7 @@ void handle_sigsegv(int sig, siginfo_t *info, void *ucontext) { /* glibc extension */ void *array[50]; - int size; - size = backtrace(array, 50); + int size UNUSED = backtrace(array, 50); #if defined __linux__ && HAVE_EXECINFO_H backtrace_symbols_fd(array, size, 2); #endif @@ -315,17 +314,6 @@ main(int argc UNUSED, char **argv) argv++; } - while (*argv) - { - char *colon; - unsigned long vaddr = strtoul(*argv, &colon, 16); - if (*colon != ':') - error_msg_and_die("Bad format: '%s'", *argv); - if (_UCD_add_backing_file_at_vaddr(ui, vaddr, colon + 1) < 0) - error_msg("Can't add backing file '%s'", colon + 1); - argv++; - } - for (;;) { unw_word_t ip; diff --git a/src/native/external/libunwind/tests/x64-test-dwarf-expressions.S b/src/native/external/libunwind/tests/x64-test-dwarf-expressions.S index f275625df1006..19ebc9d438d99 100644 --- a/src/native/external/libunwind/tests/x64-test-dwarf-expressions.S +++ b/src/native/external/libunwind/tests/x64-test-dwarf-expressions.S @@ -64,7 +64,7 @@ DW_CFA_expression_inner: # DW_CFA_expression(0x10), r12(0x0c), Length(0x02), (preamble) # DW_OP_lit16(0x40), DW_OP_minus(0x1c) (instructions) # Parsing starts with the CFA on the stack, then pushes 16, then does a minus - # which is eqivalent to a=pop(), b=pop(), push(b-a), leaving us with a value + # which is equivalent to a=pop(), b=pop(), push(b-a), leaving us with a value # of cfa-16 (cfa points at old rsp, cfa-8 is our rip, so we stored r12 at # cfa-16). xor %r12, %r12 # Trash r12